diff --git a/ObjectiveGit/Categories/NSError+Git.h b/ObjectiveGit/Categories/NSError+Git.h index bfe453dc0..4f7532f62 100644 --- a/ObjectiveGit/Categories/NSError+Git.h +++ b/ObjectiveGit/Categories/NSError+Git.h @@ -29,8 +29,12 @@ #import +/// The error domain used by Objective-Git extern NSString * const GTGitErrorDomain; +/// Error userinfo keys +extern NSString * const GTGitErrorOID; + @interface NSError (Git) /// Describes the given libgit2 error code, using any message provided by diff --git a/ObjectiveGit/Categories/NSError+Git.m b/ObjectiveGit/Categories/NSError+Git.m index cbc31509b..e66d2fcb3 100644 --- a/ObjectiveGit/Categories/NSError+Git.m +++ b/ObjectiveGit/Categories/NSError+Git.m @@ -31,6 +31,7 @@ #import "git2/errors.h" NSString * const GTGitErrorDomain = @"GTGitErrorDomain"; +NSString * const GTGitErrorOID = @"GTOID"; @implementation NSError (Git) diff --git a/ObjectiveGit/GTEnumerator.h b/ObjectiveGit/GTEnumerator.h index d3d9d60c2..900d3e60a 100644 --- a/ObjectiveGit/GTEnumerator.h +++ b/ObjectiveGit/GTEnumerator.h @@ -117,6 +117,16 @@ NS_ASSUME_NONNULL_BEGIN /// Returns a (possibly empty) array of GTCommits, or nil if an error occurs. - (nullable NSArray *)allObjectsWithError:(NSError **)error; +/// Get the next OID. +/// +/// success - If not NULL, this will be set to whether getting the next object +/// was successful. This will be YES if the receiver is exhausted, so +/// it can be used to interpret the meaning of a nil return value. +/// error - If not NULL, set to any error that occurs during traversal. +/// +/// Returns nil if an error occurs or the enumeration is done. +- (nullable GTOID *)nextOIDWithSuccess:(nullable BOOL *)success error:(NSError **)error; + /// Gets the next commit. /// /// success - If not NULL, this will be set to whether getting the next object diff --git a/ObjectiveGit/GTEnumerator.m b/ObjectiveGit/GTEnumerator.m index 673d7f8c6..4b45a59f8 100644 --- a/ObjectiveGit/GTEnumerator.m +++ b/ObjectiveGit/GTEnumerator.m @@ -145,16 +145,34 @@ - (void)resetWithOptions:(GTEnumeratorOptions)options { #pragma mark Enumerating -- (GTCommit *)nextObjectWithSuccess:(BOOL *)success error:(NSError **)error { +- (GTOID *)nextOIDWithSuccess:(BOOL *)success error:(NSError **)error { git_oid oid; + int gitError = git_revwalk_next(&oid, self.walk); if (gitError == GIT_ITEROVER) { if (success != NULL) *success = YES; return nil; } + if (gitError != GIT_OK) { + if (success != NULL) *success = NO; + if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Enumeration failed"]; + return nil; + } + + if (success != NULL) *success = YES; + return [GTOID oidWithGitOid:&oid]; +} + +- (GTCommit *)nextObjectWithSuccess:(BOOL *)success error:(NSError **)error { + GTOID *oid = [self nextOIDWithSuccess:success error:error]; + if (oid == nil) { + // We don't care whether the iteration completed, or an error occurred, + // there's nothing to lookup. + return nil; + } // Ignore error if we can't lookup object and just return nil. - GTCommit *commit = [self.repository lookUpObjectByGitOid:&oid objectType:GTObjectTypeCommit error:error]; + GTCommit *commit = [self.repository lookUpObjectByOID:oid objectType:GTObjectTypeCommit error:error]; if (success != NULL) *success = (commit != nil); return commit; } diff --git a/ObjectiveGit/GTRepository.m b/ObjectiveGit/GTRepository.m index c2483ab57..fc1e22d98 100644 --- a/ObjectiveGit/GTRepository.m +++ b/ObjectiveGit/GTRepository.m @@ -290,7 +290,7 @@ - (id)lookUpObjectByGitOid:(const git_oid *)oid objectType:(GTObjectType)type er if (error != NULL) { char oid_str[GIT_OID_HEXSZ+1]; git_oid_tostr(oid_str, sizeof(oid_str), oid); - *error = [NSError git_errorFor:gitError description:@"Failed to lookup object %s in repository.", oid_str]; + *error = [NSError git_errorFor:gitError description:@"Failed to lookup object" userInfo:@{GTGitErrorOID: [GTOID oidWithGitOid:oid]} failureReason:@"The object %s couldn't be found in the repository.", oid_str]; } return nil; }