Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
5b8c66b
editor script HELLA GOOD???
kiprasmel Mar 6, 2022
5647335
initial experimentation with editorScript and reducePath
kiprasmel Mar 17, 2022
bc211d5
more experimentation
kiprasmel Mar 17, 2022
d19d21a
more experimentation. fix reducePath - if key === value, don't reduce…
kiprasmel Mar 17, 2022
f844c4a
find the (bug?) in git's post-rewrite hook, attempt initial fix by me…
kiprasmel Mar 18, 2022
34e3d42
add the current commit's SHA to the rewritten list
kiprasmel Mar 18, 2022
7494261
move deletion into a separate phase so that multiple keys w/ same val…
kiprasmel Mar 18, 2022
49fa3fd
undo the "current commit printing into rewrittenList"
kiprasmel Mar 18, 2022
3a76a02
add back the "$1" in rewrittenList (type of command - amend or rebase)
kiprasmel Mar 18, 2022
f4a75b8
merge amends into the 1st rebase that comes after them
kiprasmel Mar 19, 2022
dbfd890
create the full/combined rewritten-list
kiprasmel Mar 19, 2022
9af948f
turn reduce-path's logic into "combineRewrittenLists" function
kiprasmel Mar 19, 2022
b950722
rename reduce-path.js to .ts
kiprasmel Mar 19, 2022
31dc640
typescript-ify reduce-path
kiprasmel Mar 19, 2022
8848704
use reduce-path (combineRewrittenLists) to make git-stacked-rebase wo…
kiprasmel Mar 19, 2022
6b9409d
move rewrittenList file into the "done" state after an "apply" to avo…
kiprasmel Mar 19, 2022
3959f4a
fix "doesNeedToApply" - if there's no rewritten-list, then there's no…
kiprasmel Mar 19, 2022
bfe9938
fix the "no-longer-there" rewritten-list by reading the .applied file…
kiprasmel Mar 19, 2022
3ec733c
rename the "applied" filename to "rewritten-list.applied" because mak…
kiprasmel Mar 19, 2022
10c9be6
refactor: extract rewritten-list reading logic into apply.ts
kiprasmel Mar 19, 2022
fabc87e
refactor: move `applyIfNeedsToApply` up into a more related context
kiprasmel Mar 19, 2022
6fc4fdd
fix: only move rewrittenList to applied if it exists
kiprasmel Mar 19, 2022
904b8ab
remove .git/stacked-rebase dir from existance after apply'ing (need t…
kiprasmel Mar 20, 2022
e35f1d5
mkdir -p "$STACKED_REBASE_DIR" in post-rewrite script
kiprasmel Mar 20, 2022
41e6971
explain where i'm going with this
kiprasmel Mar 20, 2022
e68cf6f
strongly refactor branchSequencer to work with simple boundaries (bra…
kiprasmel Mar 20, 2022
205b841
feat: implement custom `getBoundariesInclInitial` for `forcePush`, us…
kiprasmel Mar 22, 2022
2b712d8
fix: create the .git/stacked-rebase/ dir only right before starting o…
kiprasmel Mar 20, 2022
15ba720
misc: fix the `main` entrypoint in package.json
kiprasmel Mar 21, 2022
09a278d
extend merging logic in `combineRewrittenLists` after doing a big rebase
kiprasmel Mar 22, 2022
3275f25
reducePath extras
kiprasmel Mar 28, 2022
b511d2f
remove docs for --continue since not really needed anymore
kiprasmel Mar 22, 2022
8e1439c
fix: handle leftover `prev` amends if no further rebase happened
kiprasmel Apr 11, 2022
7ae0629
fix: use the *last* rebase list, instead of the first
kiprasmel Apr 11, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 119 additions & 84 deletions apply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ import path from "path";
import Git from "nodegit";

import { createQuestion } from "./util/createQuestion";
import { noop } from "./util/noop";

import { filenames } from "./filenames";
import { configKeys } from "./configKeys";
// eslint-disable-next-line import/no-cycle
import {
BranchSequencerBase, //
branchSequencer,
ActionInsideEachCheckedOutBranch,
CallbackAfterDone,
BranchSequencerArgsBase,
} from "./branchSequencer";
import { combineRewrittenLists } from "./reducePath";

export const apply: BranchSequencerBase = (args) =>
branchSequencer({
Expand All @@ -30,13 +30,12 @@ const defaultApplyAction: ActionInsideEachCheckedOutBranch = async ({
repo, //
// targetBranch,
targetCommitSHA,
cmd,
isFinalCheckout,
// execSyncInRepo,
}) => {
const commit: Git.Commit = await Git.Commit.lookup(repo, targetCommitSHA);

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

console.log({ isFinalCheckout });

Expand All @@ -52,36 +51,6 @@ const defaultApplyAction: ActionInsideEachCheckedOutBranch = async ({
export const getBackupPathOfPreviousStackedRebase = (pathToStackedRebaseDirInsideDotGit: string): string =>
pathToStackedRebaseDirInsideDotGit + ".previous";

/**
* disabled because `forcePush` also became a thing
* and it's no longer clear what marks a stacked-rebase "done",
*
* thus making it hard to work with the temporary/previous directories
* without introducing a good amount of bugs.
*
*/
const defaultApplyCallback__disabled: CallbackAfterDone = ({
pathToStackedRebaseDirInsideDotGit, //
}): void => {
const backupPath: string = getBackupPathOfPreviousStackedRebase(pathToStackedRebaseDirInsideDotGit);

/**
* backup dir just in case, but in inactive path
* (so e.g --apply won't go off again accidently)
*/
if (fs.existsSync(backupPath)) {
fs.rmdirSync(backupPath, { recursive: true });
}
fs.renameSync(pathToStackedRebaseDirInsideDotGit, backupPath);

// diffCommands.forEach((cmd) => {
// console.log({ cmd });
// execSyncInRepo(cmd, { ...pipestdio(repo.workdir()) });
// });
//
};
noop(defaultApplyCallback__disabled);

export type ReturnOfApplyIfNeedsToApply = {
markThatNeedsToApply: () => void;
} & (
Expand All @@ -99,56 +68,6 @@ export type ReturnOfApplyIfNeedsToApply = {
userAllowedToApplyAndWeApplied: true;
}
);

const getPaths = (
pathToStackedRebaseDirInsideDotGit: string //
) =>
({
rewrittenListPath: path.join(pathToStackedRebaseDirInsideDotGit, filenames.rewrittenList),
needsToApplyPath: path.join(pathToStackedRebaseDirInsideDotGit, filenames.needsToApply),
appliedPath: path.join(pathToStackedRebaseDirInsideDotGit, filenames.applied),
} as const);

export const markThatNeedsToApply = (
pathToStackedRebaseDirInsideDotGit: string //
): void =>
[getPaths(pathToStackedRebaseDirInsideDotGit)].map(
({ rewrittenListPath, needsToApplyPath, appliedPath }) => (
fs.existsSync(rewrittenListPath)
? fs.copyFileSync(rewrittenListPath, needsToApplyPath)
: fs.writeFileSync(needsToApplyPath, ""),
fs.existsSync(appliedPath) && fs.unlinkSync(appliedPath),
void 0
)
)[0];

export const markThatApplied = (pathToStackedRebaseDirInsideDotGit: string): void =>
[getPaths(pathToStackedRebaseDirInsideDotGit)].map(
({ rewrittenListPath, needsToApplyPath, appliedPath }) => (
fs.existsSync(needsToApplyPath) && fs.unlinkSync(needsToApplyPath), //
fs.copyFileSync(rewrittenListPath, appliedPath),
void 0
)
)[0];

const doesNeedToApply = (pathToStackedRebaseDirInsideDotGit: string): boolean => {
const { rewrittenListPath, needsToApplyPath, appliedPath } = getPaths(pathToStackedRebaseDirInsideDotGit);

const needsToApplyPart1: boolean = fs.existsSync(needsToApplyPath);
if (needsToApplyPart1) {
return true;
}

const needsToApplyPart2: boolean = fs.existsSync(appliedPath)
? /**
* check if has been applied, but that apply is outdated
*/
!fs.readFileSync(appliedPath).equals(fs.readFileSync(rewrittenListPath))
: false;

return needsToApplyPart2;
};

export async function applyIfNeedsToApply({
repo,
pathToStackedRebaseTodoFile,
Expand Down Expand Up @@ -211,3 +130,119 @@ export async function applyIfNeedsToApply({
markThatNeedsToApply: _markThatNeedsToApply,
};
}

const getPaths = (
pathToStackedRebaseDirInsideDotGit: string //
) =>
({
rewrittenListPath: path.join(pathToStackedRebaseDirInsideDotGit, filenames.rewrittenList),
needsToApplyPath: path.join(pathToStackedRebaseDirInsideDotGit, filenames.needsToApply),
appliedPath: path.join(pathToStackedRebaseDirInsideDotGit, filenames.applied),
gitRebaseTodoPath: path.join(pathToStackedRebaseDirInsideDotGit, filenames.gitRebaseTodo),
} as const);

export const markThatNeedsToApply = (
pathToStackedRebaseDirInsideDotGit: string //
): void =>
[getPaths(pathToStackedRebaseDirInsideDotGit)].map(
({ rewrittenListPath, needsToApplyPath, appliedPath }) => (
fs.existsSync(rewrittenListPath)
? fs.copyFileSync(rewrittenListPath, needsToApplyPath)
: fs.writeFileSync(needsToApplyPath, ""),
fs.existsSync(appliedPath) && fs.unlinkSync(appliedPath),
void 0
)
)[0];

export const markThatApplied = (pathToStackedRebaseDirInsideDotGit: string): void =>
[getPaths(pathToStackedRebaseDirInsideDotGit)].map(
({ rewrittenListPath, needsToApplyPath, gitRebaseTodoPath }) => (
fs.existsSync(needsToApplyPath) && fs.unlinkSync(needsToApplyPath), //
/**
* need to check if the `rewrittenListPath` exists,
* because even if it does not, then the "apply" can still go through
* and "apply", by using the already .applied file, i.e. do nothing.
*
* TODO just do not run "apply" if the file doesn't exist?
* or is there a case where it's useful still?
*
*/
// fs.existsSync(rewrittenListPath) && fs.renameSync(rewrittenListPath, appliedPath),
// // fs.existsSync(rewrittenListPath)
// // ? fs.renameSync(rewrittenListPath, appliedPath)
// // : !fs.existsSync(appliedPath) &&
// // (() => {
// // throw new Error("applying uselessly");
// // })(),
fs.existsSync(rewrittenListPath) && fs.unlinkSync(rewrittenListPath),
fs.existsSync(gitRebaseTodoPath) && fs.unlinkSync(gitRebaseTodoPath),
fs.readdirSync(pathToStackedRebaseDirInsideDotGit).length === 0 &&
fs.rmdirSync(pathToStackedRebaseDirInsideDotGit, { recursive: true }),
void 0
)
)[0];

const doesNeedToApply = (pathToStackedRebaseDirInsideDotGit: string): boolean => {
const { rewrittenListPath, needsToApplyPath, appliedPath } = getPaths(pathToStackedRebaseDirInsideDotGit);

if (!fs.existsSync(rewrittenListPath)) {
/**
* nothing to apply
*/
return false;
}

const needsToApplyPart1: boolean = fs.existsSync(needsToApplyPath);
if (needsToApplyPart1) {
return true;
}

const needsToApplyPart2: boolean = fs.existsSync(appliedPath)
? /**
* check if has been applied, but that apply is outdated
*/
!fs.readFileSync(appliedPath).equals(fs.readFileSync(rewrittenListPath))
: false;

return needsToApplyPart2;
};

export function readRewrittenListNotAppliedOrAppliedOrError(
repoPath: string
): {
pathOfRewrittenList: string;
pathOfRewrittenListApplied: string;
rewrittenListRaw: string;
/**
* you probably want these:
*/
combinedRewrittenList: string;
combinedRewrittenListLines: string[];
} {
const pathOfRewrittenList: string = path.join(repoPath, "stacked-rebase", filenames.rewrittenList);
const pathOfRewrittenListApplied: string = path.join(repoPath, "stacked-rebase", filenames.applied);

/**
* not combined yet
*/
let rewrittenListRaw: string;
if (fs.existsSync(pathOfRewrittenList)) {
rewrittenListRaw = fs.readFileSync(pathOfRewrittenList, { encoding: "utf-8" });
} else if (fs.existsSync(pathOfRewrittenListApplied)) {
rewrittenListRaw = fs.readFileSync(pathOfRewrittenListApplied, { encoding: "utf-8" });
} else {
throw new Error(
`rewritten-list not found neither in ${pathOfRewrittenList}, nor in ${pathOfRewrittenListApplied}`
);
}

const { combinedRewrittenList } = combineRewrittenLists(rewrittenListRaw);

return {
pathOfRewrittenList,
pathOfRewrittenListApplied,
rewrittenListRaw,
combinedRewrittenList,
combinedRewrittenListLines: combinedRewrittenList.split("\n").filter((line) => !!line),
};
}
Loading