Skip to content

Commit c106763

Browse files
jamillnulltoken
authored andcommitted
WIP: Rebase should report the step it is going to apply before it is actually applied.
1 parent cd3f3a0 commit c106763

File tree

2 files changed

+116
-72
lines changed

2 files changed

+116
-72
lines changed

LibGit2Sharp/Rebase.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ public virtual RebaseResult Start(Branch branch, Branch upstream, Branch onto, S
134134
RebaseOperationImpl.Run(rebaseOperationHandle,
135135
this.repository,
136136
committer,
137-
options);
137+
options,
138+
true);
138139
return rebaseResult;
139140
}
140141
finally
@@ -199,7 +200,7 @@ public virtual RebaseResult Continue(Signature committer, RebaseOptions options)
199200
}
200201
}
201202

202-
RebaseResult rebaseResult = RebaseOperationImpl.Run(rebase, repository, committer, options);
203+
RebaseResult rebaseResult = RebaseOperationImpl.Run(rebase, repository, committer, options, false);
203204
return rebaseResult;
204205
}
205206
finally

LibGit2Sharp/RebaseOperationImpl.cs

Lines changed: 113 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics;
34
using System.Linq;
45
using System.Text;
56
using 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

Comments
 (0)