Skip to content

Commit c6720b3

Browse files
committed
Merge branch 'master' into tests-to-specs
Conflicts: Classes/GTDiff.m
2 parents 87fff3b + d9cbb5c commit c6720b3

File tree

9 files changed

+189
-65
lines changed

9 files changed

+189
-65
lines changed

Classes/Categories/NSArray+StringArray.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@
1212

1313
@interface NSArray (StringArray)
1414

15+
// Creates an `NSString` array from a `git_strarray`.
16+
//
17+
// The `git_strarray` must still be freed using `git_strarray_free` after use.
18+
//
19+
// strarray - The `git_strarray` to convert.
20+
//
21+
// Returns a new array with the contents of `strarray` converted to `NSString`s.
22+
+ (instancetype)git_arrayWithStrarray:(git_strarray)strarray;
23+
1524
// Creates and returns a `git_strarray` given an `NSArray` of `NSString`s.
1625
//
1726
// Must only be called with an array of `NSString`s, otherwise an assertion will

Classes/Categories/NSArray+StringArray.m

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,37 @@
77
//
88

99
#import "NSArray+StringArray.h"
10+
#import "EXTScope.h"
1011

1112
@implementation NSArray (StringArray)
1213

14+
+ (instancetype)git_arrayWithStrarray:(git_strarray)strarray {
15+
__strong id *strings = (__strong id *)calloc(strarray.count, sizeof(*strings));
16+
@onExit {
17+
free(strings);
18+
};
19+
20+
size_t stringsCount = 0;
21+
for (size_t i = 0; i < strarray.count; i++) {
22+
const char *cStr = strarray.strings[i];
23+
if (cStr == NULL) continue;
24+
25+
strings[stringsCount++] = @(cStr);
26+
}
27+
28+
@onExit {
29+
// Make sure to set each entry in `strings` to nil, so ARC properly
30+
// releases its references.
31+
for (size_t i = 0; i < stringsCount; i++) {
32+
strings[i] = nil;
33+
}
34+
};
35+
36+
// If any of the strings were nil, we may have fewer objects than
37+
// `strarray`.
38+
return [[self alloc] initWithObjects:strings count:stringsCount];
39+
}
40+
1341
- (git_strarray)git_strarray {
1442
if (self.count < 1) return (git_strarray){ .strings = NULL, .count = 0 };
1543

Classes/GTDiff.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ + (GTDiff *)diffWorkingDirectoryFromTree:(GTTree *)tree inRepository:(GTReposito
151151
+ (GTDiff *)diffWorkingDirectoryToHEADInRepository:(GTRepository *)repository options:(NSDictionary *)options error:(NSError **)error {
152152
NSParameterAssert(repository != nil);
153153

154-
GTCommit *HEADCommit = [repository lookupObjectByRevspec:@"HEAD" error:NULL];
154+
GTCommit *HEADCommit = [[repository headReferenceWithError:NULL] resolvedTarget];
155155
GTDiff *HEADIndexDiff = [GTDiff diffIndexFromTree:HEADCommit.tree inRepository:repository options:options error:error];
156156
if (HEADIndexDiff == nil) return nil;
157157

Classes/GTRemote.m

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#import "GTRemote.h"
1010

1111
#import "NSError+Git.h"
12+
#import "NSArray+StringArray.h"
1213
#import "EXTScope.h"
1314

1415
@interface GTRemote ()
@@ -74,12 +75,8 @@ - (NSArray *)fetchRefspecs {
7475
git_strarray_free(&refspecs);
7576
};
7677

77-
NSMutableArray *fetchRefspecs = [NSMutableArray arrayWithCapacity:refspecs.count];
78-
for (size_t i = 0; i < refspecs.count; i++) {
79-
if (refspecs.strings[i] == NULL) continue;
80-
[fetchRefspecs addObject:@(refspecs.strings[i])];
81-
}
82-
return [fetchRefspecs copy];
78+
return [NSArray git_arrayWithStrarray:refspecs];
79+
8380
}
8481

8582
#pragma mark Update the remote

Classes/GTRepository+Status.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,26 @@
1010

1111
@class GTStatusDelta;
1212

13+
// An enum representing the status of a file
14+
// See git_status_t
15+
typedef enum {
16+
GTFileStatusCurrent = GIT_STATUS_CURRENT,
17+
18+
GTFileStatusNewInIndex = GIT_STATUS_INDEX_NEW,
19+
GTFileStatusModifiedInIndex = GIT_STATUS_INDEX_MODIFIED,
20+
GTFileStatusDeletedInIndex = GIT_STATUS_INDEX_DELETED,
21+
GTFileStatusRenamedInIndex = GIT_STATUS_INDEX_RENAMED,
22+
GTFileStatusTypeChangedInIndex = GIT_STATUS_INDEX_TYPECHANGE,
23+
24+
GTFileStatusNewInWorktree = GIT_STATUS_WT_NEW,
25+
GTFileStatusModifiedInWorktree = GIT_STATUS_WT_MODIFIED,
26+
GTFileStatusDeletedInWorktree = GIT_STATUS_WT_DELETED,
27+
GTFileStatusTypeChangedInWorktree = GIT_STATUS_WT_TYPECHANGE,
28+
GTFileStatusRenamedInWorktree = GIT_STATUS_WT_RENAMED,
29+
30+
GTFileStatusIgnored = GIT_STATUS_IGNORED,
31+
} GTFileStatusFlags;
32+
1333
// An `NSNumber` wrapped `GTRepositoryStatusOptionsShow` bitmask.
1434
//
1535
// For extending the reporting of status. Using the flags documented below this
@@ -88,4 +108,10 @@ extern NSString *const GTRepositoryStatusOptionsPathSpecArrayKey;
88108
// successfully.
89109
- (BOOL)enumerateFileStatusWithOptions:(NSDictionary *)options error:(NSError **)error usingBlock:(void (^)(GTStatusDelta *headToIndex, GTStatusDelta *indexToWorkingDirectory, BOOL *stop))block;
90110

111+
// Query the status of one file
112+
- (GTFileStatusFlags)statusForFile:(NSURL *)fileURL success:(BOOL *)success error:(NSError **)error;
113+
114+
// Should the file be considered as ignored ?
115+
- (BOOL)shouldFileBeIgnored:(NSURL *)fileURL success:(BOOL *)success error:(NSError **)error;
116+
91117
@end

Classes/GTRepository+Status.m

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,36 @@ - (BOOL)isWorkingDirectoryClean {
9292
return clean;
9393
}
9494

95+
- (GTFileStatusFlags)statusForFile:(NSURL *)fileURL success:(BOOL *)success error:(NSError **)error {
96+
NSParameterAssert(fileURL != nil);
97+
98+
git_status_t status;
99+
100+
int gitError = git_status_file(&status, self.git_repository, fileURL.path.fileSystemRepresentation);
101+
if (gitError != GIT_OK) {
102+
if (error) *error = [NSError git_errorFor:gitError description:@"Status failed" failureReason:@"Failed to get status for file \"%@\" in \"%@\"", fileURL.path, self.gitDirectoryURL];
103+
*success = NO;
104+
return GTFileStatusCurrent;
105+
}
106+
107+
*success = YES;
108+
return (GTFileStatusFlags)status;
109+
}
110+
111+
- (BOOL)shouldFileBeIgnored:(NSURL *)fileURL success:(BOOL *)success error:(NSError **)error {
112+
NSParameterAssert(fileURL != nil);
113+
114+
int ignoreState = 0;
115+
116+
int gitError = git_status_should_ignore(&ignoreState, self.git_repository, fileURL.path.fileSystemRepresentation);
117+
if (gitError != GIT_OK) {
118+
if (error) *error = [NSError git_errorFor:gitError description:@"Ignore failed" failureReason:@"Failed to get ignore status for file \"%@\" in \"%@\"", fileURL.path, self.gitDirectoryURL];
119+
*success = NO;
120+
return YES;
121+
}
122+
123+
*success = YES;
124+
return (ignoreState == 0 ? YES : NO);
125+
}
126+
95127
@end

Classes/GTRepository.m

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#import "GTTree.h"
4848
#import "GTCredential.h"
4949
#import "GTCredential+Private.h"
50+
#import "NSArray+StringArray.h"
5051

5152
NSString *const GTRepositoryCloneOptionsBare = @"GTRepositoryCloneOptionsBare";
5253
NSString *const GTRepositoryCloneOptionsCheckout = @"GTRepositoryCloneOptionsCheckout";
@@ -436,17 +437,11 @@ - (NSArray *)referenceNamesWithError:(NSError **)error {
436437
return nil;
437438
}
438439

439-
NSMutableArray *references = [NSMutableArray arrayWithCapacity:array.count];
440-
for (NSUInteger i = 0; i < array.count; i++) {
441-
NSString *refName = @(array.strings[i]);
442-
if (refName == nil) continue;
443-
444-
[references addObject:refName];
445-
}
440+
NSArray *referenceNames = [NSArray git_arrayWithStrarray:array];
446441

447442
git_strarray_free(&array);
448443

449-
return references;
444+
return referenceNames;
450445
}
451446

452447
- (NSURL *)fileURL {
@@ -465,11 +460,11 @@ - (NSURL *)gitDirectoryURL {
465460
}
466461

467462
- (BOOL)isBare {
468-
return self.git_repository && git_repository_is_bare(self.git_repository);
463+
return (BOOL)git_repository_is_bare(self.git_repository);
469464
}
470465

471466
- (BOOL)isHEADDetached {
472-
return (BOOL) git_repository_head_detached(self.git_repository);
467+
return (BOOL)git_repository_head_detached(self.git_repository);
473468
}
474469

475470
- (BOOL)isHEADUnborn {

ObjectiveGitTests/GTRepository+StatusSpec.m

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,35 +52,35 @@
5252
updateIndexForSubpathAndExpectStatus(subpath, status);
5353
};
5454

55-
it(@"should recognise untracked files", ^{
55+
it(@"should recognize untracked files", ^{
5656
expectSubpathToHaveWorkDirStatus(@"UntrackedImage.png", GTStatusDeltaStatusUntracked);
5757
});
5858

59-
it(@"should recognise added files", ^{
59+
it(@"should recognize added files", ^{
6060
updateIndexForSubpathAndExpectStatus(@"UntrackedImage.png", GTStatusDeltaStatusAdded);
6161
});
6262

63-
it(@"should recognise modified files", ^{
63+
it(@"should recognize modified files", ^{
6464
expect([NSFileManager.defaultManager removeItemAtURL:targetFileURL error:&err]).to.beTruthy();
6565
expect(err).to.beNil();
6666
expect([testData writeToURL:targetFileURL atomically:YES]).to.beTruthy();
6767
expectSubpathToHaveMatchingStatus(targetFileURL.lastPathComponent, GTStatusDeltaStatusModified);
6868
});
6969

70-
it(@"should recognise copied files", ^{
70+
it(@"should recognize copied files", ^{
7171
NSURL *copyLocation = [repository.fileURL URLByAppendingPathComponent:@"main2.m"];
7272
expect([NSFileManager.defaultManager copyItemAtURL:targetFileURL toURL:copyLocation error:&err]).to.beTruthy();
7373
expect(err).to.beNil();
7474
updateIndexForSubpathAndExpectStatus(copyLocation.lastPathComponent, GTStatusDeltaStatusCopied);
7575
});
7676

77-
it(@"should recognise deleted files", ^{
77+
it(@"should recognize deleted files", ^{
7878
expect([NSFileManager.defaultManager removeItemAtURL:targetFileURL error:&err]).to.beTruthy();
7979
expect(err).to.beNil();
8080
expectSubpathToHaveMatchingStatus(targetFileURL.lastPathComponent, GTStatusDeltaStatusDeleted);
8181
});
8282

83-
it(@"should recognise renamed files", ^{
83+
it(@"should recognize renamed files", ^{
8484
NSURL *moveLocation = [repository.fileURL URLByAppendingPathComponent:@"main-moved.m"];
8585
expect([NSFileManager.defaultManager moveItemAtURL:targetFileURL toURL:moveLocation error:&err]).to.beTruthy();
8686
expect(err).to.beNil();

ObjectiveGitTests/NSArray+StringArraySpec.m

Lines changed: 79 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,52 +9,89 @@
99
SpecBegin(StringArray)
1010

1111
describe(@"String arrays", ^{
12-
__block NSArray *originalArray = nil;
13-
__block git_strarray strArray;
14-
15-
beforeEach(^{
16-
originalArray = @[ @"First", @"Second", @"Third", @"Fourth", @"Fifth", @"Sixth" ];
17-
strArray = originalArray.git_strarray;
18-
});
19-
20-
afterEach(^{
21-
git_strarray_free(&strArray);
22-
});
23-
24-
it(@"should return null for an empty array", ^{
25-
NSArray *emptyArray = [NSArray array];
26-
expect(emptyArray.git_strarray.count).to.equal(0);
27-
expect(emptyArray.git_strarray.strings).to.beNil();
28-
});
2912

30-
void (^validateStrArray)(git_strarray) = ^(git_strarray arrayToValidate) {
31-
expect(arrayToValidate.count).to.equal(originalArray.count);
32-
33-
for (NSUInteger idx = 0; idx < originalArray.count; idx++) {
34-
const char *convertedString = arrayToValidate.strings[idx];
35-
NSString *comparisonString = [NSString stringWithUTF8String:convertedString];
36-
expect(originalArray[idx]).to.equal(comparisonString);
13+
void (^validateStrArray)(NSArray *, git_strarray) = ^(NSArray *array, git_strarray strArray) {
14+
expect(strArray.count).to.equal(array.count);
15+
16+
for (NSUInteger idx = 0; idx < array.count; idx++) {
17+
const char *convertedString = strArray.strings[idx];
18+
NSString *comparisonString = @(convertedString);
19+
expect(array[idx]).to.equal(comparisonString);
3720
}
3821
};
39-
40-
it(@"should correctly translate the strings", ^{
41-
validateStrArray(strArray);
42-
});
43-
44-
it(@"should be able to be copied", ^{
45-
git_strarray copiedArray;
46-
git_strarray_copy(&copiedArray, &strArray);
47-
validateStrArray(copiedArray);
48-
git_strarray_free(&copiedArray);
22+
23+
describe(@"allow conversion to a git_strarray", ^{
24+
__block NSArray *originalArray = nil;
25+
__block git_strarray strArray;
26+
27+
beforeEach(^{
28+
originalArray = @[ @"First", @"Second", @"Third", @"Fourth", @"Fifth", @"Sixth" ];
29+
strArray = originalArray.git_strarray;
30+
});
31+
32+
afterEach(^{
33+
git_strarray_free(&strArray);
34+
});
35+
36+
it(@"should return null for an empty array", ^{
37+
NSArray *emptyArray = [NSArray array];
38+
expect(emptyArray.git_strarray.count).to.equal(0);
39+
expect(emptyArray.git_strarray.strings).to.beNil();
40+
});
41+
42+
it(@"should correctly translate the strings", ^{
43+
validateStrArray(originalArray, strArray);
44+
});
45+
46+
it(@"should be able to be copied", ^{
47+
git_strarray copiedArray;
48+
git_strarray_copy(&copiedArray, &strArray);
49+
validateStrArray(originalArray, copiedArray);
50+
git_strarray_free(&copiedArray);
51+
});
52+
53+
it(@"should stay valid outside of an autorelease pool", ^{
54+
git_strarray dontAutoreleaseThis;
55+
@autoreleasepool {
56+
dontAutoreleaseThis = originalArray.git_strarray;
57+
}
58+
59+
validateStrArray(originalArray, dontAutoreleaseThis);
60+
});
4961
});
50-
51-
it(@"should stay valid outside of an autorelease pool", ^{
52-
git_strarray dontAutoreleaseThis;
53-
@autoreleasepool {
54-
dontAutoreleaseThis = originalArray.git_strarray;
55-
}
56-
57-
validateStrArray(dontAutoreleaseThis);
62+
63+
describe(@"allows conversion from a git_strarray", ^{
64+
__block git_strarray originalStrArray;
65+
66+
beforeEach(^{
67+
originalStrArray.count = 3;
68+
originalStrArray.strings = calloc(originalStrArray.count, sizeof(char *));
69+
originalStrArray.strings[0] = "First";
70+
originalStrArray.strings[1] = "Second";
71+
originalStrArray.strings[2] = "Third";
72+
});
73+
74+
afterEach(^{
75+
free(originalStrArray.strings);
76+
});
77+
78+
it(@"should return an empty array for an NULL strarray", ^{
79+
git_strarray strarray = { .strings = NULL, .count = 0 };
80+
NSArray *array = [NSArray git_arrayWithStrarray:strarray];
81+
expect(array.count).to.equal(0);
82+
});
83+
84+
it(@"should correctly translate the strarray", ^{
85+
NSArray *array = [NSArray git_arrayWithStrarray:originalStrArray];
86+
validateStrArray(array, originalStrArray);
87+
});
88+
89+
it(@"should omit NULL strings", ^{
90+
originalStrArray.strings[1] = NULL;
91+
92+
NSArray *array = [NSArray git_arrayWithStrarray:originalStrArray];
93+
expect(array).to.equal((@[ @"First", @"Third" ]));
94+
});
5895
});
5996
});
6097

0 commit comments

Comments
 (0)