11using System ;
22using System . Collections . Generic ;
3+ using System . Diagnostics ;
34using System . Linq ;
45using System . Text ;
56using LibGit2Sharp . Core ;
@@ -17,11 +18,13 @@ internal class RebaseOperationImpl
1718 /// <param name="repository">Repository in which rebase operation is being run.</param>
1819 /// <param name="committer">Committer signature to use for the rebased commits.</param>
1920 /// <param name="options">Options controlling rebase behavior.</param>
21+ /// <param name="isStarting">flag to indicate if this is being called as part of starting a rebase sequence.</param>
2022 /// <returns>RebaseResult - describing the result of the rebase operation.</returns>
2123 public static RebaseResult Run ( RebaseSafeHandle rebaseOperationHandle ,
2224 Repository repository ,
2325 Signature committer ,
24- RebaseOptions options )
26+ RebaseOptions options ,
27+ bool isStarting )
2528 {
2629 Ensure . ArgumentNotNull ( rebaseOperationHandle , "rebaseOperationHandle" ) ;
2730 Ensure . ArgumentNotNull ( repository , "repository" ) ;
@@ -34,88 +37,128 @@ public static RebaseResult Run(RebaseSafeHandle rebaseOperationHandle,
3437
3538 try
3639 {
37- GitRebaseOperation rebaseOperationReport = null ;
40+ // stepBeingApplied indicates the step that will be applied by by git_rebase_next.
41+ // The current step does not get incremented until git_rebase_next (except on
42+ // the initial step), but we want to report the step that will be applied.
43+ long stepBeingApplied = Proxy . git_rebase_operation_current ( rebaseOperationHandle ) ;
44+ if ( ! isStarting )
45+ {
46+ stepBeingApplied ++ ;
47+ }
3848
39- while ( rebaseResult == null )
49+ long totalStepCount = Proxy . git_rebase_operation_entrycount ( rebaseOperationHandle ) ;
50+
51+ // This loop will run until either:
52+ // 1) All steps have been run or
53+ // 2) rebaseResult is set - indicating that the current
54+ // sequence should be stopped and a result needs to be
55+ // reported.
56+ while ( stepBeingApplied < totalStepCount )
4057 {
41- rebaseOperationReport = Proxy . git_rebase_next ( rebaseOperationHandle , ref gitCheckoutOpts ) ;
58+ GitRebaseOperation rebaseOp = Proxy . git_rebase_operation_byindex ( rebaseOperationHandle , stepBeingApplied ) ;
59+ ObjectId idOfCommitBeingRebased = new ObjectId ( rebaseOp . id ) ;
60+ RebaseStepInfo stepInfo = new RebaseStepInfo ( rebaseOp . type ,
61+ repository . Lookup < Commit > ( idOfCommitBeingRebased ) ,
62+ LaxUtf8NoCleanupMarshaler . FromNative ( rebaseOp . exec ) ,
63+ stepBeingApplied ,
64+ totalStepCount ) ;
4265
43- long currentStepIndex = Proxy . git_rebase_operation_current ( rebaseOperationHandle ) ;
44- long totalStepCount = Proxy . git_rebase_operation_entrycount ( rebaseOperationHandle ) ;
66+ // Report the rebase step we are about to perform.
67+ if ( options . RebaseStepStarting != null )
68+ {
69+ options . RebaseStepStarting ( new BeforeRebaseStepInfo ( stepInfo ) ) ;
70+ }
71+
72+ // Perform the rebase step
73+ GitRebaseOperation rebaseOpReport = Proxy . git_rebase_next ( rebaseOperationHandle , ref gitCheckoutOpts ) ;
4574
46- if ( rebaseOperationReport == null )
75+ // The step reported via querying by index and the step returned from git_rebase_next
76+ // should be the same
77+ if ( rebaseOpReport == null ||
78+ new ObjectId ( rebaseOpReport . id ) != idOfCommitBeingRebased ||
79+ rebaseOpReport . type != rebaseOp . type )
4780 {
48- GitRebaseOptions gitRebaseOptions = new GitRebaseOptions ( )
49- {
50- version = 1 ,
51- } ;
52-
53- // Rebase is completed!
54- // currentStep is the last completed - increment it to account
55- // for the fact that we have moved past last step index.
56- Proxy . git_rebase_finish ( rebaseOperationHandle , committer , gitRebaseOptions ) ;
57- rebaseResult = new RebaseResult ( RebaseStatus . Complete ,
58- currentStepIndex + 1 ,
59- totalStepCount ,
60- null ) ;
81+ // This is indicative of a program error - should never happen.
82+ throw new LibGit2SharpException ( "Unexpected step info reported by running rebase step." ) ;
6183 }
62- else
84+
85+ // Handle the result
86+ switch ( rebaseOp . type )
6387 {
64- RebaseStepInfo stepInfo = new RebaseStepInfo ( rebaseOperationReport . type ,
65- repository . Lookup < Commit > ( new ObjectId ( rebaseOperationReport . id ) ) ,
66- LaxUtf8NoCleanupMarshaler . FromNative ( rebaseOperationReport . exec ) ,
67- currentStepIndex ,
68- totalStepCount ) ;
69-
70- if ( options . RebaseStepStarting != null )
71- {
72- options . RebaseStepStarting ( new BeforeRebaseStepInfo ( stepInfo ) ) ;
73- }
74-
75- switch ( rebaseOperationReport . type )
76- {
77- case RebaseStepOperation . Pick :
78- // commit and continue.
79- if ( repository . Index . IsFullyMerged )
80- {
81- Proxy . GitRebaseCommitResult rebase_commit_result = Proxy . git_rebase_commit ( rebaseOperationHandle , null , committer ) ;
88+ case RebaseStepOperation . Pick :
89+ // commit and continue.
90+ if ( repository . Index . IsFullyMerged )
91+ {
92+ Proxy . GitRebaseCommitResult rebase_commit_result = Proxy . git_rebase_commit ( rebaseOperationHandle , null , committer ) ;
8293
83- // Report that we just completed the step
84- if ( options . RebaseStepCompleted != null )
94+ // Report that we just completed the step
95+ if ( options . RebaseStepCompleted != null )
96+ {
97+ if ( rebase_commit_result . WasPatchAlreadyApplied )
8598 {
86- if ( rebase_commit_result . WasPatchAlreadyApplied )
87- {
88- options . RebaseStepCompleted ( new AfterRebaseStepInfo ( stepInfo ) ) ;
89- }
90- else
91- {
92- options . RebaseStepCompleted ( new AfterRebaseStepInfo ( stepInfo , repository . Lookup < Commit > ( new ObjectId ( rebase_commit_result . CommitId ) ) ) ) ;
93- }
99+ options . RebaseStepCompleted ( new AfterRebaseStepInfo ( stepInfo ) ) ;
100+ }
101+ else
102+ {
103+ options . RebaseStepCompleted ( new AfterRebaseStepInfo ( stepInfo , repository . Lookup < Commit > ( new ObjectId ( rebase_commit_result . CommitId ) ) ) ) ;
94104 }
95105 }
96- else
97- {
98- rebaseResult = new RebaseResult ( RebaseStatus . Conflicts ,
99- currentStepIndex ,
100- totalStepCount ,
101- null ) ;
102- }
103- break ;
104- case RebaseStepOperation . Squash :
105- case RebaseStepOperation . Edit :
106- case RebaseStepOperation . Exec :
107- case RebaseStepOperation . Fixup :
108- case RebaseStepOperation . Reword :
109- // These operations are not yet supported by the library.
110- throw new LibGit2SharpException ( string . Format (
111- "Rebase Operation Type ({0}) is not currently supported in LibGit2Sharp." ,
112- rebaseOperationReport . type ) ) ;
113- default :
114- throw new ArgumentException ( string . Format (
115- "Unexpected Rebase Operation Type: {0}" , rebaseOperationReport . type ) ) ;
116- }
106+ }
107+ else
108+ {
109+ rebaseResult = new RebaseResult ( RebaseStatus . Conflicts ,
110+ stepBeingApplied ,
111+ totalStepCount ,
112+ null ) ;
113+ }
114+ break ;
115+ case RebaseStepOperation . Squash :
116+ case RebaseStepOperation . Edit :
117+ case RebaseStepOperation . Exec :
118+ case RebaseStepOperation . Fixup :
119+ case RebaseStepOperation . Reword :
120+ // These operations are not yet supported by lg2.
121+ throw new LibGit2SharpException ( string . Format (
122+ "Rebase Operation Type ({0}) is not currently supported in LibGit2Sharp." ,
123+ rebaseOp . type ) ) ;
124+ default :
125+ throw new ArgumentException ( string . Format (
126+ "Unexpected Rebase Operation Type: {0}" , rebaseOp . type ) ) ;
127+ }
128+
129+ // If we have not generated a result that needs to be
130+ // reported, move to the next step.
131+ if ( rebaseResult == null )
132+ {
133+ stepBeingApplied ++ ;
134+ }
135+ else
136+ {
137+ break ;
117138 }
118139 }
140+
141+ // If the step being applied is equal to the total step count,
142+ // that means all steps have been run and we are finished.
143+ if ( stepBeingApplied == totalStepCount )
144+ {
145+ Debug . Assert ( rebaseResult == null ) ;
146+
147+ // Done!
148+ GitRebaseOptions gitRebaseOptions = new GitRebaseOptions ( )
149+ {
150+ version = 1 ,
151+ } ;
152+
153+ // Rebase is completed!
154+ // currentStep is the last completed - increment it to account
155+ // for the fact that we have moved past last step index.
156+ Proxy . git_rebase_finish ( rebaseOperationHandle , committer , gitRebaseOptions ) ;
157+ rebaseResult = new RebaseResult ( RebaseStatus . Complete ,
158+ totalStepCount ,
159+ totalStepCount ,
160+ null ) ;
161+ }
119162 }
120163 finally
121164 {
0 commit comments