Skip to content

Commit 833af6a

Browse files
committed
WIP: refactor core rebase loop
1 parent 10a57fc commit 833af6a

File tree

1 file changed

+119
-94
lines changed

1 file changed

+119
-94
lines changed

LibGit2Sharp/RebaseOperationImpl.cs

Lines changed: 119 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ private enum RebaseAction
1414
{
1515
ApplyStep,
1616
Finish,
17-
Finished,
1817
};
1918

2019
/// <summary>
@@ -42,103 +41,123 @@ public static RebaseResult Run(RebaseSafeHandle rebaseOperationHandle,
4241
GitCheckoutOpts gitCheckoutOpts = checkoutOptionsWrapper.Options;
4342
RebaseResult rebaseResult = null;
4443

45-
RebaseAction action;
46-
RebaseStepInfo stepToApplyInfo;
47-
48-
// This loop will run until either:
49-
// 1) All steps have been run or
50-
// 2) rebaseResult is set - indicating that the current
51-
// sequence should be stopped and a result needs to be
52-
// reported.
53-
while ((action = NextRebaseAction(out stepToApplyInfo, repository, rebaseOperationHandle, isStarting)) == RebaseAction.ApplyStep)
44+
// This loop will run until a rebase result has been set.
45+
while (rebaseResult == null)
5446
{
47+
RebaseStepInfo stepToApplyInfo;
48+
RebaseAction action = NextRebaseAction(out stepToApplyInfo, repository, rebaseOperationHandle, isStarting);
5549
isStarting = false;
5650

57-
// Report the rebase step we are about to perform.
58-
if (options.RebaseStepStarting != null)
51+
switch (action)
5952
{
60-
options.RebaseStepStarting(new BeforeRebaseStepInfo(stepToApplyInfo));
53+
case RebaseAction.ApplyStep:
54+
rebaseResult = ApplyRebaseStep(rebaseOperationHandle,
55+
repository,
56+
committer,
57+
options,
58+
ref gitCheckoutOpts,
59+
stepToApplyInfo);
60+
break;
61+
case RebaseAction.Finish:
62+
rebaseResult = FinishRebase(rebaseOperationHandle, committer, rebaseResult);
63+
break;
64+
default:
65+
// If we arrived in this else block, it means there is a programing error.
66+
throw new LibGit2SharpException("Unexpected Next Action. Program error.");
6167
}
68+
}
6269

63-
// Perform the rebase step
64-
GitRebaseOperation rebaseOpReport = Proxy.git_rebase_next(rebaseOperationHandle, ref gitCheckoutOpts);
70+
return rebaseResult;
71+
}
72+
}
6573

66-
VerifyRebaseOp(rebaseOpReport, stepToApplyInfo);
74+
private static RebaseResult FinishRebase(RebaseSafeHandle rebaseOperationHandle, Signature committer, RebaseResult rebaseResult)
75+
{
76+
long totalStepCount = Proxy.git_rebase_operation_entrycount(rebaseOperationHandle);
77+
GitRebaseOptions gitRebaseOptions = new GitRebaseOptions()
78+
{
79+
version = 1,
80+
};
81+
82+
// Rebase is completed!
83+
Proxy.git_rebase_finish(rebaseOperationHandle, committer, gitRebaseOptions);
84+
rebaseResult = new RebaseResult(RebaseStatus.Complete,
85+
totalStepCount,
86+
totalStepCount,
87+
null);
88+
return rebaseResult;
89+
}
6790

68-
// Handle the result
69-
switch (stepToApplyInfo.Type)
70-
{
71-
case RebaseStepOperation.Pick:
72-
// commit and continue.
73-
if (repository.Index.IsFullyMerged)
74-
{
75-
Proxy.GitRebaseCommitResult rebase_commit_result = Proxy.git_rebase_commit(rebaseOperationHandle, null, committer);
76-
77-
// Report that we just completed the step
78-
if (options.RebaseStepCompleted != null)
79-
{
80-
if (rebase_commit_result.WasPatchAlreadyApplied)
81-
{
82-
options.RebaseStepCompleted(new AfterRebaseStepInfo(stepToApplyInfo));
83-
}
84-
else
85-
{
86-
options.RebaseStepCompleted(new AfterRebaseStepInfo(stepToApplyInfo, repository.Lookup<Commit>(new ObjectId(rebase_commit_result.CommitId))));
87-
}
88-
}
89-
}
90-
else
91-
{
92-
rebaseResult = new RebaseResult(RebaseStatus.Conflicts,
93-
stepToApplyInfo.CurrentStep,
94-
stepToApplyInfo.TotalStepCount,
95-
null);
96-
}
97-
break;
98-
case RebaseStepOperation.Squash:
99-
case RebaseStepOperation.Edit:
100-
case RebaseStepOperation.Exec:
101-
case RebaseStepOperation.Fixup:
102-
case RebaseStepOperation.Reword:
103-
// These operations are not yet supported by lg2.
104-
throw new LibGit2SharpException(string.Format(
105-
"Rebase Operation Type ({0}) is not currently supported in LibGit2Sharp.",
106-
stepToApplyInfo.Type));
107-
default:
108-
throw new ArgumentException(string.Format(
109-
"Unexpected Rebase Operation Type: {0}", stepToApplyInfo.Type));
110-
}
91+
private static RebaseResult ApplyRebaseStep(RebaseSafeHandle rebaseOperationHandle, Repository repository, Signature committer, RebaseOptions options, ref GitCheckoutOpts gitCheckoutOpts, RebaseStepInfo stepToApplyInfo)
92+
{
93+
RebaseResult rebaseResult = null;
11194

112-
// If we have not generated a result that needs to be
113-
// reported, move to the next step.
114-
if (rebaseResult != null)
115-
{
116-
break;
117-
}
118-
}
95+
// Report the rebase step we are about to perform.
96+
if (options.RebaseStepStarting != null)
97+
{
98+
options.RebaseStepStarting(new BeforeRebaseStepInfo(stepToApplyInfo));
99+
}
119100

120-
// If the step being applied is equal to the total step count,
121-
// that means all steps have been run and we are finished.
122-
if (action == RebaseAction.Finish)
123-
{
124-
Debug.Assert(rebaseResult == null);
101+
// Perform the rebase step
102+
GitRebaseOperation rebaseOpReport = Proxy.git_rebase_next(rebaseOperationHandle, ref gitCheckoutOpts);
125103

126-
long totalStepCount = Proxy.git_rebase_operation_entrycount(rebaseOperationHandle);
127-
GitRebaseOptions gitRebaseOptions = new GitRebaseOptions()
104+
// Verify that the information from the native library is consistent.
105+
VerifyRebaseOp(rebaseOpReport, stepToApplyInfo);
106+
107+
// Handle the result
108+
switch (stepToApplyInfo.Type)
109+
{
110+
case RebaseStepOperation.Pick:
111+
rebaseResult = ApplyPickStep(rebaseOperationHandle, repository, committer, options, stepToApplyInfo);
112+
break;
113+
case RebaseStepOperation.Squash:
114+
case RebaseStepOperation.Edit:
115+
case RebaseStepOperation.Exec:
116+
case RebaseStepOperation.Fixup:
117+
case RebaseStepOperation.Reword:
118+
// These operations are not yet supported by lg2.
119+
throw new LibGit2SharpException(string.Format(
120+
"Rebase Operation Type ({0}) is not currently supported in LibGit2Sharp.",
121+
stepToApplyInfo.Type));
122+
default:
123+
throw new ArgumentException(string.Format(
124+
"Unexpected Rebase Operation Type: {0}", stepToApplyInfo.Type));
125+
}
126+
127+
return rebaseResult;
128+
}
129+
130+
private static RebaseResult ApplyPickStep(RebaseSafeHandle rebaseOperationHandle, Repository repository, Signature committer, RebaseOptions options, RebaseStepInfo stepToApplyInfo)
131+
{
132+
RebaseResult rebaseResult = null;
133+
134+
// commit and continue.
135+
if (repository.Index.IsFullyMerged)
136+
{
137+
Proxy.GitRebaseCommitResult rebase_commit_result = Proxy.git_rebase_commit(rebaseOperationHandle, null, committer);
138+
139+
// Report that we just completed the step
140+
if (options.RebaseStepCompleted != null)
141+
{
142+
if (rebase_commit_result.WasPatchAlreadyApplied)
143+
{
144+
options.RebaseStepCompleted(new AfterRebaseStepInfo(stepToApplyInfo));
145+
}
146+
else
128147
{
129-
version = 1,
130-
};
131-
132-
// Rebase is completed!
133-
Proxy.git_rebase_finish(rebaseOperationHandle, committer, gitRebaseOptions);
134-
rebaseResult = new RebaseResult(RebaseStatus.Complete,
135-
totalStepCount,
136-
totalStepCount,
137-
null);
148+
options.RebaseStepCompleted(new AfterRebaseStepInfo(stepToApplyInfo, repository.Lookup<Commit>(new ObjectId(rebase_commit_result.CommitId))));
149+
}
138150
}
139-
140-
return rebaseResult;
141151
}
152+
else
153+
{
154+
rebaseResult = new RebaseResult(RebaseStatus.Conflicts,
155+
stepToApplyInfo.CurrentStep,
156+
stepToApplyInfo.TotalStepCount,
157+
null);
158+
}
159+
160+
return rebaseResult;
142161
}
143162

144163
/// <summary>
@@ -178,22 +197,28 @@ private static RebaseAction NextRebaseAction(
178197

179198
long totalStepCount = Proxy.git_rebase_operation_entrycount(rebaseOperationHandle);
180199

181-
if (stepToApplyIndex == totalStepCount)
182-
{
183-
action = RebaseAction.Finish;
184-
stepToApply = null;
185-
}
186-
else
200+
if (stepToApplyIndex < totalStepCount)
187201
{
188202
action = RebaseAction.ApplyStep;
189203

190204
GitRebaseOperation rebaseOp = Proxy.git_rebase_operation_byindex(rebaseOperationHandle, stepToApplyIndex);
191205
ObjectId idOfCommitBeingRebased = new ObjectId(rebaseOp.id);
192206
stepToApply = new RebaseStepInfo(rebaseOp.type,
193-
repository.Lookup<Commit>(idOfCommitBeingRebased),
194-
LaxUtf8NoCleanupMarshaler.FromNative(rebaseOp.exec),
195-
stepToApplyIndex,
196-
totalStepCount);
207+
repository.Lookup<Commit>(idOfCommitBeingRebased),
208+
LaxUtf8NoCleanupMarshaler.FromNative(rebaseOp.exec),
209+
stepToApplyIndex,
210+
totalStepCount);
211+
}
212+
else if (stepToApplyIndex == totalStepCount)
213+
{
214+
action = RebaseAction.Finish;
215+
stepToApply = null;
216+
}
217+
else
218+
{
219+
// This is an unexpected condition - should not happen in normal operation.
220+
throw new LibGit2SharpException(string.Format("Current step ({0}) is larger than the total number of steps ({1})",
221+
stepToApplyIndex, totalStepCount));
197222
}
198223

199224
return action;

0 commit comments

Comments
 (0)