diff --git a/ObjectiveGit/GTSubmodule.h b/ObjectiveGit/GTSubmodule.h index 81d2e0a25..4c3bd2d77 100644 --- a/ObjectiveGit/GTSubmodule.h +++ b/ObjectiveGit/GTSubmodule.h @@ -60,9 +60,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong, readonly) GTRepository *parentRepository; /// The current ignore rule for this submodule. -/// -/// Setting this property will only update the rule in memory, not on disk. -@property (nonatomic, assign) GTSubmoduleIgnoreRule ignoreRule; +@property (nonatomic, readonly, assign) GTSubmoduleIgnoreRule ignoreRule; /// The OID that the submodule is pinned to in the parent repository's index. /// @@ -111,6 +109,16 @@ NS_ASSUME_NONNULL_BEGIN /// Returns whether reloading succeeded. - (BOOL)reload:(NSError **)error; +/// Write a new ignore rule to disk and get the resulting submodule. The +/// receiver will not have the new ignore rule. To update the receiver, call +/// `-reload:`. +/// +/// ignoreRule - The ignore rule. +/// error - The error if one occurred. +/// +/// Returns the updated submodule or nil if an error occurred. +- (nullable GTSubmodule *)submoduleByUpdatingIgnoreRule:(GTSubmoduleIgnoreRule)ignoreRule error:(NSError **)error; + /// Synchronizes the submodule repository's configuration files with the settings /// from the parent repository. /// @@ -124,11 +132,17 @@ NS_ASSUME_NONNULL_BEGIN /// Returns the opened repository, or nil if an error occurs. - (nullable GTRepository *)submoduleRepository:(NSError **)error; -/// Determines the status for the submodule. -/// -/// Returns the status, or `GTSubmoduleStatusUnknown` if an error occurs. +/// Calls `-statusWithIgnoreRule:error:` with the submodule's ignore rule. - (GTSubmoduleStatus)status:(NSError **)error; +/// Determine the status for the submodule using the given ignore rule. +/// +/// ignoreRule - The ignore rule to use in calculating status. +/// error - The error if one occurred. +/// +/// Returns the status or `GTSubmoduleStatusUnknown` if an error occurred. +- (GTSubmoduleStatus)statusWithIgnoreRule:(GTSubmoduleIgnoreRule)ignoreRule error:(NSError **)error; + /// Initializes the submodule by copying its information into the parent /// repository's `.git/config` file. This is equivalent to `git submodule init` /// on the command line. diff --git a/ObjectiveGit/GTSubmodule.m b/ObjectiveGit/GTSubmodule.m index b6b8c5eee..25346cf45 100644 --- a/ObjectiveGit/GTSubmodule.m +++ b/ObjectiveGit/GTSubmodule.m @@ -25,12 +25,16 @@ - (GTSubmoduleIgnoreRule)ignoreRule { return (GTSubmoduleIgnoreRule)git_submodule_ignore(self.git_submodule); } -- (void)setIgnoreRule:(GTSubmoduleIgnoreRule)ignoreRule { - git_submodule_set_ignore(self.parentRepository.git_repository, git_submodule_name(self.git_submodule), (git_submodule_ignore_t)ignoreRule); +- (GTSubmodule *)submoduleByUpdatingIgnoreRule:(GTSubmoduleIgnoreRule)ignoreRule error:(NSError **)error { + int result = git_submodule_set_ignore(self.parentRepository.git_repository, git_submodule_name(self.git_submodule), (git_submodule_ignore_t)ignoreRule); + if (result != GIT_OK) { + if (error != NULL) { + *error = [NSError git_errorFor:result description:@"Couldn't set submodule ignore rule."]; + } + return nil; + } - // The docs for `git_submodule_set_ignore` note "This does not affect any - // currently-loaded instances." So we need to reload. - git_submodule_reload(self.git_submodule, 0); + return [self.parentRepository submoduleWithName:self.name error:error]; } - (GTOID *)indexOID { @@ -98,9 +102,9 @@ - (instancetype)initWithGitSubmodule:(git_submodule *)submodule parentRepository #pragma mark Inspection -- (GTSubmoduleStatus)status:(NSError **)error { +- (GTSubmoduleStatus)statusWithIgnoreRule:(GTSubmoduleIgnoreRule)ignoreRule error:(NSError **)error { unsigned status; - int gitError = git_submodule_status(&status, self.parentRepository.git_repository, git_submodule_name(self.git_submodule), git_submodule_ignore(self.git_submodule)); + int gitError = git_submodule_status(&status, self.parentRepository.git_repository, git_submodule_name(self.git_submodule), (git_submodule_ignore_t)ignoreRule); if (gitError != GIT_OK) { if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to get submodule %@ status.", self.name]; return GTSubmoduleStatusUnknown; @@ -109,6 +113,10 @@ - (GTSubmoduleStatus)status:(NSError **)error { return status; } +- (GTSubmoduleStatus)status:(NSError **)error { + return [self statusWithIgnoreRule:self.ignoreRule error:error]; +} + #pragma mark Manipulation - (BOOL)reload:(NSError **)error { @@ -131,7 +139,7 @@ - (BOOL)sync:(NSError **)error { return YES; } -- (GTRepository *)submoduleRepository:(NSError **)error { +- (nullable GTRepository *)submoduleRepository:(NSError **)error { git_repository *repo; int gitError = git_submodule_open(&repo, self.git_submodule); if (gitError != GIT_OK) { diff --git a/ObjectiveGitTests/GTSubmoduleSpec.m b/ObjectiveGitTests/GTSubmoduleSpec.m index 8b27192b7..1039703ac 100644 --- a/ObjectiveGitTests/GTSubmoduleSpec.m +++ b/ObjectiveGitTests/GTSubmoduleSpec.m @@ -93,6 +93,16 @@ expect(@(success)).to(beTruthy()); }); +it(@"should update the ignore rule", ^{ + GTSubmodule *submodule = [repo submoduleWithName:@"Test_App" error:NULL]; + expect(submodule).notTo(beNil()); + expect(@(submodule.ignoreRule)).to(equal(@(GTSubmoduleIgnoreNone))); + + GTSubmodule *updatedSubmodule = [submodule submoduleByUpdatingIgnoreRule:GTSubmoduleIgnoreAll error:NULL]; + expect(@(updatedSubmodule.ignoreRule)).to(equal(@(GTSubmoduleIgnoreAll))); + expect(@(submodule.ignoreRule)).to(equal(@(GTSubmoduleIgnoreNone))); +}); + describe(@"clean, checked out submodule", ^{ __block GTSubmodule *submodule; @@ -204,13 +214,11 @@ }); it(@"should honor the ignore rule", ^{ - submodule.ignoreRule = GTSubmoduleIgnoreDirty; - GTSubmoduleStatus expectedStatus = GTSubmoduleStatusExistsInHEAD | GTSubmoduleStatusExistsInIndex | GTSubmoduleStatusExistsInConfig | GTSubmoduleStatusExistsInWorkingDirectory | GTSubmoduleStatusModifiedInIndex | GTSubmoduleStatusModifiedInWorkingDirectory; - expect(@([submodule status:NULL])).to(equal(@(expectedStatus))); + expect(@([submodule statusWithIgnoreRule:GTSubmoduleIgnoreDirty error:NULL])).to(equal(@(expectedStatus))); }); it(@"should open a repository" ,^{