@@ -3,13 +3,21 @@ import assert from "assert";
33
44import Git from "nodegit" ;
55
6+ import { getWantedCommitsWithBranchBoundariesOurCustomImpl } from "./git-stacked-rebase" ;
7+
68import { createExecSyncInRepo } from "./util/execSyncInRepo" ;
79import { Termination } from "./util/error" ;
10+ import { assertNever } from "./util/assertNever" ;
811
912import { parseNewGoodCommands } from "./parse-todo-of-stacked-rebase/parseNewGoodCommands" ;
1013import { GoodCommand , GoodCommandStacked } from "./parse-todo-of-stacked-rebase/validator" ;
1114
12- export type GetBranchesCtx = {
15+ export type BranchRefs = {
16+ initialBranch : Git . Reference ;
17+ currentBranch : Git . Reference ;
18+ } ;
19+
20+ export type GetBranchesCtx = BranchRefs & {
1321 pathToStackedRebaseDirInsideDotGit : string ;
1422 rootLevelCommandName : string ;
1523 repo : Git . Repository ;
@@ -24,7 +32,13 @@ export type GetBoundariesInclInitial = (
2432 ctx : GetBranchesCtx //
2533) => SimpleBranchAndCommit [ ] | Promise < SimpleBranchAndCommit [ ] > ;
2634
27- const defautlGetBoundariesInclInitial : GetBoundariesInclInitial = ( {
35+ export const isStackedRebaseInProgress = ( {
36+ pathToStackedRebaseDirInsideDotGit,
37+ } : {
38+ pathToStackedRebaseDirInsideDotGit : string ;
39+ } ) : boolean => fs . existsSync ( pathToStackedRebaseDirInsideDotGit ) ;
40+
41+ const getBoundariesInclInitialByParsingNotYetAppliedState : GetBoundariesInclInitial = ( {
2842 pathToStackedRebaseDirInsideDotGit, //
2943 rootLevelCommandName,
3044 repo,
@@ -33,7 +47,7 @@ const defautlGetBoundariesInclInitial: GetBoundariesInclInitial = ({
3347 /**
3448 * TODO REMOVE / modify this logic (see next comment)
3549 */
36- if ( ! fs . existsSync ( pathToStackedRebaseDirInsideDotGit ) ) {
50+ if ( ! isStackedRebaseInProgress ( { pathToStackedRebaseDirInsideDotGit } ) ) {
3751 throw new Termination ( `\n\nno stacked-rebase in progress? (nothing to ${ rootLevelCommandName } )\n\n` ) ;
3852 }
3953 // const hasPostRewriteHookInstalledWithLatestVersion = false;
@@ -98,6 +112,94 @@ const defautlGetBoundariesInclInitial: GetBoundariesInclInitial = ({
98112 ) ;
99113} ;
100114
115+ const getBoundariesInclInitialWithSipleBranchTraversal : GetBoundariesInclInitial = ( argsBase ) =>
116+ getWantedCommitsWithBranchBoundariesOurCustomImpl (
117+ argsBase . repo , //
118+ argsBase . initialBranch ,
119+ argsBase . currentBranch
120+ ) . then ( ( boundaries ) =>
121+ boundaries
122+ . filter ( ( b ) => ! ! b . branchEnd )
123+ . map (
124+ ( boundary ) : SimpleBranchAndCommit => ( {
125+ branchEndFullName : boundary . branchEnd ! . name ( ) , // TS ok because of the filter
126+ commitSHA : boundary . commit . sha ( ) ,
127+ } )
128+ )
129+ ) ;
130+
131+ /**
132+ * not sure if i'm a fan of this indirection tbh..
133+ */
134+ export enum BehaviorOfGetBranchBoundaries {
135+ /**
136+ * the default one.
137+ */
138+ "parse-from-not-yet-applied-state" ,
139+ /**
140+ * originally used by `--push` - since it wouldn't be allowed to run
141+ * before `--apply` was used,
142+ * having to sync from applied state was more confusion & limiting.
143+ *
144+ * further, we later got rid of the state after `--apply`ing,
145+ * so this became the only option anyway.
146+ */
147+ "ignore-unapplied-state-and-use-simple-branch-traversal" ,
148+ /**
149+ * this is the adaptive of the other 2.
150+ * originally intended for `branchSequencerExec` (`--exec`) -
151+ * we don't know what's coming from the user,
152+ * so we cannot make any assumptions.
153+ *
154+ * instead, we simply check if a stacked rebase (our) is in progress,
155+ * if so - we use the 1st option (because we have to),
156+ * otherwise - the 2nd option (because we have to, too!).
157+ */
158+ "if-stacked-rebase-in-progress-then-parse-not-applied-state-otherwise-simple-branch-traverse" ,
159+ }
160+ export const defaultGetBranchBoundariesBehavior = BehaviorOfGetBranchBoundaries [ "parse-from-not-yet-applied-state" ] ;
161+
162+ const pickBoundaryParser = ( {
163+ behaviorOfGetBranchBoundaries,
164+ pathToStackedRebaseDirInsideDotGit,
165+ } : {
166+ /**
167+ * can provide one of the predefined behaviors,
168+ * whom will decide which parser to pick,
169+ *
170+ * or can provide a custom parser function.
171+ */
172+ behaviorOfGetBranchBoundaries : BehaviorOfGetBranchBoundaries | GetBoundariesInclInitial ;
173+ pathToStackedRebaseDirInsideDotGit : string ;
174+ } ) : GetBoundariesInclInitial => {
175+ if ( typeof behaviorOfGetBranchBoundaries === "function" ) {
176+ /**
177+ * custom fn
178+ */
179+ return behaviorOfGetBranchBoundaries ;
180+ } else if ( behaviorOfGetBranchBoundaries === BehaviorOfGetBranchBoundaries [ "parse-from-not-yet-applied-state" ] ) {
181+ return getBoundariesInclInitialByParsingNotYetAppliedState ;
182+ } else if (
183+ behaviorOfGetBranchBoundaries ===
184+ BehaviorOfGetBranchBoundaries [ "ignore-unapplied-state-and-use-simple-branch-traversal" ]
185+ ) {
186+ return getBoundariesInclInitialWithSipleBranchTraversal ;
187+ } else if (
188+ behaviorOfGetBranchBoundaries ===
189+ BehaviorOfGetBranchBoundaries [
190+ "if-stacked-rebase-in-progress-then-parse-not-applied-state-otherwise-simple-branch-traverse"
191+ ]
192+ ) {
193+ if ( isStackedRebaseInProgress ( { pathToStackedRebaseDirInsideDotGit } ) ) {
194+ return getBoundariesInclInitialByParsingNotYetAppliedState ;
195+ } else {
196+ return getBoundariesInclInitialWithSipleBranchTraversal ;
197+ }
198+ } else {
199+ assertNever ( behaviorOfGetBranchBoundaries ) ;
200+ }
201+ } ;
202+
101203/**
102204 *
103205 */
@@ -111,25 +213,20 @@ export type ActionInsideEachCheckedOutBranchCtx = {
111213} ;
112214export type ActionInsideEachCheckedOutBranch = ( ctx : ActionInsideEachCheckedOutBranchCtx ) => void | Promise < void > ;
113215
114- export type BranchSequencerArgsBase = {
216+ export type BranchSequencerArgsBase = BranchRefs & {
115217 pathToStackedRebaseDirInsideDotGit : string ; //
116218 // goodCommands: GoodCommand[];
117219 pathToStackedRebaseTodoFile : string ;
118220 repo : Git . Repository ;
119221 rootLevelCommandName : string ;
120222 gitCmd : string ;
121- //
122- initialBranch : Git . Reference ;
123- currentBranch : Git . Reference ;
124223} ;
224+
125225export type BranchSequencerArgs = BranchSequencerArgsBase & {
126226 // callbackBeforeBegin?: CallbackAfterDone; // TODO
127227 actionInsideEachCheckedOutBranch : ActionInsideEachCheckedOutBranch ;
128228 delayMsBetweenCheckouts ?: number ;
129- /**
130- *
131- */
132- getBoundariesInclInitial ?: GetBoundariesInclInitial ;
229+ behaviorOfGetBranchBoundaries ?: Parameters < typeof pickBoundaryParser > [ 0 ] [ "behaviorOfGetBranchBoundaries" ] ;
133230} ;
134231
135232export type BranchSequencerBase = ( args : BranchSequencerArgsBase ) => Promise < void > ;
@@ -145,15 +242,24 @@ export const branchSequencer: BranchSequencer = async ({
145242 actionInsideEachCheckedOutBranch,
146243 gitCmd,
147244 //
148- getBoundariesInclInitial = defautlGetBoundariesInclInitial ,
245+ behaviorOfGetBranchBoundaries = defaultGetBranchBoundariesBehavior ,
246+ initialBranch,
247+ currentBranch,
149248} ) => {
150249 const execSyncInRepo = createExecSyncInRepo ( repo ) ;
151250
251+ const getBoundariesInclInitial : GetBoundariesInclInitial = pickBoundaryParser ( {
252+ behaviorOfGetBranchBoundaries,
253+ pathToStackedRebaseDirInsideDotGit,
254+ } ) ;
255+
152256 const branchesAndCommits : SimpleBranchAndCommit [ ] = await getBoundariesInclInitial ( {
153257 pathToStackedRebaseDirInsideDotGit,
154258 pathToStackedRebaseTodoFile,
155259 repo,
156260 rootLevelCommandName,
261+ initialBranch,
262+ currentBranch,
157263 } ) ;
158264
159265 return checkout ( branchesAndCommits . slice ( 1 ) as any ) ; // TODO TS
0 commit comments