git-stack-cli 1.13.0 → 1.13.1
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/dist/cjs/index.cjs +504 -372
- package/package.json +1 -1
- package/src/app/Main.tsx +4 -0
- package/src/app/ManualRebase.tsx +78 -281
- package/src/app/Store.tsx +8 -0
- package/src/app/SyncGithub.tsx +322 -0
- package/src/commands/Rebase.tsx +29 -6
- package/src/index.tsx +4 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -26213,6 +26213,7 @@ const BaseStore = createStore()(immer((set, get) => ({
|
|
|
26213
26213
|
commit_map: null,
|
|
26214
26214
|
pr_templates: [],
|
|
26215
26215
|
pr_template_body: null,
|
|
26216
|
+
sync_github: null,
|
|
26216
26217
|
step: "loading",
|
|
26217
26218
|
output: [],
|
|
26218
26219
|
pending_output: {},
|
|
@@ -30322,9 +30323,9 @@ function DirtyCheck(props) {
|
|
|
30322
30323
|
|
|
30323
30324
|
function GatherMetadata(props) {
|
|
30324
30325
|
const fallback = (reactExports.createElement(Text, { color: colors.yellow }, "Gathering local git information\u2026"));
|
|
30325
|
-
return (reactExports.createElement(Await, { fallback: fallback, function: run$
|
|
30326
|
+
return (reactExports.createElement(Await, { fallback: fallback, function: run$a }, props.children));
|
|
30326
30327
|
}
|
|
30327
|
-
async function run$
|
|
30328
|
+
async function run$a() {
|
|
30328
30329
|
const actions = Store.getState().actions;
|
|
30329
30330
|
const argv = Store.getState().argv;
|
|
30330
30331
|
try {
|
|
@@ -30418,9 +30419,9 @@ function format_time(date) {
|
|
|
30418
30419
|
}
|
|
30419
30420
|
|
|
30420
30421
|
function GithubApiError() {
|
|
30421
|
-
return reactExports.createElement(Await, { fallback: null, function: run$
|
|
30422
|
+
return reactExports.createElement(Await, { fallback: null, function: run$9 });
|
|
30422
30423
|
}
|
|
30423
|
-
async function run$
|
|
30424
|
+
async function run$9() {
|
|
30424
30425
|
const actions = Store.getState().actions;
|
|
30425
30426
|
const res = await cli(`gh api https://api.github.com/rate_limit`);
|
|
30426
30427
|
const res_json = JSON.parse(res.stdout);
|
|
@@ -30462,7 +30463,7 @@ function LocalCommitStatus(props) {
|
|
|
30462
30463
|
if (argv["mock-metadata"]) {
|
|
30463
30464
|
return (reactExports.createElement(Await, { fallback: fallback, function: mock_metadata }, props.children));
|
|
30464
30465
|
}
|
|
30465
|
-
return (reactExports.createElement(Await, { fallback: fallback, function: run$
|
|
30466
|
+
return (reactExports.createElement(Await, { fallback: fallback, function: run$8 }, props.children));
|
|
30466
30467
|
}
|
|
30467
30468
|
async function mock_metadata() {
|
|
30468
30469
|
const module = await Promise.resolve().then(function () { return metadata; });
|
|
@@ -30472,7 +30473,7 @@ async function mock_metadata() {
|
|
|
30472
30473
|
state.step = "status";
|
|
30473
30474
|
});
|
|
30474
30475
|
}
|
|
30475
|
-
async function run$
|
|
30476
|
+
async function run$8() {
|
|
30476
30477
|
const actions = Store.getState().actions;
|
|
30477
30478
|
try {
|
|
30478
30479
|
const commit_range = await range();
|
|
@@ -30552,9 +30553,21 @@ function encode(value) {
|
|
|
30552
30553
|
}
|
|
30553
30554
|
|
|
30554
30555
|
function Rebase() {
|
|
30555
|
-
|
|
30556
|
+
const abort_handler = reactExports.useRef(() => { });
|
|
30557
|
+
reactExports.useEffect(function listen_sigint() {
|
|
30558
|
+
process.once("SIGINT", sigint_handler);
|
|
30559
|
+
return function cleanup() {
|
|
30560
|
+
process.removeListener("SIGINT", sigint_handler);
|
|
30561
|
+
};
|
|
30562
|
+
function sigint_handler() {
|
|
30563
|
+
abort_handler.current();
|
|
30564
|
+
}
|
|
30565
|
+
}, []);
|
|
30566
|
+
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Rebasing commits\u2026"), function: async function () {
|
|
30567
|
+
await Rebase.run({ abort_handler });
|
|
30568
|
+
} }));
|
|
30556
30569
|
}
|
|
30557
|
-
Rebase.run = async function run() {
|
|
30570
|
+
Rebase.run = async function run(args) {
|
|
30558
30571
|
const state = Store.getState();
|
|
30559
30572
|
const actions = state.actions;
|
|
30560
30573
|
const branch_name = state.branch_name;
|
|
@@ -30566,7 +30579,10 @@ Rebase.run = async function run() {
|
|
|
30566
30579
|
invariant(commit_range, "commit_range must exist");
|
|
30567
30580
|
invariant(repo_root, "repo_root must exist");
|
|
30568
30581
|
// always listen for SIGINT event and restore git state
|
|
30569
|
-
|
|
30582
|
+
args.abort_handler.current = async function sigint_handler() {
|
|
30583
|
+
actions.output(reactExports.createElement(Text, { color: colors.red }, "\uD83D\uDEA8 Abort"));
|
|
30584
|
+
handle_exit(19);
|
|
30585
|
+
};
|
|
30570
30586
|
const temp_branch_name = `${branch_name}_${short_id()}`;
|
|
30571
30587
|
try {
|
|
30572
30588
|
// actions.debug(`commit_range=${JSON.stringify(commit_range, null, 2)}`);
|
|
@@ -30629,7 +30645,7 @@ Rebase.run = async function run() {
|
|
|
30629
30645
|
actions.error(err.message);
|
|
30630
30646
|
}
|
|
30631
30647
|
}
|
|
30632
|
-
handle_exit();
|
|
30648
|
+
handle_exit(20);
|
|
30633
30649
|
}
|
|
30634
30650
|
// cleanup git operations if cancelled during manual rebase
|
|
30635
30651
|
function restore_git() {
|
|
@@ -30651,7 +30667,7 @@ Rebase.run = async function run() {
|
|
|
30651
30667
|
}
|
|
30652
30668
|
cli.sync(`pwd`, spawn_options);
|
|
30653
30669
|
}
|
|
30654
|
-
function handle_exit() {
|
|
30670
|
+
function handle_exit(code) {
|
|
30655
30671
|
actions.output(reactExports.createElement(Text, { color: colors.yellow },
|
|
30656
30672
|
"Restoring ",
|
|
30657
30673
|
reactExports.createElement(Brackets, null, branch_name),
|
|
@@ -30661,7 +30677,7 @@ Rebase.run = async function run() {
|
|
|
30661
30677
|
"Restored ",
|
|
30662
30678
|
reactExports.createElement(Brackets, null, branch_name),
|
|
30663
30679
|
"."));
|
|
30664
|
-
actions.exit(
|
|
30680
|
+
actions.exit(code);
|
|
30665
30681
|
}
|
|
30666
30682
|
};
|
|
30667
30683
|
|
|
@@ -30669,117 +30685,22 @@ function LocalMergeRebase() {
|
|
|
30669
30685
|
return reactExports.createElement(Rebase, null);
|
|
30670
30686
|
}
|
|
30671
30687
|
|
|
30672
|
-
function write(args) {
|
|
30673
|
-
const stack_table = table(args);
|
|
30674
|
-
let result = args.body;
|
|
30675
|
-
if (RE.stack_table_link.test(result)) {
|
|
30676
|
-
// replace stack table
|
|
30677
|
-
result = result.replace(RE.stack_table_link, stack_table);
|
|
30678
|
-
}
|
|
30679
|
-
else if (RE.stack_table_legacy.test(result)) {
|
|
30680
|
-
// replace stack table
|
|
30681
|
-
result = result.replace(RE.stack_table_legacy, stack_table);
|
|
30682
|
-
}
|
|
30683
|
-
else {
|
|
30684
|
-
// append stack table
|
|
30685
|
-
result = `${result}\n\n${stack_table}`;
|
|
30686
|
-
}
|
|
30687
|
-
result = result.trimEnd();
|
|
30688
|
-
return result;
|
|
30689
|
-
}
|
|
30690
|
-
function table(args) {
|
|
30691
|
-
const stack_pr_url_list = [...args.pr_url_list];
|
|
30692
|
-
const old_stack = parse(args.body);
|
|
30693
|
-
// remove existing stack pr urls from the old stack pr urls
|
|
30694
|
-
for (const pr_url of stack_pr_url_list) {
|
|
30695
|
-
old_stack.delete(pr_url);
|
|
30696
|
-
}
|
|
30697
|
-
// add remaining old stack pr urls to the front of stack pr url list
|
|
30698
|
-
const old_pr_list = Array.from(old_stack.keys());
|
|
30699
|
-
old_pr_list.reverse();
|
|
30700
|
-
for (const pr_url of old_pr_list) {
|
|
30701
|
-
stack_pr_url_list.unshift(pr_url);
|
|
30702
|
-
}
|
|
30703
|
-
const stack_list = [];
|
|
30704
|
-
const num_digits = String(stack_pr_url_list.length).length;
|
|
30705
|
-
for (let i = 0; i < stack_pr_url_list.length; i++) {
|
|
30706
|
-
const pr_url = stack_pr_url_list[i];
|
|
30707
|
-
const selected = args.selected_url === pr_url;
|
|
30708
|
-
let icon;
|
|
30709
|
-
if (old_stack.has(pr_url)) {
|
|
30710
|
-
icon = "✅";
|
|
30711
|
-
}
|
|
30712
|
-
else if (selected) {
|
|
30713
|
-
icon = "👉";
|
|
30714
|
-
}
|
|
30715
|
-
else {
|
|
30716
|
-
icon = "⏳";
|
|
30717
|
-
}
|
|
30718
|
-
const num = String(i + 1).padStart(num_digits, "0");
|
|
30719
|
-
stack_list.push(TEMPLATE.row({ icon, num, pr_url }));
|
|
30720
|
-
}
|
|
30721
|
-
if (!stack_list.length) {
|
|
30722
|
-
return "";
|
|
30723
|
-
}
|
|
30724
|
-
return TEMPLATE.stack_table_link(["", ...stack_list, "", ""].join("\n"));
|
|
30725
|
-
}
|
|
30726
|
-
function parse(body) {
|
|
30727
|
-
let stack_table_match = body.match(RE.stack_table_link);
|
|
30728
|
-
if (!stack_table_match?.groups) {
|
|
30729
|
-
stack_table_match = body.match(RE.stack_table_legacy);
|
|
30730
|
-
}
|
|
30731
|
-
if (!stack_table_match?.groups) {
|
|
30732
|
-
return new Map();
|
|
30733
|
-
}
|
|
30734
|
-
const rows_string = stack_table_match.groups["rows"];
|
|
30735
|
-
const row_list = rows_string.split("\n");
|
|
30736
|
-
const result = new Map();
|
|
30737
|
-
for (const row of row_list) {
|
|
30738
|
-
const row_match = row.match(RE.row);
|
|
30739
|
-
const parsed_row = row_match?.groups;
|
|
30740
|
-
if (!parsed_row) {
|
|
30741
|
-
// skip invalid row
|
|
30742
|
-
continue;
|
|
30743
|
-
}
|
|
30744
|
-
if (!RE.pr_url.test(parsed_row.pr_url)) {
|
|
30745
|
-
continue;
|
|
30746
|
-
}
|
|
30747
|
-
result.set(parsed_row.pr_url, parsed_row);
|
|
30748
|
-
}
|
|
30749
|
-
return result;
|
|
30750
|
-
}
|
|
30751
|
-
const TEMPLATE = {
|
|
30752
|
-
stack_table_legacy(rows) {
|
|
30753
|
-
return `#### git stack${rows}`;
|
|
30754
|
-
},
|
|
30755
|
-
stack_table_link(rows) {
|
|
30756
|
-
return `#### [git stack](https://github.com/magus/git-stack-cli)${rows}`;
|
|
30757
|
-
},
|
|
30758
|
-
row(args) {
|
|
30759
|
-
return `- ${args.icon} \`${args.num}\` ${args.pr_url}`;
|
|
30760
|
-
},
|
|
30761
|
-
};
|
|
30762
|
-
const RE = {
|
|
30763
|
-
// https://regex101.com/r/kqB9Ft/1
|
|
30764
|
-
stack_table_legacy: new RegExp(TEMPLATE.stack_table_legacy("\\s+(?<rows>(?:- [^\r^\n]*(?:[\r\n]+)?)+)")),
|
|
30765
|
-
stack_table_link: new RegExp(TEMPLATE.stack_table_link("ROWS")
|
|
30766
|
-
.replace("[", "\\[")
|
|
30767
|
-
.replace("]", "\\]")
|
|
30768
|
-
.replace("(", "\\(")
|
|
30769
|
-
.replace(")", "\\)")
|
|
30770
|
-
.replace("ROWS", "\\s+(?<rows>(?:- [^\r^\n]*(?:[\r\n]+)?)+)")),
|
|
30771
|
-
row: new RegExp(TEMPLATE.row({
|
|
30772
|
-
icon: "(?<icon>.+)",
|
|
30773
|
-
num: "(?<num>\\d+)",
|
|
30774
|
-
pr_url: "(?<pr_url>.+)",
|
|
30775
|
-
})),
|
|
30776
|
-
pr_url: /^https:\/\/.*$/,
|
|
30777
|
-
};
|
|
30778
|
-
|
|
30779
30688
|
function ManualRebase() {
|
|
30780
|
-
|
|
30689
|
+
const abort_handler = reactExports.useRef(() => { });
|
|
30690
|
+
reactExports.useEffect(function listen_sigint() {
|
|
30691
|
+
process.once("SIGINT", sigint_handler);
|
|
30692
|
+
return function cleanup() {
|
|
30693
|
+
process.removeListener("SIGINT", sigint_handler);
|
|
30694
|
+
};
|
|
30695
|
+
async function sigint_handler() {
|
|
30696
|
+
abort_handler.current();
|
|
30697
|
+
}
|
|
30698
|
+
}, []);
|
|
30699
|
+
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Rebasing commits\u2026"), function: async function () {
|
|
30700
|
+
await run$7({ abort_handler });
|
|
30701
|
+
} }));
|
|
30781
30702
|
}
|
|
30782
|
-
async function run$
|
|
30703
|
+
async function run$7(args) {
|
|
30783
30704
|
const state = Store.getState();
|
|
30784
30705
|
const actions = state.actions;
|
|
30785
30706
|
const argv = state.argv;
|
|
@@ -30792,54 +30713,53 @@ async function run$6() {
|
|
|
30792
30713
|
invariant(commit_map, "commit_map must exist");
|
|
30793
30714
|
invariant(repo_root, "repo_root must exist");
|
|
30794
30715
|
// always listen for SIGINT event and restore git state
|
|
30795
|
-
|
|
30796
|
-
|
|
30797
|
-
|
|
30798
|
-
|
|
30799
|
-
let commit_range = await range(commit_map);
|
|
30800
|
-
// reverse group list to ensure we create git revise in correct order
|
|
30801
|
-
commit_range.group_list.reverse();
|
|
30802
|
-
for (const commit of commit_range.commit_list) {
|
|
30803
|
-
const group_from_map = commit_map[commit.sha];
|
|
30804
|
-
commit.branch_id = group_from_map.id;
|
|
30805
|
-
commit.title = group_from_map.title;
|
|
30806
|
-
}
|
|
30807
|
-
await GitReviseTodo.execute({
|
|
30808
|
-
rebase_group_index: 0,
|
|
30809
|
-
rebase_merge_base: merge_base,
|
|
30810
|
-
commit_range,
|
|
30811
|
-
});
|
|
30812
|
-
let DEFAULT_PR_BODY = "";
|
|
30813
|
-
if (state.pr_template_body) {
|
|
30814
|
-
DEFAULT_PR_BODY = state.pr_template_body;
|
|
30815
|
-
}
|
|
30716
|
+
args.abort_handler.current = function sigint_handler() {
|
|
30717
|
+
actions.output(reactExports.createElement(Text, { color: colors.red }, "\uD83D\uDEA8 Abort"));
|
|
30718
|
+
handle_exit(15);
|
|
30719
|
+
};
|
|
30816
30720
|
const temp_branch_name = `${branch_name}_${short_id()}`;
|
|
30817
|
-
|
|
30818
|
-
|
|
30819
|
-
|
|
30820
|
-
|
|
30821
|
-
|
|
30822
|
-
|
|
30823
|
-
|
|
30824
|
-
|
|
30825
|
-
|
|
30721
|
+
try {
|
|
30722
|
+
// get latest merge_base relative to local master
|
|
30723
|
+
const merge_base = (await cli(`git merge-base HEAD ${master_branch}`))
|
|
30724
|
+
.stdout;
|
|
30725
|
+
// immediately paint all commit to preserve selected commit ranges
|
|
30726
|
+
let commit_range = await range(commit_map);
|
|
30727
|
+
// reverse group list to ensure we create git revise in correct order
|
|
30728
|
+
commit_range.group_list.reverse();
|
|
30729
|
+
for (const commit of commit_range.commit_list) {
|
|
30730
|
+
const group_from_map = commit_map[commit.sha];
|
|
30731
|
+
commit.branch_id = group_from_map.id;
|
|
30732
|
+
commit.title = group_from_map.title;
|
|
30826
30733
|
}
|
|
30827
|
-
|
|
30828
|
-
|
|
30829
|
-
|
|
30830
|
-
|
|
30831
|
-
|
|
30734
|
+
await GitReviseTodo.execute({
|
|
30735
|
+
rebase_group_index: 0,
|
|
30736
|
+
rebase_merge_base: merge_base,
|
|
30737
|
+
commit_range,
|
|
30738
|
+
});
|
|
30739
|
+
commit_range = await range(commit_map);
|
|
30740
|
+
// reverse commit list so that we can cherry-pick in order
|
|
30741
|
+
commit_range.group_list.reverse();
|
|
30742
|
+
let rebase_merge_base = merge_base;
|
|
30743
|
+
let rebase_group_index = 0;
|
|
30744
|
+
for (let i = 0; i < commit_range.group_list.length; i++) {
|
|
30745
|
+
const group = commit_range.group_list[i];
|
|
30746
|
+
if (!group.dirty) {
|
|
30747
|
+
continue;
|
|
30748
|
+
}
|
|
30749
|
+
if (i > 0) {
|
|
30750
|
+
const prev_group = commit_range.group_list[i - 1];
|
|
30751
|
+
const prev_commit = prev_group.commits[prev_group.commits.length - 1];
|
|
30752
|
+
rebase_merge_base = prev_commit.sha;
|
|
30753
|
+
rebase_group_index = i;
|
|
30754
|
+
}
|
|
30755
|
+
break;
|
|
30832
30756
|
}
|
|
30833
|
-
|
|
30834
|
-
|
|
30835
|
-
|
|
30836
|
-
actions.debug(`rebase_group_index = ${rebase_group_index}`);
|
|
30837
|
-
// actions.debug(`commit_range=${JSON.stringify(commit_range, null, 2)}`);
|
|
30838
|
-
try {
|
|
30757
|
+
actions.debug(`rebase_merge_base = ${rebase_merge_base}`);
|
|
30758
|
+
actions.debug(`rebase_group_index = ${rebase_group_index}`);
|
|
30759
|
+
// actions.debug(`commit_range=${JSON.stringify(commit_range, null, 2)}`);
|
|
30839
30760
|
// must perform rebase from repo root for applying git patch
|
|
30840
30761
|
process.chdir(repo_root);
|
|
30841
30762
|
await cli(`pwd`);
|
|
30842
|
-
actions.output(reactExports.createElement(Text, { color: colors.yellow, wrap: "truncate-end" }, "Rebasing\u2026"));
|
|
30843
30763
|
// create temporary branch
|
|
30844
30764
|
await cli(`git checkout -b ${temp_branch_name}`);
|
|
30845
30765
|
await GitReviseTodo.execute({
|
|
@@ -30850,13 +30770,18 @@ async function run$6() {
|
|
|
30850
30770
|
// after all commits have been modified move the pointer
|
|
30851
30771
|
// of original branch to the newly created temporary branch
|
|
30852
30772
|
await cli(`git branch -f ${branch_name} ${temp_branch_name}`);
|
|
30773
|
+
restore_git();
|
|
30853
30774
|
if (argv.sync) {
|
|
30854
|
-
|
|
30775
|
+
actions.set((state) => {
|
|
30776
|
+
state.step = "sync-github";
|
|
30777
|
+
state.sync_github = { commit_range, rebase_group_index };
|
|
30778
|
+
});
|
|
30779
|
+
}
|
|
30780
|
+
else {
|
|
30781
|
+
actions.set((state) => {
|
|
30782
|
+
state.step = "post-rebase-status";
|
|
30783
|
+
});
|
|
30855
30784
|
}
|
|
30856
|
-
restore_git();
|
|
30857
|
-
actions.set((state) => {
|
|
30858
|
-
state.step = "post-rebase-status";
|
|
30859
|
-
});
|
|
30860
30785
|
}
|
|
30861
30786
|
catch (err) {
|
|
30862
30787
|
if (err instanceof Error) {
|
|
@@ -30866,164 +30791,7 @@ async function run$6() {
|
|
|
30866
30791
|
if (!argv.verbose) {
|
|
30867
30792
|
actions.error("Try again with `--verbose` to see more information.");
|
|
30868
30793
|
}
|
|
30869
|
-
handle_exit();
|
|
30870
|
-
}
|
|
30871
|
-
async function sync_github() {
|
|
30872
|
-
// in order to sync we walk from rebase_group_index to HEAD
|
|
30873
|
-
// checking out each group and syncing to github
|
|
30874
|
-
// start from HEAD and work backward to rebase_group_index
|
|
30875
|
-
const push_group_list = [];
|
|
30876
|
-
let lookback_index = 0;
|
|
30877
|
-
for (let i = 0; i < commit_range.group_list.length; i++) {
|
|
30878
|
-
const index = commit_range.group_list.length - 1 - i;
|
|
30879
|
-
// do not go past rebase_group_index
|
|
30880
|
-
if (index < rebase_group_index) {
|
|
30881
|
-
break;
|
|
30882
|
-
}
|
|
30883
|
-
const group = commit_range.group_list[index];
|
|
30884
|
-
// console.debug({ i, index, group });
|
|
30885
|
-
if (i > 0) {
|
|
30886
|
-
const prev_group = commit_range.group_list[index + 1];
|
|
30887
|
-
lookback_index += prev_group.commits.length;
|
|
30888
|
-
}
|
|
30889
|
-
// console.debug(`git show head~${lookback_index}`);
|
|
30890
|
-
// push group and lookback_index onto front of push_group_list
|
|
30891
|
-
push_group_list.unshift({ group, lookback_index });
|
|
30892
|
-
}
|
|
30893
|
-
actions.output(reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow, wrap: "truncate-end" }), message: "Syncing {group_list}\u2026", values: {
|
|
30894
|
-
group_list: (reactExports.createElement(reactExports.Fragment, null, push_group_list.map((push_group) => {
|
|
30895
|
-
const group = push_group.group;
|
|
30896
|
-
return (reactExports.createElement(Brackets, { key: group.id }, group.pr?.title || group.title || group.id));
|
|
30897
|
-
}))),
|
|
30898
|
-
} }));
|
|
30899
|
-
// for all push targets in push_group_list
|
|
30900
|
-
// things that can be done in parallel are grouped by numbers
|
|
30901
|
-
//
|
|
30902
|
-
// -----------------------------------
|
|
30903
|
-
// 1 (before_push) temp mark draft
|
|
30904
|
-
// --------------------------------------
|
|
30905
|
-
// 2 push simultaneously to github
|
|
30906
|
-
// --------------------------------------
|
|
30907
|
-
// 2 create PR / edit PR
|
|
30908
|
-
// 2 (after_push) undo temp mark draft
|
|
30909
|
-
// --------------------------------------
|
|
30910
|
-
const before_push_tasks = [];
|
|
30911
|
-
for (const push_group of push_group_list) {
|
|
30912
|
-
before_push_tasks.push(before_push(push_group));
|
|
30913
|
-
}
|
|
30914
|
-
await Promise.all(before_push_tasks);
|
|
30915
|
-
const push_target_list = push_group_list.map((push_group) => {
|
|
30916
|
-
return `HEAD~${push_group.lookback_index}:${push_group.group.id}`;
|
|
30917
|
-
});
|
|
30918
|
-
const push_target_args = push_target_list.join(" ");
|
|
30919
|
-
const git_push_command = [`git push -f origin ${push_target_args}`];
|
|
30920
|
-
if (argv.verify === false) {
|
|
30921
|
-
git_push_command.push("--no-verify");
|
|
30922
|
-
}
|
|
30923
|
-
await cli(git_push_command);
|
|
30924
|
-
const pr_url_list = commit_range.group_list.map(get_group_url);
|
|
30925
|
-
const after_push_tasks = [];
|
|
30926
|
-
for (const push_group of push_group_list) {
|
|
30927
|
-
const group = push_group.group;
|
|
30928
|
-
after_push_tasks.push(after_push({ group, pr_url_list }));
|
|
30929
|
-
}
|
|
30930
|
-
await Promise.all(after_push_tasks);
|
|
30931
|
-
// finally, ensure all prs have the updated stack table from updated pr_url_list
|
|
30932
|
-
for (let i = 0; i < commit_range.group_list.length; i++) {
|
|
30933
|
-
const group = commit_range.group_list[i];
|
|
30934
|
-
// use the updated pr_url_list to get the actual selected_url
|
|
30935
|
-
const selected_url = pr_url_list[i];
|
|
30936
|
-
invariant(group.base, "group.base must exist");
|
|
30937
|
-
const body = group.pr?.body || DEFAULT_PR_BODY;
|
|
30938
|
-
const update_body = write({
|
|
30939
|
-
body,
|
|
30940
|
-
pr_url_list,
|
|
30941
|
-
selected_url,
|
|
30942
|
-
});
|
|
30943
|
-
if (update_body === body) {
|
|
30944
|
-
actions.debug(`Skipping body update for ${selected_url}`);
|
|
30945
|
-
}
|
|
30946
|
-
else {
|
|
30947
|
-
actions.debug(`Update body for ${selected_url}`);
|
|
30948
|
-
await pr_edit({
|
|
30949
|
-
branch: group.id,
|
|
30950
|
-
base: group.base,
|
|
30951
|
-
body: update_body,
|
|
30952
|
-
});
|
|
30953
|
-
}
|
|
30954
|
-
}
|
|
30955
|
-
}
|
|
30956
|
-
async function before_push(args) {
|
|
30957
|
-
const { group } = args;
|
|
30958
|
-
invariant(group.base, "group.base must exist");
|
|
30959
|
-
// we may temporarily mark PR as a draft before editing it
|
|
30960
|
-
// if it is not already a draft PR, to avoid notification spam
|
|
30961
|
-
let is_temp_draft = !group.pr?.isDraft;
|
|
30962
|
-
// before pushing reset base to master temporarily
|
|
30963
|
-
// avoid accidentally pointing to orphaned parent commit
|
|
30964
|
-
// should hopefully fix issues where a PR includes a bunch of commits after pushing
|
|
30965
|
-
if (group.pr) {
|
|
30966
|
-
if (!group.pr.isDraft) {
|
|
30967
|
-
is_temp_draft = true;
|
|
30968
|
-
}
|
|
30969
|
-
if (is_temp_draft) {
|
|
30970
|
-
await pr_draft({
|
|
30971
|
-
branch: group.id,
|
|
30972
|
-
draft: true,
|
|
30973
|
-
});
|
|
30974
|
-
}
|
|
30975
|
-
await pr_edit({
|
|
30976
|
-
branch: group.id,
|
|
30977
|
-
base: master_branch,
|
|
30978
|
-
});
|
|
30979
|
-
}
|
|
30980
|
-
}
|
|
30981
|
-
async function after_push(args) {
|
|
30982
|
-
const { group, pr_url_list } = args;
|
|
30983
|
-
invariant(group.base, "group.base must exist");
|
|
30984
|
-
const selected_url = get_group_url(group);
|
|
30985
|
-
if (group.pr) {
|
|
30986
|
-
// ensure base matches pr in github
|
|
30987
|
-
await pr_edit({
|
|
30988
|
-
branch: group.id,
|
|
30989
|
-
base: group.base,
|
|
30990
|
-
body: write({
|
|
30991
|
-
body: group.pr.body,
|
|
30992
|
-
pr_url_list,
|
|
30993
|
-
selected_url,
|
|
30994
|
-
}),
|
|
30995
|
-
});
|
|
30996
|
-
// we may temporarily mark PR as a draft before editing it
|
|
30997
|
-
// if it is not already a draft PR, to avoid notification spam
|
|
30998
|
-
let is_temp_draft = !group.pr?.isDraft;
|
|
30999
|
-
if (is_temp_draft) {
|
|
31000
|
-
// mark pr as ready for review again
|
|
31001
|
-
await pr_draft({
|
|
31002
|
-
branch: group.id,
|
|
31003
|
-
draft: false,
|
|
31004
|
-
});
|
|
31005
|
-
}
|
|
31006
|
-
}
|
|
31007
|
-
else {
|
|
31008
|
-
// create pr in github
|
|
31009
|
-
const pr_url = await pr_create({
|
|
31010
|
-
branch: group.id,
|
|
31011
|
-
base: group.base,
|
|
31012
|
-
title: group.title,
|
|
31013
|
-
body: DEFAULT_PR_BODY,
|
|
31014
|
-
draft: argv.draft,
|
|
31015
|
-
});
|
|
31016
|
-
if (!pr_url) {
|
|
31017
|
-
throw new Error("unable to create pr");
|
|
31018
|
-
}
|
|
31019
|
-
// update pr_url_list with created pr_url
|
|
31020
|
-
for (let i = 0; i < pr_url_list.length; i++) {
|
|
31021
|
-
const url = pr_url_list[i];
|
|
31022
|
-
if (url === selected_url) {
|
|
31023
|
-
pr_url_list[i] = pr_url;
|
|
31024
|
-
}
|
|
31025
|
-
}
|
|
31026
|
-
}
|
|
30794
|
+
handle_exit(16);
|
|
31027
30795
|
}
|
|
31028
30796
|
// cleanup git operations if cancelled during manual rebase
|
|
31029
30797
|
function restore_git() {
|
|
@@ -31045,7 +30813,7 @@ async function run$6() {
|
|
|
31045
30813
|
}
|
|
31046
30814
|
cli.sync(`pwd`, spawn_options);
|
|
31047
30815
|
}
|
|
31048
|
-
function handle_exit() {
|
|
30816
|
+
function handle_exit(code) {
|
|
31049
30817
|
actions.output(reactExports.createElement(Text, { color: colors.yellow },
|
|
31050
30818
|
"Restoring ",
|
|
31051
30819
|
reactExports.createElement(Brackets, null, branch_name),
|
|
@@ -31055,10 +30823,9 @@ async function run$6() {
|
|
|
31055
30823
|
"Restored ",
|
|
31056
30824
|
reactExports.createElement(Brackets, null, branch_name),
|
|
31057
30825
|
"."));
|
|
31058
|
-
actions.exit(
|
|
30826
|
+
actions.exit(code);
|
|
31059
30827
|
}
|
|
31060
30828
|
}
|
|
31061
|
-
const get_group_url = (group) => group.pr?.url || group.id;
|
|
31062
30829
|
|
|
31063
30830
|
function Table(props) {
|
|
31064
30831
|
if (!props.data.length) {
|
|
@@ -31237,9 +31004,9 @@ function get_status_bold(row) {
|
|
|
31237
31004
|
}
|
|
31238
31005
|
|
|
31239
31006
|
function PostRebaseStatus() {
|
|
31240
|
-
return reactExports.createElement(Await, { fallback: null, function: run$
|
|
31007
|
+
return reactExports.createElement(Await, { fallback: null, function: run$6 });
|
|
31241
31008
|
}
|
|
31242
|
-
async function run$
|
|
31009
|
+
async function run$6() {
|
|
31243
31010
|
const actions = Store.getState().actions;
|
|
31244
31011
|
// reset github pr cache before refreshing via commit range below
|
|
31245
31012
|
actions.reset_pr();
|
|
@@ -31269,9 +31036,9 @@ function PreLocalMergeRebase() {
|
|
|
31269
31036
|
}
|
|
31270
31037
|
|
|
31271
31038
|
function PreManualRebase() {
|
|
31272
|
-
return reactExports.createElement(Await, { fallback: null, function: run$
|
|
31039
|
+
return reactExports.createElement(Await, { fallback: null, function: run$5 });
|
|
31273
31040
|
}
|
|
31274
|
-
async function run$
|
|
31041
|
+
async function run$5() {
|
|
31275
31042
|
const state = Store.getState();
|
|
31276
31043
|
const actions = state.actions;
|
|
31277
31044
|
const repo_root = state.repo_root;
|
|
@@ -31773,59 +31540,419 @@ function SelectCommitRangesInternal(props) {
|
|
|
31773
31540
|
set_group_input(false);
|
|
31774
31541
|
}
|
|
31775
31542
|
}
|
|
31776
|
-
const SYMBOL = {
|
|
31777
|
-
left: "←",
|
|
31778
|
-
right: "→",
|
|
31779
|
-
enter: "Enter",
|
|
31543
|
+
const SYMBOL = {
|
|
31544
|
+
left: "←",
|
|
31545
|
+
right: "→",
|
|
31546
|
+
enter: "Enter",
|
|
31547
|
+
};
|
|
31548
|
+
|
|
31549
|
+
function Status() {
|
|
31550
|
+
return reactExports.createElement(Await, { fallback: null, function: run$4 });
|
|
31551
|
+
}
|
|
31552
|
+
async function run$4() {
|
|
31553
|
+
const state = Store.getState();
|
|
31554
|
+
const actions = state.actions;
|
|
31555
|
+
const argv = state.argv;
|
|
31556
|
+
const commit_range = Store.getState().commit_range;
|
|
31557
|
+
invariant(commit_range, "commit_range must exist");
|
|
31558
|
+
actions.output(reactExports.createElement(StatusTable, null));
|
|
31559
|
+
let needs_rebase = false;
|
|
31560
|
+
let needs_update = false;
|
|
31561
|
+
for (const group of commit_range.group_list) {
|
|
31562
|
+
if (group.dirty) {
|
|
31563
|
+
needs_update = true;
|
|
31564
|
+
}
|
|
31565
|
+
if (group.pr?.state === "MERGED") {
|
|
31566
|
+
needs_rebase = true;
|
|
31567
|
+
}
|
|
31568
|
+
}
|
|
31569
|
+
if (argv.check) {
|
|
31570
|
+
actions.exit(0);
|
|
31571
|
+
}
|
|
31572
|
+
else if (needs_rebase) {
|
|
31573
|
+
Store.setState((state) => {
|
|
31574
|
+
state.step = "pre-local-merge-rebase";
|
|
31575
|
+
});
|
|
31576
|
+
}
|
|
31577
|
+
else if (needs_update) {
|
|
31578
|
+
Store.setState((state) => {
|
|
31579
|
+
state.step = "pre-select-commit-ranges";
|
|
31580
|
+
});
|
|
31581
|
+
}
|
|
31582
|
+
else if (argv.force) {
|
|
31583
|
+
Store.setState((state) => {
|
|
31584
|
+
state.step = "select-commit-ranges";
|
|
31585
|
+
});
|
|
31586
|
+
}
|
|
31587
|
+
else {
|
|
31588
|
+
actions.output(reactExports.createElement(Text, null, "\u2705 Everything up to date."));
|
|
31589
|
+
actions.output(reactExports.createElement(Text, { color: colors.gray },
|
|
31590
|
+
reactExports.createElement(Text, null, "Run with"),
|
|
31591
|
+
reactExports.createElement(Text, { bold: true, color: colors.yellow }, ` --force `),
|
|
31592
|
+
reactExports.createElement(Text, null, "to force update all pull requests.")));
|
|
31593
|
+
actions.exit(0);
|
|
31594
|
+
}
|
|
31595
|
+
}
|
|
31596
|
+
|
|
31597
|
+
/**
|
|
31598
|
+
* Gets the last element of `array`.
|
|
31599
|
+
*
|
|
31600
|
+
* @static
|
|
31601
|
+
* @memberOf _
|
|
31602
|
+
* @since 0.1.0
|
|
31603
|
+
* @category Array
|
|
31604
|
+
* @param {Array} array The array to query.
|
|
31605
|
+
* @returns {*} Returns the last element of `array`.
|
|
31606
|
+
* @example
|
|
31607
|
+
*
|
|
31608
|
+
* _.last([1, 2, 3]);
|
|
31609
|
+
* // => 3
|
|
31610
|
+
*/
|
|
31611
|
+
|
|
31612
|
+
function last(array) {
|
|
31613
|
+
var length = array == null ? 0 : array.length;
|
|
31614
|
+
return length ? array[length - 1] : undefined;
|
|
31615
|
+
}
|
|
31616
|
+
|
|
31617
|
+
var last_1 = last;
|
|
31618
|
+
|
|
31619
|
+
var last$1 = /*@__PURE__*/getDefaultExportFromCjs(last_1);
|
|
31620
|
+
|
|
31621
|
+
function write(args) {
|
|
31622
|
+
const stack_table = table(args);
|
|
31623
|
+
let result = args.body;
|
|
31624
|
+
if (RE.stack_table_link.test(result)) {
|
|
31625
|
+
// replace stack table
|
|
31626
|
+
result = result.replace(RE.stack_table_link, stack_table);
|
|
31627
|
+
}
|
|
31628
|
+
else if (RE.stack_table_legacy.test(result)) {
|
|
31629
|
+
// replace stack table
|
|
31630
|
+
result = result.replace(RE.stack_table_legacy, stack_table);
|
|
31631
|
+
}
|
|
31632
|
+
else {
|
|
31633
|
+
// append stack table
|
|
31634
|
+
result = `${result}\n\n${stack_table}`;
|
|
31635
|
+
}
|
|
31636
|
+
result = result.trimEnd();
|
|
31637
|
+
return result;
|
|
31638
|
+
}
|
|
31639
|
+
function table(args) {
|
|
31640
|
+
const stack_pr_url_list = [...args.pr_url_list];
|
|
31641
|
+
const old_stack = parse(args.body);
|
|
31642
|
+
// remove existing stack pr urls from the old stack pr urls
|
|
31643
|
+
for (const pr_url of stack_pr_url_list) {
|
|
31644
|
+
old_stack.delete(pr_url);
|
|
31645
|
+
}
|
|
31646
|
+
// add remaining old stack pr urls to the front of stack pr url list
|
|
31647
|
+
const old_pr_list = Array.from(old_stack.keys());
|
|
31648
|
+
old_pr_list.reverse();
|
|
31649
|
+
for (const pr_url of old_pr_list) {
|
|
31650
|
+
stack_pr_url_list.unshift(pr_url);
|
|
31651
|
+
}
|
|
31652
|
+
const stack_list = [];
|
|
31653
|
+
const num_digits = String(stack_pr_url_list.length).length;
|
|
31654
|
+
for (let i = 0; i < stack_pr_url_list.length; i++) {
|
|
31655
|
+
const pr_url = stack_pr_url_list[i];
|
|
31656
|
+
const selected = args.selected_url === pr_url;
|
|
31657
|
+
let icon;
|
|
31658
|
+
if (old_stack.has(pr_url)) {
|
|
31659
|
+
icon = "✅";
|
|
31660
|
+
}
|
|
31661
|
+
else if (selected) {
|
|
31662
|
+
icon = "👉";
|
|
31663
|
+
}
|
|
31664
|
+
else {
|
|
31665
|
+
icon = "⏳";
|
|
31666
|
+
}
|
|
31667
|
+
const num = String(i + 1).padStart(num_digits, "0");
|
|
31668
|
+
stack_list.push(TEMPLATE.row({ icon, num, pr_url }));
|
|
31669
|
+
}
|
|
31670
|
+
if (!stack_list.length) {
|
|
31671
|
+
return "";
|
|
31672
|
+
}
|
|
31673
|
+
return TEMPLATE.stack_table_link(["", ...stack_list, "", ""].join("\n"));
|
|
31674
|
+
}
|
|
31675
|
+
function parse(body) {
|
|
31676
|
+
let stack_table_match = body.match(RE.stack_table_link);
|
|
31677
|
+
if (!stack_table_match?.groups) {
|
|
31678
|
+
stack_table_match = body.match(RE.stack_table_legacy);
|
|
31679
|
+
}
|
|
31680
|
+
if (!stack_table_match?.groups) {
|
|
31681
|
+
return new Map();
|
|
31682
|
+
}
|
|
31683
|
+
const rows_string = stack_table_match.groups["rows"];
|
|
31684
|
+
const row_list = rows_string.split("\n");
|
|
31685
|
+
const result = new Map();
|
|
31686
|
+
for (const row of row_list) {
|
|
31687
|
+
const row_match = row.match(RE.row);
|
|
31688
|
+
const parsed_row = row_match?.groups;
|
|
31689
|
+
if (!parsed_row) {
|
|
31690
|
+
// skip invalid row
|
|
31691
|
+
continue;
|
|
31692
|
+
}
|
|
31693
|
+
if (!RE.pr_url.test(parsed_row.pr_url)) {
|
|
31694
|
+
continue;
|
|
31695
|
+
}
|
|
31696
|
+
result.set(parsed_row.pr_url, parsed_row);
|
|
31697
|
+
}
|
|
31698
|
+
return result;
|
|
31699
|
+
}
|
|
31700
|
+
const TEMPLATE = {
|
|
31701
|
+
stack_table_legacy(rows) {
|
|
31702
|
+
return `#### git stack${rows}`;
|
|
31703
|
+
},
|
|
31704
|
+
stack_table_link(rows) {
|
|
31705
|
+
return `#### [git stack](https://github.com/magus/git-stack-cli)${rows}`;
|
|
31706
|
+
},
|
|
31707
|
+
row(args) {
|
|
31708
|
+
return `- ${args.icon} \`${args.num}\` ${args.pr_url}`;
|
|
31709
|
+
},
|
|
31710
|
+
};
|
|
31711
|
+
const RE = {
|
|
31712
|
+
// https://regex101.com/r/kqB9Ft/1
|
|
31713
|
+
stack_table_legacy: new RegExp(TEMPLATE.stack_table_legacy("\\s+(?<rows>(?:- [^\r^\n]*(?:[\r\n]+)?)+)")),
|
|
31714
|
+
stack_table_link: new RegExp(TEMPLATE.stack_table_link("ROWS")
|
|
31715
|
+
.replace("[", "\\[")
|
|
31716
|
+
.replace("]", "\\]")
|
|
31717
|
+
.replace("(", "\\(")
|
|
31718
|
+
.replace(")", "\\)")
|
|
31719
|
+
.replace("ROWS", "\\s+(?<rows>(?:- [^\r^\n]*(?:[\r\n]+)?)+)")),
|
|
31720
|
+
row: new RegExp(TEMPLATE.row({
|
|
31721
|
+
icon: "(?<icon>.+)",
|
|
31722
|
+
num: "(?<num>\\d+)",
|
|
31723
|
+
pr_url: "(?<pr_url>.+)",
|
|
31724
|
+
})),
|
|
31725
|
+
pr_url: /^https:\/\/.*$/,
|
|
31780
31726
|
};
|
|
31781
31727
|
|
|
31782
|
-
function
|
|
31783
|
-
|
|
31728
|
+
function SyncGithub() {
|
|
31729
|
+
const abort_handler = reactExports.useRef(() => { });
|
|
31730
|
+
reactExports.useEffect(function listen_sigint() {
|
|
31731
|
+
process.once("SIGINT", sigint_handler);
|
|
31732
|
+
return function cleanup() {
|
|
31733
|
+
process.removeListener("SIGINT", sigint_handler);
|
|
31734
|
+
};
|
|
31735
|
+
function sigint_handler() {
|
|
31736
|
+
abort_handler.current();
|
|
31737
|
+
}
|
|
31738
|
+
}, []);
|
|
31739
|
+
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Syncing\u2026"), function: async function () {
|
|
31740
|
+
await run$3({ abort_handler });
|
|
31741
|
+
} }));
|
|
31784
31742
|
}
|
|
31785
|
-
async function run$3() {
|
|
31743
|
+
async function run$3(args) {
|
|
31786
31744
|
const state = Store.getState();
|
|
31787
31745
|
const actions = state.actions;
|
|
31788
31746
|
const argv = state.argv;
|
|
31789
|
-
const
|
|
31790
|
-
|
|
31791
|
-
|
|
31792
|
-
|
|
31793
|
-
|
|
31794
|
-
|
|
31795
|
-
|
|
31796
|
-
|
|
31747
|
+
const branch_name = state.branch_name;
|
|
31748
|
+
const commit_map = state.commit_map;
|
|
31749
|
+
const master_branch = state.master_branch;
|
|
31750
|
+
const repo_root = state.repo_root;
|
|
31751
|
+
const sync_github = state.sync_github;
|
|
31752
|
+
invariant(branch_name, "branch_name must exist");
|
|
31753
|
+
invariant(commit_map, "commit_map must exist");
|
|
31754
|
+
invariant(repo_root, "repo_root must exist");
|
|
31755
|
+
invariant(sync_github, "sync_github must exist");
|
|
31756
|
+
const commit_range = sync_github.commit_range;
|
|
31757
|
+
const rebase_group_index = sync_github.rebase_group_index;
|
|
31758
|
+
// always listen for SIGINT event and restore pr state
|
|
31759
|
+
args.abort_handler.current = function sigint_handler() {
|
|
31760
|
+
actions.output(reactExports.createElement(Text, { color: colors.red }, "\uD83D\uDEA8 Abort"));
|
|
31761
|
+
handle_exit(17);
|
|
31762
|
+
};
|
|
31763
|
+
let DEFAULT_PR_BODY = "";
|
|
31764
|
+
if (state.pr_template_body) {
|
|
31765
|
+
DEFAULT_PR_BODY = state.pr_template_body;
|
|
31766
|
+
}
|
|
31767
|
+
const push_group_list = get_push_group_list();
|
|
31768
|
+
// for all push targets in push_group_list
|
|
31769
|
+
// things that can be done in parallel are grouped by numbers
|
|
31770
|
+
//
|
|
31771
|
+
// -----------------------------------
|
|
31772
|
+
// 1 (before_push) temp mark draft
|
|
31773
|
+
// --------------------------------------
|
|
31774
|
+
// 2 push simultaneously to github
|
|
31775
|
+
// --------------------------------------
|
|
31776
|
+
// 2 create PR / edit PR
|
|
31777
|
+
// 2 (after_push) undo temp mark draft
|
|
31778
|
+
// --------------------------------------
|
|
31779
|
+
try {
|
|
31780
|
+
const before_push_tasks = [];
|
|
31781
|
+
for (const group of push_group_list) {
|
|
31782
|
+
before_push_tasks.push(before_push({ group }));
|
|
31797
31783
|
}
|
|
31798
|
-
|
|
31799
|
-
|
|
31784
|
+
await Promise.all(before_push_tasks);
|
|
31785
|
+
// git push -f origin HEAD~6:OtVX7Qvrw HEAD~3:E63ytp5dj HEAD~2:gs-NBabNSjXA HEAD~1:gs-UGVJdKNoD HEAD~0:gs-6LAx-On4
|
|
31786
|
+
const git_push_command = [`git push -f origin`];
|
|
31787
|
+
if (argv.verify === false) {
|
|
31788
|
+
git_push_command.push("--no-verify");
|
|
31789
|
+
}
|
|
31790
|
+
for (const group of push_group_list) {
|
|
31791
|
+
const last_commit = last$1(group.commits);
|
|
31792
|
+
invariant(last_commit, "last_commit must exist");
|
|
31793
|
+
const target = `${last_commit.sha}:${group.id}`;
|
|
31794
|
+
git_push_command.push(target);
|
|
31795
|
+
}
|
|
31796
|
+
await cli(git_push_command);
|
|
31797
|
+
const pr_url_list = commit_range.group_list.map(get_group_url);
|
|
31798
|
+
const after_push_tasks = [];
|
|
31799
|
+
for (const group of push_group_list) {
|
|
31800
|
+
after_push_tasks.push(after_push({ group, pr_url_list }));
|
|
31801
|
+
}
|
|
31802
|
+
await Promise.all(after_push_tasks);
|
|
31803
|
+
// finally, ensure all prs have the updated stack table from updated pr_url_list
|
|
31804
|
+
// this step must come after the after_push since that step may create new PRs
|
|
31805
|
+
// we need the urls for all prs at this step so we run it after the after_push
|
|
31806
|
+
const update_pr_body_tasks = [];
|
|
31807
|
+
for (let i = 0; i < commit_range.group_list.length; i++) {
|
|
31808
|
+
const group = commit_range.group_list[i];
|
|
31809
|
+
// use the updated pr_url_list to get the actual selected_url
|
|
31810
|
+
const selected_url = pr_url_list[i];
|
|
31811
|
+
const task = update_pr_body({ group, selected_url, pr_url_list });
|
|
31812
|
+
update_pr_body_tasks.push(task);
|
|
31813
|
+
}
|
|
31814
|
+
await Promise.all(update_pr_body_tasks);
|
|
31815
|
+
actions.set((state) => {
|
|
31816
|
+
state.step = "post-rebase-status";
|
|
31817
|
+
});
|
|
31818
|
+
}
|
|
31819
|
+
catch (err) {
|
|
31820
|
+
if (err instanceof Error) {
|
|
31821
|
+
actions.error(err.message);
|
|
31822
|
+
}
|
|
31823
|
+
actions.error("Unable to sync.");
|
|
31824
|
+
if (!argv.verbose) {
|
|
31825
|
+
actions.error("Try again with `--verbose` to see more information.");
|
|
31800
31826
|
}
|
|
31827
|
+
await handle_exit(18);
|
|
31801
31828
|
}
|
|
31802
|
-
|
|
31803
|
-
|
|
31829
|
+
function get_push_group_list() {
|
|
31830
|
+
// start from HEAD and work backward to rebase_group_index
|
|
31831
|
+
const push_group_list = [];
|
|
31832
|
+
for (let i = 0; i < commit_range.group_list.length; i++) {
|
|
31833
|
+
const index = commit_range.group_list.length - 1 - i;
|
|
31834
|
+
// do not go past rebase_group_index
|
|
31835
|
+
if (index < rebase_group_index) {
|
|
31836
|
+
break;
|
|
31837
|
+
}
|
|
31838
|
+
const group = commit_range.group_list[index];
|
|
31839
|
+
push_group_list.unshift(group);
|
|
31840
|
+
}
|
|
31841
|
+
return push_group_list;
|
|
31804
31842
|
}
|
|
31805
|
-
|
|
31806
|
-
|
|
31807
|
-
|
|
31808
|
-
|
|
31843
|
+
async function before_push(args) {
|
|
31844
|
+
const { group } = args;
|
|
31845
|
+
invariant(group.base, "group.base must exist");
|
|
31846
|
+
// we may temporarily mark PR as a draft before editing it
|
|
31847
|
+
// if it is not already a draft PR, to avoid notification spam
|
|
31848
|
+
let is_temp_draft = !group.pr?.isDraft;
|
|
31849
|
+
// before pushing reset base to master temporarily
|
|
31850
|
+
// avoid accidentally pointing to orphaned parent commit
|
|
31851
|
+
// should hopefully fix issues where a PR includes a bunch of commits after pushing
|
|
31852
|
+
if (group.pr) {
|
|
31853
|
+
if (!group.pr.isDraft) {
|
|
31854
|
+
is_temp_draft = true;
|
|
31855
|
+
}
|
|
31856
|
+
if (is_temp_draft) {
|
|
31857
|
+
await pr_draft({
|
|
31858
|
+
branch: group.id,
|
|
31859
|
+
draft: true,
|
|
31860
|
+
});
|
|
31861
|
+
}
|
|
31862
|
+
await pr_edit({
|
|
31863
|
+
branch: group.id,
|
|
31864
|
+
base: master_branch,
|
|
31865
|
+
});
|
|
31866
|
+
}
|
|
31809
31867
|
}
|
|
31810
|
-
|
|
31811
|
-
|
|
31812
|
-
|
|
31813
|
-
|
|
31868
|
+
async function after_push(args) {
|
|
31869
|
+
const { group, pr_url_list } = args;
|
|
31870
|
+
invariant(group.base, "group.base must exist");
|
|
31871
|
+
const selected_url = get_group_url(group);
|
|
31872
|
+
if (group.pr) {
|
|
31873
|
+
// ensure base matches pr in github
|
|
31874
|
+
await pr_edit({
|
|
31875
|
+
branch: group.id,
|
|
31876
|
+
base: group.base,
|
|
31877
|
+
body: write({
|
|
31878
|
+
body: group.pr.body,
|
|
31879
|
+
pr_url_list,
|
|
31880
|
+
selected_url,
|
|
31881
|
+
}),
|
|
31882
|
+
});
|
|
31883
|
+
// we may temporarily mark PR as a draft before editing it
|
|
31884
|
+
// if it is not already a draft PR, to avoid notification spam
|
|
31885
|
+
let is_temp_draft = !group.pr?.isDraft;
|
|
31886
|
+
if (is_temp_draft) {
|
|
31887
|
+
// mark pr as ready for review again
|
|
31888
|
+
await pr_draft({
|
|
31889
|
+
branch: group.id,
|
|
31890
|
+
draft: false,
|
|
31891
|
+
});
|
|
31892
|
+
}
|
|
31893
|
+
}
|
|
31894
|
+
else {
|
|
31895
|
+
// create pr in github
|
|
31896
|
+
const pr_url = await pr_create({
|
|
31897
|
+
branch: group.id,
|
|
31898
|
+
base: group.base,
|
|
31899
|
+
title: group.title,
|
|
31900
|
+
body: DEFAULT_PR_BODY,
|
|
31901
|
+
draft: argv.draft,
|
|
31902
|
+
});
|
|
31903
|
+
if (!pr_url) {
|
|
31904
|
+
throw new Error("unable to create pr");
|
|
31905
|
+
}
|
|
31906
|
+
// update pr_url_list with created pr_url
|
|
31907
|
+
for (let i = 0; i < pr_url_list.length; i++) {
|
|
31908
|
+
const url = pr_url_list[i];
|
|
31909
|
+
if (url === selected_url) {
|
|
31910
|
+
pr_url_list[i] = pr_url;
|
|
31911
|
+
}
|
|
31912
|
+
}
|
|
31913
|
+
}
|
|
31814
31914
|
}
|
|
31815
|
-
|
|
31816
|
-
|
|
31817
|
-
|
|
31915
|
+
async function update_pr_body(args) {
|
|
31916
|
+
const { group, selected_url, pr_url_list } = args;
|
|
31917
|
+
invariant(group.base, "group.base must exist");
|
|
31918
|
+
const body = group.pr?.body || DEFAULT_PR_BODY;
|
|
31919
|
+
const update_body = write({
|
|
31920
|
+
body,
|
|
31921
|
+
pr_url_list,
|
|
31922
|
+
selected_url,
|
|
31818
31923
|
});
|
|
31924
|
+
if (update_body === body) {
|
|
31925
|
+
actions.debug(`Skipping body update for ${selected_url}`);
|
|
31926
|
+
}
|
|
31927
|
+
else {
|
|
31928
|
+
actions.debug(`Update body for ${selected_url}`);
|
|
31929
|
+
await pr_edit({
|
|
31930
|
+
branch: group.id,
|
|
31931
|
+
base: group.base,
|
|
31932
|
+
body: update_body,
|
|
31933
|
+
});
|
|
31934
|
+
}
|
|
31819
31935
|
}
|
|
31820
|
-
|
|
31821
|
-
actions.output(reactExports.createElement(Text,
|
|
31822
|
-
|
|
31823
|
-
|
|
31824
|
-
|
|
31825
|
-
|
|
31826
|
-
|
|
31936
|
+
function handle_exit(code) {
|
|
31937
|
+
actions.output(reactExports.createElement(Text, { color: colors.yellow }, "Restoring PR state\u2026"));
|
|
31938
|
+
for (const group of push_group_list) {
|
|
31939
|
+
// we may temporarily mark PR as a draft before editing it
|
|
31940
|
+
// if it is not already a draft PR, to avoid notification spam
|
|
31941
|
+
let is_temp_draft = !group.pr?.isDraft;
|
|
31942
|
+
// restore PR to non-draft state
|
|
31943
|
+
if (is_temp_draft) {
|
|
31944
|
+
pr_draft({
|
|
31945
|
+
branch: group.id,
|
|
31946
|
+
draft: false,
|
|
31947
|
+
})
|
|
31948
|
+
.catch(actions.error);
|
|
31949
|
+
}
|
|
31950
|
+
}
|
|
31951
|
+
actions.output(reactExports.createElement(Text, { color: colors.yellow }, "Restored PR state."));
|
|
31952
|
+
actions.exit(code);
|
|
31827
31953
|
}
|
|
31828
31954
|
}
|
|
31955
|
+
const get_group_url = (group) => group.pr?.url || group.id;
|
|
31829
31956
|
|
|
31830
31957
|
function Main() {
|
|
31831
31958
|
const step = Store.useState((state) => state.step);
|
|
@@ -31848,6 +31975,8 @@ function Main() {
|
|
|
31848
31975
|
return reactExports.createElement(PreManualRebase, null);
|
|
31849
31976
|
case "manual-rebase":
|
|
31850
31977
|
return reactExports.createElement(ManualRebase, null);
|
|
31978
|
+
case "sync-github":
|
|
31979
|
+
return reactExports.createElement(SyncGithub, null);
|
|
31851
31980
|
case "post-rebase-status":
|
|
31852
31981
|
return reactExports.createElement(PostRebaseStatus, null);
|
|
31853
31982
|
default:
|
|
@@ -37444,7 +37573,7 @@ async function command() {
|
|
|
37444
37573
|
.wrap(123)
|
|
37445
37574
|
// disallow unknown options
|
|
37446
37575
|
.strict()
|
|
37447
|
-
.version("1.13.
|
|
37576
|
+
.version("1.13.1" )
|
|
37448
37577
|
.showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`")
|
|
37449
37578
|
.help("help", "Show usage via `git stack help`")
|
|
37450
37579
|
.argv;
|
|
@@ -37529,7 +37658,10 @@ const FixupOptions = {
|
|
|
37529
37658
|
|
|
37530
37659
|
command()
|
|
37531
37660
|
.then((argv) => {
|
|
37532
|
-
const ink = render(reactExports.createElement(App, null)
|
|
37661
|
+
const ink = render(reactExports.createElement(App, null), {
|
|
37662
|
+
// If true, each update will be rendered as a separate output, without replacing the previous one.
|
|
37663
|
+
// debug: true,
|
|
37664
|
+
});
|
|
37533
37665
|
Store.setState((state) => {
|
|
37534
37666
|
state.ink = ink;
|
|
37535
37667
|
state.process_argv = process.argv;
|