1
1
using System ;
2
2
using System . Collections . Generic ;
3
+ using System . Diagnostics ;
3
4
using System . Linq ;
4
5
using System . Text ;
5
6
using LibGit2Sharp . Core ;
@@ -17,11 +18,13 @@ internal class RebaseOperationImpl
17
18
/// <param name="repository">Repository in which rebase operation is being run.</param>
18
19
/// <param name="committer">Committer signature to use for the rebased commits.</param>
19
20
/// <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>
20
22
/// <returns>RebaseResult - describing the result of the rebase operation.</returns>
21
23
public static RebaseResult Run ( RebaseSafeHandle rebaseOperationHandle ,
22
24
Repository repository ,
23
25
Signature committer ,
24
- RebaseOptions options )
26
+ RebaseOptions options ,
27
+ bool isStarting )
25
28
{
26
29
Ensure . ArgumentNotNull ( rebaseOperationHandle , "rebaseOperationHandle" ) ;
27
30
Ensure . ArgumentNotNull ( repository , "repository" ) ;
@@ -34,88 +37,128 @@ public static RebaseResult Run(RebaseSafeHandle rebaseOperationHandle,
34
37
35
38
try
36
39
{
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
+ }
38
48
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 )
40
57
{
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 ) ;
42
65
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 ) ;
45
74
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 )
47
80
{
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." ) ;
61
83
}
62
- else
84
+
85
+ // Handle the result
86
+ switch ( rebaseOp . type )
63
87
{
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 ) ;
82
93
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 )
85
98
{
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 ) ) ) ) ;
94
104
}
95
105
}
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 ;
117
138
}
118
139
}
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
+ }
119
162
}
120
163
finally
121
164
{
0 commit comments