From 9b092aceb2bdebec5a1ad14d6166900b783da521 Mon Sep 17 00:00:00 2001 From: Matt Diephouse Date: Wed, 24 Feb 2016 11:14:10 -0500 Subject: [PATCH] Add APIs to calculate and cleanup repository states --- ObjectiveGit/GTRepository.h | 31 +++++++++++++++++++++++ ObjectiveGit/GTRepository.m | 21 +++++++++++++++ ObjectiveGitTests/GTRepositorySpec.m | 38 ++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/ObjectiveGit/GTRepository.h b/ObjectiveGit/GTRepository.h index 566953624..45f3caead 100644 --- a/ObjectiveGit/GTRepository.h +++ b/ObjectiveGit/GTRepository.h @@ -150,6 +150,20 @@ extern NSString * const GTRepositoryInitOptionsInitialHEAD; /// initialization. extern NSString * const GTRepositoryInitOptionsOriginURLString; +/// The possible states for the repository to be in, based on the current ongoing operation. +typedef NS_ENUM(NSInteger, GTRepositoryStateType) { + GTRepositoryStateNone = GIT_REPOSITORY_STATE_NONE, + GTRepositoryStateMerge = GIT_REPOSITORY_STATE_MERGE, + GTRepositoryStateRevert = GIT_REPOSITORY_STATE_REVERT, + GTRepositoryStateCherryPick = GIT_REPOSITORY_STATE_CHERRYPICK, + GTRepositoryStateBisect = GIT_REPOSITORY_STATE_BISECT, + GTRepositoryStateRebase = GIT_REPOSITORY_STATE_REBASE, + GTRepositoryStateRebaseInteractive = GIT_REPOSITORY_STATE_REBASE_INTERACTIVE, + GTRepositoryStateRebaseMerge = GIT_REPOSITORY_STATE_REBASE_MERGE, + GTRepositoryStateApplyMailbox = GIT_REPOSITORY_STATE_APPLY_MAILBOX, + GTRepositoryStateApplyMailboxOrRebase = GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE, +}; + @interface GTRepository : NSObject /// The file URL for the repository's working directory. @@ -573,6 +587,23 @@ extern NSString * const GTRepositoryInitOptionsOriginURLString; /// Returns the enumerator or nil if an error occurred. - (nullable GTEnumerator *)enumeratorForUniqueCommitsFromOID:(GTOID *)fromOID relativeToOID:(GTOID *)relativeOID error:(NSError **)error; +/// Determines the status of a git repository--i.e., whether an operation +/// (merge, cherry-pick, etc) is in progress. +/// +/// state - A pointer to set the retrieved state. Must not be NULL. +/// error - The error if one occurred. +/// +/// Returns YES if operation was successful, NO otherwise +- (BOOL)calculateState:(GTRepositoryStateType *)state withError:(NSError **)error; + +/// Remove all the metadata associated with an ongoing command like merge, +/// revert, cherry-pick, etc. For example: MERGE_HEAD, MERGE_MSG, etc. +/// +/// error - The error if one occurred. +/// +/// Returns YES if operation was successful, NO otherwise +- (BOOL)cleanupStateWithError:(NSError **)error; + @end NS_ASSUME_NONNULL_END diff --git a/ObjectiveGit/GTRepository.m b/ObjectiveGit/GTRepository.m index 332c565f4..c2483ab57 100644 --- a/ObjectiveGit/GTRepository.m +++ b/ObjectiveGit/GTRepository.m @@ -898,4 +898,25 @@ - (nullable GTEnumerator *)enumeratorForUniqueCommitsFromOID:(GTOID *)fromOID re return enumerator; } +- (BOOL)calculateState:(GTRepositoryStateType *)state withError:(NSError **)error { + NSParameterAssert(state != NULL); + + int result = git_repository_state(self.git_repository); + if (result < 0) { + if (error != NULL) *error = [NSError git_errorFor:result description:@"Failed to calculate repository state"]; + return NO; + } + + *state = result; + return YES; +} + +- (BOOL)cleanupStateWithError:(NSError * _Nullable __autoreleasing *)error { + int errorCode = git_repository_state_cleanup(self.git_repository); + if (errorCode != GIT_OK) { + if (error != NULL) *error = [NSError git_errorFor:errorCode description:@"Failed to clean up repository state"]; + } + return YES; +} + @end diff --git a/ObjectiveGitTests/GTRepositorySpec.m b/ObjectiveGitTests/GTRepositorySpec.m index 4837cea71..8c7740dcc 100644 --- a/ObjectiveGitTests/GTRepositorySpec.m +++ b/ObjectiveGitTests/GTRepositorySpec.m @@ -700,6 +700,44 @@ }); }); +describe(@"-calculateState:withError:", ^{ + it(@"should find if the repository is mid-merge", ^{ + GTRepository *repository = [self conflictedFixtureRepository]; + GTRepositoryStateType state; + BOOL result; + result = [repository calculateState:&state withError:NULL]; + expect(@(result)).to(beTruthy()); + expect(@(state)).to(equal(@(GTRepositoryStateMerge))); + }); + + it(@"should return none otherwise", ^{ + GTRepository *repository = [self testAppFixtureRepository]; + GTRepositoryStateType state; + BOOL result; + result = [repository calculateState:&state withError:NULL]; + expect(@(result)).to(beTruthy()); + expect(@(state)).to(equal(@(GTRepositoryStateNone))); + }); +}); + +describe(@"-cleanupStateWithError:", ^{ + it(@"should return a repository to a pre-merge state", ^{ + GTRepository *repository = [self conflictedFixtureRepository]; + + GTRepositoryStateType state; + BOOL result; + result = [repository calculateState:&state withError:NULL]; + expect(@(result)).to(beTruthy()); + expect(@(state)).to(equal(@(GTRepositoryStateMerge))); + + expect(@([repository cleanupStateWithError:NULL])).to(beTruthy()); + + result = [repository calculateState:&state withError:NULL]; + expect(@(result)).to(beTruthy()); + expect(@(state)).to(equal(@(GTRepositoryStateNone))); + }); +}); + afterEach(^{ [self tearDown]; });