git-stack-cli 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +106 -26
- package/package.json +1 -1
- package/src/app/DirtyCheck.tsx +18 -8
- package/src/app/Main.tsx +4 -0
- package/src/app/ManualRebase.tsx +7 -2
- package/src/app/MultiSelect.tsx +8 -5
- package/src/app/PreManualRebase.tsx +92 -0
- package/src/app/SelectCommitRanges.tsx +6 -5
- package/src/app/Store.tsx +5 -0
- package/src/app/YesNoPrompt.tsx +1 -1
- package/src/command.ts +7 -0
package/dist/cjs/index.cjs
CHANGED
|
@@ -17694,7 +17694,7 @@ function YesNoPrompt(props) {
|
|
|
17694
17694
|
n));
|
|
17695
17695
|
}
|
|
17696
17696
|
return (reactExports.createElement(Box, { flexDirection: "column" },
|
|
17697
|
-
reactExports.createElement(Box,
|
|
17697
|
+
reactExports.createElement(Box, { alignItems: "flex-end" },
|
|
17698
17698
|
typeof props.message === "object" ? (props.message) : (reactExports.createElement(Text, { color: colors.yellow }, props.message)),
|
|
17699
17699
|
reactExports.createElement(Text, null, " "),
|
|
17700
17700
|
reactExports.createElement(Parens, null,
|
|
@@ -26209,6 +26209,8 @@ const BaseStore = createStore()(immer((set, get) => ({
|
|
|
26209
26209
|
branch_name: null,
|
|
26210
26210
|
commit_range: null,
|
|
26211
26211
|
commit_map: null,
|
|
26212
|
+
pr_templates: [],
|
|
26213
|
+
pr_template_body: null,
|
|
26212
26214
|
step: "loading",
|
|
26213
26215
|
output: [],
|
|
26214
26216
|
pending_output: {},
|
|
@@ -27040,10 +27042,15 @@ function DirtyCheck(props) {
|
|
|
27040
27042
|
case "done":
|
|
27041
27043
|
return props.children;
|
|
27042
27044
|
case "prompt":
|
|
27043
|
-
return (reactExports.createElement(YesNoPrompt, { message: reactExports.createElement(
|
|
27044
|
-
|
|
27045
|
-
|
|
27046
|
-
|
|
27045
|
+
return (reactExports.createElement(YesNoPrompt, { message: reactExports.createElement(Box, { flexDirection: "column" },
|
|
27046
|
+
reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow }), message: "{git} repo has uncommitted changes.", values: {
|
|
27047
|
+
git: reactExports.createElement(Command, null, "git"),
|
|
27048
|
+
git_stack: reactExports.createElement(Command, null, "git stack"),
|
|
27049
|
+
} }),
|
|
27050
|
+
reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow }), message: "Changes may be lost during {git_stack}, are you sure you want to proceed?", values: {
|
|
27051
|
+
git: reactExports.createElement(Command, null, "git"),
|
|
27052
|
+
git_stack: reactExports.createElement(Command, null, "git stack"),
|
|
27053
|
+
} })), onYes: async () => {
|
|
27047
27054
|
patch({ status: "done" });
|
|
27048
27055
|
}, onNo: async () => {
|
|
27049
27056
|
actions.exit(0);
|
|
@@ -27171,9 +27178,9 @@ function format_time(date) {
|
|
|
27171
27178
|
}
|
|
27172
27179
|
|
|
27173
27180
|
function GithubApiError() {
|
|
27174
|
-
return reactExports.createElement(Await, { fallback: null, function: run$
|
|
27181
|
+
return reactExports.createElement(Await, { fallback: null, function: run$5 });
|
|
27175
27182
|
}
|
|
27176
|
-
async function run$
|
|
27183
|
+
async function run$5() {
|
|
27177
27184
|
const actions = Store.getState().actions;
|
|
27178
27185
|
const res = await cli(`gh api https://api.github.com/rate_limit`);
|
|
27179
27186
|
const res_json = JSON.parse(res.stdout);
|
|
@@ -27630,9 +27637,9 @@ function encode(value) {
|
|
|
27630
27637
|
}
|
|
27631
27638
|
|
|
27632
27639
|
function LocalMergeRebase() {
|
|
27633
|
-
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Rebasing commits\u2026"), function: run$
|
|
27640
|
+
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Rebasing commits\u2026"), function: run$4 }));
|
|
27634
27641
|
}
|
|
27635
|
-
async function run$
|
|
27642
|
+
async function run$4() {
|
|
27636
27643
|
const state = Store.getState();
|
|
27637
27644
|
const actions = state.actions;
|
|
27638
27645
|
const branch_name = state.branch_name;
|
|
@@ -27922,9 +27929,9 @@ const RE = {
|
|
|
27922
27929
|
};
|
|
27923
27930
|
|
|
27924
27931
|
function ManualRebase() {
|
|
27925
|
-
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Rebasing commits\u2026"), function: run$
|
|
27932
|
+
return (reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Rebasing commits\u2026"), function: run$3 }));
|
|
27926
27933
|
}
|
|
27927
|
-
async function run$
|
|
27934
|
+
async function run$3() {
|
|
27928
27935
|
const state = Store.getState();
|
|
27929
27936
|
const actions = state.actions;
|
|
27930
27937
|
const argv = state.argv;
|
|
@@ -27938,6 +27945,10 @@ async function run$2() {
|
|
|
27938
27945
|
invariant(repo_root, "repo_root must exist");
|
|
27939
27946
|
// always listen for SIGINT event and restore git state
|
|
27940
27947
|
process.once("SIGINT", handle_exit);
|
|
27948
|
+
let DEFAULT_PR_BODY = "";
|
|
27949
|
+
if (state.pr_template_body) {
|
|
27950
|
+
DEFAULT_PR_BODY = state.pr_template_body;
|
|
27951
|
+
}
|
|
27941
27952
|
const temp_branch_name = `${branch_name}_${short_id()}`;
|
|
27942
27953
|
const commit_range = await range(commit_map);
|
|
27943
27954
|
// reverse commit list so that we can cherry-pick in order
|
|
@@ -28163,7 +28174,7 @@ echo "$GIT_REVISE_TODO" > "$git_revise_todo_path"
|
|
|
28163
28174
|
branch: group.id,
|
|
28164
28175
|
base: group.base,
|
|
28165
28176
|
title: group.title,
|
|
28166
|
-
body:
|
|
28177
|
+
body: DEFAULT_PR_BODY,
|
|
28167
28178
|
});
|
|
28168
28179
|
if (!pr_url) {
|
|
28169
28180
|
throw new Error("unable to create pr");
|
|
@@ -28190,7 +28201,7 @@ echo "$GIT_REVISE_TODO" > "$git_revise_todo_path"
|
|
|
28190
28201
|
// use the updated pr_url_list to get the actual selected_url
|
|
28191
28202
|
const selected_url = pr_url_list[i];
|
|
28192
28203
|
invariant(group.base, "group.base must exist");
|
|
28193
|
-
const body = group.pr?.body ||
|
|
28204
|
+
const body = group.pr?.body || DEFAULT_PR_BODY;
|
|
28194
28205
|
const update_body = write({
|
|
28195
28206
|
body,
|
|
28196
28207
|
pr_url_list,
|
|
@@ -28430,9 +28441,9 @@ function get_status_bold(row) {
|
|
|
28430
28441
|
}
|
|
28431
28442
|
|
|
28432
28443
|
function PostRebaseStatus() {
|
|
28433
|
-
return reactExports.createElement(Await, { fallback: null, function: run$
|
|
28444
|
+
return reactExports.createElement(Await, { fallback: null, function: run$2 });
|
|
28434
28445
|
}
|
|
28435
|
-
async function run$
|
|
28446
|
+
async function run$2() {
|
|
28436
28447
|
const actions = Store.getState().actions;
|
|
28437
28448
|
// reset github pr cache before refreshing via commit range below
|
|
28438
28449
|
actions.reset_pr();
|
|
@@ -28461,6 +28472,67 @@ function PreLocalMergeRebase() {
|
|
|
28461
28472
|
}, onNo: () => actions.exit(0) }));
|
|
28462
28473
|
}
|
|
28463
28474
|
|
|
28475
|
+
function PreManualRebase() {
|
|
28476
|
+
return reactExports.createElement(Await, { fallback: null, function: run$1 });
|
|
28477
|
+
}
|
|
28478
|
+
async function run$1() {
|
|
28479
|
+
const state = Store.getState();
|
|
28480
|
+
const actions = state.actions;
|
|
28481
|
+
const repo_root = state.repo_root;
|
|
28482
|
+
const argv = state.argv;
|
|
28483
|
+
invariant(repo_root, "repo_root must exist");
|
|
28484
|
+
invariant(argv, "argv must exist");
|
|
28485
|
+
if (!argv.template) {
|
|
28486
|
+
return actions.set((state) => {
|
|
28487
|
+
state.step = "manual-rebase";
|
|
28488
|
+
});
|
|
28489
|
+
}
|
|
28490
|
+
// ./.github/PULL_REQUEST_TEMPLATE/*.md
|
|
28491
|
+
let pr_templates = [];
|
|
28492
|
+
if (fs.existsSync(template_pr_template(repo_root))) {
|
|
28493
|
+
pr_templates = fs.readdirSync(template_pr_template(repo_root));
|
|
28494
|
+
}
|
|
28495
|
+
// look for pull request template
|
|
28496
|
+
// https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository
|
|
28497
|
+
// ./.github/pull_request_template.md
|
|
28498
|
+
// ./pull_request_template.md
|
|
28499
|
+
// ./docs/pull_request_template.md
|
|
28500
|
+
let pr_template_body = null;
|
|
28501
|
+
if (fs.existsSync(github_pr_template(repo_root))) {
|
|
28502
|
+
pr_template_body = fs.readFileSync(github_pr_template(repo_root), "utf-8");
|
|
28503
|
+
}
|
|
28504
|
+
else if (fs.existsSync(root_pr_template(repo_root))) {
|
|
28505
|
+
pr_template_body = fs.readFileSync(root_pr_template(repo_root), "utf-8");
|
|
28506
|
+
}
|
|
28507
|
+
else if (fs.existsSync(docs_pr_template(repo_root))) {
|
|
28508
|
+
pr_template_body = fs.readFileSync(docs_pr_template(repo_root), "utf-8");
|
|
28509
|
+
}
|
|
28510
|
+
// check if repo has multiple pr templates
|
|
28511
|
+
actions.set((state) => {
|
|
28512
|
+
state.pr_template_body = pr_template_body;
|
|
28513
|
+
state.pr_templates = pr_templates;
|
|
28514
|
+
if (pr_templates.length > 0) {
|
|
28515
|
+
actions.output(reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow }), message: "{count} queryable templates found under {dir}, but not supported.", values: {
|
|
28516
|
+
count: (reactExports.createElement(Text, { color: colors.blue }, pr_templates.length)),
|
|
28517
|
+
dir: reactExports.createElement(Brackets, null, template_pr_template("")),
|
|
28518
|
+
} }));
|
|
28519
|
+
}
|
|
28520
|
+
state.step = "manual-rebase";
|
|
28521
|
+
});
|
|
28522
|
+
}
|
|
28523
|
+
function github_pr_template(repo_root) {
|
|
28524
|
+
return path.join(repo_root, ".github", "pull_request_template.md");
|
|
28525
|
+
}
|
|
28526
|
+
function root_pr_template(repo_root) {
|
|
28527
|
+
return path.join(repo_root, "pull_request_template.md");
|
|
28528
|
+
}
|
|
28529
|
+
function docs_pr_template(repo_root) {
|
|
28530
|
+
return path.join(repo_root, "docs", "pull_request_template.md");
|
|
28531
|
+
}
|
|
28532
|
+
function template_pr_template(repo_root) {
|
|
28533
|
+
return path.join(repo_root, ".github", "PULL_REQUEST_TEMPLATE");
|
|
28534
|
+
}
|
|
28535
|
+
|
|
28464
28536
|
function PreSelectCommitRanges() {
|
|
28465
28537
|
const actions = Store.useActions();
|
|
28466
28538
|
const argv = Store.useState((state) => state.argv);
|
|
@@ -28561,11 +28633,13 @@ function MultiSelect(props) {
|
|
|
28561
28633
|
return;
|
|
28562
28634
|
}
|
|
28563
28635
|
const space = input === " ";
|
|
28564
|
-
if (
|
|
28565
|
-
|
|
28566
|
-
|
|
28567
|
-
|
|
28568
|
-
|
|
28636
|
+
if (!props.disableSelect) {
|
|
28637
|
+
if (key.return || space) {
|
|
28638
|
+
selectRef.current = true;
|
|
28639
|
+
const item = props.items[index];
|
|
28640
|
+
if (!item.disabled) {
|
|
28641
|
+
return select(index);
|
|
28642
|
+
}
|
|
28569
28643
|
}
|
|
28570
28644
|
}
|
|
28571
28645
|
if (key.upArrow) {
|
|
@@ -28774,7 +28848,7 @@ function SelectCommitRangesInternal(props) {
|
|
|
28774
28848
|
}
|
|
28775
28849
|
switch (inputLower) {
|
|
28776
28850
|
case "s":
|
|
28777
|
-
state.step = "manual-rebase";
|
|
28851
|
+
state.step = "pre-manual-rebase";
|
|
28778
28852
|
break;
|
|
28779
28853
|
}
|
|
28780
28854
|
});
|
|
@@ -28797,6 +28871,8 @@ function SelectCommitRangesInternal(props) {
|
|
|
28797
28871
|
}
|
|
28798
28872
|
});
|
|
28799
28873
|
const group = group_list[current_index];
|
|
28874
|
+
const multiselect_disabled = group_input;
|
|
28875
|
+
const multiselect_disableSelect = group.id === props.commit_range.UNASSIGNED;
|
|
28800
28876
|
const items = props.commit_range.commit_list.map((commit) => {
|
|
28801
28877
|
const commit_metadata_id = commit_map.get(commit.sha);
|
|
28802
28878
|
const selected = commit_metadata_id !== null;
|
|
@@ -28804,9 +28880,6 @@ function SelectCommitRangesInternal(props) {
|
|
|
28804
28880
|
if (group_input) {
|
|
28805
28881
|
disabled = true;
|
|
28806
28882
|
}
|
|
28807
|
-
else if (group.id === props.commit_range.UNASSIGNED) {
|
|
28808
|
-
disabled = true;
|
|
28809
|
-
}
|
|
28810
28883
|
else {
|
|
28811
28884
|
disabled = Boolean(selected && commit_metadata_id !== group.id);
|
|
28812
28885
|
}
|
|
@@ -28832,7 +28905,7 @@ function SelectCommitRangesInternal(props) {
|
|
|
28832
28905
|
const [focused, set_focused] = reactExports.useState("");
|
|
28833
28906
|
return (reactExports.createElement(Box, { flexDirection: "column" },
|
|
28834
28907
|
reactExports.createElement(Box, { height: 1 }),
|
|
28835
|
-
reactExports.createElement(MultiSelect, {
|
|
28908
|
+
reactExports.createElement(MultiSelect, { items: items, maxWidth: max_item_width, disabled: multiselect_disabled, disableSelect: multiselect_disableSelect, onFocus: (args) => {
|
|
28836
28909
|
// console.debug("onFocus", args);
|
|
28837
28910
|
set_focused(args.item.subject_line);
|
|
28838
28911
|
}, onSelect: (args) => {
|
|
@@ -28974,6 +29047,8 @@ function Main() {
|
|
|
28974
29047
|
return reactExports.createElement(PreSelectCommitRanges, null);
|
|
28975
29048
|
case "select-commit-ranges":
|
|
28976
29049
|
return reactExports.createElement(SelectCommitRanges, null);
|
|
29050
|
+
case "pre-manual-rebase":
|
|
29051
|
+
return reactExports.createElement(PreManualRebase, null);
|
|
28977
29052
|
case "manual-rebase":
|
|
28978
29053
|
return reactExports.createElement(ManualRebase, null);
|
|
28979
29054
|
case "post-rebase-status":
|
|
@@ -34448,6 +34523,11 @@ async function command() {
|
|
|
34448
34523
|
type: "boolean",
|
|
34449
34524
|
default: false,
|
|
34450
34525
|
description: "Write state to local json file for debugging",
|
|
34526
|
+
})
|
|
34527
|
+
.option("template", {
|
|
34528
|
+
type: "boolean",
|
|
34529
|
+
default: true,
|
|
34530
|
+
description: "Use automatic Github PR template, e.g. .github/pull_request_template.md, disable with --no-template",
|
|
34451
34531
|
})
|
|
34452
34532
|
.option("mock-metadata", {
|
|
34453
34533
|
hidden: true,
|
|
@@ -34461,7 +34541,7 @@ async function command() {
|
|
|
34461
34541
|
.wrap(123)
|
|
34462
34542
|
// disallow unknown options
|
|
34463
34543
|
.strict()
|
|
34464
|
-
.version("1.
|
|
34544
|
+
.version("1.7.0" )
|
|
34465
34545
|
.showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`")
|
|
34466
34546
|
.help("help", "Show usage via `git stack help`").argv);
|
|
34467
34547
|
}
|
package/package.json
CHANGED
package/src/app/DirtyCheck.tsx
CHANGED
|
@@ -37,14 +37,24 @@ export function DirtyCheck(props: Props) {
|
|
|
37
37
|
return (
|
|
38
38
|
<YesNoPrompt
|
|
39
39
|
message={
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
<Ink.Box flexDirection="column">
|
|
41
|
+
<FormatText
|
|
42
|
+
wrapper={<Ink.Text color={colors.yellow} />}
|
|
43
|
+
message="{git} repo has uncommitted changes."
|
|
44
|
+
values={{
|
|
45
|
+
git: <Command>git</Command>,
|
|
46
|
+
git_stack: <Command>git stack</Command>,
|
|
47
|
+
}}
|
|
48
|
+
/>
|
|
49
|
+
<FormatText
|
|
50
|
+
wrapper={<Ink.Text color={colors.yellow} />}
|
|
51
|
+
message="Changes may be lost during {git_stack}, are you sure you want to proceed?"
|
|
52
|
+
values={{
|
|
53
|
+
git: <Command>git</Command>,
|
|
54
|
+
git_stack: <Command>git stack</Command>,
|
|
55
|
+
}}
|
|
56
|
+
/>
|
|
57
|
+
</Ink.Box>
|
|
48
58
|
}
|
|
49
59
|
onYes={async () => {
|
|
50
60
|
patch({ status: "done" });
|
package/src/app/Main.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import { LocalMergeRebase } from "~/app/LocalMergeRebase";
|
|
|
5
5
|
import { ManualRebase } from "~/app/ManualRebase";
|
|
6
6
|
import { PostRebaseStatus } from "~/app/PostRebaseStatus";
|
|
7
7
|
import { PreLocalMergeRebase } from "~/app/PreLocalMergeRebase";
|
|
8
|
+
import { PreManualRebase } from "~/app/PreManualRebase";
|
|
8
9
|
import { PreSelectCommitRanges } from "~/app/PreSelectCommitRanges";
|
|
9
10
|
import { SelectCommitRanges } from "~/app/SelectCommitRanges";
|
|
10
11
|
import { Status } from "~/app/Status";
|
|
@@ -36,6 +37,9 @@ export function Main() {
|
|
|
36
37
|
case "select-commit-ranges":
|
|
37
38
|
return <SelectCommitRanges />;
|
|
38
39
|
|
|
40
|
+
case "pre-manual-rebase":
|
|
41
|
+
return <PreManualRebase />;
|
|
42
|
+
|
|
39
43
|
case "manual-rebase":
|
|
40
44
|
return <ManualRebase />;
|
|
41
45
|
|
package/src/app/ManualRebase.tsx
CHANGED
|
@@ -46,6 +46,11 @@ async function run() {
|
|
|
46
46
|
// always listen for SIGINT event and restore git state
|
|
47
47
|
process.once("SIGINT", handle_exit);
|
|
48
48
|
|
|
49
|
+
let DEFAULT_PR_BODY = "";
|
|
50
|
+
if (state.pr_template_body) {
|
|
51
|
+
DEFAULT_PR_BODY = state.pr_template_body;
|
|
52
|
+
}
|
|
53
|
+
|
|
49
54
|
const temp_branch_name = `${branch_name}_${short_id()}`;
|
|
50
55
|
|
|
51
56
|
const commit_range = await CommitMetadata.range(commit_map);
|
|
@@ -328,7 +333,7 @@ async function run() {
|
|
|
328
333
|
branch: group.id,
|
|
329
334
|
base: group.base,
|
|
330
335
|
title: group.title,
|
|
331
|
-
body:
|
|
336
|
+
body: DEFAULT_PR_BODY,
|
|
332
337
|
});
|
|
333
338
|
|
|
334
339
|
if (!pr_url) {
|
|
@@ -363,7 +368,7 @@ async function run() {
|
|
|
363
368
|
|
|
364
369
|
invariant(group.base, "group.base must exist");
|
|
365
370
|
|
|
366
|
-
const body = group.pr?.body ||
|
|
371
|
+
const body = group.pr?.body || DEFAULT_PR_BODY;
|
|
367
372
|
|
|
368
373
|
const update_body = StackSummaryTable.write({
|
|
369
374
|
body,
|
package/src/app/MultiSelect.tsx
CHANGED
|
@@ -12,6 +12,7 @@ type Props<T> = {
|
|
|
12
12
|
onSelect: (args: CallbackArgs<T>) => void;
|
|
13
13
|
onFocus?: (args: CallbackArgs<T>) => void;
|
|
14
14
|
disabled?: boolean;
|
|
15
|
+
disableSelect?: boolean;
|
|
15
16
|
maxWidth?: number;
|
|
16
17
|
};
|
|
17
18
|
|
|
@@ -118,11 +119,13 @@ export function MultiSelect<T>(props: Props<T>) {
|
|
|
118
119
|
|
|
119
120
|
const space = input === " ";
|
|
120
121
|
|
|
121
|
-
if (
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
122
|
+
if (!props.disableSelect) {
|
|
123
|
+
if (key.return || space) {
|
|
124
|
+
selectRef.current = true;
|
|
125
|
+
const item = props.items[index];
|
|
126
|
+
if (!item.disabled) {
|
|
127
|
+
return select(index);
|
|
128
|
+
}
|
|
126
129
|
}
|
|
127
130
|
}
|
|
128
131
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
import * as Ink from "ink-cjs";
|
|
7
|
+
|
|
8
|
+
import { Await } from "~/app/Await";
|
|
9
|
+
import { Brackets } from "~/app/Brackets";
|
|
10
|
+
import { FormatText } from "~/app/FormatText";
|
|
11
|
+
import { Store } from "~/app/Store";
|
|
12
|
+
import { colors } from "~/core/colors";
|
|
13
|
+
import { invariant } from "~/core/invariant";
|
|
14
|
+
|
|
15
|
+
export function PreManualRebase() {
|
|
16
|
+
return <Await fallback={null} function={run} />;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function run() {
|
|
20
|
+
const state = Store.getState();
|
|
21
|
+
const actions = state.actions;
|
|
22
|
+
const repo_root = state.repo_root;
|
|
23
|
+
const argv = state.argv;
|
|
24
|
+
|
|
25
|
+
invariant(repo_root, "repo_root must exist");
|
|
26
|
+
invariant(argv, "argv must exist");
|
|
27
|
+
|
|
28
|
+
if (!argv.template) {
|
|
29
|
+
return actions.set((state) => {
|
|
30
|
+
state.step = "manual-rebase";
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// ./.github/PULL_REQUEST_TEMPLATE/*.md
|
|
35
|
+
let pr_templates: Array<string> = [];
|
|
36
|
+
if (fs.existsSync(template_pr_template(repo_root))) {
|
|
37
|
+
pr_templates = fs.readdirSync(template_pr_template(repo_root));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// look for pull request template
|
|
41
|
+
// https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository
|
|
42
|
+
// ./.github/pull_request_template.md
|
|
43
|
+
// ./pull_request_template.md
|
|
44
|
+
// ./docs/pull_request_template.md
|
|
45
|
+
let pr_template_body: null | string = null;
|
|
46
|
+
if (fs.existsSync(github_pr_template(repo_root))) {
|
|
47
|
+
pr_template_body = fs.readFileSync(github_pr_template(repo_root), "utf-8");
|
|
48
|
+
} else if (fs.existsSync(root_pr_template(repo_root))) {
|
|
49
|
+
pr_template_body = fs.readFileSync(root_pr_template(repo_root), "utf-8");
|
|
50
|
+
} else if (fs.existsSync(docs_pr_template(repo_root))) {
|
|
51
|
+
pr_template_body = fs.readFileSync(docs_pr_template(repo_root), "utf-8");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// check if repo has multiple pr templates
|
|
55
|
+
actions.set((state) => {
|
|
56
|
+
state.pr_template_body = pr_template_body;
|
|
57
|
+
state.pr_templates = pr_templates;
|
|
58
|
+
|
|
59
|
+
if (pr_templates.length > 0) {
|
|
60
|
+
actions.output(
|
|
61
|
+
<FormatText
|
|
62
|
+
wrapper={<Ink.Text color={colors.yellow} />}
|
|
63
|
+
message="{count} queryable templates found under {dir}, but not supported."
|
|
64
|
+
values={{
|
|
65
|
+
count: (
|
|
66
|
+
<Ink.Text color={colors.blue}>{pr_templates.length}</Ink.Text>
|
|
67
|
+
),
|
|
68
|
+
dir: <Brackets>{template_pr_template("")}</Brackets>,
|
|
69
|
+
}}
|
|
70
|
+
/>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
state.step = "manual-rebase";
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function github_pr_template(repo_root: string) {
|
|
79
|
+
return path.join(repo_root, ".github", "pull_request_template.md");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function root_pr_template(repo_root: string) {
|
|
83
|
+
return path.join(repo_root, "pull_request_template.md");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function docs_pr_template(repo_root: string) {
|
|
87
|
+
return path.join(repo_root, "docs", "pull_request_template.md");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function template_pr_template(repo_root: string) {
|
|
91
|
+
return path.join(repo_root, ".github", "PULL_REQUEST_TEMPLATE");
|
|
92
|
+
}
|
|
@@ -143,7 +143,7 @@ function SelectCommitRangesInternal(props: Props) {
|
|
|
143
143
|
|
|
144
144
|
switch (inputLower) {
|
|
145
145
|
case "s":
|
|
146
|
-
state.step = "manual-rebase";
|
|
146
|
+
state.step = "pre-manual-rebase";
|
|
147
147
|
break;
|
|
148
148
|
}
|
|
149
149
|
});
|
|
@@ -171,6 +171,9 @@ function SelectCommitRangesInternal(props: Props) {
|
|
|
171
171
|
|
|
172
172
|
const group = group_list[current_index];
|
|
173
173
|
|
|
174
|
+
const multiselect_disabled = group_input;
|
|
175
|
+
const multiselect_disableSelect = group.id === props.commit_range.UNASSIGNED;
|
|
176
|
+
|
|
174
177
|
const items = props.commit_range.commit_list.map((commit) => {
|
|
175
178
|
const commit_metadata_id = commit_map.get(commit.sha);
|
|
176
179
|
|
|
@@ -180,8 +183,6 @@ function SelectCommitRangesInternal(props: Props) {
|
|
|
180
183
|
|
|
181
184
|
if (group_input) {
|
|
182
185
|
disabled = true;
|
|
183
|
-
} else if (group.id === props.commit_range.UNASSIGNED) {
|
|
184
|
-
disabled = true;
|
|
185
186
|
} else {
|
|
186
187
|
disabled = Boolean(selected && commit_metadata_id !== group.id);
|
|
187
188
|
}
|
|
@@ -218,10 +219,10 @@ function SelectCommitRangesInternal(props: Props) {
|
|
|
218
219
|
<Ink.Box height={1} />
|
|
219
220
|
|
|
220
221
|
<MultiSelect
|
|
221
|
-
key={group.id}
|
|
222
222
|
items={items}
|
|
223
223
|
maxWidth={max_item_width}
|
|
224
|
-
disabled={
|
|
224
|
+
disabled={multiselect_disabled}
|
|
225
|
+
disableSelect={multiselect_disableSelect}
|
|
225
226
|
onFocus={(args) => {
|
|
226
227
|
// console.debug("onFocus", args);
|
|
227
228
|
|
package/src/app/Store.tsx
CHANGED
|
@@ -38,6 +38,8 @@ export type State = {
|
|
|
38
38
|
branch_name: null | string;
|
|
39
39
|
commit_range: null | CommitMetadata.CommitRange;
|
|
40
40
|
commit_map: null | CommitMap;
|
|
41
|
+
pr_templates: Array<string>;
|
|
42
|
+
pr_template_body: null | string;
|
|
41
43
|
|
|
42
44
|
step:
|
|
43
45
|
| "github-api-error"
|
|
@@ -47,6 +49,7 @@ export type State = {
|
|
|
47
49
|
| "local-merge-rebase"
|
|
48
50
|
| "pre-select-commit-ranges"
|
|
49
51
|
| "select-commit-ranges"
|
|
52
|
+
| "pre-manual-rebase"
|
|
50
53
|
| "manual-rebase"
|
|
51
54
|
| "post-rebase-status";
|
|
52
55
|
|
|
@@ -98,6 +101,8 @@ const BaseStore = createStore<State>()(
|
|
|
98
101
|
branch_name: null,
|
|
99
102
|
commit_range: null,
|
|
100
103
|
commit_map: null,
|
|
104
|
+
pr_templates: [],
|
|
105
|
+
pr_template_body: null,
|
|
101
106
|
|
|
102
107
|
step: "loading",
|
|
103
108
|
|
package/src/app/YesNoPrompt.tsx
CHANGED
package/src/command.ts
CHANGED
|
@@ -78,6 +78,13 @@ export async function command() {
|
|
|
78
78
|
description: "Write state to local json file for debugging",
|
|
79
79
|
})
|
|
80
80
|
|
|
81
|
+
.option("template", {
|
|
82
|
+
type: "boolean",
|
|
83
|
+
default: true,
|
|
84
|
+
description:
|
|
85
|
+
"Use automatic Github PR template, e.g. .github/pull_request_template.md, disable with --no-template",
|
|
86
|
+
})
|
|
87
|
+
|
|
81
88
|
.option("mock-metadata", {
|
|
82
89
|
hidden: true,
|
|
83
90
|
type: "boolean",
|