git-stack-cli 1.13.0 → 1.13.2
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 +527 -373
- 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 +338 -0
- package/src/commands/Rebase.tsx +29 -6
- package/src/core/github.tsx +8 -1
- 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: {},
|
|
@@ -29781,7 +29782,13 @@ async function pr_status(branch) {
|
|
|
29781
29782
|
}
|
|
29782
29783
|
async function pr_create(args) {
|
|
29783
29784
|
const title = safe_quote(args.title);
|
|
29784
|
-
|
|
29785
|
+
// explicit refs/heads head branch to avoid creation failing
|
|
29786
|
+
//
|
|
29787
|
+
// ❯ gh pr create --head origin/gs-ED2etrzv2 --base gs-6LAx-On45 --title="2024-01-05 test" --body=""
|
|
29788
|
+
// pull request create failed: GraphQL: Head sha can't be blank, Base sha can't be blank, No commits between gs-6LAx-On45 and origin/gs-ED2etrzv2, Head ref must be a branch (createPullRequest)
|
|
29789
|
+
//
|
|
29790
|
+
// https://github.com/cli/cli/issues/5465
|
|
29791
|
+
let command = `gh pr create --head refs/heads/${args.branch} --base ${args.base} --title="${title}" --body="${args.body}"`;
|
|
29785
29792
|
if (args.draft) {
|
|
29786
29793
|
command += " --draft";
|
|
29787
29794
|
}
|
|
@@ -30322,9 +30329,9 @@ function DirtyCheck(props) {
|
|
|
30322
30329
|
|
|
30323
30330
|
function GatherMetadata(props) {
|
|
30324
30331
|
const fallback = (reactExports.createElement(Text, { color: colors.yellow }, "Gathering local git information\u2026"));
|
|
30325
|
-
return (reactExports.createElement(Await, { fallback: fallback, function: run$
|
|
30332
|
+
return (reactExports.createElement(Await, { fallback: fallback, function: run$a }, props.children));
|
|
30326
30333
|
}
|
|
30327
|
-
async function run$
|
|
30334
|
+
async function run$a() {
|
|
30328
30335
|
const actions = Store.getState().actions;
|
|
30329
30336
|
const argv = Store.getState().argv;
|
|
30330
30337
|
try {
|
|
@@ -30418,9 +30425,9 @@ function format_time(date) {
|
|
|
30418
30425
|
}
|
|
30419
30426
|
|
|
30420
30427
|
function GithubApiError() {
|
|
30421
|
-
return reactExports.createElement(Await, { fallback: null, function: run$
|
|
30428
|
+
return reactExports.createElement(Await, { fallback: null, function: run$9 });
|
|
30422
30429
|
}
|
|
30423
|
-
async function run$
|
|
30430
|
+
async function run$9() {
|
|
30424
30431
|
const actions = Store.getState().actions;
|
|
30425
30432
|
const res = await cli(`gh api https://api.github.com/rate_limit`);
|
|
30426
30433
|
const res_json = JSON.parse(res.stdout);
|
|
@@ -30462,7 +30469,7 @@ function LocalCommitStatus(props) {
|
|
|
30462
30469
|
if (argv["mock-metadata"]) {
|
|
30463
30470
|
return (reactExports.createElement(Await, { fallback: fallback, function: mock_metadata }, props.children));
|
|
30464
30471
|
}
|
|
30465
|
-
return (reactExports.createElement(Await, { fallback: fallback, function: run$
|
|
30472
|
+
return (reactExports.createElement(Await, { fallback: fallback, function: run$8 }, props.children));
|
|
30466
30473
|
}
|
|
30467
30474
|
async function mock_metadata() {
|
|
30468
30475
|
const module = await Promise.resolve().then(function () { return metadata; });
|
|
@@ -30472,7 +30479,7 @@ async function mock_metadata() {
|
|
|
30472
30479
|
state.step = "status";
|
|
30473
30480
|
});
|
|
30474
30481
|
}
|
|
30475
|
-
async function run$
|
|
30482
|
+
async function run$8() {
|
|
30476
30483
|
const actions = Store.getState().actions;
|
|
30477
30484
|
try {
|
|
30478
30485
|
const commit_range = await range();
|
|
@@ -30552,9 +30559,21 @@ function encode(value) {
|
|
|
30552
30559
|
}
|
|
30553
30560
|
|
|
30554
30561
|
function Rebase() {
|
|
30555
|
-
|
|
30562
|
+
const abort_handler = reactExports.useRef(() => { });
|
|
30563
|
+
reactExports.useEffect(function listen_sigint() {
|
|
30564
|
+
process.once("SIGINT", sigint_handler);
|
|
30565
|
+
return function cleanup() {
|
|
30566
|
+
process.removeListener("SIGINT", sigint_handler);
|
|
30567
|
+
};
|
|
30568
|
+
function sigint_handler() {
|
|
30569
|
+
abort_handler.current();
|
|
30570
|
+
}
|
|
30571
|
+
}, []);
|
|
30572
|
+
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Rebasing commits\u2026"), function: async function () {
|
|
30573
|
+
await Rebase.run({ abort_handler });
|
|
30574
|
+
} }));
|
|
30556
30575
|
}
|
|
30557
|
-
Rebase.run = async function run() {
|
|
30576
|
+
Rebase.run = async function run(args) {
|
|
30558
30577
|
const state = Store.getState();
|
|
30559
30578
|
const actions = state.actions;
|
|
30560
30579
|
const branch_name = state.branch_name;
|
|
@@ -30566,7 +30585,10 @@ Rebase.run = async function run() {
|
|
|
30566
30585
|
invariant(commit_range, "commit_range must exist");
|
|
30567
30586
|
invariant(repo_root, "repo_root must exist");
|
|
30568
30587
|
// always listen for SIGINT event and restore git state
|
|
30569
|
-
|
|
30588
|
+
args.abort_handler.current = async function sigint_handler() {
|
|
30589
|
+
actions.output(reactExports.createElement(Text, { color: colors.red }, "\uD83D\uDEA8 Abort"));
|
|
30590
|
+
handle_exit(19);
|
|
30591
|
+
};
|
|
30570
30592
|
const temp_branch_name = `${branch_name}_${short_id()}`;
|
|
30571
30593
|
try {
|
|
30572
30594
|
// actions.debug(`commit_range=${JSON.stringify(commit_range, null, 2)}`);
|
|
@@ -30629,7 +30651,7 @@ Rebase.run = async function run() {
|
|
|
30629
30651
|
actions.error(err.message);
|
|
30630
30652
|
}
|
|
30631
30653
|
}
|
|
30632
|
-
handle_exit();
|
|
30654
|
+
handle_exit(20);
|
|
30633
30655
|
}
|
|
30634
30656
|
// cleanup git operations if cancelled during manual rebase
|
|
30635
30657
|
function restore_git() {
|
|
@@ -30651,7 +30673,7 @@ Rebase.run = async function run() {
|
|
|
30651
30673
|
}
|
|
30652
30674
|
cli.sync(`pwd`, spawn_options);
|
|
30653
30675
|
}
|
|
30654
|
-
function handle_exit() {
|
|
30676
|
+
function handle_exit(code) {
|
|
30655
30677
|
actions.output(reactExports.createElement(Text, { color: colors.yellow },
|
|
30656
30678
|
"Restoring ",
|
|
30657
30679
|
reactExports.createElement(Brackets, null, branch_name),
|
|
@@ -30661,7 +30683,7 @@ Rebase.run = async function run() {
|
|
|
30661
30683
|
"Restored ",
|
|
30662
30684
|
reactExports.createElement(Brackets, null, branch_name),
|
|
30663
30685
|
"."));
|
|
30664
|
-
actions.exit(
|
|
30686
|
+
actions.exit(code);
|
|
30665
30687
|
}
|
|
30666
30688
|
};
|
|
30667
30689
|
|
|
@@ -30669,117 +30691,22 @@ function LocalMergeRebase() {
|
|
|
30669
30691
|
return reactExports.createElement(Rebase, null);
|
|
30670
30692
|
}
|
|
30671
30693
|
|
|
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
30694
|
function ManualRebase() {
|
|
30780
|
-
|
|
30695
|
+
const abort_handler = reactExports.useRef(() => { });
|
|
30696
|
+
reactExports.useEffect(function listen_sigint() {
|
|
30697
|
+
process.once("SIGINT", sigint_handler);
|
|
30698
|
+
return function cleanup() {
|
|
30699
|
+
process.removeListener("SIGINT", sigint_handler);
|
|
30700
|
+
};
|
|
30701
|
+
async function sigint_handler() {
|
|
30702
|
+
abort_handler.current();
|
|
30703
|
+
}
|
|
30704
|
+
}, []);
|
|
30705
|
+
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Rebasing commits\u2026"), function: async function () {
|
|
30706
|
+
await run$7({ abort_handler });
|
|
30707
|
+
} }));
|
|
30781
30708
|
}
|
|
30782
|
-
async function run$
|
|
30709
|
+
async function run$7(args) {
|
|
30783
30710
|
const state = Store.getState();
|
|
30784
30711
|
const actions = state.actions;
|
|
30785
30712
|
const argv = state.argv;
|
|
@@ -30792,54 +30719,53 @@ async function run$6() {
|
|
|
30792
30719
|
invariant(commit_map, "commit_map must exist");
|
|
30793
30720
|
invariant(repo_root, "repo_root must exist");
|
|
30794
30721
|
// 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
|
-
}
|
|
30722
|
+
args.abort_handler.current = function sigint_handler() {
|
|
30723
|
+
actions.output(reactExports.createElement(Text, { color: colors.red }, "\uD83D\uDEA8 Abort"));
|
|
30724
|
+
handle_exit(15);
|
|
30725
|
+
};
|
|
30816
30726
|
const temp_branch_name = `${branch_name}_${short_id()}`;
|
|
30817
|
-
|
|
30818
|
-
|
|
30819
|
-
|
|
30820
|
-
|
|
30821
|
-
|
|
30822
|
-
|
|
30823
|
-
|
|
30824
|
-
|
|
30825
|
-
|
|
30727
|
+
try {
|
|
30728
|
+
// get latest merge_base relative to local master
|
|
30729
|
+
const merge_base = (await cli(`git merge-base HEAD ${master_branch}`))
|
|
30730
|
+
.stdout;
|
|
30731
|
+
// immediately paint all commit to preserve selected commit ranges
|
|
30732
|
+
let commit_range = await range(commit_map);
|
|
30733
|
+
// reverse group list to ensure we create git revise in correct order
|
|
30734
|
+
commit_range.group_list.reverse();
|
|
30735
|
+
for (const commit of commit_range.commit_list) {
|
|
30736
|
+
const group_from_map = commit_map[commit.sha];
|
|
30737
|
+
commit.branch_id = group_from_map.id;
|
|
30738
|
+
commit.title = group_from_map.title;
|
|
30826
30739
|
}
|
|
30827
|
-
|
|
30828
|
-
|
|
30829
|
-
|
|
30830
|
-
|
|
30831
|
-
|
|
30740
|
+
await GitReviseTodo.execute({
|
|
30741
|
+
rebase_group_index: 0,
|
|
30742
|
+
rebase_merge_base: merge_base,
|
|
30743
|
+
commit_range,
|
|
30744
|
+
});
|
|
30745
|
+
commit_range = await range(commit_map);
|
|
30746
|
+
// reverse commit list so that we can cherry-pick in order
|
|
30747
|
+
commit_range.group_list.reverse();
|
|
30748
|
+
let rebase_merge_base = merge_base;
|
|
30749
|
+
let rebase_group_index = 0;
|
|
30750
|
+
for (let i = 0; i < commit_range.group_list.length; i++) {
|
|
30751
|
+
const group = commit_range.group_list[i];
|
|
30752
|
+
if (!group.dirty) {
|
|
30753
|
+
continue;
|
|
30754
|
+
}
|
|
30755
|
+
if (i > 0) {
|
|
30756
|
+
const prev_group = commit_range.group_list[i - 1];
|
|
30757
|
+
const prev_commit = prev_group.commits[prev_group.commits.length - 1];
|
|
30758
|
+
rebase_merge_base = prev_commit.sha;
|
|
30759
|
+
rebase_group_index = i;
|
|
30760
|
+
}
|
|
30761
|
+
break;
|
|
30832
30762
|
}
|
|
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 {
|
|
30763
|
+
actions.debug(`rebase_merge_base = ${rebase_merge_base}`);
|
|
30764
|
+
actions.debug(`rebase_group_index = ${rebase_group_index}`);
|
|
30765
|
+
// actions.debug(`commit_range=${JSON.stringify(commit_range, null, 2)}`);
|
|
30839
30766
|
// must perform rebase from repo root for applying git patch
|
|
30840
30767
|
process.chdir(repo_root);
|
|
30841
30768
|
await cli(`pwd`);
|
|
30842
|
-
actions.output(reactExports.createElement(Text, { color: colors.yellow, wrap: "truncate-end" }, "Rebasing\u2026"));
|
|
30843
30769
|
// create temporary branch
|
|
30844
30770
|
await cli(`git checkout -b ${temp_branch_name}`);
|
|
30845
30771
|
await GitReviseTodo.execute({
|
|
@@ -30850,13 +30776,18 @@ async function run$6() {
|
|
|
30850
30776
|
// after all commits have been modified move the pointer
|
|
30851
30777
|
// of original branch to the newly created temporary branch
|
|
30852
30778
|
await cli(`git branch -f ${branch_name} ${temp_branch_name}`);
|
|
30779
|
+
restore_git();
|
|
30853
30780
|
if (argv.sync) {
|
|
30854
|
-
|
|
30781
|
+
actions.set((state) => {
|
|
30782
|
+
state.step = "sync-github";
|
|
30783
|
+
state.sync_github = { commit_range, rebase_group_index };
|
|
30784
|
+
});
|
|
30785
|
+
}
|
|
30786
|
+
else {
|
|
30787
|
+
actions.set((state) => {
|
|
30788
|
+
state.step = "post-rebase-status";
|
|
30789
|
+
});
|
|
30855
30790
|
}
|
|
30856
|
-
restore_git();
|
|
30857
|
-
actions.set((state) => {
|
|
30858
|
-
state.step = "post-rebase-status";
|
|
30859
|
-
});
|
|
30860
30791
|
}
|
|
30861
30792
|
catch (err) {
|
|
30862
30793
|
if (err instanceof Error) {
|
|
@@ -30866,164 +30797,7 @@ async function run$6() {
|
|
|
30866
30797
|
if (!argv.verbose) {
|
|
30867
30798
|
actions.error("Try again with `--verbose` to see more information.");
|
|
30868
30799
|
}
|
|
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
|
-
}
|
|
30800
|
+
handle_exit(16);
|
|
31027
30801
|
}
|
|
31028
30802
|
// cleanup git operations if cancelled during manual rebase
|
|
31029
30803
|
function restore_git() {
|
|
@@ -31045,7 +30819,7 @@ async function run$6() {
|
|
|
31045
30819
|
}
|
|
31046
30820
|
cli.sync(`pwd`, spawn_options);
|
|
31047
30821
|
}
|
|
31048
|
-
function handle_exit() {
|
|
30822
|
+
function handle_exit(code) {
|
|
31049
30823
|
actions.output(reactExports.createElement(Text, { color: colors.yellow },
|
|
31050
30824
|
"Restoring ",
|
|
31051
30825
|
reactExports.createElement(Brackets, null, branch_name),
|
|
@@ -31055,10 +30829,9 @@ async function run$6() {
|
|
|
31055
30829
|
"Restored ",
|
|
31056
30830
|
reactExports.createElement(Brackets, null, branch_name),
|
|
31057
30831
|
"."));
|
|
31058
|
-
actions.exit(
|
|
30832
|
+
actions.exit(code);
|
|
31059
30833
|
}
|
|
31060
30834
|
}
|
|
31061
|
-
const get_group_url = (group) => group.pr?.url || group.id;
|
|
31062
30835
|
|
|
31063
30836
|
function Table(props) {
|
|
31064
30837
|
if (!props.data.length) {
|
|
@@ -31237,9 +31010,9 @@ function get_status_bold(row) {
|
|
|
31237
31010
|
}
|
|
31238
31011
|
|
|
31239
31012
|
function PostRebaseStatus() {
|
|
31240
|
-
return reactExports.createElement(Await, { fallback: null, function: run$
|
|
31013
|
+
return reactExports.createElement(Await, { fallback: null, function: run$6 });
|
|
31241
31014
|
}
|
|
31242
|
-
async function run$
|
|
31015
|
+
async function run$6() {
|
|
31243
31016
|
const actions = Store.getState().actions;
|
|
31244
31017
|
// reset github pr cache before refreshing via commit range below
|
|
31245
31018
|
actions.reset_pr();
|
|
@@ -31269,9 +31042,9 @@ function PreLocalMergeRebase() {
|
|
|
31269
31042
|
}
|
|
31270
31043
|
|
|
31271
31044
|
function PreManualRebase() {
|
|
31272
|
-
return reactExports.createElement(Await, { fallback: null, function: run$
|
|
31045
|
+
return reactExports.createElement(Await, { fallback: null, function: run$5 });
|
|
31273
31046
|
}
|
|
31274
|
-
async function run$
|
|
31047
|
+
async function run$5() {
|
|
31275
31048
|
const state = Store.getState();
|
|
31276
31049
|
const actions = state.actions;
|
|
31277
31050
|
const repo_root = state.repo_root;
|
|
@@ -31773,59 +31546,435 @@ function SelectCommitRangesInternal(props) {
|
|
|
31773
31546
|
set_group_input(false);
|
|
31774
31547
|
}
|
|
31775
31548
|
}
|
|
31776
|
-
const SYMBOL = {
|
|
31777
|
-
left: "←",
|
|
31778
|
-
right: "→",
|
|
31779
|
-
enter: "Enter",
|
|
31549
|
+
const SYMBOL = {
|
|
31550
|
+
left: "←",
|
|
31551
|
+
right: "→",
|
|
31552
|
+
enter: "Enter",
|
|
31553
|
+
};
|
|
31554
|
+
|
|
31555
|
+
function Status() {
|
|
31556
|
+
return reactExports.createElement(Await, { fallback: null, function: run$4 });
|
|
31557
|
+
}
|
|
31558
|
+
async function run$4() {
|
|
31559
|
+
const state = Store.getState();
|
|
31560
|
+
const actions = state.actions;
|
|
31561
|
+
const argv = state.argv;
|
|
31562
|
+
const commit_range = Store.getState().commit_range;
|
|
31563
|
+
invariant(commit_range, "commit_range must exist");
|
|
31564
|
+
actions.output(reactExports.createElement(StatusTable, null));
|
|
31565
|
+
let needs_rebase = false;
|
|
31566
|
+
let needs_update = false;
|
|
31567
|
+
for (const group of commit_range.group_list) {
|
|
31568
|
+
if (group.dirty) {
|
|
31569
|
+
needs_update = true;
|
|
31570
|
+
}
|
|
31571
|
+
if (group.pr?.state === "MERGED") {
|
|
31572
|
+
needs_rebase = true;
|
|
31573
|
+
}
|
|
31574
|
+
}
|
|
31575
|
+
if (argv.check) {
|
|
31576
|
+
actions.exit(0);
|
|
31577
|
+
}
|
|
31578
|
+
else if (needs_rebase) {
|
|
31579
|
+
Store.setState((state) => {
|
|
31580
|
+
state.step = "pre-local-merge-rebase";
|
|
31581
|
+
});
|
|
31582
|
+
}
|
|
31583
|
+
else if (needs_update) {
|
|
31584
|
+
Store.setState((state) => {
|
|
31585
|
+
state.step = "pre-select-commit-ranges";
|
|
31586
|
+
});
|
|
31587
|
+
}
|
|
31588
|
+
else if (argv.force) {
|
|
31589
|
+
Store.setState((state) => {
|
|
31590
|
+
state.step = "select-commit-ranges";
|
|
31591
|
+
});
|
|
31592
|
+
}
|
|
31593
|
+
else {
|
|
31594
|
+
actions.output(reactExports.createElement(Text, null, "\u2705 Everything up to date."));
|
|
31595
|
+
actions.output(reactExports.createElement(Text, { color: colors.gray },
|
|
31596
|
+
reactExports.createElement(Text, null, "Run with"),
|
|
31597
|
+
reactExports.createElement(Text, { bold: true, color: colors.yellow }, ` --force `),
|
|
31598
|
+
reactExports.createElement(Text, null, "to force update all pull requests.")));
|
|
31599
|
+
actions.exit(0);
|
|
31600
|
+
}
|
|
31601
|
+
}
|
|
31602
|
+
|
|
31603
|
+
/**
|
|
31604
|
+
* Gets the last element of `array`.
|
|
31605
|
+
*
|
|
31606
|
+
* @static
|
|
31607
|
+
* @memberOf _
|
|
31608
|
+
* @since 0.1.0
|
|
31609
|
+
* @category Array
|
|
31610
|
+
* @param {Array} array The array to query.
|
|
31611
|
+
* @returns {*} Returns the last element of `array`.
|
|
31612
|
+
* @example
|
|
31613
|
+
*
|
|
31614
|
+
* _.last([1, 2, 3]);
|
|
31615
|
+
* // => 3
|
|
31616
|
+
*/
|
|
31617
|
+
|
|
31618
|
+
function last(array) {
|
|
31619
|
+
var length = array == null ? 0 : array.length;
|
|
31620
|
+
return length ? array[length - 1] : undefined;
|
|
31621
|
+
}
|
|
31622
|
+
|
|
31623
|
+
var last_1 = last;
|
|
31624
|
+
|
|
31625
|
+
var last$1 = /*@__PURE__*/getDefaultExportFromCjs(last_1);
|
|
31626
|
+
|
|
31627
|
+
function write(args) {
|
|
31628
|
+
const stack_table = table(args);
|
|
31629
|
+
let result = args.body;
|
|
31630
|
+
if (RE.stack_table_link.test(result)) {
|
|
31631
|
+
// replace stack table
|
|
31632
|
+
result = result.replace(RE.stack_table_link, stack_table);
|
|
31633
|
+
}
|
|
31634
|
+
else if (RE.stack_table_legacy.test(result)) {
|
|
31635
|
+
// replace stack table
|
|
31636
|
+
result = result.replace(RE.stack_table_legacy, stack_table);
|
|
31637
|
+
}
|
|
31638
|
+
else {
|
|
31639
|
+
// append stack table
|
|
31640
|
+
result = `${result}\n\n${stack_table}`;
|
|
31641
|
+
}
|
|
31642
|
+
result = result.trimEnd();
|
|
31643
|
+
return result;
|
|
31644
|
+
}
|
|
31645
|
+
function table(args) {
|
|
31646
|
+
const stack_pr_url_list = [...args.pr_url_list];
|
|
31647
|
+
const old_stack = parse(args.body);
|
|
31648
|
+
// remove existing stack pr urls from the old stack pr urls
|
|
31649
|
+
for (const pr_url of stack_pr_url_list) {
|
|
31650
|
+
old_stack.delete(pr_url);
|
|
31651
|
+
}
|
|
31652
|
+
// add remaining old stack pr urls to the front of stack pr url list
|
|
31653
|
+
const old_pr_list = Array.from(old_stack.keys());
|
|
31654
|
+
old_pr_list.reverse();
|
|
31655
|
+
for (const pr_url of old_pr_list) {
|
|
31656
|
+
stack_pr_url_list.unshift(pr_url);
|
|
31657
|
+
}
|
|
31658
|
+
const stack_list = [];
|
|
31659
|
+
const num_digits = String(stack_pr_url_list.length).length;
|
|
31660
|
+
for (let i = 0; i < stack_pr_url_list.length; i++) {
|
|
31661
|
+
const pr_url = stack_pr_url_list[i];
|
|
31662
|
+
const selected = args.selected_url === pr_url;
|
|
31663
|
+
let icon;
|
|
31664
|
+
if (old_stack.has(pr_url)) {
|
|
31665
|
+
icon = "✅";
|
|
31666
|
+
}
|
|
31667
|
+
else if (selected) {
|
|
31668
|
+
icon = "👉";
|
|
31669
|
+
}
|
|
31670
|
+
else {
|
|
31671
|
+
icon = "⏳";
|
|
31672
|
+
}
|
|
31673
|
+
const num = String(i + 1).padStart(num_digits, "0");
|
|
31674
|
+
stack_list.push(TEMPLATE.row({ icon, num, pr_url }));
|
|
31675
|
+
}
|
|
31676
|
+
if (!stack_list.length) {
|
|
31677
|
+
return "";
|
|
31678
|
+
}
|
|
31679
|
+
return TEMPLATE.stack_table_link(["", ...stack_list, "", ""].join("\n"));
|
|
31680
|
+
}
|
|
31681
|
+
function parse(body) {
|
|
31682
|
+
let stack_table_match = body.match(RE.stack_table_link);
|
|
31683
|
+
if (!stack_table_match?.groups) {
|
|
31684
|
+
stack_table_match = body.match(RE.stack_table_legacy);
|
|
31685
|
+
}
|
|
31686
|
+
if (!stack_table_match?.groups) {
|
|
31687
|
+
return new Map();
|
|
31688
|
+
}
|
|
31689
|
+
const rows_string = stack_table_match.groups["rows"];
|
|
31690
|
+
const row_list = rows_string.split("\n");
|
|
31691
|
+
const result = new Map();
|
|
31692
|
+
for (const row of row_list) {
|
|
31693
|
+
const row_match = row.match(RE.row);
|
|
31694
|
+
const parsed_row = row_match?.groups;
|
|
31695
|
+
if (!parsed_row) {
|
|
31696
|
+
// skip invalid row
|
|
31697
|
+
continue;
|
|
31698
|
+
}
|
|
31699
|
+
if (!RE.pr_url.test(parsed_row.pr_url)) {
|
|
31700
|
+
continue;
|
|
31701
|
+
}
|
|
31702
|
+
result.set(parsed_row.pr_url, parsed_row);
|
|
31703
|
+
}
|
|
31704
|
+
return result;
|
|
31705
|
+
}
|
|
31706
|
+
const TEMPLATE = {
|
|
31707
|
+
stack_table_legacy(rows) {
|
|
31708
|
+
return `#### git stack${rows}`;
|
|
31709
|
+
},
|
|
31710
|
+
stack_table_link(rows) {
|
|
31711
|
+
return `#### [git stack](https://github.com/magus/git-stack-cli)${rows}`;
|
|
31712
|
+
},
|
|
31713
|
+
row(args) {
|
|
31714
|
+
return `- ${args.icon} \`${args.num}\` ${args.pr_url}`;
|
|
31715
|
+
},
|
|
31716
|
+
};
|
|
31717
|
+
const RE = {
|
|
31718
|
+
// https://regex101.com/r/kqB9Ft/1
|
|
31719
|
+
stack_table_legacy: new RegExp(TEMPLATE.stack_table_legacy("\\s+(?<rows>(?:- [^\r^\n]*(?:[\r\n]+)?)+)")),
|
|
31720
|
+
stack_table_link: new RegExp(TEMPLATE.stack_table_link("ROWS")
|
|
31721
|
+
.replace("[", "\\[")
|
|
31722
|
+
.replace("]", "\\]")
|
|
31723
|
+
.replace("(", "\\(")
|
|
31724
|
+
.replace(")", "\\)")
|
|
31725
|
+
.replace("ROWS", "\\s+(?<rows>(?:- [^\r^\n]*(?:[\r\n]+)?)+)")),
|
|
31726
|
+
row: new RegExp(TEMPLATE.row({
|
|
31727
|
+
icon: "(?<icon>.+)",
|
|
31728
|
+
num: "(?<num>\\d+)",
|
|
31729
|
+
pr_url: "(?<pr_url>.+)",
|
|
31730
|
+
})),
|
|
31731
|
+
pr_url: /^https:\/\/.*$/,
|
|
31780
31732
|
};
|
|
31781
31733
|
|
|
31782
|
-
function
|
|
31783
|
-
|
|
31734
|
+
function SyncGithub() {
|
|
31735
|
+
const abort_handler = reactExports.useRef(() => { });
|
|
31736
|
+
reactExports.useEffect(function listen_sigint() {
|
|
31737
|
+
process.once("SIGINT", sigint_handler);
|
|
31738
|
+
return function cleanup() {
|
|
31739
|
+
process.removeListener("SIGINT", sigint_handler);
|
|
31740
|
+
};
|
|
31741
|
+
function sigint_handler() {
|
|
31742
|
+
abort_handler.current();
|
|
31743
|
+
}
|
|
31744
|
+
}, []);
|
|
31745
|
+
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Syncing\u2026"), function: async function () {
|
|
31746
|
+
await run$3({ abort_handler });
|
|
31747
|
+
} }));
|
|
31784
31748
|
}
|
|
31785
|
-
async function run$3() {
|
|
31749
|
+
async function run$3(args) {
|
|
31786
31750
|
const state = Store.getState();
|
|
31787
31751
|
const actions = state.actions;
|
|
31788
31752
|
const argv = state.argv;
|
|
31789
|
-
const
|
|
31790
|
-
|
|
31791
|
-
|
|
31792
|
-
|
|
31793
|
-
|
|
31794
|
-
|
|
31795
|
-
|
|
31796
|
-
|
|
31753
|
+
const branch_name = state.branch_name;
|
|
31754
|
+
const commit_map = state.commit_map;
|
|
31755
|
+
const master_branch = state.master_branch;
|
|
31756
|
+
const repo_root = state.repo_root;
|
|
31757
|
+
const sync_github = state.sync_github;
|
|
31758
|
+
invariant(branch_name, "branch_name must exist");
|
|
31759
|
+
invariant(commit_map, "commit_map must exist");
|
|
31760
|
+
invariant(repo_root, "repo_root must exist");
|
|
31761
|
+
invariant(sync_github, "sync_github must exist");
|
|
31762
|
+
const commit_range = sync_github.commit_range;
|
|
31763
|
+
const rebase_group_index = sync_github.rebase_group_index;
|
|
31764
|
+
// always listen for SIGINT event and restore pr state
|
|
31765
|
+
args.abort_handler.current = function sigint_handler() {
|
|
31766
|
+
actions.output(reactExports.createElement(Text, { color: colors.red }, "\uD83D\uDEA8 Abort"));
|
|
31767
|
+
handle_exit(17);
|
|
31768
|
+
};
|
|
31769
|
+
let DEFAULT_PR_BODY = "";
|
|
31770
|
+
if (state.pr_template_body) {
|
|
31771
|
+
DEFAULT_PR_BODY = state.pr_template_body;
|
|
31772
|
+
}
|
|
31773
|
+
const push_group_list = get_push_group_list();
|
|
31774
|
+
// for all push targets in push_group_list
|
|
31775
|
+
// things that can be done in parallel are grouped by numbers
|
|
31776
|
+
//
|
|
31777
|
+
// -----------------------------------
|
|
31778
|
+
// 1 (before_push) temp mark draft
|
|
31779
|
+
// --------------------------------------
|
|
31780
|
+
// 2 push simultaneously to github
|
|
31781
|
+
// --------------------------------------
|
|
31782
|
+
// 2 create PR / edit PR
|
|
31783
|
+
// 2 (after_push) undo temp mark draft
|
|
31784
|
+
// --------------------------------------
|
|
31785
|
+
try {
|
|
31786
|
+
const before_push_tasks = [];
|
|
31787
|
+
for (const group of push_group_list) {
|
|
31788
|
+
before_push_tasks.push(before_push({ group }));
|
|
31797
31789
|
}
|
|
31798
|
-
|
|
31799
|
-
|
|
31790
|
+
await Promise.all(before_push_tasks);
|
|
31791
|
+
const git_push_command = [`git push -f origin`];
|
|
31792
|
+
if (argv.verify === false) {
|
|
31793
|
+
git_push_command.push("--no-verify");
|
|
31794
|
+
}
|
|
31795
|
+
for (const group of push_group_list) {
|
|
31796
|
+
const last_commit = last$1(group.commits);
|
|
31797
|
+
invariant(last_commit, "last_commit must exist");
|
|
31798
|
+
// explicit refs/heads head branch to avoid push failing
|
|
31799
|
+
//
|
|
31800
|
+
// ❯ git push -f origin --no-verify f6e249051b4820a03deb957ddebc19acfd7dfd7c:gs-ED2etrzv2
|
|
31801
|
+
// error: The destination you provided is not a full refname (i.e.,
|
|
31802
|
+
// starting with "refs/"). We tried to guess what you meant by:
|
|
31803
|
+
//
|
|
31804
|
+
// - Looking for a ref that matches 'gs-ED2etrzv2' on the remote side.
|
|
31805
|
+
// - Checking if the <src> being pushed ('f6e249051b4820a03deb957ddebc19acfd7dfd7c')
|
|
31806
|
+
// is a ref in "refs/{heads,tags}/". If so we add a corresponding
|
|
31807
|
+
// refs/{heads,tags}/ prefix on the remote side.
|
|
31808
|
+
//
|
|
31809
|
+
// Neither worked, so we gave up. You must fully qualify the ref.
|
|
31810
|
+
// hint: The <src> part of the refspec is a commit object.
|
|
31811
|
+
// hint: Did you mean to create a new branch by pushing to
|
|
31812
|
+
// hint: 'f6e249051b4820a03deb957ddebc19acfd7dfd7c:refs/heads/gs-ED2etrzv2'?
|
|
31813
|
+
// error: failed to push some refs to 'github.com:magus/git-multi-diff-playground.git'
|
|
31814
|
+
//
|
|
31815
|
+
const target = `${last_commit.sha}:refs/heads/${group.id}`;
|
|
31816
|
+
git_push_command.push(target);
|
|
31817
|
+
}
|
|
31818
|
+
await cli(git_push_command);
|
|
31819
|
+
const pr_url_list = commit_range.group_list.map(get_group_url);
|
|
31820
|
+
const after_push_tasks = [];
|
|
31821
|
+
for (const group of push_group_list) {
|
|
31822
|
+
after_push_tasks.push(after_push({ group, pr_url_list }));
|
|
31823
|
+
}
|
|
31824
|
+
await Promise.all(after_push_tasks);
|
|
31825
|
+
// finally, ensure all prs have the updated stack table from updated pr_url_list
|
|
31826
|
+
// this step must come after the after_push since that step may create new PRs
|
|
31827
|
+
// we need the urls for all prs at this step so we run it after the after_push
|
|
31828
|
+
const update_pr_body_tasks = [];
|
|
31829
|
+
for (let i = 0; i < commit_range.group_list.length; i++) {
|
|
31830
|
+
const group = commit_range.group_list[i];
|
|
31831
|
+
// use the updated pr_url_list to get the actual selected_url
|
|
31832
|
+
const selected_url = pr_url_list[i];
|
|
31833
|
+
const task = update_pr_body({ group, selected_url, pr_url_list });
|
|
31834
|
+
update_pr_body_tasks.push(task);
|
|
31835
|
+
}
|
|
31836
|
+
await Promise.all(update_pr_body_tasks);
|
|
31837
|
+
actions.set((state) => {
|
|
31838
|
+
state.step = "post-rebase-status";
|
|
31839
|
+
});
|
|
31840
|
+
}
|
|
31841
|
+
catch (err) {
|
|
31842
|
+
if (err instanceof Error) {
|
|
31843
|
+
actions.error(err.message);
|
|
31844
|
+
}
|
|
31845
|
+
actions.error("Unable to sync.");
|
|
31846
|
+
if (!argv.verbose) {
|
|
31847
|
+
actions.error("Try again with `--verbose` to see more information.");
|
|
31800
31848
|
}
|
|
31849
|
+
await handle_exit(18);
|
|
31801
31850
|
}
|
|
31802
|
-
|
|
31803
|
-
|
|
31851
|
+
function get_push_group_list() {
|
|
31852
|
+
// start from HEAD and work backward to rebase_group_index
|
|
31853
|
+
const push_group_list = [];
|
|
31854
|
+
for (let i = 0; i < commit_range.group_list.length; i++) {
|
|
31855
|
+
const index = commit_range.group_list.length - 1 - i;
|
|
31856
|
+
// do not go past rebase_group_index
|
|
31857
|
+
if (index < rebase_group_index) {
|
|
31858
|
+
break;
|
|
31859
|
+
}
|
|
31860
|
+
const group = commit_range.group_list[index];
|
|
31861
|
+
push_group_list.unshift(group);
|
|
31862
|
+
}
|
|
31863
|
+
return push_group_list;
|
|
31804
31864
|
}
|
|
31805
|
-
|
|
31806
|
-
|
|
31807
|
-
|
|
31808
|
-
|
|
31865
|
+
async function before_push(args) {
|
|
31866
|
+
const { group } = args;
|
|
31867
|
+
invariant(group.base, "group.base must exist");
|
|
31868
|
+
// we may temporarily mark PR as a draft before editing it
|
|
31869
|
+
// if it is not already a draft PR, to avoid notification spam
|
|
31870
|
+
let is_temp_draft = !group.pr?.isDraft;
|
|
31871
|
+
// before pushing reset base to master temporarily
|
|
31872
|
+
// avoid accidentally pointing to orphaned parent commit
|
|
31873
|
+
// should hopefully fix issues where a PR includes a bunch of commits after pushing
|
|
31874
|
+
if (group.pr) {
|
|
31875
|
+
if (!group.pr.isDraft) {
|
|
31876
|
+
is_temp_draft = true;
|
|
31877
|
+
}
|
|
31878
|
+
if (is_temp_draft) {
|
|
31879
|
+
await pr_draft({
|
|
31880
|
+
branch: group.id,
|
|
31881
|
+
draft: true,
|
|
31882
|
+
});
|
|
31883
|
+
}
|
|
31884
|
+
await pr_edit({
|
|
31885
|
+
branch: group.id,
|
|
31886
|
+
base: master_branch,
|
|
31887
|
+
});
|
|
31888
|
+
}
|
|
31809
31889
|
}
|
|
31810
|
-
|
|
31811
|
-
|
|
31812
|
-
|
|
31813
|
-
|
|
31890
|
+
async function after_push(args) {
|
|
31891
|
+
const { group, pr_url_list } = args;
|
|
31892
|
+
invariant(group.base, "group.base must exist");
|
|
31893
|
+
const selected_url = get_group_url(group);
|
|
31894
|
+
if (group.pr) {
|
|
31895
|
+
// ensure base matches pr in github
|
|
31896
|
+
await pr_edit({
|
|
31897
|
+
branch: group.id,
|
|
31898
|
+
base: group.base,
|
|
31899
|
+
body: write({
|
|
31900
|
+
body: group.pr.body,
|
|
31901
|
+
pr_url_list,
|
|
31902
|
+
selected_url,
|
|
31903
|
+
}),
|
|
31904
|
+
});
|
|
31905
|
+
// we may temporarily mark PR as a draft before editing it
|
|
31906
|
+
// if it is not already a draft PR, to avoid notification spam
|
|
31907
|
+
let is_temp_draft = !group.pr?.isDraft;
|
|
31908
|
+
if (is_temp_draft) {
|
|
31909
|
+
// mark pr as ready for review again
|
|
31910
|
+
await pr_draft({
|
|
31911
|
+
branch: group.id,
|
|
31912
|
+
draft: false,
|
|
31913
|
+
});
|
|
31914
|
+
}
|
|
31915
|
+
}
|
|
31916
|
+
else {
|
|
31917
|
+
// create pr in github
|
|
31918
|
+
const pr_url = await pr_create({
|
|
31919
|
+
branch: group.id,
|
|
31920
|
+
base: group.base,
|
|
31921
|
+
title: group.title,
|
|
31922
|
+
body: DEFAULT_PR_BODY,
|
|
31923
|
+
draft: argv.draft,
|
|
31924
|
+
});
|
|
31925
|
+
if (!pr_url) {
|
|
31926
|
+
throw new Error("unable to create pr");
|
|
31927
|
+
}
|
|
31928
|
+
// update pr_url_list with created pr_url
|
|
31929
|
+
for (let i = 0; i < pr_url_list.length; i++) {
|
|
31930
|
+
const url = pr_url_list[i];
|
|
31931
|
+
if (url === selected_url) {
|
|
31932
|
+
pr_url_list[i] = pr_url;
|
|
31933
|
+
}
|
|
31934
|
+
}
|
|
31935
|
+
}
|
|
31814
31936
|
}
|
|
31815
|
-
|
|
31816
|
-
|
|
31817
|
-
|
|
31937
|
+
async function update_pr_body(args) {
|
|
31938
|
+
const { group, selected_url, pr_url_list } = args;
|
|
31939
|
+
invariant(group.base, "group.base must exist");
|
|
31940
|
+
const body = group.pr?.body || DEFAULT_PR_BODY;
|
|
31941
|
+
const update_body = write({
|
|
31942
|
+
body,
|
|
31943
|
+
pr_url_list,
|
|
31944
|
+
selected_url,
|
|
31818
31945
|
});
|
|
31946
|
+
if (update_body === body) {
|
|
31947
|
+
actions.debug(`Skipping body update for ${selected_url}`);
|
|
31948
|
+
}
|
|
31949
|
+
else {
|
|
31950
|
+
actions.debug(`Update body for ${selected_url}`);
|
|
31951
|
+
await pr_edit({
|
|
31952
|
+
branch: group.id,
|
|
31953
|
+
base: group.base,
|
|
31954
|
+
body: update_body,
|
|
31955
|
+
});
|
|
31956
|
+
}
|
|
31819
31957
|
}
|
|
31820
|
-
|
|
31821
|
-
actions.output(reactExports.createElement(Text,
|
|
31822
|
-
|
|
31823
|
-
|
|
31824
|
-
|
|
31825
|
-
|
|
31826
|
-
|
|
31958
|
+
function handle_exit(code) {
|
|
31959
|
+
actions.output(reactExports.createElement(Text, { color: colors.yellow }, "Restoring PR state\u2026"));
|
|
31960
|
+
for (const group of push_group_list) {
|
|
31961
|
+
// we may temporarily mark PR as a draft before editing it
|
|
31962
|
+
// if it is not already a draft PR, to avoid notification spam
|
|
31963
|
+
let is_temp_draft = !group.pr?.isDraft;
|
|
31964
|
+
// restore PR to non-draft state
|
|
31965
|
+
if (is_temp_draft) {
|
|
31966
|
+
pr_draft({
|
|
31967
|
+
branch: group.id,
|
|
31968
|
+
draft: false,
|
|
31969
|
+
})
|
|
31970
|
+
.catch(actions.error);
|
|
31971
|
+
}
|
|
31972
|
+
}
|
|
31973
|
+
actions.output(reactExports.createElement(Text, { color: colors.yellow }, "Restored PR state."));
|
|
31974
|
+
actions.exit(code);
|
|
31827
31975
|
}
|
|
31828
31976
|
}
|
|
31977
|
+
const get_group_url = (group) => group.pr?.url || group.id;
|
|
31829
31978
|
|
|
31830
31979
|
function Main() {
|
|
31831
31980
|
const step = Store.useState((state) => state.step);
|
|
@@ -31848,6 +31997,8 @@ function Main() {
|
|
|
31848
31997
|
return reactExports.createElement(PreManualRebase, null);
|
|
31849
31998
|
case "manual-rebase":
|
|
31850
31999
|
return reactExports.createElement(ManualRebase, null);
|
|
32000
|
+
case "sync-github":
|
|
32001
|
+
return reactExports.createElement(SyncGithub, null);
|
|
31851
32002
|
case "post-rebase-status":
|
|
31852
32003
|
return reactExports.createElement(PostRebaseStatus, null);
|
|
31853
32004
|
default:
|
|
@@ -37444,7 +37595,7 @@ async function command() {
|
|
|
37444
37595
|
.wrap(123)
|
|
37445
37596
|
// disallow unknown options
|
|
37446
37597
|
.strict()
|
|
37447
|
-
.version("1.13.
|
|
37598
|
+
.version("1.13.2" )
|
|
37448
37599
|
.showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`")
|
|
37449
37600
|
.help("help", "Show usage via `git stack help`")
|
|
37450
37601
|
.argv;
|
|
@@ -37529,7 +37680,10 @@ const FixupOptions = {
|
|
|
37529
37680
|
|
|
37530
37681
|
command()
|
|
37531
37682
|
.then((argv) => {
|
|
37532
|
-
const ink = render(reactExports.createElement(App, null)
|
|
37683
|
+
const ink = render(reactExports.createElement(App, null), {
|
|
37684
|
+
// If true, each update will be rendered as a separate output, without replacing the previous one.
|
|
37685
|
+
// debug: true,
|
|
37686
|
+
});
|
|
37533
37687
|
Store.setState((state) => {
|
|
37534
37688
|
state.ink = ink;
|
|
37535
37689
|
state.process_argv = process.argv;
|