@@ -17,6 +17,7 @@ public class RebaseFixture : BaseFixture
1717 const string topicBranch1Name = "T1" ;
1818 const string topicBranch2Name = "T2" ;
1919 const string conflictBranch1Name = "C1" ;
20+ const string topicBranch1PrimeName = "T1Prime" ;
2021
2122 [ Theory ]
2223 [ InlineData ( topicBranch2Name , topicBranch2Name , topicBranch1Name , masterBranch1Name , 3 ) ]
@@ -50,7 +51,7 @@ public void CanRebase(string initialBranchName,
5051 int afterStepCallCount = 0 ;
5152
5253 List < ObjectId > PreRebaseCommits = new List < ObjectId > ( ) ;
53- List < ObjectId > PostRebaseCommits = new List < ObjectId > ( ) ;
54+ List < CompletedRebaseStepInfo > PostRebaseResults = new List < CompletedRebaseStepInfo > ( ) ;
5455 ObjectId expectedParentId = upstream . Tip . Id ;
5556
5657 RebaseOptions options = new RebaseOptions ( )
@@ -63,7 +64,7 @@ public void CanRebase(string initialBranchName,
6364 RebaseStepCompleted = x =>
6465 {
6566 afterStepCallCount ++ ;
66- PostRebaseCommits . Add ( x . CommitId ) ;
67+ PostRebaseResults . Add ( new CompletedRebaseStepInfo ( x . CommitId , x . WasPatchAlreadyApplied ) ) ;
6768 } ,
6869 } ;
6970
@@ -91,19 +92,61 @@ public void CanRebase(string initialBranchName,
9192
9293 // Verify the chain of commits that resulted from the rebase.
9394 Commit expectedParent = expectedOntoCommit ;
94- foreach ( Commit rebasedCommit in PostRebaseCommits . Select ( id => repo . Lookup < Commit > ( id ) ) )
95+ foreach ( CompletedRebaseStepInfo stepInfo in PostRebaseResults )
9596 {
97+ Commit rebasedCommit = repo . Lookup < Commit > ( stepInfo . ObjectId ) ;
9698 Assert . Equal ( expectedParent . Id , rebasedCommit . Parents . First ( ) . Id ) ;
99+ Assert . False ( stepInfo . WasPatchAlreadyApplied ) ;
97100 expectedParent = rebasedCommit ;
98101 }
99102
100- Assert . Equal ( repo . Head . Tip . Id , PostRebaseCommits . Last ( ) ) ;
103+ Assert . Equal ( repo . Head . Tip . Id , PostRebaseResults . Last ( ) . ObjectId ) ;
101104 }
102105 }
103106
104- private class rebaseStepInfo
107+ private class CompletedRebaseStepInfo
105108 {
106- public Commit Commit { get ; set ; }
109+ public CompletedRebaseStepInfo ( ObjectId objectId , bool wasPatchAlreadyApplied )
110+ {
111+ ObjectId = objectId ;
112+ WasPatchAlreadyApplied = wasPatchAlreadyApplied ;
113+ }
114+
115+ public ObjectId ObjectId { get ; set ; }
116+
117+ public bool WasPatchAlreadyApplied { get ; set ; }
118+ }
119+
120+ private class CompletedRebaseStepInfoEqualityComparer : IEqualityComparer < CompletedRebaseStepInfo >
121+ {
122+ bool IEqualityComparer < CompletedRebaseStepInfo > . Equals ( CompletedRebaseStepInfo x , CompletedRebaseStepInfo y )
123+ {
124+ if ( x == null && y == null )
125+ {
126+ return true ;
127+ }
128+
129+ if ( ( x == null && y != null ) ||
130+ ( x != null && y == null ) )
131+ {
132+ return false ;
133+ }
134+
135+ return x . WasPatchAlreadyApplied == y . WasPatchAlreadyApplied &&
136+ ObjectId . Equals ( x . ObjectId , y . ObjectId ) ;
137+ }
138+
139+ int IEqualityComparer < CompletedRebaseStepInfo > . GetHashCode ( CompletedRebaseStepInfo obj )
140+ {
141+ int hashCode = obj . WasPatchAlreadyApplied . GetHashCode ( ) ;
142+
143+ if ( obj . ObjectId != null )
144+ {
145+ hashCode += obj . ObjectId . GetHashCode ( ) ;
146+ }
147+
148+ return hashCode ;
149+ }
107150 }
108151
109152 /// <summary>
@@ -335,7 +378,7 @@ public void RebaseWhileAlreadyRebasingThrows()
335378
336379 Assert . Throws < LibGit2SharpException > ( ( ) =>
337380 repo . Rebase . Start ( branch , upstream , onto , Constants . Signature , null ) ) ;
338- }
381+ }
339382 }
340383
341384 [ Fact ]
@@ -371,6 +414,57 @@ public void CurrentStepInfoIsNullWhenNotRebasing()
371414 }
372415 }
373416
417+ [ Fact ]
418+ public void CanRebaseHandlePatchAlreadyApplied ( )
419+ {
420+ SelfCleaningDirectory scd = BuildSelfCleaningDirectory ( ) ;
421+ var path = Repository . Init ( scd . DirectoryPath ) ;
422+ using ( Repository repo = new Repository ( path ) )
423+ {
424+ ConstructRebaseTestRepository ( repo ) ;
425+
426+ repo . Checkout ( topicBranch1Name ) ;
427+
428+ Branch topicBranch1Prime = repo . CreateBranch ( topicBranch1PrimeName , masterBranch1Name ) ;
429+
430+ string newFileRelativePath = "new_file.txt" ;
431+ Touch ( repo . Info . WorkingDirectory , newFileRelativePath , "New Content" ) ;
432+ repo . Stage ( newFileRelativePath ) ;
433+ Commit commit = repo . Commit ( "new commit 1" , Constants . Signature , Constants . Signature , new CommitOptions ( ) ) ;
434+
435+ repo . Checkout ( topicBranch1Prime ) ;
436+ var cherryPickResult = repo . CherryPick ( commit , Constants . Signature2 ) ;
437+ Assert . Equal ( CherryPickStatus . CherryPicked , cherryPickResult . Status ) ;
438+
439+ string newFileRelativePath2 = "new_file_2.txt" ;
440+ Touch ( repo . Info . WorkingDirectory , newFileRelativePath2 , "New Content for path 2" ) ;
441+ repo . Stage ( newFileRelativePath2 ) ;
442+ repo . Commit ( "new commit 2" , Constants . Signature , Constants . Signature , new CommitOptions ( ) ) ;
443+
444+ Branch upstreamBranch = repo . Branches [ topicBranch1Name ] ;
445+
446+ List < CompletedRebaseStepInfo > rebaseResults = new List < CompletedRebaseStepInfo > ( ) ;
447+
448+ RebaseOptions options = new RebaseOptions ( )
449+ {
450+ RebaseStepCompleted = x =>
451+ {
452+ rebaseResults . Add ( new CompletedRebaseStepInfo ( x . CommitId , x . WasPatchAlreadyApplied ) ) ;
453+ }
454+ } ;
455+
456+ repo . Rebase . Start ( null , upstreamBranch , null , Constants . Signature2 , options ) ;
457+
458+ List < CompletedRebaseStepInfo > expectedRebaseResults = new List < CompletedRebaseStepInfo > ( )
459+ {
460+ new CompletedRebaseStepInfo ( null , true ) ,
461+ new CompletedRebaseStepInfo ( new ObjectId ( "ebdea37ecf583fb7fa5c806a1c00b82f3987fbaa" ) , false ) ,
462+ } ;
463+
464+ Assert . Equal < CompletedRebaseStepInfo > ( expectedRebaseResults , rebaseResults , new CompletedRebaseStepInfoEqualityComparer ( ) ) ;
465+ }
466+ }
467+
374468 private void ConstructRebaseTestRepository ( Repository repo )
375469 {
376470 // Constructs a graph that looks like:
@@ -425,7 +519,7 @@ private void ConstructRebaseTestRepository(Repository repo)
425519 repo . Stage ( filePathC ) ;
426520 commit = repo . Commit ( "commit 3" , Constants . Signature , Constants . Signature , new CommitOptions ( ) ) ;
427521
428- repo . CreateBranch ( masterBranch1Name , commit , Constants . Signature ) ;
522+ Branch masterBranch1 = repo . CreateBranch ( masterBranch1Name , commit , Constants . Signature ) ;
429523
430524 Touch ( workdir , filePathB , string . Join ( lineEnding , fileContentB1 , fileContentB2 ) ) ;
431525 repo . Stage ( filePathB ) ;
@@ -455,7 +549,7 @@ private void ConstructRebaseTestRepository(Repository repo)
455549
456550 repo . CreateBranch ( topicBranch2Name , commit , Constants . Signature ) ;
457551
458- repo . Checkout ( masterBranch1Name ) ;
552+ repo . Checkout ( masterBranch1 . Tip ) ;
459553 Touch ( workdir , filePathD , fileContentD1 ) ;
460554 repo . Stage ( filePathD ) ;
461555 commit = repo . Commit ( "commit 10" , Constants . Signature , Constants . Signature , new CommitOptions ( ) ) ;
0 commit comments