Skip to content

Commit

Permalink
Merge pull request #450 from libgit2/oid-ahead-behind
Browse files Browse the repository at this point in the history
Support OIDs for ahead/behind count and enumeration
  • Loading branch information
robrix committed Mar 21, 2015
2 parents 2811537 + 7301dd3 commit 3503fc0
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 63 deletions.
2 changes: 1 addition & 1 deletion ObjectiveGit/GTBranch.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ typedef NS_ENUM(NSInteger, GTBranchType) {

@property (nonatomic, readonly) NSString *name;
@property (nonatomic, readonly) NSString *shortName;
@property (nonatomic, readonly) NSString *SHA;
@property (nonatomic, copy, readonly) GTOID *OID;
@property (nonatomic, readonly) NSString *remoteName;
@property (nonatomic, readonly) GTBranchType branchType;
@property (nonatomic, readonly, strong) GTRepository *repository;
Expand Down
55 changes: 15 additions & 40 deletions ObjectiveGit/GTBranch.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@
//

#import "GTBranch.h"
#import "GTReference.h"
#import "GTEnumerator.h"
#import "GTRepository.h"

#import "GTCommit.h"
#import "GTEnumerator.h"
#import "GTOID.h"
#import "GTReference.h"
#import "GTRemote.h"
#import "GTRepository.h"
#import "NSError+Git.h"

#import "git2/branch.h"
Expand All @@ -38,18 +40,18 @@
@implementation GTBranch

- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p> name: %@, shortName: %@, sha: %@, remoteName: %@, repository: %@", NSStringFromClass([self class]), self, self.name, self.shortName, self.SHA, self.remoteName, self.repository];
return [NSString stringWithFormat:@"<%@: %p> name: %@, shortName: %@, sha: %@, remoteName: %@, repository: %@", NSStringFromClass([self class]), self, self.name, self.shortName, self.OID, self.remoteName, self.repository];
}

- (BOOL)isEqual:(GTBranch *)otherBranch {
if (otherBranch == self) return YES;
if (![otherBranch isKindOfClass:self.class]) return NO;

return [self.name isEqual:otherBranch.name] && [self.SHA isEqual:otherBranch.SHA];
return [self.name isEqual:otherBranch.name] && [self.OID isEqual:otherBranch.OID];
}

- (NSUInteger)hash {
return self.name.hash ^ self.SHA.hash;
return self.name.hash ^ self.OID.hash;
}


Expand Down Expand Up @@ -100,8 +102,8 @@ - (NSString *)shortName {
return @(name);
}

- (NSString *)SHA {
return self.reference.targetSHA;
- (GTOID *)OID {
return self.reference.targetOID;
}

- (NSString *)remoteName {
Expand All @@ -119,19 +121,19 @@ - (NSString *)remoteName {
}

- (GTCommit *)targetCommitAndReturnError:(NSError **)error {
if (self.SHA == nil) {
if (self.OID == nil) {
if (error != NULL) *error = GTReference.invalidReferenceError;
return nil;
}

return [self.repository lookUpObjectBySHA:self.SHA objectType:GTObjectTypeCommit error:error];
return [self.repository lookUpObjectByOID:self.OID objectType:GTObjectTypeCommit error:error];
}

- (NSUInteger)numberOfCommitsWithError:(NSError **)error {
GTEnumerator *enumerator = [[GTEnumerator alloc] initWithRepository:self.repository error:error];
if (enumerator == nil) return NSNotFound;

if (![enumerator pushSHA:self.SHA error:error]) return NSNotFound;
if (![enumerator pushSHA:self.OID.SHA error:error]) return NSNotFound;
return [enumerator countRemainingObjects:error];
}

Expand All @@ -144,22 +146,7 @@ - (GTBranchType)branchType {
}

- (NSArray *)uniqueCommitsRelativeToBranch:(GTBranch *)otherBranch error:(NSError **)error {
NSParameterAssert(otherBranch != nil);

GTCommit *mergeBase = [self.repository mergeBaseBetweenFirstOID:self.reference.OID secondOID:otherBranch.reference.OID error:error];
if (mergeBase == nil) return nil;

GTEnumerator *enumerator = [[GTEnumerator alloc] initWithRepository:self.repository error:error];
if (enumerator == nil) return nil;

[enumerator resetWithOptions:GTEnumeratorOptionsTimeSort];

BOOL success = [enumerator pushSHA:self.SHA error:error];
if (!success) return nil;

success = [enumerator hideSHA:mergeBase.SHA error:error];
if (!success) return nil;

GTEnumerator *enumerator = [self.repository enumerateUniqueCommitsUpToOID:self.OID relativeToOID:otherBranch.OID error:error];
return [enumerator allObjectsWithError:error];
}

Expand Down Expand Up @@ -223,19 +210,7 @@ - (GTBranch *)reloadedBranchWithError:(NSError **)error {
}

- (BOOL)calculateAhead:(size_t *)ahead behind:(size_t *)behind relativeTo:(GTBranch *)branch error:(NSError **)error {
if (branch == nil) {
*ahead = 0;
*behind = 0;
return YES;
}

int errorCode = git_graph_ahead_behind(ahead, behind, self.repository.git_repository, self.reference.git_oid, branch.reference.git_oid);
if (errorCode != GIT_OK && error != NULL) {
*error = [NSError git_errorFor:errorCode description:@"Failed to calculate ahead/behind count of %@ relative to %@", self, branch];
return NO;
}

return YES;
return [self.repository calculateAhead:ahead behind:behind ofOID:self.OID relativeToOID:branch.OID error:error];
}

@end
4 changes: 2 additions & 2 deletions ObjectiveGit/GTReference.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ typedef NS_OPTIONS(NSInteger, GTReferenceType) {
/// The last direct reference in a chain
@property (nonatomic, readonly, copy) GTReference *resolvedReference;

/// The SHA of the target object
@property (nonatomic, readonly, copy) NSString *targetSHA;
/// The OID of the target object.
@property (nonatomic, readonly, copy) GTOID *targetOID;

/// Updates the on-disk reference to point to the target and returns the updated
/// reference.
Expand Down
4 changes: 2 additions & 2 deletions ObjectiveGit/GTReference.m
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ - (GTReference *)resolvedReference {
return [self.class referenceByResolvingSymbolicReference:self error:NULL];
}

- (NSString *)targetSHA {
return [self.resolvedTarget SHA];
- (GTOID *)targetOID {
return [self.resolvedTarget OID];
}

- (GTReference *)referenceByUpdatingTarget:(NSString *)newTarget message:(NSString *)message error:(NSError **)error {
Expand Down
12 changes: 12 additions & 0 deletions ObjectiveGit/GTRepository.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,4 +498,16 @@ extern NSString * const GTRepositoryInitOptionsOriginURLString;
/// distinguished using the value of `success`.
- (GTFilterList *)filterListWithPath:(NSString *)path blob:(GTBlob *)blob mode:(GTFilterSourceMode)mode options:(GTFilterListOptions)options success:(BOOL *)success error:(NSError **)error;

/// Creates an enumerator for finding all commits in the history of `headOID`
/// that do not exist in the history of `baseOID`.
///
/// Returns the created enumerator upon success, or `nil` if an error occurred.
- (GTEnumerator *)enumerateUniqueCommitsUpToOID:(GTOID *)headOID relativeToOID:(GTOID *)baseOID error:(NSError **)error;

/// Calculates how far ahead/behind the commit represented by `headOID` is,
/// relative to the commit represented by `baseOID`.
///
/// Returns whether `ahead` and `behind` were successfully calculated.
- (BOOL)calculateAhead:(size_t *)ahead behind:(size_t *)behind ofOID:(GTOID *)headOID relativeToOID:(GTOID *)baseOID error:(NSError **)error;

@end
32 changes: 32 additions & 0 deletions ObjectiveGit/GTRepository.m
Original file line number Diff line number Diff line change
Expand Up @@ -885,4 +885,36 @@ - (GTFilterList *)filterListWithPath:(NSString *)path blob:(GTBlob *)blob mode:(
}
}

- (GTEnumerator *)enumerateUniqueCommitsUpToOID:(GTOID *)headOID relativeToOID:(GTOID *)baseOID error:(NSError **)error {
NSParameterAssert(headOID != nil);
NSParameterAssert(baseOID != nil);

GTCommit *mergeBase = [self mergeBaseBetweenFirstOID:headOID secondOID:baseOID error:error];
if (mergeBase == nil) return nil;

GTEnumerator *enumerator = [[GTEnumerator alloc] initWithRepository:self error:error];
if (enumerator == nil) return nil;

[enumerator resetWithOptions:GTEnumeratorOptionsTimeSort];

if (![enumerator pushSHA:headOID.SHA error:error]) return nil;
if (![enumerator hideSHA:mergeBase.OID.SHA error:error]) return nil;

return enumerator;
}

- (BOOL)calculateAhead:(size_t *)ahead behind:(size_t *)behind ofOID:(GTOID *)headOID relativeToOID:(GTOID *)baseOID error:(NSError **)error {
NSParameterAssert(headOID != nil);
NSParameterAssert(baseOID != nil);

int errorCode = git_graph_ahead_behind(ahead, behind, self.git_repository, headOID.git_oid, baseOID.git_oid);
if (errorCode != GIT_OK) {
if (error != NULL) *error = [NSError git_errorFor:errorCode description:@"Failed to calculate ahead/behind count of %@ relative to %@", headOID, baseOID];

return NO;
}

return YES;
}

@end
2 changes: 1 addition & 1 deletion ObjectiveGitTests/GTEnumeratorSpec.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
GTReference *HEADRef = [repo headReferenceWithError:NULL];
expect(HEADRef).notTo(beNil());

[enumerator pushSHA:HEADRef.targetSHA error:NULL];
[enumerator pushSHA:HEADRef.targetOID.SHA error:NULL];
NSUInteger count = [enumerator allObjects].count;
expect(@(count)).to(equal(@3));
expect(error).to(beNil());
Expand Down
8 changes: 4 additions & 4 deletions ObjectiveGitTests/GTReferenceSpec.m
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
reference = [repository createReferenceNamed:testRefName fromOID:testRefOID message:nil error:&error];
expect(reference).notTo(beNil());
expect(reference.name).to(equal(testRefName));
expect(reference.targetSHA).to(equal(testRefOID.SHA));
expect(reference.targetOID).to(equal(testRefOID));
});

it(@"should be able to be renamed", ^{
Expand All @@ -74,7 +74,7 @@
GTReference *renamedRef = [reference referenceByRenaming:newRefName error:NULL];
expect(renamedRef).notTo(beNil());
expect(renamedRef.name).to(equal(newRefName));
expect(renamedRef.targetSHA).to(equal(testRefOID.SHA));
expect(renamedRef.targetOID).to(equal(testRefOID));
});

it(@"should be able to change the target", ^{
Expand All @@ -83,7 +83,7 @@
GTReference *updatedRef = [reference referenceByUpdatingTarget:newRefTarget message:nil error:NULL];
expect(updatedRef).notTo(beNil());
expect(updatedRef.name).to(equal(testRefName));
expect(updatedRef.targetSHA).to(equal(newRefTarget));
expect(updatedRef.targetOID.SHA).to(equal(newRefTarget));
});
});

Expand Down Expand Up @@ -119,7 +119,7 @@

void (^expectValidReference)(GTReference *ref, NSString *SHA, GTReferenceType type, NSString *name) = ^(GTReference *ref, NSString *SHA, GTReferenceType type, NSString *name) {
expect(ref).notTo(beNil());
expect(ref.targetSHA).to(equal(SHA));
expect(ref.targetOID.SHA).to(equal(SHA));
expect(@(ref.referenceType)).to(equal(@(type)));
expect(ref.name).to(equal(name));
};
Expand Down
2 changes: 1 addition & 1 deletion ObjectiveGitTests/GTRemotePushSpec.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
GTReference *headReference = [repo headReferenceWithError:nil];

GTEnumerator *commitEnum = [[GTEnumerator alloc] initWithRepository:repo error:nil];
[commitEnum pushSHA:[headReference targetSHA] error:nil];
[commitEnum pushSHA:[headReference targetOID].SHA error:nil];
GTCommit *parent = [commitEnum nextObject];

GTCommit *testCommit = [repo createCommitWithTree:testTree message:message parents:@[ parent ] updatingReferenceNamed:headReference.name error:nil];
Expand Down
2 changes: 1 addition & 1 deletion ObjectiveGitTests/GTRemoteSpec.m
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
GTReference *headReference = [repo headReferenceWithError:nil];

GTEnumerator *commitEnum = [[GTEnumerator alloc] initWithRepository:repo error:nil];
[commitEnum pushSHA:[headReference targetSHA] error:nil];
[commitEnum pushSHA:headReference.targetOID.SHA error:nil];
GTCommit *parent = [commitEnum nextObject];

GTCommit *testCommit = [repo createCommitWithTree:testTree message:message parents:@[parent] updatingReferenceNamed:headReference.name error:nil];
Expand Down
6 changes: 3 additions & 3 deletions ObjectiveGitTests/GTRepositoryResetSpec.m
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@

GTCommit *commit = [repository lookUpObjectBySHA:resetTargetSHA error:NULL];
expect(commit).notTo(beNil());
GTCommit *originalHeadCommit = [repository lookUpObjectBySHA:originalHead.targetSHA error:NULL];
GTCommit *originalHeadCommit = [repository lookUpObjectByOID:originalHead.targetOID error:NULL];
expect(originalHeadCommit).notTo(beNil());

BOOL success = [repository resetToCommit:commit resetType:GTRepositoryResetTypeSoft error:&error];
Expand All @@ -77,14 +77,14 @@

GTReference *head = [repository headReferenceWithError:&error];
expect(head).notTo(beNil());
expect(head.targetSHA).to(equal(resetTargetSHA));
expect(head.targetOID.SHA).to(equal(resetTargetSHA));

success = [repository resetToCommit:originalHeadCommit resetType:GTRepositoryResetTypeSoft error:&error];
expect(@(success)).to(beTruthy());
expect(error).to(beNil());

head = [repository headReferenceWithError:&error];
expect(head.targetSHA).to(equal(originalHead.targetSHA));
expect(head.targetOID).to(equal(originalHead.targetOID));
});
});

Expand Down
16 changes: 8 additions & 8 deletions ObjectiveGitTests/GTRepositorySpec.m
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
GTReference *head = [repository headReferenceWithError:&error];
expect(head).notTo(beNil());
expect(error).to(beNil());
expect(head.targetSHA).to(equal(@"36060c58702ed4c2a40832c51758d5344201d89a"));
expect(head.targetOID.SHA).to(equal(@"36060c58702ed4c2a40832c51758d5344201d89a"));
expect(@(head.referenceType)).to(equal(@(GTReferenceTypeOid)));
});

Expand All @@ -120,7 +120,7 @@
GTReference *head = [repository headReferenceWithError:&error];
expect(head).notTo(beNil());
expect(error).to(beNil());
expect(head.targetSHA).to(equal(@"36060c58702ed4c2a40832c51758d5344201d89a"));
expect(head.targetOID.SHA).to(equal(@"36060c58702ed4c2a40832c51758d5344201d89a"));
expect(@(head.referenceType)).to(equal(@(GTReferenceTypeOid)));
});

Expand Down Expand Up @@ -183,7 +183,7 @@
GTReference *head = [self.bareFixtureRepository headReferenceWithError:&error];
expect(head).notTo(beNil());
expect(error).to(beNil());
expect(head.targetSHA).to(equal(@"36060c58702ed4c2a40832c51758d5344201d89a"));
expect(head.targetOID.SHA).to(equal(@"36060c58702ed4c2a40832c51758d5344201d89a"));
expect(@(head.referenceType)).to(equal(@(GTReferenceTypeOid)));
});

Expand Down Expand Up @@ -276,13 +276,13 @@
NSString *branchName = @"new-test-branch";

NSError *error = nil;
GTBranch *newBranch = [repository createBranchNamed:branchName fromOID:[[GTOID alloc] initWithSHA:currentBranch.SHA] message:nil error:&error];
GTBranch *newBranch = [repository createBranchNamed:branchName fromOID:currentBranch.OID message:nil error:&error];
expect(newBranch).notTo(beNil());
expect(error).to(beNil());

expect(newBranch.shortName).to(equal(branchName));
expect(@(newBranch.branchType)).to(equal(@(GTBranchTypeLocal)));
expect(newBranch.SHA).to(equal(currentBranch.SHA));
expect(newBranch.OID).to(equal(currentBranch.OID));
});
});

Expand Down Expand Up @@ -409,7 +409,7 @@

GTCommit *commit = [repository lookUpObjectBySHA:resetTargetSHA error:NULL];
expect(commit).notTo(beNil());
GTCommit *originalHeadCommit = [repository lookUpObjectBySHA:originalHead.targetSHA error:NULL];
GTCommit *originalHeadCommit = [repository lookUpObjectByOID:originalHead.targetOID error:NULL];
expect(originalHeadCommit).notTo(beNil());

BOOL success = [repository resetToCommit:commit resetType:GTRepositoryResetTypeSoft error:&error];
Expand All @@ -418,14 +418,14 @@

GTReference *head = [repository headReferenceWithError:&error];
expect(head).notTo(beNil());
expect(head.targetSHA).to(equal(resetTargetSHA));
expect(head.targetOID.SHA).to(equal(resetTargetSHA));

success = [repository resetToCommit:originalHeadCommit resetType:GTRepositoryResetTypeSoft error:&error];
expect(@(success)).to(beTruthy());
expect(error).to(beNil());

head = [repository headReferenceWithError:&error];
expect(head.targetSHA).to(equal(originalHead.targetSHA));
expect(head.targetOID).to(equal(originalHead.targetOID));
});
});

Expand Down

0 comments on commit 3503fc0

Please sign in to comment.