From 4730e275216322927dda2a0471dd996d219ae88d Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Wed, 17 Jun 2015 13:22:15 -0600 Subject: [PATCH 01/47] Initial pull implementation --- ObjectiveGit/GTRepository+Pull.h | 35 +++++++++ ObjectiveGit/GTRepository+Pull.m | 78 +++++++++++++++++++ .../project.pbxproj | 13 ++++ 3 files changed, 126 insertions(+) create mode 100644 ObjectiveGit/GTRepository+Pull.h create mode 100644 ObjectiveGit/GTRepository+Pull.m diff --git a/ObjectiveGit/GTRepository+Pull.h b/ObjectiveGit/GTRepository+Pull.h new file mode 100644 index 000000000..f1b357456 --- /dev/null +++ b/ObjectiveGit/GTRepository+Pull.h @@ -0,0 +1,35 @@ +// +// GTRepository+Pull.h +// ObjectiveGitFramework +// +// Created by Ben Chatelain on 6/17/15. +// Copyright © 2015 GitHub, Inc. All rights reserved. +// + +#import "GTRepository.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^GTRemoteFetchTransferProgressBlock)(const git_transfer_progress *progress, BOOL *stop); + +@interface GTRepository (Pull) + +#pragma mark - Pull + +/// Pull a single branch from a remote. +/// +/// branch - The branch to pull. +/// remote - The remote to pull from. +/// options - Options applied to the fetch operation. +/// Recognized options are: +/// `GTRepositoryRemoteOptionsCredentialProvider` +/// error - The error if one occurred. Can be NULL. +/// progressBlock - An optional callback for monitoring progress. +/// +/// Returns YES if the pull was successful, NO otherwise (and `error`, if provided, +/// will point to an error describing what happened). +- (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions:(nullable NSDictionary *)options error:(NSError **)error progress:(nullable GTRemoteFetchTransferProgressBlock)progressBlock; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m new file mode 100644 index 000000000..594aac79b --- /dev/null +++ b/ObjectiveGit/GTRepository+Pull.m @@ -0,0 +1,78 @@ +// +// GTRepository+Pull.m +// ObjectiveGitFramework +// +// Created by Ben Chatelain on 6/17/15. +// Copyright © 2015 GitHub, Inc. All rights reserved. +// + +#import "GTRepository+Pull.h" + +#import "GTCommit.h" +#import "GTRemote.h" +#import "GTRepository+Committing.h" +#import "GTRepository+RemoteOperations.h" + +@implementation GTRepository (Pull) + +#pragma mark - Pull + +- (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions:(NSDictionary *)options + error:(NSError **)error progress:(GTRemoteFetchTransferProgressBlock)progressBlock +{ + NSParameterAssert(branch); + NSParameterAssert(remote); + + GTRepository *repo = remote.repository; + + GTBranch *remoteBranch; + if (branch.branchType == GTBranchTypeLocal) { + BOOL success; + remoteBranch = [branch trackingBranchWithError:error success:&success]; + if (!success) { + return NO; + } + } + else { + remoteBranch = branch; + } + + if (![self fetchRemote:remote withOptions:options error:error progress:progressBlock]) { + return NO; + } + + // Check if merge is necessary + GTBranch *localBranch = [repo currentBranchWithError:error]; + if (*error) { + return NO; + } + + GTCommit *localCommit = [localBranch targetCommitAndReturnError:error]; + if (*error) { + return NO; + } + + GTCommit *remoteCommit = [remoteBranch targetCommitAndReturnError:error]; + if (*error) { + return NO; + } + + if ([localCommit.SHA isEqualToString:remoteCommit.SHA]) { + return YES; + } + + // Merge + GTTree *remoteTree = remoteCommit.tree; + NSString *message = [NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName]; + NSArray *parents = @[ localCommit, remoteCommit ]; + GTCommit *mergeCommit = [repo createCommitWithTree:remoteTree message:message + parents:parents updatingReferenceNamed:localBranch.name + error:error]; + if (!mergeCommit) { + return NO; + } + + return YES; +} + +@end \ No newline at end of file diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index 4ca80aa71..8ad0ee8b8 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -311,6 +311,10 @@ DD3D9513182A81E1004AF532 /* GTBlame.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3D9511182A81E1004AF532 /* GTBlame.m */; }; DD3D951C182AB25C004AF532 /* GTBlameHunk.h in Headers */ = {isa = PBXBuildFile; fileRef = DD3D951A182AB25C004AF532 /* GTBlameHunk.h */; settings = {ATTRIBUTES = (Public, ); }; }; DD3D951D182AB25C004AF532 /* GTBlameHunk.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3D951B182AB25C004AF532 /* GTBlameHunk.m */; }; + F8D1BDEE1B31FE7C00CDEC90 /* GTRepository+Pull.h in Headers */ = {isa = PBXBuildFile; fileRef = F8D1BDEC1B31FE7C00CDEC90 /* GTRepository+Pull.h */; }; + F8D1BDEF1B31FE7C00CDEC90 /* GTRepository+Pull.h in Headers */ = {isa = PBXBuildFile; fileRef = F8D1BDEC1B31FE7C00CDEC90 /* GTRepository+Pull.h */; }; + F8D1BDF01B31FE7C00CDEC90 /* GTRepository+Pull.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D1BDED1B31FE7C00CDEC90 /* GTRepository+Pull.m */; }; + F8D1BDF11B31FE7C00CDEC90 /* GTRepository+Pull.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D1BDED1B31FE7C00CDEC90 /* GTRepository+Pull.m */; }; F8E4A2911A170CA6006485A8 /* GTRemotePushSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = F8E4A2901A170CA6006485A8 /* GTRemotePushSpec.m */; }; /* End PBXBuildFile section */ @@ -574,6 +578,8 @@ DD3D951B182AB25C004AF532 /* GTBlameHunk.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTBlameHunk.m; sourceTree = ""; }; E46931A7172740D300F2077D /* update_libgit2 */ = {isa = PBXFileReference; lastKnownFileType = text; name = update_libgit2; path = script/update_libgit2; sourceTree = ""; }; E46931A8172740D300F2077D /* update_libgit2_ios */ = {isa = PBXFileReference; lastKnownFileType = text; name = update_libgit2_ios; path = script/update_libgit2_ios; sourceTree = ""; }; + F8D1BDEC1B31FE7C00CDEC90 /* GTRepository+Pull.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTRepository+Pull.h"; sourceTree = ""; }; + F8D1BDED1B31FE7C00CDEC90 /* GTRepository+Pull.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTRepository+Pull.m"; sourceTree = ""; }; F8E4A2901A170CA6006485A8 /* GTRemotePushSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTRemotePushSpec.m; sourceTree = ""; }; /* End PBXFileReference section */ @@ -783,6 +789,8 @@ D015F7C917F695E800AD5E1F /* GTRepository+Stashing.m */, 88746CC217FA1C950005888A /* GTRepository+Committing.h */, 88746CC317FA1C950005888A /* GTRepository+Committing.m */, + F8D1BDEC1B31FE7C00CDEC90 /* GTRepository+Pull.h */, + F8D1BDED1B31FE7C00CDEC90 /* GTRepository+Pull.m */, 4DFFB159183AA8D600D1565E /* GTRepository+RemoteOperations.h */, 4DFFB15A183AA8D600D1565E /* GTRepository+RemoteOperations.m */, 88B2131A1B20E785005CF2C5 /* GTRepository+References.h */, @@ -1000,6 +1008,7 @@ 8821547D17147B3600D76B76 /* GTOID.h in Headers */, 20F43DE318A2F668007D3621 /* GTRepository+Blame.h in Headers */, D0CE552018B6C58F008EB8E0 /* GTFilterList.h in Headers */, + F8D1BDEE1B31FE7C00CDEC90 /* GTRepository+Pull.h in Headers */, D021DF4F1806899000934E32 /* NSArray+StringArray.h in Headers */, 30DCBA6317B45A78009B0EBD /* GTRepository+Status.h in Headers */, 8821547617147A5200D76B76 /* GTReflogEntry.h in Headers */, @@ -1015,6 +1024,7 @@ buildActionMask = 2147483647; files = ( D01B6F3D19F82F8700D411BC /* GTTag.h in Headers */, + F8D1BDEF1B31FE7C00CDEC90 /* GTRepository+Pull.h in Headers */, D01B6F4119F82F8700D411BC /* GTIndexEntry.h in Headers */, D01B6F2319F82F8700D411BC /* GTRepository+Reset.h in Headers */, D01B6F2D19F82F8700D411BC /* GTEnumerator.h in Headers */, @@ -1136,6 +1146,7 @@ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 0700; LastTestingUpgradeCheck = 0510; LastUpgradeCheck = 0620; ORGANIZATIONNAME = "GitHub, Inc"; @@ -1306,6 +1317,7 @@ BD6B0418131496CC001909D0 /* GTTreeEntry.m in Sources */, DD3D951D182AB25C004AF532 /* GTBlameHunk.m in Sources */, 306123AE17EA5261006591D4 /* EXTScope.m in Sources */, + F8D1BDF01B31FE7C00CDEC90 /* GTRepository+Pull.m in Sources */, BDD6279A1318391200DE34D1 /* GTBlob.m in Sources */, BDD62925131C03D600DE34D1 /* GTTag.m in Sources */, BDFAF9C4131C1845000508BC /* GTIndex.m in Sources */, @@ -1364,6 +1376,7 @@ 884C8A3A19FF4B890017E98D /* EXTScope.m in Sources */, D01B6F4E19F82F8700D411BC /* GTRemote.m in Sources */, D01B6F3019F82F8700D411BC /* GTObject.m in Sources */, + F8D1BDF11B31FE7C00CDEC90 /* GTRepository+Pull.m in Sources */, D01B6F4619F82F8700D411BC /* GTBranch.m in Sources */, D01B6F3A19F82F8700D411BC /* GTTreeEntry.m in Sources */, D01B6F2419F82F8700D411BC /* GTRepository+Reset.m in Sources */, From 4f058f4b6afde48e208b3bd0a2105403580fea0f Mon Sep 17 00:00:00 2001 From: Piet Brauer Date: Thu, 18 Jun 2015 16:20:25 +0200 Subject: [PATCH 02/47] Add GitMergeAnalysis handling --- ObjectiveGit/GTRepository+Pull.h | 20 +++++++++++ ObjectiveGit/GTRepository+Pull.m | 62 ++++++++++++++++++++++++++------ 2 files changed, 71 insertions(+), 11 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.h b/ObjectiveGit/GTRepository+Pull.h index f1b357456..3100f7cec 100644 --- a/ObjectiveGit/GTRepository+Pull.h +++ b/ObjectiveGit/GTRepository+Pull.h @@ -7,9 +7,20 @@ // #import "GTRepository.h" +#import "git2/merge.h" NS_ASSUME_NONNULL_BEGIN +/// An enum describing the result of the merge analysis. +/// See `git_merge_analysis_t`. +typedef NS_ENUM(NSInteger, GTMergeAnalysis) { + GTMergeAnalysisNone = GIT_MERGE_ANALYSIS_NONE, + GTMergeAnalysisNormal = GIT_MERGE_ANALYSIS_NORMAL, + GTMergeAnalysisUpToDate = GIT_MERGE_ANALYSIS_UP_TO_DATE, + GTMergeAnalysisUnborn = GIT_MERGE_ANALYSIS_UNBORN, + GTMergeAnalysisFastForward = GIT_MERGE_ANALYSIS_FASTFORWARD, +}; + typedef void (^GTRemoteFetchTransferProgressBlock)(const git_transfer_progress *progress, BOOL *stop); @interface GTRepository (Pull) @@ -30,6 +41,15 @@ typedef void (^GTRemoteFetchTransferProgressBlock)(const git_transfer_progress * /// will point to an error describing what happened). - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions:(nullable NSDictionary *)options error:(NSError **)error progress:(nullable GTRemoteFetchTransferProgressBlock)progressBlock; +/// Analyse which merge to perform +/// +/// toBranch - The current branch. +/// fromBranch - The remote to pull from. +/// error - The error if one occurred. Can be NULL. +/// +/// Returns the result as a GTMergeAnalysis. +- (GTMergeAnalysis)analyseMerge:(GTBranch *)toBranch fromBranch:(GTBranch *)fromBranch error:(NSError **)error; + @end NS_ASSUME_NONNULL_END diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 594aac79b..88b4ef73e 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -12,13 +12,14 @@ #import "GTRemote.h" #import "GTRepository+Committing.h" #import "GTRepository+RemoteOperations.h" +#import "git2/merge.h" @implementation GTRepository (Pull) #pragma mark - Pull - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions:(NSDictionary *)options - error:(NSError **)error progress:(GTRemoteFetchTransferProgressBlock)progressBlock + error:(NSError **)error progress:(GTRemoteFetchTransferProgressBlock)progressBlock { NSParameterAssert(branch); NSParameterAssert(remote); @@ -61,18 +62,57 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: return YES; } - // Merge - GTTree *remoteTree = remoteCommit.tree; - NSString *message = [NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName]; - NSArray *parents = @[ localCommit, remoteCommit ]; - GTCommit *mergeCommit = [repo createCommitWithTree:remoteTree message:message - parents:parents updatingReferenceNamed:localBranch.name - error:error]; - if (!mergeCommit) { + GTMergeAnalysis analysis = [self analyseMerge:branch fromBranch:remoteBranch error:error]; + + if (*error) { + return NO; + } + + if (analysis & GTMergeAnalysisUpToDate) { + // Nothing to do + return YES; + } else if (analysis & GTMergeAnalysisFastForward) { + // Do FastForward + NSLog(@"Fast-Forward merge is not yet supported"); + return NO; + } else if (analysis & GTMergeAnalysisNormal) { + // Do normal merge + GTTree *remoteTree = remoteCommit.tree; + NSString *message = [NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName]; + NSArray *parents = @[ localCommit, remoteCommit ]; + GTCommit *mergeCommit = [repo createCommitWithTree:remoteTree message:message + parents:parents updatingReferenceNamed:localBranch.name + error:error]; + if (!mergeCommit) { + return NO; + } + + return YES; + } else if (analysis & GTMergeAnalysisUnborn) { + // Do unborn merge + NSLog(@"Unborn merge is not yet supported"); return NO; } - return YES; + return NO; +} + +- (GTMergeAnalysis)analyseMerge:(GTBranch *)toBranch fromBranch:(GTBranch *)fromBranch error:(NSError **)error +{ + git_merge_analysis_t analysis; + git_merge_preference_t preference; + git_annotated_commit *annotatedCommit; + + GTCommit *fromCommit = [fromBranch targetCommitAndReturnError:error]; + if (*error) { + return GTMergeAnalysisNone; + } + + git_annotated_commit_lookup(&annotatedCommit, self.git_repository, git_object_id(fromCommit.git_object)); + git_merge_analysis(&analysis, &preference, self.git_repository, (const git_annotated_commit **) &annotatedCommit, 1); + git_annotated_commit_free(annotatedCommit); + + return (GTMergeAnalysis)analysis; } -@end \ No newline at end of file +@end From 5aae55ab74ec8cb988d477a76ffb193994a3b428 Mon Sep 17 00:00:00 2001 From: Piet Brauer Date: Thu, 18 Jun 2015 16:22:19 +0200 Subject: [PATCH 03/47] Convert GTRepository+Pull to tabs --- ObjectiveGit/GTRepository+Pull.h | 10 +- ObjectiveGit/GTRepository+Pull.m | 178 +++++++++++++++---------------- 2 files changed, 94 insertions(+), 94 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.h b/ObjectiveGit/GTRepository+Pull.h index 3100f7cec..2ad8e5f26 100644 --- a/ObjectiveGit/GTRepository+Pull.h +++ b/ObjectiveGit/GTRepository+Pull.h @@ -14,11 +14,11 @@ NS_ASSUME_NONNULL_BEGIN /// An enum describing the result of the merge analysis. /// See `git_merge_analysis_t`. typedef NS_ENUM(NSInteger, GTMergeAnalysis) { - GTMergeAnalysisNone = GIT_MERGE_ANALYSIS_NONE, - GTMergeAnalysisNormal = GIT_MERGE_ANALYSIS_NORMAL, - GTMergeAnalysisUpToDate = GIT_MERGE_ANALYSIS_UP_TO_DATE, - GTMergeAnalysisUnborn = GIT_MERGE_ANALYSIS_UNBORN, - GTMergeAnalysisFastForward = GIT_MERGE_ANALYSIS_FASTFORWARD, + GTMergeAnalysisNone = GIT_MERGE_ANALYSIS_NONE, + GTMergeAnalysisNormal = GIT_MERGE_ANALYSIS_NORMAL, + GTMergeAnalysisUpToDate = GIT_MERGE_ANALYSIS_UP_TO_DATE, + GTMergeAnalysisUnborn = GIT_MERGE_ANALYSIS_UNBORN, + GTMergeAnalysisFastForward = GIT_MERGE_ANALYSIS_FASTFORWARD, }; typedef void (^GTRemoteFetchTransferProgressBlock)(const git_transfer_progress *progress, BOOL *stop); diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 88b4ef73e..6f7f51a8b 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -19,100 +19,100 @@ @implementation GTRepository (Pull) #pragma mark - Pull - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions:(NSDictionary *)options - error:(NSError **)error progress:(GTRemoteFetchTransferProgressBlock)progressBlock + error:(NSError **)error progress:(GTRemoteFetchTransferProgressBlock)progressBlock { - NSParameterAssert(branch); - NSParameterAssert(remote); - - GTRepository *repo = remote.repository; - - GTBranch *remoteBranch; - if (branch.branchType == GTBranchTypeLocal) { - BOOL success; - remoteBranch = [branch trackingBranchWithError:error success:&success]; - if (!success) { - return NO; - } - } - else { - remoteBranch = branch; - } - - if (![self fetchRemote:remote withOptions:options error:error progress:progressBlock]) { - return NO; - } - - // Check if merge is necessary - GTBranch *localBranch = [repo currentBranchWithError:error]; - if (*error) { - return NO; - } - - GTCommit *localCommit = [localBranch targetCommitAndReturnError:error]; - if (*error) { - return NO; - } - - GTCommit *remoteCommit = [remoteBranch targetCommitAndReturnError:error]; - if (*error) { - return NO; - } - - if ([localCommit.SHA isEqualToString:remoteCommit.SHA]) { - return YES; - } - - GTMergeAnalysis analysis = [self analyseMerge:branch fromBranch:remoteBranch error:error]; - - if (*error) { - return NO; - } - - if (analysis & GTMergeAnalysisUpToDate) { - // Nothing to do - return YES; - } else if (analysis & GTMergeAnalysisFastForward) { - // Do FastForward - NSLog(@"Fast-Forward merge is not yet supported"); - return NO; - } else if (analysis & GTMergeAnalysisNormal) { - // Do normal merge - GTTree *remoteTree = remoteCommit.tree; - NSString *message = [NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName]; - NSArray *parents = @[ localCommit, remoteCommit ]; - GTCommit *mergeCommit = [repo createCommitWithTree:remoteTree message:message - parents:parents updatingReferenceNamed:localBranch.name - error:error]; - if (!mergeCommit) { - return NO; - } - - return YES; - } else if (analysis & GTMergeAnalysisUnborn) { - // Do unborn merge - NSLog(@"Unborn merge is not yet supported"); - return NO; - } - - return NO; + NSParameterAssert(branch); + NSParameterAssert(remote); + + GTRepository *repo = remote.repository; + + GTBranch *remoteBranch; + if (branch.branchType == GTBranchTypeLocal) { + BOOL success; + remoteBranch = [branch trackingBranchWithError:error success:&success]; + if (!success) { + return NO; + } + } + else { + remoteBranch = branch; + } + + if (![self fetchRemote:remote withOptions:options error:error progress:progressBlock]) { + return NO; + } + + // Check if merge is necessary + GTBranch *localBranch = [repo currentBranchWithError:error]; + if (*error) { + return NO; + } + + GTCommit *localCommit = [localBranch targetCommitAndReturnError:error]; + if (*error) { + return NO; + } + + GTCommit *remoteCommit = [remoteBranch targetCommitAndReturnError:error]; + if (*error) { + return NO; + } + + if ([localCommit.SHA isEqualToString:remoteCommit.SHA]) { + return YES; + } + + GTMergeAnalysis analysis = [self analyseMerge:branch fromBranch:remoteBranch error:error]; + + if (*error) { + return NO; + } + + if (analysis & GTMergeAnalysisUpToDate) { + // Nothing to do + return YES; + } else if (analysis & GTMergeAnalysisFastForward) { + // Do FastForward + NSLog(@"Fast-Forward merge is not yet supported"); + return NO; + } else if (analysis & GTMergeAnalysisNormal) { + // Do normal merge + GTTree *remoteTree = remoteCommit.tree; + NSString *message = [NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName]; + NSArray *parents = @[ localCommit, remoteCommit ]; + GTCommit *mergeCommit = [repo createCommitWithTree:remoteTree message:message + parents:parents updatingReferenceNamed:localBranch.name + error:error]; + if (!mergeCommit) { + return NO; + } + + return YES; + } else if (analysis & GTMergeAnalysisUnborn) { + // Do unborn merge + NSLog(@"Unborn merge is not yet supported"); + return NO; + } + + return NO; } - (GTMergeAnalysis)analyseMerge:(GTBranch *)toBranch fromBranch:(GTBranch *)fromBranch error:(NSError **)error { - git_merge_analysis_t analysis; - git_merge_preference_t preference; - git_annotated_commit *annotatedCommit; - - GTCommit *fromCommit = [fromBranch targetCommitAndReturnError:error]; - if (*error) { - return GTMergeAnalysisNone; - } - - git_annotated_commit_lookup(&annotatedCommit, self.git_repository, git_object_id(fromCommit.git_object)); - git_merge_analysis(&analysis, &preference, self.git_repository, (const git_annotated_commit **) &annotatedCommit, 1); - git_annotated_commit_free(annotatedCommit); - - return (GTMergeAnalysis)analysis; + git_merge_analysis_t analysis; + git_merge_preference_t preference; + git_annotated_commit *annotatedCommit; + + GTCommit *fromCommit = [fromBranch targetCommitAndReturnError:error]; + if (*error) { + return GTMergeAnalysisNone; + } + + git_annotated_commit_lookup(&annotatedCommit, self.git_repository, git_object_id(fromCommit.git_object)); + git_merge_analysis(&analysis, &preference, self.git_repository, (const git_annotated_commit **) &annotatedCommit, 1); + git_annotated_commit_free(annotatedCommit); + + return (GTMergeAnalysis)analysis; } @end From f7133265b42d844b5cbfca53b6aeb47f3908cac0 Mon Sep 17 00:00:00 2001 From: Piet Brauer Date: Thu, 18 Jun 2015 17:07:04 +0200 Subject: [PATCH 04/47] Add fast-forward and unborn merge --- ObjectiveGit/GTRepository+Pull.m | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 6f7f51a8b..329d86a89 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -10,9 +10,9 @@ #import "GTCommit.h" #import "GTRemote.h" +#import "GTSignature.h" #import "GTRepository+Committing.h" #import "GTRepository+RemoteOperations.h" -#import "git2/merge.h" @implementation GTRepository (Pull) @@ -71,10 +71,16 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: if (analysis & GTMergeAnalysisUpToDate) { // Nothing to do return YES; - } else if (analysis & GTMergeAnalysisFastForward) { + } else if (analysis & GTMergeAnalysisFastForward || + analysis & GTMergeAnalysisUnborn) { // Do FastForward - NSLog(@"Fast-Forward merge is not yet supported"); - return NO; + [localBranch.reference referenceByUpdatingTarget:remoteCommit.SHA + committer:[self userSignatureForNow] + message:[NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName] + error:error]; + + return *error == nil; + } else if (analysis & GTMergeAnalysisNormal) { // Do normal merge GTTree *remoteTree = remoteCommit.tree; @@ -83,15 +89,7 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: GTCommit *mergeCommit = [repo createCommitWithTree:remoteTree message:message parents:parents updatingReferenceNamed:localBranch.name error:error]; - if (!mergeCommit) { - return NO; - } - - return YES; - } else if (analysis & GTMergeAnalysisUnborn) { - // Do unborn merge - NSLog(@"Unborn merge is not yet supported"); - return NO; + return mergeCommit != nil; } return NO; From c7b439adba7afbdb5611cf0ea88dbd76e2717ff8 Mon Sep 17 00:00:00 2001 From: Piet Brauer Date: Thu, 18 Jun 2015 17:50:14 +0200 Subject: [PATCH 05/47] Use GTMergeAnalysis as parameter instead of return type --- ObjectiveGit/GTRepository+Pull.h | 7 ++++--- ObjectiveGit/GTRepository+Pull.m | 12 ++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.h b/ObjectiveGit/GTRepository+Pull.h index 2ad8e5f26..184e473c1 100644 --- a/ObjectiveGit/GTRepository+Pull.h +++ b/ObjectiveGit/GTRepository+Pull.h @@ -43,12 +43,13 @@ typedef void (^GTRemoteFetchTransferProgressBlock)(const git_transfer_progress * /// Analyse which merge to perform /// -/// toBranch - The current branch. +/// analysis - The resulting analysis. /// fromBranch - The remote to pull from. /// error - The error if one occurred. Can be NULL. /// -/// Returns the result as a GTMergeAnalysis. -- (GTMergeAnalysis)analyseMerge:(GTBranch *)toBranch fromBranch:(GTBranch *)fromBranch error:(NSError **)error; +/// Returns YES if the analysis was successful, NO otherwise (and `error`, if provided, +/// will point to an error describing what happened). +- (BOOL)analyseMerge:(GTMergeAnalysis *)analysis fromBranch:(GTBranch *)fromBranch error:(NSError **)error; @end diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 329d86a89..1f54baacc 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -62,7 +62,8 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: return YES; } - GTMergeAnalysis analysis = [self analyseMerge:branch fromBranch:remoteBranch error:error]; + GTMergeAnalysis analysis; + [self analyseMerge:&analysis fromBranch:remoteBranch error:error]; if (*error) { return NO; @@ -95,22 +96,21 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: return NO; } -- (GTMergeAnalysis)analyseMerge:(GTBranch *)toBranch fromBranch:(GTBranch *)fromBranch error:(NSError **)error +- (BOOL)analyseMerge:(GTMergeAnalysis *)analysis fromBranch:(GTBranch *)fromBranch error:(NSError **)error { - git_merge_analysis_t analysis; git_merge_preference_t preference; git_annotated_commit *annotatedCommit; GTCommit *fromCommit = [fromBranch targetCommitAndReturnError:error]; if (*error) { - return GTMergeAnalysisNone; + return NO; } git_annotated_commit_lookup(&annotatedCommit, self.git_repository, git_object_id(fromCommit.git_object)); - git_merge_analysis(&analysis, &preference, self.git_repository, (const git_annotated_commit **) &annotatedCommit, 1); + git_merge_analysis((git_merge_analysis_t *)analysis, &preference, self.git_repository, (const git_annotated_commit **) &annotatedCommit, 1); git_annotated_commit_free(annotatedCommit); - return (GTMergeAnalysis)analysis; + return YES; } @end From 1a2fd36c6892aea0d2379dbb89009679de2fb0e0 Mon Sep 17 00:00:00 2001 From: Piet Brauer Date: Thu, 18 Jun 2015 17:50:39 +0200 Subject: [PATCH 06/47] Checkout reference after updating HEAD --- ObjectiveGit/GTRepository+Pull.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 1f54baacc..2abb63439 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -80,8 +80,12 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: message:[NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName] error:error]; - return *error == nil; + [self checkoutReference:localBranch.reference + strategy:GTCheckoutStrategyForce + error:error + progressBlock:nil]; + return *error == nil; } else if (analysis & GTMergeAnalysisNormal) { // Do normal merge GTTree *remoteTree = remoteCommit.tree; From b510505a90c7c54cc0b5bf8e37a749135f7ad0b8 Mon Sep 17 00:00:00 2001 From: Piet Brauer Date: Thu, 18 Jun 2015 17:56:37 +0200 Subject: [PATCH 07/47] Remove new lines and use one line only for long method calls This stays consistent with the project. See https://github.com/libgit2/objective-git/blob/master/ObjectiveGit/GTRepository.m#L173 for example. --- ObjectiveGit/GTRepository+Pull.m | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 2abb63439..f52887e62 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -18,8 +18,7 @@ @implementation GTRepository (Pull) #pragma mark - Pull -- (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions:(NSDictionary *)options - error:(NSError **)error progress:(GTRemoteFetchTransferProgressBlock)progressBlock +- (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions:(NSDictionary *)options error:(NSError **)error progress:(GTRemoteFetchTransferProgressBlock)progressBlock { NSParameterAssert(branch); NSParameterAssert(remote); @@ -75,15 +74,9 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: } else if (analysis & GTMergeAnalysisFastForward || analysis & GTMergeAnalysisUnborn) { // Do FastForward - [localBranch.reference referenceByUpdatingTarget:remoteCommit.SHA - committer:[self userSignatureForNow] - message:[NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName] - error:error]; + [localBranch.reference referenceByUpdatingTarget:remoteCommit.SHA committer:[self userSignatureForNow] message:[NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName] error:error]; - [self checkoutReference:localBranch.reference - strategy:GTCheckoutStrategyForce - error:error - progressBlock:nil]; + [self checkoutReference:localBranch.reference strategy:GTCheckoutStrategyForce error:error progressBlock:nil]; return *error == nil; } else if (analysis & GTMergeAnalysisNormal) { @@ -91,9 +84,7 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: GTTree *remoteTree = remoteCommit.tree; NSString *message = [NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName]; NSArray *parents = @[ localCommit, remoteCommit ]; - GTCommit *mergeCommit = [repo createCommitWithTree:remoteTree message:message - parents:parents updatingReferenceNamed:localBranch.name - error:error]; + GTCommit *mergeCommit = [repo createCommitWithTree:remoteTree message:message parents:parents updatingReferenceNamed:localBranch.name error:error]; return mergeCommit != nil; } From ea66aa081c1dcfcd2a3cd05ca0033e09d5116eaa Mon Sep 17 00:00:00 2001 From: Piet Brauer Date: Thu, 18 Jun 2015 19:50:26 +0200 Subject: [PATCH 08/47] Make header public --- ObjectiveGit/ObjectiveGit.h | 1 + ObjectiveGitFramework.xcodeproj/project.pbxproj | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ObjectiveGit/ObjectiveGit.h b/ObjectiveGit/ObjectiveGit.h index da4a672eb..ef8126cb3 100644 --- a/ObjectiveGit/ObjectiveGit.h +++ b/ObjectiveGit/ObjectiveGit.h @@ -40,6 +40,7 @@ FOUNDATION_EXPORT const unsigned char ObjectiveGitVersionString[]; #import #import #import +#import #import #import #import diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index 8ad0ee8b8..4368d1c46 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -311,8 +311,8 @@ DD3D9513182A81E1004AF532 /* GTBlame.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3D9511182A81E1004AF532 /* GTBlame.m */; }; DD3D951C182AB25C004AF532 /* GTBlameHunk.h in Headers */ = {isa = PBXBuildFile; fileRef = DD3D951A182AB25C004AF532 /* GTBlameHunk.h */; settings = {ATTRIBUTES = (Public, ); }; }; DD3D951D182AB25C004AF532 /* GTBlameHunk.m in Sources */ = {isa = PBXBuildFile; fileRef = DD3D951B182AB25C004AF532 /* GTBlameHunk.m */; }; - F8D1BDEE1B31FE7C00CDEC90 /* GTRepository+Pull.h in Headers */ = {isa = PBXBuildFile; fileRef = F8D1BDEC1B31FE7C00CDEC90 /* GTRepository+Pull.h */; }; - F8D1BDEF1B31FE7C00CDEC90 /* GTRepository+Pull.h in Headers */ = {isa = PBXBuildFile; fileRef = F8D1BDEC1B31FE7C00CDEC90 /* GTRepository+Pull.h */; }; + F8D1BDEE1B31FE7C00CDEC90 /* GTRepository+Pull.h in Headers */ = {isa = PBXBuildFile; fileRef = F8D1BDEC1B31FE7C00CDEC90 /* GTRepository+Pull.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F8D1BDEF1B31FE7C00CDEC90 /* GTRepository+Pull.h in Headers */ = {isa = PBXBuildFile; fileRef = F8D1BDEC1B31FE7C00CDEC90 /* GTRepository+Pull.h */; settings = {ATTRIBUTES = (Public, ); }; }; F8D1BDF01B31FE7C00CDEC90 /* GTRepository+Pull.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D1BDED1B31FE7C00CDEC90 /* GTRepository+Pull.m */; }; F8D1BDF11B31FE7C00CDEC90 /* GTRepository+Pull.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D1BDED1B31FE7C00CDEC90 /* GTRepository+Pull.m */; }; F8E4A2911A170CA6006485A8 /* GTRemotePushSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = F8E4A2901A170CA6006485A8 /* GTRemotePushSpec.m */; }; @@ -1008,13 +1008,13 @@ 8821547D17147B3600D76B76 /* GTOID.h in Headers */, 20F43DE318A2F668007D3621 /* GTRepository+Blame.h in Headers */, D0CE552018B6C58F008EB8E0 /* GTFilterList.h in Headers */, - F8D1BDEE1B31FE7C00CDEC90 /* GTRepository+Pull.h in Headers */, D021DF4F1806899000934E32 /* NSArray+StringArray.h in Headers */, 30DCBA6317B45A78009B0EBD /* GTRepository+Status.h in Headers */, 8821547617147A5200D76B76 /* GTReflogEntry.h in Headers */, 30DCBA5C17B45213009B0EBD /* GTStatusDelta.h in Headers */, 88746CC417FA1C950005888A /* GTRepository+Committing.h in Headers */, D09C2E361755F16200065E36 /* GTSubmodule.h in Headers */, + F8D1BDEE1B31FE7C00CDEC90 /* GTRepository+Pull.h in Headers */, 4D79C0EE17DF9F4D00997DE4 /* GTCredential.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1024,7 +1024,6 @@ buildActionMask = 2147483647; files = ( D01B6F3D19F82F8700D411BC /* GTTag.h in Headers */, - F8D1BDEF1B31FE7C00CDEC90 /* GTRepository+Pull.h in Headers */, D01B6F4119F82F8700D411BC /* GTIndexEntry.h in Headers */, D01B6F2319F82F8700D411BC /* GTRepository+Reset.h in Headers */, D01B6F2D19F82F8700D411BC /* GTEnumerator.h in Headers */, @@ -1075,6 +1074,7 @@ D01B6F1B19F82F7B00D411BC /* NSDate+GTTimeAdditions.h in Headers */, D01B6F6319F82FA600D411BC /* GTFilterList.h in Headers */, 889923FB19FF5DD40092A9A6 /* git2 in Headers */, + F8D1BDEF1B31FE7C00CDEC90 /* GTRepository+Pull.h in Headers */, D01B6F1419F82F6000D411BC /* git2.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; From d88ba4d7c00d598ec3d78fff5866b89a497fd6db Mon Sep 17 00:00:00 2001 From: Piet Brauer Date: Thu, 18 Jun 2015 19:51:21 +0200 Subject: [PATCH 09/47] Also checkout after merge commit --- ObjectiveGit/GTRepository+Pull.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index f52887e62..baf06bc83 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -85,6 +85,9 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: NSString *message = [NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName]; NSArray *parents = @[ localCommit, remoteCommit ]; GTCommit *mergeCommit = [repo createCommitWithTree:remoteTree message:message parents:parents updatingReferenceNamed:localBranch.name error:error]; + + [self checkoutReference:localBranch.reference strategy:GTCheckoutStrategyForce error:error progressBlock:nil]; + return mergeCommit != nil; } From 2de17e1c0c1bc0e1b939a42d61abd0f7fe9bc2ef Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Thu, 18 Jun 2015 17:38:56 -0600 Subject: [PATCH 10/47] Use return values to determine when to bail out --- ObjectiveGit/GTRepository+Pull.m | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index baf06bc83..230fa36a2 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -43,17 +43,17 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: // Check if merge is necessary GTBranch *localBranch = [repo currentBranchWithError:error]; - if (*error) { + if (!localBranch) { return NO; } GTCommit *localCommit = [localBranch targetCommitAndReturnError:error]; - if (*error) { + if (!localCommit) { return NO; } GTCommit *remoteCommit = [remoteBranch targetCommitAndReturnError:error]; - if (*error) { + if (!remoteCommit) { return NO; } @@ -62,9 +62,8 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: } GTMergeAnalysis analysis; - [self analyseMerge:&analysis fromBranch:remoteBranch error:error]; - - if (*error) { + BOOL success = [self analyseMerge:&analysis fromBranch:remoteBranch error:error]; + if (!success) { return NO; } @@ -76,9 +75,9 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: // Do FastForward [localBranch.reference referenceByUpdatingTarget:remoteCommit.SHA committer:[self userSignatureForNow] message:[NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName] error:error]; - [self checkoutReference:localBranch.reference strategy:GTCheckoutStrategyForce error:error progressBlock:nil]; + BOOL success = [self checkoutReference:localBranch.reference strategy:GTCheckoutStrategyForce error:error progressBlock:nil]; - return *error == nil; + return success; } else if (analysis & GTMergeAnalysisNormal) { // Do normal merge GTTree *remoteTree = remoteCommit.tree; @@ -100,7 +99,7 @@ - (BOOL)analyseMerge:(GTMergeAnalysis *)analysis fromBranch:(GTBranch *)fromBran git_annotated_commit *annotatedCommit; GTCommit *fromCommit = [fromBranch targetCommitAndReturnError:error]; - if (*error) { + if (!fromCommit) { return NO; } From 0bd6b02ffa83366d67dc6da0ddd99e37b532cfef Mon Sep 17 00:00:00 2001 From: Piet Brauer Date: Fri, 19 Jun 2015 07:41:37 +0200 Subject: [PATCH 11/47] Use referenceByUpdatingTarget:message:error --- ObjectiveGit/GTRepository+Pull.m | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 230fa36a2..8dd7bdabe 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -10,7 +10,7 @@ #import "GTCommit.h" #import "GTRemote.h" -#import "GTSignature.h" +#import "GTReference.h" #import "GTRepository+Committing.h" #import "GTRepository+RemoteOperations.h" @@ -73,11 +73,10 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: } else if (analysis & GTMergeAnalysisFastForward || analysis & GTMergeAnalysisUnborn) { // Do FastForward - [localBranch.reference referenceByUpdatingTarget:remoteCommit.SHA committer:[self userSignatureForNow] message:[NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName] error:error]; + [localBranch.reference referenceByUpdatingTarget:remoteCommit.SHA message:nil error:error]; + BOOL checkoutSuccess = [self checkoutReference:localBranch.reference strategy:GTCheckoutStrategyForce error:error progressBlock:nil]; - BOOL success = [self checkoutReference:localBranch.reference strategy:GTCheckoutStrategyForce error:error progressBlock:nil]; - - return success; + return checkoutSuccess; } else if (analysis & GTMergeAnalysisNormal) { // Do normal merge GTTree *remoteTree = remoteCommit.tree; From 18b86b214d3c9fb6da73af8a73f22bbb9c37c08e Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Fri, 19 Jun 2015 21:35:10 -0600 Subject: [PATCH 12/47] Abandon pull if tracking branch cannot be found --- ObjectiveGit/GTRepository+Pull.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 8dd7bdabe..f126c8eec 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -29,7 +29,7 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: if (branch.branchType == GTBranchTypeLocal) { BOOL success; remoteBranch = [branch trackingBranchWithError:error success:&success]; - if (!success) { + if (!remoteBranch) { return NO; } } From b9c8b8e19721f4faad8fb9484e2631caae8048ac Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Sat, 27 Jun 2015 08:50:46 -0600 Subject: [PATCH 13/47] Ignore Carthage/Build --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b193eb3f5..a086e539f 100644 --- a/.gitignore +++ b/.gitignore @@ -27,5 +27,7 @@ ObjectiveGitTests/fixtures/Fixtures/* External/ios-openssl/include External/ios-openssl/lib - External/libssh2-ios + +Carthage/Build + From f8bd53e403c0bf05baef0cf4723dd885b9c2a0bf Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Sun, 28 Jun 2015 09:45:50 -0600 Subject: [PATCH 14/47] Change calls to targetCommitWithError: targetCommitAndReturnError: is deprecated --- ObjectiveGit/GTRepository+Pull.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index f126c8eec..a2288d847 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -47,12 +47,12 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: return NO; } - GTCommit *localCommit = [localBranch targetCommitAndReturnError:error]; + GTCommit *localCommit = [localBranch targetCommitWithError:error]; if (!localCommit) { return NO; } - GTCommit *remoteCommit = [remoteBranch targetCommitAndReturnError:error]; + GTCommit *remoteCommit = [remoteBranch targetCommitWithError:error]; if (!remoteCommit) { return NO; } @@ -97,7 +97,7 @@ - (BOOL)analyseMerge:(GTMergeAnalysis *)analysis fromBranch:(GTBranch *)fromBran git_merge_preference_t preference; git_annotated_commit *annotatedCommit; - GTCommit *fromCommit = [fromBranch targetCommitAndReturnError:error]; + GTCommit *fromCommit = [fromBranch targetCommitWithError:error]; if (!fromCommit) { return NO; } From ed5ca8ba9b2e53f458b3e73af1d81e82444d76d9 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Sun, 28 Jun 2015 09:52:15 -0600 Subject: [PATCH 15/47] Sort specs by name --- .../project.pbxproj | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index 90b0a2dfd..1e03c9582 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -718,40 +718,40 @@ 88F05A7516011E5400B7AD1D /* ObjectiveGitTests */ = { isa = PBXGroup; children = ( - 88F05A7616011E5400B7AD1D /* Supporting Files */, + 200578C418932A82001C06C3 /* GTBlameSpec.m */, 4D1C40D7182C006D00BE2960 /* GTBlobSpec.m */, 88A994B916FCE7D400402C7B /* GTBranchSpec.m */, 88F05AA416011FFD00B7AD1D /* GTCommitSpec.m */, 88C0BC5817038CF3009E99AA /* GTConfigurationSpec.m */, + 8870390A1975E3F2004118D7 /* GTDiffDeltaSpec.m */, 30865A90167F503400B1AB6E /* GTDiffSpec.m */, D06D9E001755D10000558C17 /* GTEnumeratorSpec.m */, + D0751CD818BE520400134314 /* GTFilterListSpec.m */, + 886E623618AECD86000611A0 /* GTFilterSpec.m */, 8832811E173D8816006D7DCF /* GTIndexSpec.m */, + 88948AC81779243600809CDA /* GTObjectDatabaseSpec.m */, 88F05AA816011FFD00B7AD1D /* GTObjectSpec.m */, + D040AF6F177B9779001AD9EB /* GTOIDSpec.m */, D00F6815175D373C004DB9D6 /* GTReferenceSpec.m */, 88215482171499BE00D76B76 /* GTReflogSpec.m */, F8E4A2901A170CA6006485A8 /* GTRemotePushSpec.m */, 4DBA4A3117DA73CE006CD5F5 /* GTRemoteSpec.m */, - 200578C418932A82001C06C3 /* GTBlameSpec.m */, - D0AC906B172F941F00347DC4 /* GTRepositorySpec.m */, + 30A269AC17B4878C000FE64E /* GTRepository+StatusSpec.m */, + 88E353051982EA6B0051001F /* GTRepositoryAttributesSpec.m */, 4D12323F178E009E0048F785 /* GTRepositoryCommittingSpec.m */, + 88234B2518F2FE260039972E /* GTRepositoryResetSpec.m */, + D0AC906B172F941F00347DC4 /* GTRepositorySpec.m */, + D015F7D417F6965400AD5E1F /* GTRepositoryStashingSpec.m */, + D040AF77177B9A9E001AD9EB /* GTSignatureSpec.m */, D03B7C401756AB370034A610 /* GTSubmoduleSpec.m */, 2089E43B17D9A58000F451DA /* GTTagSpec.m */, 30B1E7FF1703871900D0814D /* GTTimeAdditionsSpec.m */, 5BE612921745EEBC00266D8C /* GTTreeBuilderSpec.m */, 88328127173D8A64006D7DCF /* GTTreeSpec.m */, - 88948AC81779243600809CDA /* GTObjectDatabaseSpec.m */, - D040AF6F177B9779001AD9EB /* GTOIDSpec.m */, - D040AF77177B9A9E001AD9EB /* GTSignatureSpec.m */, - 30A269AC17B4878C000FE64E /* GTRepository+StatusSpec.m */, 307623AA17C6C8BD00E2CDF1 /* NSArray+StringArraySpec.m */, - D0F4E28917C7F24200BBDE30 /* NSErrorGitSpec.m */, D01EFD9F195DEF2200838D24 /* NSDataGitSpec.m */, - D015F7D417F6965400AD5E1F /* GTRepositoryStashingSpec.m */, - 886E623618AECD86000611A0 /* GTFilterSpec.m */, - D0751CD818BE520400134314 /* GTFilterListSpec.m */, - 88234B2518F2FE260039972E /* GTRepositoryResetSpec.m */, - 8870390A1975E3F2004118D7 /* GTDiffDeltaSpec.m */, - 88E353051982EA6B0051001F /* GTRepositoryAttributesSpec.m */, + D0F4E28917C7F24200BBDE30 /* NSErrorGitSpec.m */, + 88F05A7616011E5400B7AD1D /* Supporting Files */, ); path = ObjectiveGitTests; sourceTree = ""; From 935711a9ad54f483560d72c4e5e89124ece6005b Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Sun, 28 Jun 2015 12:34:09 -0600 Subject: [PATCH 16/47] Extract common testing functions createCommitInRepository and localBranchWithName now live in GTUtilityFunctions --- .../project.pbxproj | 8 +++- ObjectiveGitTests/GTRemotePushSpec.m | 31 +------------ ObjectiveGitTests/GTRemoteSpec.m | 21 +-------- ObjectiveGitTests/GTUtilityFunctions.h | 31 +++++++++++++ ObjectiveGitTests/GTUtilityFunctions.m | 46 +++++++++++++++++++ 5 files changed, 86 insertions(+), 51 deletions(-) create mode 100644 ObjectiveGitTests/GTUtilityFunctions.h create mode 100644 ObjectiveGitTests/GTUtilityFunctions.m diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index 1e03c9582..c543c6548 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -316,6 +316,7 @@ F8D1BDF01B31FE7C00CDEC90 /* GTRepository+Pull.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D1BDED1B31FE7C00CDEC90 /* GTRepository+Pull.m */; }; F8D1BDF11B31FE7C00CDEC90 /* GTRepository+Pull.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D1BDED1B31FE7C00CDEC90 /* GTRepository+Pull.m */; }; F8E4A2911A170CA6006485A8 /* GTRemotePushSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = F8E4A2901A170CA6006485A8 /* GTRemotePushSpec.m */; }; + F8EFA03A1B4059ED000FF7D0 /* GTUtilityFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = F8EFA0391B4059ED000FF7D0 /* GTUtilityFunctions.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -580,6 +581,8 @@ F8D1BDEC1B31FE7C00CDEC90 /* GTRepository+Pull.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTRepository+Pull.h"; sourceTree = ""; }; F8D1BDED1B31FE7C00CDEC90 /* GTRepository+Pull.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTRepository+Pull.m"; sourceTree = ""; }; F8E4A2901A170CA6006485A8 /* GTRemotePushSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTRemotePushSpec.m; sourceTree = ""; }; + F8EFA0381B4059ED000FF7D0 /* GTUtilityFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTUtilityFunctions.h; sourceTree = ""; }; + F8EFA0391B4059ED000FF7D0 /* GTUtilityFunctions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTUtilityFunctions.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -759,11 +762,13 @@ 88F05A7616011E5400B7AD1D /* Supporting Files */ = { isa = PBXGroup; children = ( + D09C2E50175602A500065E36 /* fixtures.zip */, + F8EFA0381B4059ED000FF7D0 /* GTUtilityFunctions.h */, + F8EFA0391B4059ED000FF7D0 /* GTUtilityFunctions.m */, D01B6F0F19F82F3C00D411BC /* Info.plist */, 88A994C916FCED1D00402C7B /* QuickSpec+GTFixtures.h */, 88A994CA16FCED1D00402C7B /* QuickSpec+GTFixtures.m */, D0A0129619F9A660007F1914 /* SwiftSpec.swift */, - D09C2E50175602A500065E36 /* fixtures.zip */, ); name = "Supporting Files"; sourceTree = ""; @@ -1271,6 +1276,7 @@ 2089E43C17D9A58000F451DA /* GTTagSpec.m in Sources */, D015F7D517F6965400AD5E1F /* GTRepositoryStashingSpec.m in Sources */, 88A994CB16FCED1D00402C7B /* QuickSpec+GTFixtures.m in Sources */, + F8EFA03A1B4059ED000FF7D0 /* GTUtilityFunctions.m in Sources */, 30B1E8001703871900D0814D /* GTTimeAdditionsSpec.m in Sources */, 8870390B1975E3F2004118D7 /* GTDiffDeltaSpec.m in Sources */, 88C0BC5917038CF3009E99AA /* GTConfigurationSpec.m in Sources */, diff --git a/ObjectiveGitTests/GTRemotePushSpec.m b/ObjectiveGitTests/GTRemotePushSpec.m index b84466493..6b7d617cc 100644 --- a/ObjectiveGitTests/GTRemotePushSpec.m +++ b/ObjectiveGitTests/GTRemotePushSpec.m @@ -11,36 +11,7 @@ #import #import "QuickSpec+GTFixtures.h" - -// Helper to quickly create commits -GTCommit *(^createCommitInRepository)(NSString *, NSData *, NSString *, GTRepository *) = ^ GTCommit * (NSString *message, NSData *fileData, NSString *fileName, GTRepository *repo) { - GTTreeBuilder *treeBuilder = [[GTTreeBuilder alloc] initWithTree:nil repository:repo error:nil]; - [treeBuilder addEntryWithData:fileData fileName:fileName fileMode:GTFileModeBlob error:nil]; - - GTTree *testTree = [treeBuilder writeTree:nil]; - - // We need the parent commit to make the new one - GTReference *headReference = [repo headReferenceWithError:nil]; - - GTEnumerator *commitEnum = [[GTEnumerator alloc] initWithRepository:repo 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]; - expect(testCommit).notTo(beNil()); - - return testCommit; -}; - -GTBranch *(^localBranchWithName)(NSString *, GTRepository *) = ^ GTBranch * (NSString *branchName, GTRepository *repo) { - NSString *reference = [GTBranch.localNamePrefix stringByAppendingString:branchName]; - NSArray *branches = [repo branchesWithPrefix:reference error:NULL]; - expect(branches).notTo(beNil()); - expect(@(branches.count)).to(equal(@1)); - expect(((GTBranch *)branches[0]).shortName).to(equal(branchName)); - - return branches[0]; -}; +#import "GTUtilityFunctions.h" #pragma mark - GTRemotePushSpec diff --git a/ObjectiveGitTests/GTRemoteSpec.m b/ObjectiveGitTests/GTRemoteSpec.m index a59e37527..3656f8cdf 100644 --- a/ObjectiveGitTests/GTRemoteSpec.m +++ b/ObjectiveGitTests/GTRemoteSpec.m @@ -11,6 +11,7 @@ #import #import "QuickSpec+GTFixtures.h" +#import "GTUtilityFunctions.h" QuickSpecBegin(GTRemoteSpec) @@ -140,26 +141,6 @@ }); }); - // Helper to quickly create commits - GTCommit *(^createCommitInRepository)(NSString *, NSData *, NSString *, GTRepository *) = ^(NSString *message, NSData *fileData, NSString *fileName, GTRepository *repo) { - GTTreeBuilder *treeBuilder = [[GTTreeBuilder alloc] initWithTree:nil repository:repo error:nil]; - [treeBuilder addEntryWithData:fileData fileName:fileName fileMode:GTFileModeBlob error:nil]; - - GTTree *testTree = [treeBuilder writeTree:nil]; - - // We need the parent commit to make the new one - GTReference *headReference = [repo headReferenceWithError:nil]; - - GTEnumerator *commitEnum = [[GTEnumerator alloc] initWithRepository:repo 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]; - expect(testCommit).notTo(beNil()); - - return testCommit; - }; - describe(@"-[GTRepository fetchRemote:withOptions:error:progress:]", ^{ it(@"allows remotes to be fetched", ^{ NSError *error = nil; diff --git a/ObjectiveGitTests/GTUtilityFunctions.h b/ObjectiveGitTests/GTUtilityFunctions.h new file mode 100644 index 000000000..73741692e --- /dev/null +++ b/ObjectiveGitTests/GTUtilityFunctions.h @@ -0,0 +1,31 @@ +// +// GTUtilityFunctions.h +// ObjectiveGitFramework +// +// Created by Ben Chatelain on 6/28/15. +// Copyright (c) 2015 GitHub, Inc. All rights reserved. +// + +#import +#import +#import + +@import Foundation; + +@class GTBranch; +@class GTCommit; +@class GTRepository; + +#pragma mark - Commit + +typedef GTCommit *(^CreateCommitBlock)(NSString *message, NSData *fileData, NSString *fileName, GTRepository *repo); + +// Helper to quickly create commits +extern CreateCommitBlock createCommitInRepository; + +#pragma mark - Branch + +typedef GTBranch *(^BranchBlock)(NSString *, GTRepository *); + +// Helper to retrieve a branch by name +extern BranchBlock localBranchWithName; diff --git a/ObjectiveGitTests/GTUtilityFunctions.m b/ObjectiveGitTests/GTUtilityFunctions.m new file mode 100644 index 000000000..25e3aedd5 --- /dev/null +++ b/ObjectiveGitTests/GTUtilityFunctions.m @@ -0,0 +1,46 @@ +// +// GTUtilityFunctions.m +// ObjectiveGitFramework +// +// Created by Ben Chatelain on 6/28/15. +// Copyright (c) 2015 GitHub, Inc. All rights reserved. +// + +#import +#import +#import + +#import "GTUtilityFunctions.h" + +#pragma mark - Commit + +CreateCommitBlock createCommitInRepository = ^ GTCommit * (NSString *message, NSData *fileData, NSString *fileName, GTRepository *repo) { + GTTreeBuilder *treeBuilder = [[GTTreeBuilder alloc] initWithTree:nil repository:repo error:nil]; + [treeBuilder addEntryWithData:fileData fileName:fileName fileMode:GTFileModeBlob error:nil]; + + GTTree *testTree = [treeBuilder writeTree:nil]; + + // We need the parent commit to make the new one + GTReference *headReference = [repo headReferenceWithError:nil]; + + GTEnumerator *commitEnum = [[GTEnumerator alloc] initWithRepository:repo 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]; + expect(testCommit).notTo(beNil()); + + return testCommit; +}; + +#pragma mark - Branch + +BranchBlock localBranchWithName = ^ GTBranch * (NSString *branchName, GTRepository *repo) { + NSString *reference = [GTBranch.localNamePrefix stringByAppendingString:branchName]; + NSArray *branches = [repo branchesWithPrefix:reference error:NULL]; + expect(branches).notTo(beNil()); + expect(@(branches.count)).to(equal(@1)); + expect(((GTBranch *)branches[0]).shortName).to(equal(branchName)); + + return branches[0]; +}; From accc3b463a3a9c769a12bb61c2c064b773e3d8fa Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Sun, 28 Jun 2015 12:35:10 -0600 Subject: [PATCH 17/47] Add GTRepository+PullSpec with simplest case --- .../project.pbxproj | 4 + ObjectiveGitTests/GTRepository+PullSpec.m | 101 ++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 ObjectiveGitTests/GTRepository+PullSpec.m diff --git a/ObjectiveGitFramework.xcodeproj/project.pbxproj b/ObjectiveGitFramework.xcodeproj/project.pbxproj index c543c6548..d8721ef78 100644 --- a/ObjectiveGitFramework.xcodeproj/project.pbxproj +++ b/ObjectiveGitFramework.xcodeproj/project.pbxproj @@ -316,6 +316,7 @@ F8D1BDF01B31FE7C00CDEC90 /* GTRepository+Pull.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D1BDED1B31FE7C00CDEC90 /* GTRepository+Pull.m */; }; F8D1BDF11B31FE7C00CDEC90 /* GTRepository+Pull.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D1BDED1B31FE7C00CDEC90 /* GTRepository+Pull.m */; }; F8E4A2911A170CA6006485A8 /* GTRemotePushSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = F8E4A2901A170CA6006485A8 /* GTRemotePushSpec.m */; }; + F8EFA0371B405020000FF7D0 /* GTRepository+PullSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = F8EFA0361B405020000FF7D0 /* GTRepository+PullSpec.m */; }; F8EFA03A1B4059ED000FF7D0 /* GTUtilityFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = F8EFA0391B4059ED000FF7D0 /* GTUtilityFunctions.m */; }; /* End PBXBuildFile section */ @@ -581,6 +582,7 @@ F8D1BDEC1B31FE7C00CDEC90 /* GTRepository+Pull.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTRepository+Pull.h"; sourceTree = ""; }; F8D1BDED1B31FE7C00CDEC90 /* GTRepository+Pull.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTRepository+Pull.m"; sourceTree = ""; }; F8E4A2901A170CA6006485A8 /* GTRemotePushSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTRemotePushSpec.m; sourceTree = ""; }; + F8EFA0361B405020000FF7D0 /* GTRepository+PullSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTRepository+PullSpec.m"; sourceTree = ""; }; F8EFA0381B4059ED000FF7D0 /* GTUtilityFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTUtilityFunctions.h; sourceTree = ""; }; F8EFA0391B4059ED000FF7D0 /* GTUtilityFunctions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTUtilityFunctions.m; sourceTree = ""; }; /* End PBXFileReference section */ @@ -739,6 +741,7 @@ 88215482171499BE00D76B76 /* GTReflogSpec.m */, F8E4A2901A170CA6006485A8 /* GTRemotePushSpec.m */, 4DBA4A3117DA73CE006CD5F5 /* GTRemoteSpec.m */, + F8EFA0361B405020000FF7D0 /* GTRepository+PullSpec.m */, 30A269AC17B4878C000FE64E /* GTRepository+StatusSpec.m */, 88E353051982EA6B0051001F /* GTRepositoryAttributesSpec.m */, 4D12323F178E009E0048F785 /* GTRepositoryCommittingSpec.m */, @@ -1286,6 +1289,7 @@ D0AC906C172F941F00347DC4 /* GTRepositorySpec.m in Sources */, D01EFDA0195DEF2200838D24 /* NSDataGitSpec.m in Sources */, 30A269AD17B4878C000FE64E /* GTRepository+StatusSpec.m in Sources */, + F8EFA0371B405020000FF7D0 /* GTRepository+PullSpec.m in Sources */, 307623AB17C6C8BD00E2CDF1 /* NSArray+StringArraySpec.m in Sources */, 8832811F173D8816006D7DCF /* GTIndexSpec.m in Sources */, D0F4E28A17C7F24200BBDE30 /* NSErrorGitSpec.m in Sources */, diff --git a/ObjectiveGitTests/GTRepository+PullSpec.m b/ObjectiveGitTests/GTRepository+PullSpec.m new file mode 100644 index 000000000..31bfcc2a7 --- /dev/null +++ b/ObjectiveGitTests/GTRepository+PullSpec.m @@ -0,0 +1,101 @@ +// +// GTRepository+PullSpec.m +// ObjectiveGitFramework +// +// Created by Ben Chatelain on 6/28/15. +// Copyright (c) 2015 GitHub, Inc. All rights reserved. +// + +#import +#import +#import + +#import "QuickSpec+GTFixtures.h" +#import "GTUtilityFunctions.h" + +#pragma mark - GTRepository+PullSpec + +QuickSpecBegin(GTRepositoryPullSpec) + +describe(@"pulling", ^{ + __block GTRepository *notBareRepo; + + beforeEach(^{ + notBareRepo = self.bareFixtureRepository; + expect(notBareRepo).notTo(beNil()); + // This repo is not really "bare" according to libgit2 + expect(@(notBareRepo.isBare)).to(beFalsy()); + }); + + describe(@"from remote", ^{ // via local transport + __block NSURL *remoteRepoURL; + __block NSURL *localRepoURL; + __block GTRepository *remoteRepo; + __block GTRepository *localRepo; + __block GTRemote *remote; + __block NSError *error; + + beforeEach(^{ + // Make a bare clone to serve as the remote + remoteRepoURL = [notBareRepo.gitDirectoryURL.URLByDeletingLastPathComponent URLByAppendingPathComponent:@"bare_remote_repo.git"]; + NSDictionary *options = @{ GTRepositoryCloneOptionsBare: @1 }; + remoteRepo = [GTRepository cloneFromURL:notBareRepo.gitDirectoryURL toWorkingDirectory:remoteRepoURL options:options error:&error transferProgressBlock:NULL checkoutProgressBlock:NULL]; + expect(error).to(beNil()); + expect(remoteRepo).notTo(beNil()); + expect(@(remoteRepo.isBare)).to(beTruthy()); // that's better + + localRepoURL = [remoteRepoURL.URLByDeletingLastPathComponent URLByAppendingPathComponent:@"local_pull_repo"]; + expect(localRepoURL).notTo(beNil()); + + // Local clone for testing pushes + localRepo = [GTRepository cloneFromURL:remoteRepoURL toWorkingDirectory:localRepoURL options:nil error:&error transferProgressBlock:NULL checkoutProgressBlock:NULL]; + + expect(error).to(beNil()); + expect(localRepo).notTo(beNil()); + + GTConfiguration *configuration = [localRepo configurationWithError:&error]; + expect(error).to(beNil()); + expect(configuration).notTo(beNil()); + + expect(@(configuration.remotes.count)).to(equal(@1)); + + remote = configuration.remotes[0]; + expect(remote.name).to(equal(@"origin")); + }); + + afterEach(^{ + [NSFileManager.defaultManager removeItemAtURL:remoteRepoURL error:&error]; + expect(error).to(beNil()); + [NSFileManager.defaultManager removeItemAtURL:localRepoURL error:&error]; + expect(error).to(beNil()); + error = NULL; + }); + + context(@"when the local and remote branches are in sync", ^{ + it(@"should pull no commits", ^{ + GTBranch *masterBranch = localBranchWithName(@"master", localRepo); + expect(@([masterBranch numberOfCommitsWithError:NULL])).to(equal(@3)); + + GTBranch *remoteMasterBranch = localBranchWithName(@"master", remoteRepo); + expect(@([remoteMasterBranch numberOfCommitsWithError:NULL])).to(equal(@3)); + + // Push + __block BOOL transferProgressed = NO; + BOOL result = [localRepo pullBranch:masterBranch fromRemote:remote withOptions:nil error:&error progress:^(const git_transfer_progress *progress, BOOL *stop) { + transferProgressed = YES; + }]; + expect(error).to(beNil()); + expect(@(result)).to(beTruthy()); + expect(@(transferProgressed)).to(beFalsy()); // Local transport doesn't currently call progress callbacks + + // Same number of commits after pull, refresh branch from disk first + remoteMasterBranch = localBranchWithName(@"master", remoteRepo); + expect(@([remoteMasterBranch numberOfCommitsWithError:NULL])).to(equal(@3)); + }); + }); + + }); + +}); + +QuickSpecEnd From 1efd44d2119c8343dc6828e57ccb3d7dfad49658 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Mon, 29 Jun 2015 21:36:26 -0600 Subject: [PATCH 18/47] Add test for pulling one commit --- ObjectiveGitTests/GTRepository+PullSpec.m | 44 ++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/ObjectiveGitTests/GTRepository+PullSpec.m b/ObjectiveGitTests/GTRepository+PullSpec.m index 31bfcc2a7..44eb2b68d 100644 --- a/ObjectiveGitTests/GTRepository+PullSpec.m +++ b/ObjectiveGitTests/GTRepository+PullSpec.m @@ -79,7 +79,7 @@ GTBranch *remoteMasterBranch = localBranchWithName(@"master", remoteRepo); expect(@([remoteMasterBranch numberOfCommitsWithError:NULL])).to(equal(@3)); - // Push + // Pull __block BOOL transferProgressed = NO; BOOL result = [localRepo pullBranch:masterBranch fromRemote:remote withOptions:nil error:&error progress:^(const git_transfer_progress *progress, BOOL *stop) { transferProgressed = YES; @@ -94,6 +94,48 @@ }); }); + /// This test stages a pull by modifying a clone, resetting it back in history + /// then using pull to bring the repos back in sync. + it(@"can pull one commit", ^{ + GTBranch *masterBranch = localBranchWithName(@"master", localRepo); + expect(@([masterBranch numberOfCommitsWithError:NULL])).to(equal(@3)); + + // Reset local master back one commit + GTCommit *commit = [localRepo lookUpObjectByRevParse:@"HEAD^" error:&error]; + BOOL success = [localRepo resetToCommit:commit resetType:GTRepositoryResetTypeHard error:&error]; + expect(@(success)).to(beTruthy()); + expect(error).to(beNil()); + + // Verify rollback, must refresh branch from disk + masterBranch = localBranchWithName(@"master", localRepo); + expect(@([masterBranch numberOfCommitsWithError:NULL])).to(equal(@2)); + + // HEADs point to different objects + expect([[localRepo headReferenceWithError:NULL] OID]) + .toNot(equal([[remoteRepo headReferenceWithError:NULL] OID])); + + // Remote has 3 commits + GTBranch *remoteMasterBranch = localBranchWithName(@"master", remoteRepo); + expect(@([remoteMasterBranch numberOfCommitsWithError:NULL])).to(equal(@3)); + + // Pull + __block BOOL transferProgressed = NO; + BOOL result = [localRepo pullBranch:masterBranch fromRemote:remote withOptions:nil error:&error progress:^(const git_transfer_progress *progress, BOOL *stop) { + transferProgressed = YES; + }]; + expect(error).to(beNil()); + expect(@(result)).to(beTruthy()); + expect(@(transferProgressed)).to(beFalsy()); // Local transport doesn't currently call progress callbacks + + // Verify same number of commits after pull, refresh branch from disk first + masterBranch = localBranchWithName(@"master", localRepo); + expect(@([masterBranch numberOfCommitsWithError:NULL])).to(equal(@3)); + + // Verify HEADs are in sync + expect([[localRepo headReferenceWithError:NULL] OID]) + .to(equal([[remoteRepo headReferenceWithError:NULL] OID])); + }); + }); }); From 4f85b2713d3ef0c741b7bfd19847900366a9490c Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Wed, 1 Jul 2015 23:22:48 -0600 Subject: [PATCH 19/47] Add pending unborn test --- ObjectiveGitTests/GTRepository+PullSpec.m | 45 +++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/ObjectiveGitTests/GTRepository+PullSpec.m b/ObjectiveGitTests/GTRepository+PullSpec.m index 44eb2b68d..10f5bf041 100644 --- a/ObjectiveGitTests/GTRepository+PullSpec.m +++ b/ObjectiveGitTests/GTRepository+PullSpec.m @@ -69,6 +69,7 @@ [NSFileManager.defaultManager removeItemAtURL:localRepoURL error:&error]; expect(error).to(beNil()); error = NULL; + [self tearDown]; }); context(@"when the local and remote branches are in sync", ^{ @@ -94,6 +95,50 @@ }); }); + /// Unborn + /// Can't get a GTBranch reference wrapping HEAD when its symref is unborn + pending(@"can pull into an empty repo", ^{ + // Create an empty local repo + localRepoURL = [remoteRepoURL.URLByDeletingLastPathComponent URLByAppendingPathComponent:@"empty_pull_repo"]; + NSLog(@"localRepoURL: %@", localRepoURL); + NSDictionary *options = @{ GTRepositoryInitOptionsOriginURLString: [remoteRepoURL absoluteString] }; + localRepo = [GTRepository initializeEmptyRepositoryAtFileURL:localRepoURL options:options error:&error]; + expect(localRepo).toNot(beNil()); + expect(error).to(beNil()); + + // Verify unborn + expect(@(localRepo.isHEADUnborn)).to(beTruthy()); + + // Configure tracking + GTConfiguration *configuration = [localRepo configurationWithError:&error]; + expect(configuration).toNot(beNil()); + expect(error).to(beNil()); + [configuration setString:@"origin" forKey:@"branch.master.remote"]; + [configuration setString:@"refs/heads/master" forKey:@"branch.master.merge"]; + + GTReference *head = [localRepo headReferenceWithError:&error]; + expect(head).toNot(beNil()); + expect(error).to(beNil()); + +// GTBranch *masterBranch = localBranchWithName(@"master", localRepo); + GTBranch *masterBranch = [localRepo currentBranchWithError:&error]; + expect(masterBranch).toNot(beNil()); + + // Pull + __block BOOL transferProgressed = NO; + BOOL result = [localRepo pullBranch:masterBranch fromRemote:remote withOptions:nil error:&error progress:^(const git_transfer_progress *progress, BOOL *stop) { + transferProgressed = YES; + }]; + expect(@(result)).to(beTruthy()); + expect(error).to(beNil()); + expect(@(transferProgressed)).to(beFalsy()); // Local transport doesn't currently call progress callbacks + +// GTReference *head = [localRepo headReferenceWithError:&error]; +// expect(head).toNot(beNil()); + + }); + + /// # Fast-forward /// This test stages a pull by modifying a clone, resetting it back in history /// then using pull to bring the repos back in sync. it(@"can pull one commit", ^{ From 0c611f43d734fc38a8cf282679725f9060a983cd Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Thu, 2 Jul 2015 21:42:19 -0600 Subject: [PATCH 20/47] Amend error description when GTBranch can't init due to HEAD being unborn --- ObjectiveGit/GTRepository.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ObjectiveGit/GTRepository.m b/ObjectiveGit/GTRepository.m index 237aa6a61..e539fc2e9 100644 --- a/ObjectiveGit/GTRepository.m +++ b/ObjectiveGit/GTRepository.m @@ -361,7 +361,11 @@ - (GTReference *)headReferenceWithError:(NSError **)error { git_reference *headRef; int gitError = git_repository_head(&headRef, self.git_repository); if (gitError != GIT_OK) { - if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to get HEAD"]; + NSString *unborn = @""; + if (gitError == GIT_EUNBORNBRANCH) { + unborn = @" (unborn)"; + } + if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to get HEAD%@", unborn]; return nil; } From 696b4bd6c6311c86e42e781f1d04d7db5ded7b56 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Thu, 2 Jul 2015 21:42:43 -0600 Subject: [PATCH 21/47] Use updated reference to checkout at end of pull --- ObjectiveGit/GTRepository+Pull.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index a2288d847..0ce30948a 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -72,9 +72,9 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: return YES; } else if (analysis & GTMergeAnalysisFastForward || analysis & GTMergeAnalysisUnborn) { - // Do FastForward - [localBranch.reference referenceByUpdatingTarget:remoteCommit.SHA message:nil error:error]; - BOOL checkoutSuccess = [self checkoutReference:localBranch.reference strategy:GTCheckoutStrategyForce error:error progressBlock:nil]; + // Fast-forward branch + GTReference *reference = [localBranch.reference referenceByUpdatingTarget:remoteCommit.SHA message:nil error:error]; + BOOL checkoutSuccess = [self checkoutReference:reference strategy:GTCheckoutStrategyForce error:error progressBlock:nil]; return checkoutSuccess; } else if (analysis & GTMergeAnalysisNormal) { From 4c50988a428c738c745ebc6665f643edaa1682aa Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Thu, 2 Jul 2015 21:44:51 -0600 Subject: [PATCH 22/47] Include reflog message --- ObjectiveGit/GTRepository+Pull.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 0ce30948a..ded8821a0 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -58,6 +58,7 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: } if ([localCommit.SHA isEqualToString:remoteCommit.SHA]) { + // Local and remote tracking branch are already in sync return YES; } @@ -73,7 +74,8 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: } else if (analysis & GTMergeAnalysisFastForward || analysis & GTMergeAnalysisUnborn) { // Fast-forward branch - GTReference *reference = [localBranch.reference referenceByUpdatingTarget:remoteCommit.SHA message:nil error:error]; + NSString *message = [NSString stringWithFormat:@"merge %@/%@: Fast-forward", remote.name, remoteBranch.name]; + GTReference *reference = [localBranch.reference referenceByUpdatingTarget:remoteCommit.SHA message:message error:error]; BOOL checkoutSuccess = [self checkoutReference:reference strategy:GTCheckoutStrategyForce error:error progressBlock:nil]; return checkoutSuccess; From af571dee8632e87744c6256a82e024fdb38525e5 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Tue, 14 Jul 2015 18:25:14 -0600 Subject: [PATCH 23/47] Add test for pull with normal merge --- ObjectiveGitTests/GTRepository+PullSpec.m | 40 ++++++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/ObjectiveGitTests/GTRepository+PullSpec.m b/ObjectiveGitTests/GTRepository+PullSpec.m index 10f5bf041..dbfddccd4 100644 --- a/ObjectiveGitTests/GTRepository+PullSpec.m +++ b/ObjectiveGitTests/GTRepository+PullSpec.m @@ -17,7 +17,7 @@ QuickSpecBegin(GTRepositoryPullSpec) -describe(@"pulling", ^{ +describe(@"pull", ^{ __block GTRepository *notBareRepo; beforeEach(^{ @@ -97,7 +97,7 @@ /// Unborn /// Can't get a GTBranch reference wrapping HEAD when its symref is unborn - pending(@"can pull into an empty repo", ^{ + pending(@"into an empty repo", ^{ // Create an empty local repo localRepoURL = [remoteRepoURL.URLByDeletingLastPathComponent URLByAppendingPathComponent:@"empty_pull_repo"]; NSLog(@"localRepoURL: %@", localRepoURL); @@ -138,10 +138,11 @@ }); - /// # Fast-forward - /// This test stages a pull by modifying a clone, resetting it back in history + /// Fast-Forward Merge + /// + /// Stages a pull by modifying a clone, resetting it back in history /// then using pull to bring the repos back in sync. - it(@"can pull one commit", ^{ + it(@"fast-forwards one commit", ^{ GTBranch *masterBranch = localBranchWithName(@"master", localRepo); expect(@([masterBranch numberOfCommitsWithError:NULL])).to(equal(@3)); @@ -181,6 +182,35 @@ .to(equal([[remoteRepo headReferenceWithError:NULL] OID])); }); + /// Normal Merge + it(@"merges the upstream changes", ^{ + // Create a new commit in the local repo + GTCommit *localCommit = createCommitInRepository(@"Local commit", [@"Test" dataUsingEncoding:NSUTF8StringEncoding], @"test.txt", localRepo); + + localCommit = [localRepo lookUpObjectByOID:localCommit.OID objectType:GTObjectTypeCommit error:&error]; + expect(localCommit).notTo(beNil()); + expect(error).to(beNil()); + + // Create a new commit in the remote repo + GTCommit *upstreamCommit = createCommitInRepository(@"Upstream commit", [@"# So Fancy" dataUsingEncoding:NSUTF8StringEncoding], @"fancy.md", remoteRepo); + + // Pull + __block BOOL transferProgressed = NO; + GTBranch *masterBranch = localBranchWithName(@"master", localRepo); + BOOL result = [localRepo pullBranch:masterBranch fromRemote:remote withOptions:nil error:&error progress:^(const git_transfer_progress *progress, BOOL *stop) { + transferProgressed = YES; + }]; + expect(@(result)).to(beTruthy()); + expect(error).to(beNil()); + // TODO: This one works? + expect(@(transferProgressed)).to(beTruthy()); + + // Validate upstream commit is now in local repo + upstreamCommit = [remoteRepo lookUpObjectByOID:upstreamCommit.OID objectType:GTObjectTypeCommit error:&error]; + expect(upstreamCommit).notTo(beNil()); + expect(error).to(beNil()); + }); + }); }); From 436204ba7dd560cc53cdee890f5837127edd33ff Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Tue, 14 Jul 2015 18:29:18 -0600 Subject: [PATCH 24/47] #import Nimble-Swift.h Gets rid of innocuous errors --- ObjectiveGitTests/GTRepository+PullSpec.m | 1 + 1 file changed, 1 insertion(+) diff --git a/ObjectiveGitTests/GTRepository+PullSpec.m b/ObjectiveGitTests/GTRepository+PullSpec.m index dbfddccd4..8a3cf081f 100644 --- a/ObjectiveGitTests/GTRepository+PullSpec.m +++ b/ObjectiveGitTests/GTRepository+PullSpec.m @@ -7,6 +7,7 @@ // #import +#import #import #import From 130046938ddb1eb35df5ee2d34d096644195b084 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Wed, 15 Jul 2015 08:52:48 -0600 Subject: [PATCH 25/47] Add -description to GTRemote --- ObjectiveGit/GTRemote.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ObjectiveGit/GTRemote.m b/ObjectiveGit/GTRemote.m index 56c97199f..25ffd2b3f 100644 --- a/ObjectiveGit/GTRemote.m +++ b/ObjectiveGit/GTRemote.m @@ -95,6 +95,10 @@ - (NSUInteger)hash { return self.name.hash ^ self.URLString.hash; } +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p> name: %@, URLString: %@", NSStringFromClass([self class]), self, self.name, self.URLString]; +} + #pragma mark API + (BOOL)isValidRemoteName:(NSString *)name { From 277e98db0573c420f3e3cbf960081901b3a74621 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Wed, 15 Jul 2015 08:53:44 -0600 Subject: [PATCH 26/47] Better description for bare GTRepository --- ObjectiveGit/GTRepository.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ObjectiveGit/GTRepository.m b/ObjectiveGit/GTRepository.m index 332fda210..a239c41c5 100644 --- a/ObjectiveGit/GTRepository.m +++ b/ObjectiveGit/GTRepository.m @@ -91,6 +91,9 @@ @interface GTRepository () @implementation GTRepository - (NSString *)description { + if (self.isBare) { + return [NSString stringWithFormat:@"<%@: %p> (bare) gitDirectoryURL: %@", self.class, self, self.gitDirectoryURL]; + } return [NSString stringWithFormat:@"<%@: %p> fileURL: %@", self.class, self, self.fileURL]; } From 64b6b9f83e82e529675b5aee7608b8794033a71d Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Wed, 15 Jul 2015 20:12:17 -0600 Subject: [PATCH 27/47] Initialize GTMergeAnalysis with .None --- ObjectiveGit/GTRepository+Pull.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index ded8821a0..cdecf827c 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -9,6 +9,7 @@ #import "GTRepository+Pull.h" #import "GTCommit.h" +#import "GTOID.h" #import "GTRemote.h" #import "GTReference.h" #import "GTRepository+Committing.h" @@ -62,7 +63,7 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: return YES; } - GTMergeAnalysis analysis; + GTMergeAnalysis analysis = GTMergeAnalysisNone; BOOL success = [self analyseMerge:&analysis fromBranch:remoteBranch error:error]; if (!success) { return NO; @@ -104,7 +105,7 @@ - (BOOL)analyseMerge:(GTMergeAnalysis *)analysis fromBranch:(GTBranch *)fromBran return NO; } - git_annotated_commit_lookup(&annotatedCommit, self.git_repository, git_object_id(fromCommit.git_object)); + git_annotated_commit_lookup(&annotatedCommit, self.git_repository, fromCommit.OID.git_oid); git_merge_analysis((git_merge_analysis_t *)analysis, &preference, self.git_repository, (const git_annotated_commit **) &annotatedCommit, 1); git_annotated_commit_free(annotatedCommit); From cc06002bb124411e56b1fada7c921df3d64a4b98 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Wed, 15 Jul 2015 20:22:25 -0600 Subject: [PATCH 28/47] No preference on merge type --- ObjectiveGit/GTRepository+Pull.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index cdecf827c..b5cc2ea25 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -97,7 +97,7 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: - (BOOL)analyseMerge:(GTMergeAnalysis *)analysis fromBranch:(GTBranch *)fromBranch error:(NSError **)error { - git_merge_preference_t preference; + git_merge_preference_t preference = GIT_MERGE_PREFERENCE_NONE; git_annotated_commit *annotatedCommit; GTCommit *fromCommit = [fromBranch targetCommitWithError:error]; From 369106f2f11ca53c61517640c9922145f0924f74 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Thu, 16 Jul 2015 20:56:28 -0600 Subject: [PATCH 29/47] Fix issue preventing pull merge test from passing --- ObjectiveGit/GTRepository+Pull.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index b5cc2ea25..28763b097 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -26,6 +26,11 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: GTRepository *repo = remote.repository; + if (![self fetchRemote:remote withOptions:options error:error progress:progressBlock]) { + return NO; + } + + // Get remote branch after fetch so that it is up-to-date and doesn't need to be refreshed from disk GTBranch *remoteBranch; if (branch.branchType == GTBranchTypeLocal) { BOOL success; @@ -38,10 +43,6 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: remoteBranch = branch; } - if (![self fetchRemote:remote withOptions:options error:error progress:progressBlock]) { - return NO; - } - // Check if merge is necessary GTBranch *localBranch = [repo currentBranchWithError:error]; if (!localBranch) { From 1d141c6f180fb0bbfdd815822d0f37c83c3f8e67 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Thu, 16 Jul 2015 20:58:38 -0600 Subject: [PATCH 30/47] Add more checks to merge test to detect lack of merge --- ObjectiveGitTests/GTRepository+PullSpec.m | 42 +++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/ObjectiveGitTests/GTRepository+PullSpec.m b/ObjectiveGitTests/GTRepository+PullSpec.m index 8a3cf081f..3c58d5346 100644 --- a/ObjectiveGitTests/GTRepository+PullSpec.m +++ b/ObjectiveGitTests/GTRepository+PullSpec.m @@ -185,8 +185,17 @@ /// Normal Merge it(@"merges the upstream changes", ^{ + // 3 commits + GTBranch *masterBranch = localBranchWithName(@"master", localRepo); + expect(@([masterBranch numberOfCommitsWithError:NULL])).to(equal(@3)); + // Create a new commit in the local repo GTCommit *localCommit = createCommitInRepository(@"Local commit", [@"Test" dataUsingEncoding:NSUTF8StringEncoding], @"test.txt", localRepo); + expect(localCommit).notTo(beNil()); + + // 4 commits + masterBranch = localBranchWithName(@"master", localRepo); + expect(@([masterBranch numberOfCommitsWithError:NULL])).to(equal(@4)); localCommit = [localRepo lookUpObjectByOID:localCommit.OID objectType:GTObjectTypeCommit error:&error]; expect(localCommit).notTo(beNil()); @@ -194,22 +203,43 @@ // Create a new commit in the remote repo GTCommit *upstreamCommit = createCommitInRepository(@"Upstream commit", [@"# So Fancy" dataUsingEncoding:NSUTF8StringEncoding], @"fancy.md", remoteRepo); + expect(upstreamCommit).notTo(beNil()); + + masterBranch = localBranchWithName(@"master", localRepo); + + // Validate there is one unique local commit before merge + BOOL success = NO; + GTBranch *remoteTrackingBranch = [masterBranch trackingBranchWithError:&error success:&success]; + expect(@(success)).to(beTrue()); + expect(error).to(beNil()); + expect(remoteTrackingBranch).toNot(beNil()); + + NSArray *uniqueLocalCommits = [localRepo localCommitsRelativeToRemoteBranch:remoteTrackingBranch error:&error]; + expect(uniqueLocalCommits).toNot(beNil()); + expect(error).to(beNil()); + expect(@(uniqueLocalCommits.count)).to(equal(@1)); // Pull __block BOOL transferProgressed = NO; - GTBranch *masterBranch = localBranchWithName(@"master", localRepo); + // FIXME: This is analyzing merge as "up-to-date" BOOL result = [localRepo pullBranch:masterBranch fromRemote:remote withOptions:nil error:&error progress:^(const git_transfer_progress *progress, BOOL *stop) { transferProgressed = YES; }]; expect(@(result)).to(beTruthy()); expect(error).to(beNil()); - // TODO: This one works? - expect(@(transferProgressed)).to(beTruthy()); + expect(@(transferProgressed)).to(beTruthy()); // TODO: This one works? - // Validate upstream commit is now in local repo - upstreamCommit = [remoteRepo lookUpObjectByOID:upstreamCommit.OID objectType:GTObjectTypeCommit error:&error]; - expect(upstreamCommit).notTo(beNil()); + // Validate + + // 5 commits + masterBranch = localBranchWithName(@"master", localRepo); + expect(@([masterBranch numberOfCommitsWithError:NULL])).to(equal(@6)); + + // We should have have an additional merge commit after the pull + uniqueLocalCommits = [localRepo localCommitsRelativeToRemoteBranch:remoteTrackingBranch error:&error]; + expect(uniqueLocalCommits).toNot(beNil()); expect(error).to(beNil()); + expect(@(uniqueLocalCommits.count)).to(equal(@3)); }); }); From 2d989bc787634dda690ef23903a7c2dc0df5e2d3 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Thu, 16 Jul 2015 20:59:26 -0600 Subject: [PATCH 31/47] Asserts and error feedback --- ObjectiveGit/GTRepository+Pull.m | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 28763b097..6ff7a9381 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -14,6 +14,8 @@ #import "GTReference.h" #import "GTRepository+Committing.h" #import "GTRepository+RemoteOperations.h" +#import "NSError+Git.h" +#import "git2/errors.h" @implementation GTRepository (Pull) @@ -87,10 +89,14 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: NSString *message = [NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName]; NSArray *parents = @[ localCommit, remoteCommit ]; GTCommit *mergeCommit = [repo createCommitWithTree:remoteTree message:message parents:parents updatingReferenceNamed:localBranch.name error:error]; + if (!mergeCommit) { + return NO; + } - [self checkoutReference:localBranch.reference strategy:GTCheckoutStrategyForce error:error progressBlock:nil]; + // TODO: Detect merge conflict - return mergeCommit != nil; + BOOL success = [self checkoutReference:localBranch.reference strategy:GTCheckoutStrategyForce error:error progressBlock:nil]; + return success; } return NO; @@ -98,16 +104,29 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: - (BOOL)analyseMerge:(GTMergeAnalysis *)analysis fromBranch:(GTBranch *)fromBranch error:(NSError **)error { - git_merge_preference_t preference = GIT_MERGE_PREFERENCE_NONE; - git_annotated_commit *annotatedCommit; + NSParameterAssert(analysis != NULL); + NSParameterAssert(fromBranch != nil); GTCommit *fromCommit = [fromBranch targetCommitWithError:error]; if (!fromCommit) { return NO; } + git_annotated_commit *annotatedCommit; + + // TODO: Check for lookup error git_annotated_commit_lookup(&annotatedCommit, self.git_repository, fromCommit.OID.git_oid); - git_merge_analysis((git_merge_analysis_t *)analysis, &preference, self.git_repository, (const git_annotated_commit **) &annotatedCommit, 1); + + git_merge_preference_t preference = GIT_MERGE_PREFERENCE_NONE; + + // Merge analysis + int gitError = git_merge_analysis((git_merge_analysis_t *)analysis, &preference, self.git_repository, (const git_annotated_commit **) &annotatedCommit, 1); + if (gitError != GIT_OK) { + if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to analyze merge"]; + return NO; + } + + // Cleanup git_annotated_commit_free(annotatedCommit); return YES; From 12a173c95b2caec153c0be653e979f1bc609ae60 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Thu, 16 Jul 2015 21:00:50 -0600 Subject: [PATCH 32/47] Add libgit2 folder reference to workspace So that Xcode knows where the source is when debugging into libgit2 --- ObjectiveGitFramework.xcworkspace/contents.xcworkspacedata | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ObjectiveGitFramework.xcworkspace/contents.xcworkspacedata b/ObjectiveGitFramework.xcworkspace/contents.xcworkspacedata index 522f3ee5b..f9725c4b5 100644 --- a/ObjectiveGitFramework.xcworkspace/contents.xcworkspacedata +++ b/ObjectiveGitFramework.xcworkspace/contents.xcworkspacedata @@ -4,6 +4,9 @@ + + From f2c6ea3570946b8065796fc62c16a3fcc060ee6d Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Fri, 17 Jul 2015 22:02:21 -0600 Subject: [PATCH 33/47] Ensure all non-happy paths return error info --- ObjectiveGit/GTRepository+Pull.m | 34 +++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 6ff7a9381..78e6fbb16 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -32,17 +32,23 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: return NO; } - // Get remote branch after fetch so that it is up-to-date and doesn't need to be refreshed from disk - GTBranch *remoteBranch; + // Get tracking branch after fetch so that it is up-to-date and doesn't need to be refreshed from disk + GTBranch *trackingBranch; if (branch.branchType == GTBranchTypeLocal) { - BOOL success; - remoteBranch = [branch trackingBranchWithError:error success:&success]; - if (!remoteBranch) { + BOOL success = NO; + trackingBranch = [branch trackingBranchWithError:error success:&success]; + if (!success) { + if (error != NULL) *error = [NSError git_errorFor:GIT_ERROR description:@"Tracking branch not found for %@", branch.name]; + return NO; + } + else if (!trackingBranch) { + // Error should already be provided by libgit2 return NO; } } else { - remoteBranch = branch; + // When given a remote branch, use it as the tracking branch + trackingBranch = branch; } // Check if merge is necessary @@ -56,7 +62,7 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: return NO; } - GTCommit *remoteCommit = [remoteBranch targetCommitWithError:error]; + GTCommit *remoteCommit = [trackingBranch targetCommitWithError:error]; if (!remoteCommit) { return NO; } @@ -67,7 +73,7 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: } GTMergeAnalysis analysis = GTMergeAnalysisNone; - BOOL success = [self analyseMerge:&analysis fromBranch:remoteBranch error:error]; + BOOL success = [self analyseMerge:&analysis fromBranch:trackingBranch error:error]; if (!success) { return NO; } @@ -78,7 +84,7 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: } else if (analysis & GTMergeAnalysisFastForward || analysis & GTMergeAnalysisUnborn) { // Fast-forward branch - NSString *message = [NSString stringWithFormat:@"merge %@/%@: Fast-forward", remote.name, remoteBranch.name]; + NSString *message = [NSString stringWithFormat:@"merge %@/%@: Fast-forward", remote.name, trackingBranch.name]; GTReference *reference = [localBranch.reference referenceByUpdatingTarget:remoteCommit.SHA message:message error:error]; BOOL checkoutSuccess = [self checkoutReference:reference strategy:GTCheckoutStrategyForce error:error progressBlock:nil]; @@ -114,13 +120,17 @@ - (BOOL)analyseMerge:(GTMergeAnalysis *)analysis fromBranch:(GTBranch *)fromBran git_annotated_commit *annotatedCommit; - // TODO: Check for lookup error - git_annotated_commit_lookup(&annotatedCommit, self.git_repository, fromCommit.OID.git_oid); + int gitError = git_annotated_commit_lookup(&annotatedCommit, self.git_repository, fromCommit.OID.git_oid); + if (gitError != GIT_OK) { + if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to lookup annotated comit for %@", fromCommit]; + return NO; + } + // Allow fast-forward or normal merge git_merge_preference_t preference = GIT_MERGE_PREFERENCE_NONE; // Merge analysis - int gitError = git_merge_analysis((git_merge_analysis_t *)analysis, &preference, self.git_repository, (const git_annotated_commit **) &annotatedCommit, 1); + gitError = git_merge_analysis((git_merge_analysis_t *)analysis, &preference, self.git_repository, (const git_annotated_commit **) &annotatedCommit, 1); if (gitError != GIT_OK) { if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Failed to analyze merge"]; return NO; From e18935e0b15467bf020c5cc84a10c7792e3f01ac Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Fri, 17 Jul 2015 22:19:01 -0600 Subject: [PATCH 34/47] Fix createCommitInRepository to reuse tree from HEAD --- ObjectiveGitTests/GTUtilityFunctions.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ObjectiveGitTests/GTUtilityFunctions.m b/ObjectiveGitTests/GTUtilityFunctions.m index 25e3aedd5..95889e6de 100644 --- a/ObjectiveGitTests/GTUtilityFunctions.m +++ b/ObjectiveGitTests/GTUtilityFunctions.m @@ -15,7 +15,11 @@ #pragma mark - Commit CreateCommitBlock createCommitInRepository = ^ GTCommit * (NSString *message, NSData *fileData, NSString *fileName, GTRepository *repo) { - GTTreeBuilder *treeBuilder = [[GTTreeBuilder alloc] initWithTree:nil repository:repo error:nil]; + GTReference *head = [repo headReferenceWithError:NULL]; + GTBranch *branch = [GTBranch branchWithReference:head repository:repo]; + GTCommit *headCommit = [branch targetCommitWithError:NULL]; + + GTTreeBuilder *treeBuilder = [[GTTreeBuilder alloc] initWithTree:headCommit.tree repository:repo error:nil]; [treeBuilder addEntryWithData:fileData fileName:fileName fileMode:GTFileModeBlob error:nil]; GTTree *testTree = [treeBuilder writeTree:nil]; From 878d2c3c806e2781bffeca40ff71b0a63ce0ae8e Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Sat, 18 Jul 2015 12:39:53 -0600 Subject: [PATCH 35/47] Check for conflicts after merging trees --- ObjectiveGit/GTRepository+Pull.m | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 78e6fbb16..950852bf8 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -9,11 +9,13 @@ #import "GTRepository+Pull.h" #import "GTCommit.h" +#import "GTIndex.h" #import "GTOID.h" #import "GTRemote.h" #import "GTReference.h" #import "GTRepository+Committing.h" #import "GTRepository+RemoteOperations.h" +#import "GTTree.h" #import "NSError+Git.h" #import "git2/errors.h" @@ -91,16 +93,35 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: return checkoutSuccess; } else if (analysis & GTMergeAnalysisNormal) { // Do normal merge + GTTree *localTree = localCommit.tree; GTTree *remoteTree = remoteCommit.tree; + + // TODO: Find common ancestor + GTTree *ancestorTree = nil; + + // Merge + GTIndex *index = [localTree merge:remoteTree ancestor:ancestorTree error:error]; + if (!index) { + return NO; + } + + // Check for conflict + int gitError = git_index_has_conflicts(index.git_index); + if (gitError != GIT_OK) { + if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Merge conflict, pull aborted"]; + return NO; + } + + // Create merge commit NSString *message = [NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName]; NSArray *parents = @[ localCommit, remoteCommit ]; + + // FIXME: This is stepping on the local tree GTCommit *mergeCommit = [repo createCommitWithTree:remoteTree message:message parents:parents updatingReferenceNamed:localBranch.name error:error]; if (!mergeCommit) { return NO; } - // TODO: Detect merge conflict - BOOL success = [self checkoutReference:localBranch.reference strategy:GTCheckoutStrategyForce error:error progressBlock:nil]; return success; } From 3e69a1c364c08021c6b9da0dd0e1113d3d35916a Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Sat, 18 Jul 2015 12:41:41 -0600 Subject: [PATCH 36/47] Use hasConflicts --- ObjectiveGit/GTRepository+Pull.m | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 950852bf8..704f7e820 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -106,9 +106,8 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: } // Check for conflict - int gitError = git_index_has_conflicts(index.git_index); - if (gitError != GIT_OK) { - if (error != NULL) *error = [NSError git_errorFor:gitError description:@"Merge conflict, pull aborted"]; + if (index.hasConflicts) { + if (error != NULL) *error = [NSError git_errorFor:GIT_ECONFLICT description:@"Merge conflict, pull aborted"]; return NO; } From e8b2aca7e67b2622d316d49fd9939f3db7255ee2 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Sat, 18 Jul 2015 12:52:02 -0600 Subject: [PATCH 37/47] Write merge tree to repo --- ObjectiveGit/GTRepository+Pull.m | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 704f7e820..983c1e630 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -28,7 +28,7 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: NSParameterAssert(branch); NSParameterAssert(remote); - GTRepository *repo = remote.repository; + GTRepository *repo = branch.repository; if (![self fetchRemote:remote withOptions:options error:error progress:progressBlock]) { return NO; @@ -111,12 +111,17 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: return NO; } + GTTree *newTree = [index writeTreeToRepository:repo error:error]; + if (!newTree) { + return NO; + } + // Create merge commit NSString *message = [NSString stringWithFormat:@"Merge branch '%@'", localBranch.shortName]; NSArray *parents = @[ localCommit, remoteCommit ]; // FIXME: This is stepping on the local tree - GTCommit *mergeCommit = [repo createCommitWithTree:remoteTree message:message parents:parents updatingReferenceNamed:localBranch.name error:error]; + GTCommit *mergeCommit = [repo createCommitWithTree:newTree message:message parents:parents updatingReferenceNamed:localBranch.name error:error]; if (!mergeCommit) { return NO; } From 31b39c77050b2c7556d455819d4ad1aa3410fb1b Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Sat, 18 Jul 2015 13:04:01 -0600 Subject: [PATCH 38/47] Add test for merge conflict --- ObjectiveGitTests/GTRepository+PullSpec.m | 29 ++++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/ObjectiveGitTests/GTRepository+PullSpec.m b/ObjectiveGitTests/GTRepository+PullSpec.m index 3c58d5346..21c36785f 100644 --- a/ObjectiveGitTests/GTRepository+PullSpec.m +++ b/ObjectiveGitTests/GTRepository+PullSpec.m @@ -65,10 +65,8 @@ }); afterEach(^{ - [NSFileManager.defaultManager removeItemAtURL:remoteRepoURL error:&error]; - expect(error).to(beNil()); - [NSFileManager.defaultManager removeItemAtURL:localRepoURL error:&error]; - expect(error).to(beNil()); + [NSFileManager.defaultManager removeItemAtURL:remoteRepoURL error:NULL]; + [NSFileManager.defaultManager removeItemAtURL:localRepoURL error:NULL]; error = NULL; [self tearDown]; }); @@ -221,13 +219,12 @@ // Pull __block BOOL transferProgressed = NO; - // FIXME: This is analyzing merge as "up-to-date" BOOL result = [localRepo pullBranch:masterBranch fromRemote:remote withOptions:nil error:&error progress:^(const git_transfer_progress *progress, BOOL *stop) { transferProgressed = YES; }]; expect(@(result)).to(beTruthy()); expect(error).to(beNil()); - expect(@(transferProgressed)).to(beTruthy()); // TODO: This one works? + expect(@(transferProgressed)).to(beTruthy()); // Validate @@ -242,6 +239,26 @@ expect(@(uniqueLocalCommits.count)).to(equal(@3)); }); + /// Conflict During Merge + it(@"erupts in a ball of 🔥 with a merge conflict ", ^{ + // Stage a conflict by adding the same file with different contents to both repos + GTCommit *localCommit = createCommitInRepository(@"Local commit", [@"TestLocal" dataUsingEncoding:NSUTF8StringEncoding], @"test.txt", localRepo); + expect(localCommit).notTo(beNil()); + GTCommit *remoteCommit = createCommitInRepository(@"Upstream commit", [@"TestUpstream" dataUsingEncoding:NSUTF8StringEncoding], @"test.txt", remoteRepo); + expect(remoteCommit).notTo(beNil()); + + GTBranch *masterBranch = localBranchWithName(@"master", localRepo); + + // Pull + __block BOOL transferProgressed = NO; + BOOL result = [localRepo pullBranch:masterBranch fromRemote:remote withOptions:nil error:&error progress:^(const git_transfer_progress *progress, BOOL *stop) { + transferProgressed = YES; + }]; + expect(@(result)).to(beFalsy()); + expect(error).toNot(beNil()); + expect(@(transferProgressed)).to(beTruthy()); + }); + }); }); From ff601a689585ac599f4e7e8e4328ff761a6ef568 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Sat, 18 Jul 2015 13:34:36 -0600 Subject: [PATCH 39/47] Tabs --- ObjectiveGitTests/GTRepository+PullSpec.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ObjectiveGitTests/GTRepository+PullSpec.m b/ObjectiveGitTests/GTRepository+PullSpec.m index 21c36785f..547b19946 100644 --- a/ObjectiveGitTests/GTRepository+PullSpec.m +++ b/ObjectiveGitTests/GTRepository+PullSpec.m @@ -218,7 +218,7 @@ expect(@(uniqueLocalCommits.count)).to(equal(@1)); // Pull - __block BOOL transferProgressed = NO; + __block BOOL transferProgressed = NO; BOOL result = [localRepo pullBranch:masterBranch fromRemote:remote withOptions:nil error:&error progress:^(const git_transfer_progress *progress, BOOL *stop) { transferProgressed = YES; }]; @@ -245,9 +245,9 @@ GTCommit *localCommit = createCommitInRepository(@"Local commit", [@"TestLocal" dataUsingEncoding:NSUTF8StringEncoding], @"test.txt", localRepo); expect(localCommit).notTo(beNil()); GTCommit *remoteCommit = createCommitInRepository(@"Upstream commit", [@"TestUpstream" dataUsingEncoding:NSUTF8StringEncoding], @"test.txt", remoteRepo); - expect(remoteCommit).notTo(beNil()); + expect(remoteCommit).notTo(beNil()); - GTBranch *masterBranch = localBranchWithName(@"master", localRepo); + GTBranch *masterBranch = localBranchWithName(@"master", localRepo); // Pull __block BOOL transferProgressed = NO; From 2333aaa38cca2fdc6e262ab45ec55ca4779c4caa Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Wed, 22 Jul 2015 19:26:56 -0600 Subject: [PATCH 40/47] Analyse -> Analyze --- ObjectiveGit/GTRepository+Pull.h | 4 ++-- ObjectiveGit/GTRepository+Pull.m | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.h b/ObjectiveGit/GTRepository+Pull.h index 184e473c1..510716270 100644 --- a/ObjectiveGit/GTRepository+Pull.h +++ b/ObjectiveGit/GTRepository+Pull.h @@ -41,7 +41,7 @@ typedef void (^GTRemoteFetchTransferProgressBlock)(const git_transfer_progress * /// will point to an error describing what happened). - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions:(nullable NSDictionary *)options error:(NSError **)error progress:(nullable GTRemoteFetchTransferProgressBlock)progressBlock; -/// Analyse which merge to perform +/// Analyze which merge to perform /// /// analysis - The resulting analysis. /// fromBranch - The remote to pull from. @@ -49,7 +49,7 @@ typedef void (^GTRemoteFetchTransferProgressBlock)(const git_transfer_progress * /// /// Returns YES if the analysis was successful, NO otherwise (and `error`, if provided, /// will point to an error describing what happened). -- (BOOL)analyseMerge:(GTMergeAnalysis *)analysis fromBranch:(GTBranch *)fromBranch error:(NSError **)error; +- (BOOL)analyzeMerge:(GTMergeAnalysis *)analysis fromBranch:(GTBranch *)fromBranch error:(NSError **)error; @end diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 983c1e630..dffc8ba56 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -75,7 +75,7 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: } GTMergeAnalysis analysis = GTMergeAnalysisNone; - BOOL success = [self analyseMerge:&analysis fromBranch:trackingBranch error:error]; + BOOL success = [self analyzeMerge:&analysis fromBranch:trackingBranch error:error]; if (!success) { return NO; } @@ -133,7 +133,7 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: return NO; } -- (BOOL)analyseMerge:(GTMergeAnalysis *)analysis fromBranch:(GTBranch *)fromBranch error:(NSError **)error +- (BOOL)analyzeMerge:(GTMergeAnalysis *)analysis fromBranch:(GTBranch *)fromBranch error:(NSError **)error { NSParameterAssert(analysis != NULL); NSParameterAssert(fromBranch != nil); From f167004893241f27a647c343dd5ada81a8c46227 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Wed, 22 Jul 2015 19:28:51 -0600 Subject: [PATCH 41/47] Dial down the indentation --- ObjectiveGit/GTRepository+Pull.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.h b/ObjectiveGit/GTRepository+Pull.h index 510716270..30146e7cd 100644 --- a/ObjectiveGit/GTRepository+Pull.h +++ b/ObjectiveGit/GTRepository+Pull.h @@ -43,9 +43,9 @@ typedef void (^GTRemoteFetchTransferProgressBlock)(const git_transfer_progress * /// Analyze which merge to perform /// -/// analysis - The resulting analysis. -/// fromBranch - The remote to pull from. -/// error - The error if one occurred. Can be NULL. +/// analysis - The resulting analysis. +/// fromBranch - The remote to pull from. +/// error - The error if one occurred. Can be NULL. /// /// Returns YES if the analysis was successful, NO otherwise (and `error`, if provided, /// will point to an error describing what happened). From d8bf6c2af68b6b658e06b577029a6cb5be128b1d Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Wed, 22 Jul 2015 19:31:30 -0600 Subject: [PATCH 42/47] Doc revision --- ObjectiveGit/GTRepository+Pull.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.h b/ObjectiveGit/GTRepository+Pull.h index 30146e7cd..463e52cdd 100644 --- a/ObjectiveGit/GTRepository+Pull.h +++ b/ObjectiveGit/GTRepository+Pull.h @@ -41,10 +41,10 @@ typedef void (^GTRemoteFetchTransferProgressBlock)(const git_transfer_progress * /// will point to an error describing what happened). - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions:(nullable NSDictionary *)options error:(NSError **)error progress:(nullable GTRemoteFetchTransferProgressBlock)progressBlock; -/// Analyze which merge to perform +/// Analyze which merge to perform. /// /// analysis - The resulting analysis. -/// fromBranch - The remote to pull from. +/// fromBranch - The branch to merge from. /// error - The error if one occurred. Can be NULL. /// /// Returns YES if the analysis was successful, NO otherwise (and `error`, if provided, From 1dd20bae0883146910bac10a67f54d2688cabab9 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Wed, 22 Jul 2015 19:33:24 -0600 Subject: [PATCH 43/47] Fix curly braces --- ObjectiveGit/GTRepository+Pull.m | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index dffc8ba56..341b146e5 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -23,8 +23,7 @@ @implementation GTRepository (Pull) #pragma mark - Pull -- (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions:(NSDictionary *)options error:(NSError **)error progress:(GTRemoteFetchTransferProgressBlock)progressBlock -{ +- (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions:(NSDictionary *)options error:(NSError **)error progress:(GTRemoteFetchTransferProgressBlock)progressBlock { NSParameterAssert(branch); NSParameterAssert(remote); @@ -133,8 +132,7 @@ - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions: return NO; } -- (BOOL)analyzeMerge:(GTMergeAnalysis *)analysis fromBranch:(GTBranch *)fromBranch error:(NSError **)error -{ +- (BOOL)analyzeMerge:(GTMergeAnalysis *)analysis fromBranch:(GTBranch *)fromBranch error:(NSError **)error { NSParameterAssert(analysis != NULL); NSParameterAssert(fromBranch != nil); From 6b4d2e003ec418b6dc80ec20abf33f3cd41c5f10 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Wed, 22 Jul 2015 19:34:55 -0600 Subject: [PATCH 44/47] Explicit comparison to nil --- ObjectiveGit/GTRepository+Pull.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ObjectiveGit/GTRepository+Pull.m b/ObjectiveGit/GTRepository+Pull.m index 341b146e5..24bbb3e2d 100644 --- a/ObjectiveGit/GTRepository+Pull.m +++ b/ObjectiveGit/GTRepository+Pull.m @@ -24,8 +24,8 @@ @implementation GTRepository (Pull) #pragma mark - Pull - (BOOL)pullBranch:(GTBranch *)branch fromRemote:(GTRemote *)remote withOptions:(NSDictionary *)options error:(NSError **)error progress:(GTRemoteFetchTransferProgressBlock)progressBlock { - NSParameterAssert(branch); - NSParameterAssert(remote); + NSParameterAssert(branch != nil); + NSParameterAssert(remote != nil); GTRepository *repo = branch.repository; From 04f1c4c0724ce9fefaec43d0edaaa72cc265645b Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 9 Aug 2015 10:26:03 -0600 Subject: [PATCH 45/47] =?UTF-8?q?=F0=9F=94=A5=20the=20emoji=20from=20examp?= =?UTF-8?q?le=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ObjectiveGitTests/GTRepository+PullSpec.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ObjectiveGitTests/GTRepository+PullSpec.m b/ObjectiveGitTests/GTRepository+PullSpec.m index 547b19946..82bd9a419 100644 --- a/ObjectiveGitTests/GTRepository+PullSpec.m +++ b/ObjectiveGitTests/GTRepository+PullSpec.m @@ -240,7 +240,7 @@ }); /// Conflict During Merge - it(@"erupts in a ball of 🔥 with a merge conflict ", ^{ + it(@"fails to merge whene there is a conflict", ^{ // Stage a conflict by adding the same file with different contents to both repos GTCommit *localCommit = createCommitInRepository(@"Local commit", [@"TestLocal" dataUsingEncoding:NSUTF8StringEncoding], @"test.txt", localRepo); expect(localCommit).notTo(beNil()); From 6dbc38f8a7986beb593db129290edacc93ff551c Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 9 Aug 2015 16:40:34 -0600 Subject: [PATCH 46/47] whene -> when --- ObjectiveGitTests/GTRepository+PullSpec.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ObjectiveGitTests/GTRepository+PullSpec.m b/ObjectiveGitTests/GTRepository+PullSpec.m index 82bd9a419..67798beba 100644 --- a/ObjectiveGitTests/GTRepository+PullSpec.m +++ b/ObjectiveGitTests/GTRepository+PullSpec.m @@ -240,7 +240,7 @@ }); /// Conflict During Merge - it(@"fails to merge whene there is a conflict", ^{ + it(@"fails to merge when there is a conflict", ^{ // Stage a conflict by adding the same file with different contents to both repos GTCommit *localCommit = createCommitInRepository(@"Local commit", [@"TestLocal" dataUsingEncoding:NSUTF8StringEncoding], @"test.txt", localRepo); expect(localCommit).notTo(beNil()); From 4feb8c632eff35d851af1b08cf556c8921908ad0 Mon Sep 17 00:00:00 2001 From: Ben Chatelain Date: Mon, 24 Aug 2015 09:28:36 -0600 Subject: [PATCH 47/47] Comment out pending test --- ObjectiveGitTests/GTRepository+PullSpec.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ObjectiveGitTests/GTRepository+PullSpec.m b/ObjectiveGitTests/GTRepository+PullSpec.m index 67798beba..6c4dd3b78 100644 --- a/ObjectiveGitTests/GTRepository+PullSpec.m +++ b/ObjectiveGitTests/GTRepository+PullSpec.m @@ -94,6 +94,7 @@ }); }); +/* pending tests break build on travis /// Unborn /// Can't get a GTBranch reference wrapping HEAD when its symref is unborn pending(@"into an empty repo", ^{ @@ -136,6 +137,7 @@ // expect(head).toNot(beNil()); }); +*/ /// Fast-Forward Merge ///