git-stack-cli 1.0.7 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -7
- package/dist/cjs/index.cjs +350 -129
- package/package.json +4 -4
- package/{rollup.config.mjs → rollup.config.js} +11 -3
- package/scripts/git-sequence-editor.sh +35 -0
- package/src/app/DependencyCheck.tsx +150 -95
- package/src/app/LocalMergeRebase.tsx +1 -4
- package/src/app/ManualRebase.tsx +221 -87
- package/src/app/SelectCommitRanges.tsx +1 -0
- package/src/command.ts +19 -3
- package/src/core/GitReviseTodo.test.ts +572 -0
- package/src/core/GitReviseTodo.ts +79 -0
- package/src/types/global.d.ts +2 -0
package/README.md
CHANGED
|
@@ -87,14 +87,11 @@ npm run build:standalone
|
|
|
87
87
|
>
|
|
88
88
|
> **You must update the `version` in `package.json` and commit all changes first!**
|
|
89
89
|
|
|
90
|
-
### NPM
|
|
91
|
-
|
|
92
90
|
```bash
|
|
93
|
-
npm run release
|
|
94
|
-
```
|
|
91
|
+
npm run release
|
|
95
92
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
# release individually
|
|
94
|
+
npm run release:npm
|
|
95
|
+
npm run release:github
|
|
99
96
|
npm run release:brew
|
|
100
97
|
```
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -26883,6 +26883,12 @@ const RE$4 = {
|
|
|
26883
26883
|
};
|
|
26884
26884
|
|
|
26885
26885
|
function DependencyCheck(props) {
|
|
26886
|
+
return (reactExports.createElement(CheckGit, null,
|
|
26887
|
+
reactExports.createElement(CheckGithubCli, null,
|
|
26888
|
+
reactExports.createElement(CheckGithubCliAuth, null,
|
|
26889
|
+
reactExports.createElement(CheckGitRevise, null, props.children)))));
|
|
26890
|
+
}
|
|
26891
|
+
function CheckGit(props) {
|
|
26886
26892
|
const actions = Store.useActions();
|
|
26887
26893
|
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow },
|
|
26888
26894
|
"Checking ",
|
|
@@ -26899,65 +26905,84 @@ function DependencyCheck(props) {
|
|
|
26899
26905
|
reactExports.createElement(Command, null, "git"),
|
|
26900
26906
|
" must be installed."));
|
|
26901
26907
|
actions.exit(2);
|
|
26902
|
-
} },
|
|
26903
|
-
|
|
26908
|
+
} }, props.children));
|
|
26909
|
+
}
|
|
26910
|
+
function CheckGithubCli(props) {
|
|
26911
|
+
const actions = Store.useActions();
|
|
26912
|
+
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow },
|
|
26913
|
+
reactExports.createElement(Text, null,
|
|
26904
26914
|
"Checking ",
|
|
26905
|
-
reactExports.createElement(Command, null, "
|
|
26906
|
-
" install..."), function: async () => {
|
|
26907
|
-
|
|
26908
|
-
|
|
26909
|
-
|
|
26915
|
+
reactExports.createElement(Command, null, "gh"),
|
|
26916
|
+
" install...")), function: async () => {
|
|
26917
|
+
if (is_command_available("gh")) {
|
|
26918
|
+
return;
|
|
26919
|
+
}
|
|
26920
|
+
actions.output(reactExports.createElement(Text, { color: colors.yellow },
|
|
26921
|
+
reactExports.createElement(Command, null, "gh"),
|
|
26922
|
+
" must be installed."));
|
|
26923
|
+
actions.output(reactExports.createElement(Text, { color: colors.yellow },
|
|
26924
|
+
reactExports.createElement(Text, null, "Visit "),
|
|
26925
|
+
reactExports.createElement(Url, null, "https://cli.github.com"),
|
|
26926
|
+
reactExports.createElement(Text, null, " to install the github cli "),
|
|
26927
|
+
reactExports.createElement(Parens, null,
|
|
26928
|
+
reactExports.createElement(Command, null, "gh"))));
|
|
26929
|
+
actions.exit(3);
|
|
26930
|
+
} }, props.children));
|
|
26931
|
+
}
|
|
26932
|
+
function CheckGithubCliAuth(props) {
|
|
26933
|
+
const actions = Store.useActions();
|
|
26934
|
+
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow },
|
|
26935
|
+
reactExports.createElement(Text, null,
|
|
26936
|
+
"Checking ",
|
|
26937
|
+
reactExports.createElement(Command, null, "gh auth status"),
|
|
26938
|
+
"...")), function: async () => {
|
|
26939
|
+
const options = { ignoreExitCode: true };
|
|
26940
|
+
const auth_status$1 = await cli(`gh auth status`, options);
|
|
26941
|
+
if (auth_status$1.code === 0) {
|
|
26942
|
+
const username = auth_status(auth_status$1.stdout);
|
|
26943
|
+
if (username) {
|
|
26944
|
+
actions.set((state) => {
|
|
26945
|
+
state.username = username;
|
|
26946
|
+
});
|
|
26910
26947
|
return;
|
|
26911
26948
|
}
|
|
26912
|
-
|
|
26913
|
-
|
|
26914
|
-
|
|
26915
|
-
|
|
26916
|
-
|
|
26917
|
-
|
|
26918
|
-
|
|
26919
|
-
|
|
26920
|
-
|
|
26921
|
-
|
|
26922
|
-
|
|
26923
|
-
|
|
26924
|
-
|
|
26925
|
-
|
|
26926
|
-
|
|
26927
|
-
|
|
26928
|
-
|
|
26929
|
-
|
|
26930
|
-
|
|
26931
|
-
|
|
26932
|
-
|
|
26933
|
-
|
|
26934
|
-
|
|
26935
|
-
|
|
26936
|
-
|
|
26937
|
-
|
|
26938
|
-
|
|
26939
|
-
|
|
26940
|
-
|
|
26941
|
-
|
|
26942
|
-
|
|
26943
|
-
|
|
26944
|
-
|
|
26945
|
-
|
|
26946
|
-
|
|
26947
|
-
|
|
26948
|
-
|
|
26949
|
-
return;
|
|
26950
|
-
}
|
|
26951
|
-
}
|
|
26952
|
-
if (actions.isDebug()) {
|
|
26953
|
-
actions.error("gh auth status could not find username");
|
|
26954
|
-
}
|
|
26955
|
-
actions.output(reactExports.createElement(Text, { color: colors.yellow },
|
|
26956
|
-
reactExports.createElement(Command, null, "gh"),
|
|
26957
|
-
reactExports.createElement(Text, null, " requires login, please run "),
|
|
26958
|
-
reactExports.createElement(Command, null, "gh auth login")));
|
|
26959
|
-
actions.exit(4);
|
|
26960
|
-
} }, props.children)))));
|
|
26949
|
+
}
|
|
26950
|
+
if (actions.isDebug()) {
|
|
26951
|
+
actions.error("gh auth status could not find username");
|
|
26952
|
+
}
|
|
26953
|
+
actions.output(reactExports.createElement(Text, { color: colors.yellow },
|
|
26954
|
+
reactExports.createElement(Command, null, "gh"),
|
|
26955
|
+
reactExports.createElement(Text, null, " requires login, please run "),
|
|
26956
|
+
reactExports.createElement(Command, null, "gh auth login")));
|
|
26957
|
+
actions.exit(4);
|
|
26958
|
+
} }, props.children));
|
|
26959
|
+
}
|
|
26960
|
+
function CheckGitRevise(props) {
|
|
26961
|
+
const actions = Store.useActions();
|
|
26962
|
+
const argv = Store.useState((state) => state.argv);
|
|
26963
|
+
// skip git revise check when `rebase` is not git-revise
|
|
26964
|
+
if (argv?.["rebase"] !== "git-revise") {
|
|
26965
|
+
return props.children;
|
|
26966
|
+
}
|
|
26967
|
+
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow },
|
|
26968
|
+
reactExports.createElement(Text, null,
|
|
26969
|
+
"Checking ",
|
|
26970
|
+
reactExports.createElement(Command, null, "git-revise"),
|
|
26971
|
+
" install...")), function: async () => {
|
|
26972
|
+
if (is_command_available("git-revise")) {
|
|
26973
|
+
return;
|
|
26974
|
+
}
|
|
26975
|
+
actions.output(reactExports.createElement(Text, { color: colors.yellow },
|
|
26976
|
+
reactExports.createElement(Command, null, "git-revise"),
|
|
26977
|
+
" must be installed."));
|
|
26978
|
+
actions.output(reactExports.createElement(Text, { color: colors.yellow },
|
|
26979
|
+
reactExports.createElement(Text, null, "Visit "),
|
|
26980
|
+
reactExports.createElement(Url, null, "https://github.com/mystor/git-revise#install"),
|
|
26981
|
+
reactExports.createElement(Text, null, " to install the git revise cli "),
|
|
26982
|
+
reactExports.createElement(Parens, null,
|
|
26983
|
+
reactExports.createElement(Command, null, "git-revise"))));
|
|
26984
|
+
actions.exit(10);
|
|
26985
|
+
} }, props.children));
|
|
26961
26986
|
}
|
|
26962
26987
|
|
|
26963
26988
|
function GatherMetadata(props) {
|
|
@@ -27566,7 +27591,7 @@ async function run$3() {
|
|
|
27566
27591
|
await cli(`git add --all`);
|
|
27567
27592
|
let new_message;
|
|
27568
27593
|
if (commit.branch_id) {
|
|
27569
|
-
new_message =
|
|
27594
|
+
new_message = write$1(commit.full_message, commit.branch_id);
|
|
27570
27595
|
}
|
|
27571
27596
|
else {
|
|
27572
27597
|
new_message = commit.full_message;
|
|
@@ -27651,6 +27676,69 @@ async function run$3() {
|
|
|
27651
27676
|
}
|
|
27652
27677
|
const PATCH_FILE$1 = "git-stack-cli-patch.patch";
|
|
27653
27678
|
|
|
27679
|
+
// https://git-revise.readthedocs.io/en/latest/man.html#interactive-mode
|
|
27680
|
+
//
|
|
27681
|
+
// # Interactive Revise Todos(4 commands)
|
|
27682
|
+
// #
|
|
27683
|
+
// # Commands:
|
|
27684
|
+
// # p, pick <commit> = use commit
|
|
27685
|
+
// # r, reword <commit> = use commit, but edit the commit message
|
|
27686
|
+
// # s, squash <commit> = use commit, but meld into previous commit
|
|
27687
|
+
// # f, fixup <commit> = like squash, but discard this commit's message
|
|
27688
|
+
// # c, cut <commit> = interactively split commit into two smaller commits
|
|
27689
|
+
// # i, index <commit> = leave commit changes staged, but uncommitted
|
|
27690
|
+
// #
|
|
27691
|
+
// # Each command block is prefixed by a '++' marker, followed by the command to
|
|
27692
|
+
// # run, the commit hash and after a newline the complete commit message until
|
|
27693
|
+
// # the next '++' marker or the end of the file.
|
|
27694
|
+
// #
|
|
27695
|
+
// # Commit messages will be reworded to match the provided message before the
|
|
27696
|
+
// # command is performed.
|
|
27697
|
+
// #
|
|
27698
|
+
// # These blocks are executed from top to bottom. They can be re-ordered and
|
|
27699
|
+
// # their commands can be changed, however the number of blocks must remain
|
|
27700
|
+
// # identical. If present, index blocks must be at the bottom of the list,
|
|
27701
|
+
// # i.e. they can not be followed by non-index blocks.
|
|
27702
|
+
// #
|
|
27703
|
+
// #
|
|
27704
|
+
// # If you remove everything, the revising process will be aborted.
|
|
27705
|
+
// calculate git-revise-todo from commit_range and rebase_group_index
|
|
27706
|
+
//
|
|
27707
|
+
// Example
|
|
27708
|
+
// ----------------------------
|
|
27709
|
+
// ++ pick d36d63499425
|
|
27710
|
+
// cantaloupe color
|
|
27711
|
+
//
|
|
27712
|
+
// git-stack-id: E63ytp5dj
|
|
27713
|
+
//
|
|
27714
|
+
// ++ pick 4f98dd3e67d0
|
|
27715
|
+
// banana sweet
|
|
27716
|
+
//
|
|
27717
|
+
// git-stack-id: E63ytp5dj
|
|
27718
|
+
//
|
|
27719
|
+
// ++ pick f143d03c723c
|
|
27720
|
+
// apple sweet
|
|
27721
|
+
//
|
|
27722
|
+
function GitReviseTodo(args) {
|
|
27723
|
+
const entry_list = [];
|
|
27724
|
+
const group_list = args.commit_range.group_list;
|
|
27725
|
+
for (let i = args.rebase_group_index; i < group_list.length; i++) {
|
|
27726
|
+
const group = group_list[i];
|
|
27727
|
+
for (const commit of group.commits) {
|
|
27728
|
+
// update git commit message with stack id
|
|
27729
|
+
const message_with_id = write$1(commit.full_message, group.id);
|
|
27730
|
+
// get first 12 characters of commit sha
|
|
27731
|
+
const sha = commit.sha.slice(0, 12);
|
|
27732
|
+
// generate git revise entry
|
|
27733
|
+
const entry_lines = [`++ pick ${sha}`, message_with_id];
|
|
27734
|
+
const entry = entry_lines.join("\n");
|
|
27735
|
+
entry_list.push(entry);
|
|
27736
|
+
}
|
|
27737
|
+
}
|
|
27738
|
+
const todo = entry_list.join("\n\n");
|
|
27739
|
+
return todo;
|
|
27740
|
+
}
|
|
27741
|
+
|
|
27654
27742
|
function write(args) {
|
|
27655
27743
|
const stack_table = table(args);
|
|
27656
27744
|
let result = args.body;
|
|
@@ -27770,17 +27858,141 @@ async function run$2(props) {
|
|
|
27770
27858
|
continue;
|
|
27771
27859
|
}
|
|
27772
27860
|
if (i > 0) {
|
|
27773
|
-
const
|
|
27774
|
-
const
|
|
27775
|
-
rebase_merge_base =
|
|
27861
|
+
const prev_group = commit_range.group_list[i - 1];
|
|
27862
|
+
const prev_commit = prev_group.commits[prev_group.commits.length - 1];
|
|
27863
|
+
rebase_merge_base = prev_commit.sha;
|
|
27776
27864
|
rebase_group_index = i;
|
|
27777
27865
|
}
|
|
27778
27866
|
break;
|
|
27779
27867
|
}
|
|
27868
|
+
actions.debug(`rebase_merge_base=${rebase_merge_base}`);
|
|
27869
|
+
actions.debug(`rebase_group_index=${rebase_group_index}`);
|
|
27870
|
+
actions.debug(`commit_range=${JSON.stringify(commit_range, null, 2)}`);
|
|
27780
27871
|
try {
|
|
27781
27872
|
// must perform rebase from repo root for applying git patch
|
|
27782
27873
|
process.chdir(repo_root);
|
|
27783
27874
|
await cli(`pwd`);
|
|
27875
|
+
if (argv["rebase"] === "git-revise") {
|
|
27876
|
+
await rebase_git_revise();
|
|
27877
|
+
}
|
|
27878
|
+
else {
|
|
27879
|
+
await rebase_cherry_pick();
|
|
27880
|
+
}
|
|
27881
|
+
// after all commits have been cherry-picked and amended
|
|
27882
|
+
// move the branch pointer to the newly created temporary branch
|
|
27883
|
+
// now we are in locally in sync with github and on the original branch
|
|
27884
|
+
await cli(`git branch -f ${branch_name} ${temp_branch_name}`);
|
|
27885
|
+
restore_git();
|
|
27886
|
+
actions.set((state) => {
|
|
27887
|
+
state.step = "post-rebase-status";
|
|
27888
|
+
});
|
|
27889
|
+
}
|
|
27890
|
+
catch (err) {
|
|
27891
|
+
actions.error("Unable to rebase.");
|
|
27892
|
+
if (err instanceof Error) {
|
|
27893
|
+
if (actions.isDebug()) {
|
|
27894
|
+
actions.error(err.message);
|
|
27895
|
+
}
|
|
27896
|
+
}
|
|
27897
|
+
handle_exit();
|
|
27898
|
+
}
|
|
27899
|
+
async function rebase_git_revise() {
|
|
27900
|
+
invariant(argv, "argv must exist");
|
|
27901
|
+
actions.debug(`rebase_git_revise`);
|
|
27902
|
+
actions.output(reactExports.createElement(Text, { color: colors.yellow, wrap: "truncate-end" }, "Rebasing\u2026"));
|
|
27903
|
+
// generate temporary directory and drop sequence editor script
|
|
27904
|
+
const tmp_git_sequence_editor_path = path.join(os.tmpdir(), "git-sequence-editor.sh");
|
|
27905
|
+
actions.debug(`tmp_git_sequence_editor_path=${tmp_git_sequence_editor_path}`);
|
|
27906
|
+
// replaced at build time with literal contents of `scripts/git-sequence-editor.sh`
|
|
27907
|
+
const GIT_SEQUENCE_EDITOR_SCRIPT = `#!/bin/sh
|
|
27908
|
+
|
|
27909
|
+
# Example
|
|
27910
|
+
#
|
|
27911
|
+
# GIT_REVISE_TODO="abc" GIT_EDITOR="$(pwd)/scripts/git-sequence-editor.sh" git revise --edit -i head~4
|
|
27912
|
+
#
|
|
27913
|
+
# Note
|
|
27914
|
+
# ----------------
|
|
27915
|
+
# Use \`GIT_EDITOR\` above instead of \`GIT_SEQUENCE_EDITOR\` because \`git revise\` does not use
|
|
27916
|
+
# \`GIT_SEQUENCE_EDITOR\` when passing the \`--edit\` flag, but does work without the \`--edit\` flag
|
|
27917
|
+
#
|
|
27918
|
+
#
|
|
27919
|
+
|
|
27920
|
+
# debug print env variables
|
|
27921
|
+
echo "GIT_REVISE_TODO=$GIT_REVISE_TODO"
|
|
27922
|
+
echo "CLI=$0 $*"
|
|
27923
|
+
echo "PWD=$(pwd)"
|
|
27924
|
+
|
|
27925
|
+
# ensure \`GIT_REVISE_TODO\` is not empty
|
|
27926
|
+
if [ -z "$GIT_REVISE_TODO" ]; then
|
|
27927
|
+
echo "🚨 GIT_REVISE_TODO environment variable is empty" >&2
|
|
27928
|
+
exit 1
|
|
27929
|
+
fi
|
|
27930
|
+
|
|
27931
|
+
# first argument into git sequence editor is git-revise-todo file
|
|
27932
|
+
git_revise_todo_path="$1"
|
|
27933
|
+
|
|
27934
|
+
# debug print git-revise-todo file passed into command
|
|
27935
|
+
echo "$git_revise_todo_path"
|
|
27936
|
+
echo "----- START -----"
|
|
27937
|
+
cat "$git_revise_todo_path"
|
|
27938
|
+
echo "------ END ------"
|
|
27939
|
+
|
|
27940
|
+
# write content of \`GIT_REVISE_TODO\` env variable to \`git_revise_todo_path\`
|
|
27941
|
+
echo "$GIT_REVISE_TODO" > "$git_revise_todo_path"
|
|
27942
|
+
`;
|
|
27943
|
+
// write script to temporary path
|
|
27944
|
+
fs.writeFileSync(tmp_git_sequence_editor_path, GIT_SEQUENCE_EDITOR_SCRIPT);
|
|
27945
|
+
// ensure script is executable
|
|
27946
|
+
fs.chmodSync(tmp_git_sequence_editor_path, "755");
|
|
27947
|
+
// create temporary branch
|
|
27948
|
+
await cli(`git checkout -b ${temp_branch_name}`);
|
|
27949
|
+
const git_revise_todo = GitReviseTodo({ rebase_group_index, commit_range });
|
|
27950
|
+
// execute cli with temporary git sequence editor script
|
|
27951
|
+
// revise from merge base to pick correct commits
|
|
27952
|
+
await cli([
|
|
27953
|
+
`GIT_EDITOR="${tmp_git_sequence_editor_path}"`,
|
|
27954
|
+
`GIT_REVISE_TODO="${git_revise_todo}"`,
|
|
27955
|
+
`git`,
|
|
27956
|
+
`revise --edit -i ${rebase_merge_base}`,
|
|
27957
|
+
]);
|
|
27958
|
+
// start from HEAD and work backward to rebase_group_index
|
|
27959
|
+
const push_group_list = [];
|
|
27960
|
+
let lookback_index = 0;
|
|
27961
|
+
for (let i = 0; i < commit_range.group_list.length; i++) {
|
|
27962
|
+
const index = commit_range.group_list.length - 1 - i;
|
|
27963
|
+
// do not go past rebase_group_index
|
|
27964
|
+
if (index < rebase_group_index) {
|
|
27965
|
+
break;
|
|
27966
|
+
}
|
|
27967
|
+
const group = commit_range.group_list[index];
|
|
27968
|
+
// console.debug({ i, index, group });
|
|
27969
|
+
if (i > 0) {
|
|
27970
|
+
const prev_group = commit_range.group_list[index + 1];
|
|
27971
|
+
lookback_index += prev_group.commits.length;
|
|
27972
|
+
}
|
|
27973
|
+
// console.debug(`git show head~${lookback_index}`);
|
|
27974
|
+
// push group and lookback_index onto front of push_group_list
|
|
27975
|
+
push_group_list.unshift({ group, lookback_index });
|
|
27976
|
+
}
|
|
27977
|
+
const pr_url_list = commit_range.group_list.map(get_group_url);
|
|
27978
|
+
// use push_group_list to sync each group HEAD to github
|
|
27979
|
+
for (const push_group of push_group_list) {
|
|
27980
|
+
const { group } = push_group;
|
|
27981
|
+
// move to temporary branch for resetting to lookback_index to create PR
|
|
27982
|
+
await cli(`git checkout -b ${group.id}`);
|
|
27983
|
+
// prepare branch for sync, reset to commit at lookback index
|
|
27984
|
+
await cli(`git reset --hard HEAD~${push_group.lookback_index}`);
|
|
27985
|
+
await sync_group_github({ group, pr_url_list, skip_checkout: true });
|
|
27986
|
+
// done, remove temp push branch and move back to temp branch
|
|
27987
|
+
await cli(`git checkout ${temp_branch_name}`);
|
|
27988
|
+
await cli(`git branch -D ${group.id}`);
|
|
27989
|
+
}
|
|
27990
|
+
// finally, ensure all prs have the updated stack table from updated pr_url_list
|
|
27991
|
+
await update_pr_tables(pr_url_list);
|
|
27992
|
+
}
|
|
27993
|
+
async function rebase_cherry_pick() {
|
|
27994
|
+
invariant(argv, "argv must exist");
|
|
27995
|
+
actions.debug("rebase_cherry_pick");
|
|
27784
27996
|
// create temporary branch based on merge base
|
|
27785
27997
|
await cli(`git checkout -b ${temp_branch_name} ${rebase_merge_base}`);
|
|
27786
27998
|
const pr_url_list = commit_range.group_list.map(get_group_url);
|
|
@@ -27790,7 +28002,6 @@ async function run$2(props) {
|
|
|
27790
28002
|
actions.output(reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow, wrap: "truncate-end" }), message: "Rebasing {group}\u2026", values: {
|
|
27791
28003
|
group: (reactExports.createElement(Brackets, null, group.pr?.title || group.title || group.id)),
|
|
27792
28004
|
} }));
|
|
27793
|
-
const selected_url = get_group_url(group);
|
|
27794
28005
|
// cherry-pick and amend commits one by one
|
|
27795
28006
|
for (const commit of group.commits) {
|
|
27796
28007
|
// ensure clean base to avoid conflicts when applying patch
|
|
@@ -27801,63 +28012,78 @@ async function run$2(props) {
|
|
|
27801
28012
|
await cli(`rm ${PATCH_FILE}`);
|
|
27802
28013
|
// add all changes to stage
|
|
27803
28014
|
await cli(`git add --all`);
|
|
27804
|
-
const new_message =
|
|
28015
|
+
const new_message = write$1(commit.full_message, group.id);
|
|
27805
28016
|
const git_commit_comand = [`git commit -m "${new_message}"`];
|
|
27806
28017
|
if (argv.verify === false) {
|
|
27807
28018
|
git_commit_comand.push("--no-verify");
|
|
27808
28019
|
}
|
|
27809
28020
|
await cli(git_commit_comand);
|
|
27810
28021
|
}
|
|
27811
|
-
|
|
27812
|
-
|
|
27813
|
-
|
|
27814
|
-
|
|
27815
|
-
|
|
27816
|
-
|
|
27817
|
-
|
|
27818
|
-
|
|
27819
|
-
|
|
27820
|
-
|
|
27821
|
-
|
|
27822
|
-
|
|
27823
|
-
|
|
27824
|
-
|
|
27825
|
-
|
|
27826
|
-
|
|
27827
|
-
|
|
27828
|
-
|
|
27829
|
-
|
|
27830
|
-
|
|
27831
|
-
|
|
27832
|
-
|
|
27833
|
-
|
|
27834
|
-
|
|
27835
|
-
|
|
27836
|
-
|
|
27837
|
-
|
|
27838
|
-
|
|
27839
|
-
|
|
27840
|
-
|
|
27841
|
-
|
|
27842
|
-
|
|
27843
|
-
|
|
27844
|
-
|
|
27845
|
-
|
|
27846
|
-
|
|
27847
|
-
|
|
27848
|
-
|
|
27849
|
-
|
|
27850
|
-
|
|
27851
|
-
|
|
27852
|
-
|
|
27853
|
-
|
|
27854
|
-
|
|
27855
|
-
|
|
27856
|
-
|
|
28022
|
+
await sync_group_github({ group, pr_url_list, skip_checkout: false });
|
|
28023
|
+
}
|
|
28024
|
+
// finally, ensure all prs have the updated stack table from updated pr_url_list
|
|
28025
|
+
await update_pr_tables(pr_url_list);
|
|
28026
|
+
}
|
|
28027
|
+
async function sync_group_github(args) {
|
|
28028
|
+
if (props.skipSync) {
|
|
28029
|
+
return;
|
|
28030
|
+
}
|
|
28031
|
+
const { group, pr_url_list } = args;
|
|
28032
|
+
invariant(argv, "argv must exist");
|
|
28033
|
+
invariant(group.base, "group.base must exist");
|
|
28034
|
+
actions.output(reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow, wrap: "truncate-end" }), message: "Syncing {group}\u2026", values: {
|
|
28035
|
+
group: (reactExports.createElement(Brackets, null, group.pr?.title || group.title || group.id)),
|
|
28036
|
+
} }));
|
|
28037
|
+
// push to origin since github requires commit shas to line up perfectly
|
|
28038
|
+
const git_push_command = [`git push -f origin HEAD:${group.id}`];
|
|
28039
|
+
if (argv.verify === false) {
|
|
28040
|
+
git_push_command.push("--no-verify");
|
|
28041
|
+
}
|
|
28042
|
+
await cli(git_push_command);
|
|
28043
|
+
const selected_url = get_group_url(group);
|
|
28044
|
+
if (group.pr) {
|
|
28045
|
+
// ensure base matches pr in github
|
|
28046
|
+
await pr_edit({
|
|
28047
|
+
branch: group.id,
|
|
28048
|
+
base: group.base,
|
|
28049
|
+
body: write({
|
|
28050
|
+
body: group.pr.body,
|
|
28051
|
+
pr_url_list,
|
|
28052
|
+
selected_url,
|
|
28053
|
+
}),
|
|
28054
|
+
});
|
|
28055
|
+
}
|
|
28056
|
+
else {
|
|
28057
|
+
if (!args.skip_checkout) {
|
|
28058
|
+
// delete local group branch if leftover
|
|
28059
|
+
await cli(`git branch -D ${group.id}`, { ignoreExitCode: true });
|
|
28060
|
+
// move to temporary branch for creating pr
|
|
28061
|
+
await cli(`git checkout -b ${group.id}`);
|
|
28062
|
+
}
|
|
28063
|
+
// create pr in github
|
|
28064
|
+
const pr_url = await pr_create({
|
|
28065
|
+
branch: group.id,
|
|
28066
|
+
base: group.base,
|
|
28067
|
+
title: group.title,
|
|
28068
|
+
body: "",
|
|
28069
|
+
});
|
|
28070
|
+
if (!pr_url) {
|
|
28071
|
+
throw new Error("unable to create pr");
|
|
28072
|
+
}
|
|
28073
|
+
// update pr_url_list with created pr_url
|
|
28074
|
+
for (let i = 0; i < pr_url_list.length; i++) {
|
|
28075
|
+
const url = pr_url_list[i];
|
|
28076
|
+
if (url === selected_url) {
|
|
28077
|
+
pr_url_list[i] = pr_url;
|
|
27857
28078
|
}
|
|
27858
28079
|
}
|
|
28080
|
+
// move back to temp branch
|
|
28081
|
+
if (!args.skip_checkout) {
|
|
28082
|
+
await cli(`git checkout ${temp_branch_name}`);
|
|
28083
|
+
}
|
|
27859
28084
|
}
|
|
27860
|
-
|
|
28085
|
+
}
|
|
28086
|
+
async function update_pr_tables(pr_url_list) {
|
|
27861
28087
|
for (let i = 0; i < commit_range.group_list.length; i++) {
|
|
27862
28088
|
const group = commit_range.group_list[i];
|
|
27863
28089
|
// use the updated pr_url_list to get the actual selected_url
|
|
@@ -27881,23 +28107,6 @@ async function run$2(props) {
|
|
|
27881
28107
|
});
|
|
27882
28108
|
}
|
|
27883
28109
|
}
|
|
27884
|
-
// after all commits have been cherry-picked and amended
|
|
27885
|
-
// move the branch pointer to the newly created temporary branch
|
|
27886
|
-
// now we are in locally in sync with github and on the original branch
|
|
27887
|
-
await cli(`git branch -f ${branch_name} ${temp_branch_name}`);
|
|
27888
|
-
restore_git();
|
|
27889
|
-
actions.set((state) => {
|
|
27890
|
-
state.step = "post-rebase-status";
|
|
27891
|
-
});
|
|
27892
|
-
}
|
|
27893
|
-
catch (err) {
|
|
27894
|
-
actions.error("Unable to rebase.");
|
|
27895
|
-
if (err instanceof Error) {
|
|
27896
|
-
if (actions.isDebug()) {
|
|
27897
|
-
actions.error(err.message);
|
|
27898
|
-
}
|
|
27899
|
-
}
|
|
27900
|
-
handle_exit();
|
|
27901
28110
|
}
|
|
27902
28111
|
// cleanup git operations if cancelled during manual rebase
|
|
27903
28112
|
function restore_git() {
|
|
@@ -28451,6 +28660,7 @@ function SelectCommitRangesInternal(props) {
|
|
|
28451
28660
|
switch (inputLower) {
|
|
28452
28661
|
case "s":
|
|
28453
28662
|
state.step = "manual-rebase";
|
|
28663
|
+
// state.step = "manual-rebase-no-sync";
|
|
28454
28664
|
break;
|
|
28455
28665
|
}
|
|
28456
28666
|
});
|
|
@@ -34080,6 +34290,12 @@ async function command() {
|
|
|
34080
34290
|
type: "boolean",
|
|
34081
34291
|
default: true,
|
|
34082
34292
|
description: "Skip git hooks such as pre-commit and pre-push",
|
|
34293
|
+
})
|
|
34294
|
+
.option("rebase", {
|
|
34295
|
+
type: "string",
|
|
34296
|
+
choices: [Rebase["git-revise"], Rebase["cherry-pick"]],
|
|
34297
|
+
default: Rebase["git-revise"],
|
|
34298
|
+
description: `Rebase implementation, "${Rebase["git-revise"]}" by default to perform in-memory rebase. "${Rebase["cherry-pick"]}" can be used to use disk and incrementally rebase each commit`,
|
|
34083
34299
|
})
|
|
34084
34300
|
.option("verbose", {
|
|
34085
34301
|
type: "boolean",
|
|
@@ -34111,14 +34327,19 @@ async function command() {
|
|
|
34111
34327
|
description: "Mock local store metadata for testing",
|
|
34112
34328
|
})
|
|
34113
34329
|
// do not wrap to 80 columns (yargs default)
|
|
34114
|
-
//
|
|
34115
|
-
|
|
34330
|
+
// 140 seems to look decent so lets do that instead
|
|
34331
|
+
// passing null will wrap to terminal width
|
|
34332
|
+
.wrap(140)
|
|
34116
34333
|
// disallow unknown options
|
|
34117
34334
|
.strict()
|
|
34118
|
-
.version("1.0
|
|
34335
|
+
.version("1.2.0" )
|
|
34119
34336
|
.showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`")
|
|
34120
34337
|
.help("help", "Show usage via `git stack help`").argv);
|
|
34121
34338
|
}
|
|
34339
|
+
const Rebase = Object.freeze({
|
|
34340
|
+
"git-revise": "git-revise",
|
|
34341
|
+
"cherry-pick": "cherry-pick",
|
|
34342
|
+
});
|
|
34122
34343
|
|
|
34123
34344
|
command()
|
|
34124
34345
|
.then((argv) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-stack-cli",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "magus",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
"scripts",
|
|
18
18
|
"src",
|
|
19
19
|
"package-lock.json",
|
|
20
|
-
"rollup.config.
|
|
20
|
+
"rollup.config.js",
|
|
21
21
|
"tsconfig.json"
|
|
22
22
|
],
|
|
23
23
|
"scripts": {
|
|
24
24
|
"dev": "npm run build -- --watch",
|
|
25
|
-
"build": "rollup -c rollup.config.
|
|
26
|
-
"build:standalone": "bun run scripts/build-standalone.ts",
|
|
25
|
+
"build": "rollup -c rollup.config.js",
|
|
26
|
+
"build:standalone": "GIT_STACK_STANDALONE=true bun run scripts/build-standalone.ts",
|
|
27
27
|
"release:npm": "bun run scripts/release-npm.ts",
|
|
28
28
|
"release:github": "bun run scripts/release-github.ts",
|
|
29
29
|
"release:brew": "bun run scripts/release-brew.ts",
|
|
@@ -12,10 +12,16 @@ import replace from "@rollup/plugin-replace";
|
|
|
12
12
|
import typescript from "@rollup/plugin-typescript";
|
|
13
13
|
|
|
14
14
|
const SCRIPT_DIR = path.dirname(url.fileURLToPath(import.meta.url));
|
|
15
|
+
|
|
15
16
|
const PACKAGE_JSON_PATH = path.join(SCRIPT_DIR, "package.json");
|
|
17
|
+
const PACKAGE_JSON = JSON.parse(await fs.readFile(PACKAGE_JSON_PATH, "utf-8"));
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
+
// prettier-ignore
|
|
20
|
+
const GIT_SEQUENCE_EDITOR_SCRIPT_PATH = path.join(SCRIPT_DIR, "scripts", "git-sequence-editor.sh");
|
|
21
|
+
// prettier-ignore
|
|
22
|
+
const UNSAFE_GIT_SEQUENCE_EDITOR_SCRIPT = await fs.readFile(GIT_SEQUENCE_EDITOR_SCRIPT_PATH, "utf-8");
|
|
23
|
+
// prettier-ignore
|
|
24
|
+
const GIT_SEQUENCE_EDITOR_SCRIPT = UNSAFE_GIT_SEQUENCE_EDITOR_SCRIPT.replace(/`/g, "\\`");
|
|
19
25
|
|
|
20
26
|
export default {
|
|
21
27
|
input: "src/index.tsx",
|
|
@@ -39,7 +45,9 @@ export default {
|
|
|
39
45
|
preventAssignment: true,
|
|
40
46
|
values: {
|
|
41
47
|
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
42
|
-
"process.env.CLI_VERSION": JSON.stringify(String(
|
|
48
|
+
"process.env.CLI_VERSION": JSON.stringify(String(PACKAGE_JSON.version)),
|
|
49
|
+
"process.env.GIT_STACK_STANDALONE": process.env.GIT_STACK_STANDALONE,
|
|
50
|
+
"process.env.GIT_SEQUENCE_EDITOR_SCRIPT": GIT_SEQUENCE_EDITOR_SCRIPT,
|
|
43
51
|
},
|
|
44
52
|
}),
|
|
45
53
|
],
|