Skip to content

Commit e96d75a

Browse files
committed
strongly refactor branchSequencer to work with simple boundaries (branch & commit)
Signed-off-by: Kipras Melnikovas <kipras@kipras.org>
1 parent f58afc9 commit e96d75a

File tree

3 files changed

+98
-156
lines changed

3 files changed

+98
-156
lines changed

apply.ts

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import path from "path";
44
import Git from "nodegit";
55

66
import { createQuestion } from "./util/createQuestion";
7-
import { noop } from "./util/noop";
87

98
import { filenames } from "./filenames";
109
import { configKeys } from "./configKeys";
@@ -13,7 +12,6 @@ import {
1312
BranchSequencerBase, //
1413
branchSequencer,
1514
ActionInsideEachCheckedOutBranch,
16-
CallbackAfterDone,
1715
BranchSequencerArgsBase,
1816
} from "./branchSequencer";
1917
import { combineRewrittenLists } from "./reducePath";
@@ -32,13 +30,12 @@ const defaultApplyAction: ActionInsideEachCheckedOutBranch = async ({
3230
repo, //
3331
// targetBranch,
3432
targetCommitSHA,
35-
cmd,
3633
isFinalCheckout,
3734
// execSyncInRepo,
3835
}) => {
3936
const commit: Git.Commit = await Git.Commit.lookup(repo, targetCommitSHA);
4037

41-
console.log("will reset because", cmd.commandOrAliasName, "to commit", commit.summary(), commit.sha());
38+
console.log("will reset to commit", commit.sha(), "(" + commit.summary() + ")");
4239

4340
console.log({ isFinalCheckout });
4441

@@ -54,36 +51,6 @@ const defaultApplyAction: ActionInsideEachCheckedOutBranch = async ({
5451
export const getBackupPathOfPreviousStackedRebase = (pathToStackedRebaseDirInsideDotGit: string): string =>
5552
pathToStackedRebaseDirInsideDotGit + ".previous";
5653

57-
/**
58-
* disabled because `forcePush` also became a thing
59-
* and it's no longer clear what marks a stacked-rebase "done",
60-
*
61-
* thus making it hard to work with the temporary/previous directories
62-
* without introducing a good amount of bugs.
63-
*
64-
*/
65-
const defaultApplyCallback__disabled: CallbackAfterDone = ({
66-
pathToStackedRebaseDirInsideDotGit, //
67-
}): void => {
68-
const backupPath: string = getBackupPathOfPreviousStackedRebase(pathToStackedRebaseDirInsideDotGit);
69-
70-
/**
71-
* backup dir just in case, but in inactive path
72-
* (so e.g --apply won't go off again accidently)
73-
*/
74-
if (fs.existsSync(backupPath)) {
75-
fs.rmdirSync(backupPath, { recursive: true });
76-
}
77-
fs.renameSync(pathToStackedRebaseDirInsideDotGit, backupPath);
78-
79-
// diffCommands.forEach((cmd) => {
80-
// console.log({ cmd });
81-
// execSyncInRepo(cmd, { ...pipestdio(repo.workdir()) });
82-
// });
83-
//
84-
};
85-
noop(defaultApplyCallback__disabled);
86-
8754
export type ReturnOfApplyIfNeedsToApply = {
8855
markThatNeedsToApply: () => void;
8956
} & (

branchSequencer.ts

Lines changed: 85 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -7,67 +7,26 @@ import { createExecSyncInRepo } from "./util/execSyncInRepo";
77
import { Termination } from "./util/error";
88

99
import { parseNewGoodCommands } from "./parse-todo-of-stacked-rebase/parseNewGoodCommands";
10-
import { GoodCommand } from "./parse-todo-of-stacked-rebase/validator";
10+
import { GoodCommand, GoodCommandStacked } from "./parse-todo-of-stacked-rebase/validator";
1111

12-
export type ActionInsideEachCheckedOutBranch = (ctx: ArgsForActionInsideEachCheckedOutBranch) => void | Promise<void>;
13-
14-
/**
15-
*
16-
*/
17-
18-
export type ArgsForActionInsideEachCheckedOutBranch = {
19-
repo: Git.Repository; //
20-
targetBranch: string;
21-
targetCommitSHA: string;
22-
cmd: GoodCommand;
23-
isFinalCheckout: boolean;
24-
execSyncInRepo: ReturnType<typeof createExecSyncInRepo>;
25-
};
26-
27-
/**
28-
*
29-
*/
30-
31-
export type CtxForCallbackAfterDone = {
12+
export type GetBranchesCtx = {
3213
pathToStackedRebaseDirInsideDotGit: string;
33-
};
34-
35-
export type CallbackAfterDone = (ctx: CtxForCallbackAfterDone) => void | Promise<void>;
36-
37-
/**
38-
*
39-
*/
40-
41-
export type BranchSequencerArgsBase = {
42-
pathToStackedRebaseDirInsideDotGit: string; //
43-
// goodCommands: GoodCommand[];
44-
pathToStackedRebaseTodoFile: string;
45-
repo: Git.Repository;
4614
rootLevelCommandName: string;
47-
gitCmd: string;
15+
repo: Git.Repository;
16+
pathToStackedRebaseTodoFile: string;
4817
};
49-
50-
export type BranchSequencerArgs = BranchSequencerArgsBase & {
51-
// callbackBeforeBegin?: CallbackAfterDone; // TODO
52-
actionInsideEachCheckedOutBranch: ActionInsideEachCheckedOutBranch;
53-
delayMsBetweenCheckouts?: number;
54-
callbackAfterDone?: CallbackAfterDone;
18+
export type SimpleBranchAndCommit = {
19+
commitSHA: string | null;
20+
branchEndFullName: string;
21+
// branchExistsYet: boolean; // TODO
5522
};
23+
export type GetBoundariesInclInitial = (ctx: GetBranchesCtx) => SimpleBranchAndCommit[];
5624

57-
export type BranchSequencerBase = (args: BranchSequencerArgsBase) => Promise<void>;
58-
export type BranchSequencer = (args: BranchSequencerArgs) => Promise<void>;
59-
60-
export const branchSequencer: BranchSequencer = async ({
25+
const defautlGetBoundariesInclInitial: GetBoundariesInclInitial = ({
6126
pathToStackedRebaseDirInsideDotGit, //
62-
// goodCommands,
63-
pathToStackedRebaseTodoFile,
64-
repo,
6527
rootLevelCommandName,
66-
delayMsBetweenCheckouts = 0,
67-
// callbackBeforeBegin,
68-
actionInsideEachCheckedOutBranch,
69-
callbackAfterDone = (): void => {},
70-
gitCmd,
28+
repo,
29+
pathToStackedRebaseTodoFile,
7130
}) => {
7231
/**
7332
* TODO REMOVE / modify this logic (see next comment)
@@ -122,74 +81,102 @@ export const branchSequencer: BranchSequencer = async ({
12281
*/
12382
const stackedRebaseCommandsNew: GoodCommand[] = parseNewGoodCommands(repo, pathToStackedRebaseTodoFile);
12483

125-
// const remotes: Git.Remote[] = await repo.getRemotes();
126-
// const remote: Git.Remote | undefined = remotes.find((r) =>
127-
// stackedRebaseCommandsOld.find((cmd) => cmd.targets && cmd.targets[0].includes(r.name()))
128-
// );
84+
for (const cmd of stackedRebaseCommandsNew) {
85+
assert(cmd.rebaseKind === "stacked");
86+
assert(cmd.targets?.length);
87+
}
12988

130-
// const diffCommands: string[] = stackedRebaseCommandsOld
131-
// .map((cmd, idx) => {
132-
// const otherCmd: GoodCommand = stackedRebaseCommandsNew[idx];
133-
// assert(cmd.commandName === otherCmd.commandName);
134-
// assert(cmd.targets?.length);
135-
// assert(otherCmd.targets?.length);
136-
// assert(cmd.targets.every((t) => otherCmd.targets?.every((otherT) => t === otherT)));
89+
return (stackedRebaseCommandsNew //
90+
.filter((cmd) => cmd.rebaseKind === "stacked") as GoodCommandStacked[]) //
91+
.map(
92+
(cmd): SimpleBranchAndCommit => ({
93+
commitSHA: cmd.commitSHAThatBranchPointsTo,
94+
branchEndFullName: cmd.targets![0],
95+
})
96+
);
97+
};
13798

138-
// const trim = (str: string): string => str.replace("refs/heads/", "").replace("refs/remotes/", "");
99+
/**
100+
*
101+
*/
139102

140-
// return !remote || idx === 0 // || idx === stackedRebaseCommandsOld.length - 1
141-
// ? ""
142-
// : `git -c core.pager='' diff -u ${remote.name()}/${trim(cmd.targets[0])} ${trim(
143-
// otherCmd.targets[0]
144-
// )}`;
145-
// })
146-
// .filter((cmd) => !!cmd);
103+
export type ActionInsideEachCheckedOutBranchCtx = {
104+
repo: Git.Repository; //
105+
targetBranch: string;
106+
targetCommitSHA: string;
107+
isFinalCheckout: boolean;
108+
execSyncInRepo: ReturnType<typeof createExecSyncInRepo>;
109+
};
110+
export type ActionInsideEachCheckedOutBranch = (ctx: ActionInsideEachCheckedOutBranchCtx) => void | Promise<void>;
147111

112+
export type BranchSequencerArgsBase = {
113+
pathToStackedRebaseDirInsideDotGit: string; //
114+
// goodCommands: GoodCommand[];
115+
pathToStackedRebaseTodoFile: string;
116+
repo: Git.Repository;
117+
rootLevelCommandName: string;
118+
gitCmd: string;
119+
};
120+
export type BranchSequencerArgs = BranchSequencerArgsBase & {
121+
// callbackBeforeBegin?: CallbackAfterDone; // TODO
122+
actionInsideEachCheckedOutBranch: ActionInsideEachCheckedOutBranch;
123+
delayMsBetweenCheckouts?: number;
148124
/**
149-
* first actually reset, only then diff
125+
*
150126
*/
127+
getBoundariesInclInitial?: GetBoundariesInclInitial;
128+
};
151129

152-
// const commitsWithBranchBoundaries: CommitAndBranchBoundary[] = (
153-
// await getWantedCommitsWithBranchBoundaries(
154-
// repo, //
155-
// initialBranch
156-
// )
157-
// ).reverse();
158-
159-
// const previousTargetBranchName: string = stackedRebaseCommandsNew[0]
160-
// ? stackedRebaseCommandsNew[0].targets?.[0] ?? ""
161-
// : "";
130+
export type BranchSequencerBase = (args: BranchSequencerArgsBase) => Promise<void>;
131+
export type BranchSequencer = (args: BranchSequencerArgs) => Promise<void>;
162132

133+
export const branchSequencer: BranchSequencer = async ({
134+
pathToStackedRebaseDirInsideDotGit, //
135+
pathToStackedRebaseTodoFile,
136+
repo,
137+
rootLevelCommandName,
138+
delayMsBetweenCheckouts = 0,
139+
// callbackBeforeBegin,
140+
actionInsideEachCheckedOutBranch,
141+
gitCmd,
142+
//
143+
getBoundariesInclInitial = defautlGetBoundariesInclInitial,
144+
}) => {
163145
const execSyncInRepo = createExecSyncInRepo(repo);
164146

165-
const checkout = async (cmds: GoodCommand[]): Promise<void> => {
166-
if (!cmds.length) {
147+
const branchesAndCommits: SimpleBranchAndCommit[] = getBoundariesInclInitial({
148+
pathToStackedRebaseDirInsideDotGit,
149+
pathToStackedRebaseTodoFile,
150+
repo,
151+
rootLevelCommandName,
152+
});
153+
154+
return checkout(branchesAndCommits.slice(1) as any); // TODO TS
155+
156+
async function checkout(boundaries: SimpleBranchAndCommit[]): Promise<void> {
157+
if (!boundaries.length) {
167158
return;
168159
}
169160

170-
console.log("\ncheckout", cmds.length);
161+
console.log("\ncheckout", boundaries.length);
171162

172163
const goNext = () =>
173164
new Promise<void>((r) => {
174165
setTimeout(() => {
175-
checkout(cmds.slice(1)).then(() => r());
166+
checkout(boundaries.slice(1)).then(() => r());
176167
}, delayMsBetweenCheckouts);
177168
});
178169

179-
const cmd = cmds[0];
180-
181-
assert(cmd.rebaseKind === "stacked");
182-
183-
const targetCommitSHA: string | null = cmd.commitSHAThatBranchPointsTo;
170+
const boundary = boundaries[0];
171+
const branch = boundary.branchEndFullName;
172+
const targetCommitSHA: string | null = boundary.commitSHA;
184173

185174
if (!targetCommitSHA) {
186175
return goNext();
187176
}
188177

189-
assert(cmd.targets?.length);
190-
191-
let targetBranch = cmd.targets[0].replace("refs/heads/", "");
192-
assert(targetBranch && typeof targetBranch === "string");
178+
let targetBranch = branch.replace("refs/heads/", "");
179+
assert(targetBranch);
193180

194181
/**
195182
* if we only have the remote branch, but it's not checked out locally,
@@ -246,7 +233,7 @@ export const branchSequencer: BranchSequencer = async ({
246233
/**
247234
* meaning we're on the latest branch
248235
*/
249-
const isFinalCheckout: boolean = cmds.length === 1;
236+
const isFinalCheckout: boolean = boundaries.length === 1;
250237

251238
/**
252239
* https://libgit2.org/libgit2/#HEAD/group/checkout/git_checkout_head
@@ -258,22 +245,10 @@ export const branchSequencer: BranchSequencer = async ({
258245
repo, //
259246
targetBranch,
260247
targetCommitSHA,
261-
cmd,
262248
isFinalCheckout,
263249
execSyncInRepo,
264250
});
265251

266252
return goNext();
267-
268-
// for (const cmd of stackedRebaseCommandsNew) {
269-
// };
270-
};
271-
272-
await checkout(stackedRebaseCommandsNew.slice(1) as any); // TODO TS
273-
274-
await callbackAfterDone({
275-
pathToStackedRebaseDirInsideDotGit,
276-
});
277-
278-
return;
253+
}
279254
};

parse-todo-of-stacked-rebase/validator.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ type BadCommand = {
267267
reasons: string[];
268268
};
269269

270-
export type GoodCommand = {
270+
export type GoodCommandBase = {
271271
commandOrAliasName: EitherRebaseEitherCommandOrAlias;
272272
lineNumber: number;
273273
fullLine: string;
@@ -280,17 +280,17 @@ export type GoodCommand = {
280280
index: number;
281281

282282
// commandName: EitherRebaseCommand;
283-
} & (
284-
| {
285-
rebaseKind: "regular";
286-
commandName: RegularRebaseCommand;
287-
}
288-
| {
289-
rebaseKind: "stacked";
290-
commandName: StackedRebaseCommand;
291-
commitSHAThatBranchPointsTo: string | null;
292-
}
293-
);
283+
};
284+
export type GoodCommandRegular = GoodCommandBase & {
285+
rebaseKind: "regular";
286+
commandName: RegularRebaseCommand;
287+
};
288+
export type GoodCommandStacked = GoodCommandBase & {
289+
rebaseKind: "stacked";
290+
commandName: StackedRebaseCommand;
291+
commitSHAThatBranchPointsTo: string | null;
292+
};
293+
export type GoodCommand = GoodCommandRegular | GoodCommandStacked;
294294

295295
export function validate(
296296
linesOfEditedRebaseTodo: string[], //

0 commit comments

Comments
 (0)