git-stack-cli 1.15.0 → 1.15.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/README.md +2 -4
- package/dist/cjs/index.cjs +150 -83
- package/package.json +2 -1
- package/scripts/link.ts +14 -0
- package/src/app/App.tsx +39 -31
- package/src/app/AutoUpdate.tsx +9 -24
- package/src/app/CherryPickCheck.tsx +1 -2
- package/src/app/Debug.tsx +3 -5
- package/src/app/DependencyCheck.tsx +6 -6
- package/src/app/DetectInitialPR.tsx +2 -8
- package/src/app/DirtyCheck.tsx +15 -1
- package/src/app/Exit.tsx +1 -5
- package/src/app/FormatText.tsx +1 -5
- package/src/app/GatherMetadata.tsx +6 -13
- package/src/app/GithubApiError.tsx +1 -1
- package/src/app/HandleCtrlCSigint.tsx +1 -12
- package/src/app/LocalCommitStatus.tsx +1 -3
- package/src/app/LogTimestamp.tsx +1 -5
- package/src/app/ManualRebase.tsx +4 -8
- package/src/app/MultiSelect.tsx +2 -2
- package/src/app/PostRebaseStatus.tsx +2 -0
- package/src/app/PreManualRebase.tsx +3 -5
- package/src/app/RebaseCheck.tsx +1 -2
- package/src/app/SelectCommitRanges.tsx +6 -10
- package/src/app/Status.tsx +1 -1
- package/src/app/StatusTable.tsx +1 -4
- package/src/app/Store.tsx +5 -1
- package/src/app/SyncGithub.tsx +4 -16
- package/src/app/Table.tsx +4 -14
- package/src/app/TextInput.tsx +2 -7
- package/src/app/VerboseDebugInfo.tsx +1 -5
- package/src/app/YesNoPrompt.tsx +42 -31
- package/src/command.ts +8 -17
- package/src/commands/Fixup.tsx +15 -22
- package/src/commands/Log.tsx +3 -7
- package/src/commands/Rebase.tsx +6 -8
- package/src/components/ErrorBoundary.tsx +79 -0
- package/src/components/ExitingGate.tsx +27 -0
- package/src/core/CommitMetadata.ts +1 -1
- package/src/core/GitReviseTodo.test.ts +3 -3
- package/src/core/GitReviseTodo.ts +2 -8
- package/src/core/Metadata.test.ts +4 -4
- package/src/core/StackSummaryTable.ts +3 -3
- package/src/core/chalk.ts +1 -5
- package/src/core/cli.ts +2 -2
- package/src/core/github.tsx +7 -13
- package/src/core/pretty_json.ts +1 -6
- package/src/github/gh.auth_status.test.ts +2 -6
- package/src/index.tsx +24 -3
package/README.md
CHANGED
|
@@ -129,12 +129,10 @@ Ensure `node --version` is the same across both projects you are using to test t
|
|
|
129
129
|
git submodule update --init --recursive
|
|
130
130
|
npm i
|
|
131
131
|
npm run dev
|
|
132
|
-
npm
|
|
133
|
-
npm link
|
|
132
|
+
npm run link
|
|
134
133
|
|
|
135
134
|
# navigate to project to test within
|
|
136
|
-
npm unlink git-stack-cli
|
|
137
|
-
npm link git-stack-cli
|
|
135
|
+
npm unlink git-stack-cli && npm link git-stack-cli
|
|
138
136
|
|
|
139
137
|
git stack --verbose
|
|
140
138
|
```
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -17667,33 +17667,42 @@ function Parens(props) {
|
|
|
17667
17667
|
|
|
17668
17668
|
function YesNoPrompt(props) {
|
|
17669
17669
|
const [answer, set_answer] = reactExports.useState("");
|
|
17670
|
+
const answered_ref = reactExports.useRef(false);
|
|
17670
17671
|
useInput((input) => {
|
|
17671
|
-
|
|
17672
|
-
|
|
17673
|
-
|
|
17672
|
+
// prevent answering multiple times
|
|
17673
|
+
if (answered_ref.current) {
|
|
17674
|
+
return;
|
|
17675
|
+
}
|
|
17676
|
+
const input_lower = input.toLowerCase();
|
|
17677
|
+
let handler;
|
|
17678
|
+
switch (input_lower) {
|
|
17674
17679
|
case "n":
|
|
17675
|
-
|
|
17680
|
+
handler = props.onNo;
|
|
17681
|
+
break;
|
|
17676
17682
|
case "y":
|
|
17677
|
-
|
|
17683
|
+
handler = props.onYes;
|
|
17684
|
+
break;
|
|
17685
|
+
}
|
|
17686
|
+
// handler if valid answer (y or n)
|
|
17687
|
+
if (handler) {
|
|
17688
|
+
answered_ref.current = true;
|
|
17689
|
+
set_answer(input_lower);
|
|
17690
|
+
handler();
|
|
17678
17691
|
}
|
|
17679
17692
|
});
|
|
17680
|
-
|
|
17681
|
-
|
|
17682
|
-
|
|
17683
|
-
|
|
17684
|
-
|
|
17685
|
-
|
|
17686
|
-
|
|
17687
|
-
|
|
17688
|
-
|
|
17689
|
-
|
|
17690
|
-
|
|
17691
|
-
|
|
17692
|
-
|
|
17693
|
-
y,
|
|
17694
|
-
reactExports.createElement(Text, null, "/"),
|
|
17695
|
-
n));
|
|
17696
|
-
}
|
|
17693
|
+
const choices = (function get_choices() {
|
|
17694
|
+
// prettier-ignore
|
|
17695
|
+
const y = reactExports.createElement(Text, { bold: true, color: colors.green }, "Y");
|
|
17696
|
+
const n = reactExports.createElement(Text, { color: colors.red }, "n");
|
|
17697
|
+
switch (answer) {
|
|
17698
|
+
case "y":
|
|
17699
|
+
return y;
|
|
17700
|
+
case "n":
|
|
17701
|
+
return n;
|
|
17702
|
+
default:
|
|
17703
|
+
return reactExports.createElement(FormatText, { message: "{y}/{n}", values: { y, n } });
|
|
17704
|
+
}
|
|
17705
|
+
})();
|
|
17697
17706
|
return (reactExports.createElement(Box, { flexDirection: "column" },
|
|
17698
17707
|
reactExports.createElement(Box, { alignItems: "flex-end" },
|
|
17699
17708
|
typeof props.message === "object" ? (props.message) : (reactExports.createElement(Text, { color: colors.yellow }, props.message)),
|
|
@@ -26220,7 +26229,7 @@ function friendlyDateTime(dateTimeish) {
|
|
|
26220
26229
|
}
|
|
26221
26230
|
|
|
26222
26231
|
function LogTimestamp() {
|
|
26223
|
-
return
|
|
26232
|
+
return reactExports.createElement(Text, { dimColor: true }, DateTime.now().toFormat("[yyyy-MM-dd HH:mm:ss.SSS] "));
|
|
26224
26233
|
}
|
|
26225
26234
|
|
|
26226
26235
|
function pretty_json(input) {
|
|
@@ -26246,6 +26255,7 @@ const BaseStore = createStore()(immer((set, get) => ({
|
|
|
26246
26255
|
sync_github: null,
|
|
26247
26256
|
is_dirty_check_stash: false,
|
|
26248
26257
|
abort_handler: null,
|
|
26258
|
+
is_exiting: false,
|
|
26249
26259
|
step: "loading",
|
|
26250
26260
|
output: [],
|
|
26251
26261
|
pending_output: {},
|
|
@@ -26253,6 +26263,7 @@ const BaseStore = createStore()(immer((set, get) => ({
|
|
|
26253
26263
|
actions: {
|
|
26254
26264
|
exit(code, clear = true) {
|
|
26255
26265
|
set((state) => {
|
|
26266
|
+
state.is_exiting = true;
|
|
26256
26267
|
const node = reactExports.createElement(Exit, { clear: clear, code: code });
|
|
26257
26268
|
state.mutate.output(state, { node });
|
|
26258
26269
|
});
|
|
@@ -26634,9 +26645,7 @@ function AutoUpdate(props) {
|
|
|
26634
26645
|
if (props_ref.current.verbose) {
|
|
26635
26646
|
handle_output(reactExports.createElement(Text, { key: "init" }, "Checking for latest version..."));
|
|
26636
26647
|
}
|
|
26637
|
-
const timeout_ms = is_finite_value(props.timeoutMs)
|
|
26638
|
-
? props.timeoutMs
|
|
26639
|
-
: 2 * 1000;
|
|
26648
|
+
const timeout_ms = is_finite_value(props.timeoutMs) ? props.timeoutMs : 2 * 1000;
|
|
26640
26649
|
const npm_json = await Promise.race([
|
|
26641
26650
|
fetch_json(`https://registry.npmjs.org/${props.name}`),
|
|
26642
26651
|
sleep(timeout_ms).then(() => {
|
|
@@ -26697,8 +26706,8 @@ function AutoUpdate(props) {
|
|
|
26697
26706
|
case "prompt":
|
|
26698
26707
|
return (reactExports.createElement(YesNoPrompt, { message: reactExports.createElement(Text, { color: colors.yellow }, "New version available, would you like to update?"), onYes: async () => {
|
|
26699
26708
|
handle_output(reactExports.createElement(FormatText, { key: "install", wrapper: reactExports.createElement(Text, null), message: "Installing {name}@{version}...", values: {
|
|
26700
|
-
name:
|
|
26701
|
-
version:
|
|
26709
|
+
name: reactExports.createElement(Text, { color: colors.yellow }, props.name),
|
|
26710
|
+
version: reactExports.createElement(Text, { color: colors.blue }, state.latest_version),
|
|
26702
26711
|
} }));
|
|
26703
26712
|
patch({ status: "install" });
|
|
26704
26713
|
await cli(`npm install -g ${props.name}@latest`);
|
|
@@ -29863,9 +29872,7 @@ async function pr_draft(args) {
|
|
|
29863
29872
|
// https://cli.github.com/manual/gh_api
|
|
29864
29873
|
// https://docs.github.com/en/graphql/reference/mutations#convertpullrequesttodraft
|
|
29865
29874
|
// https://docs.github.com/en/graphql/reference/mutations#markpullrequestreadyforreview
|
|
29866
|
-
const mutation_name = args.draft
|
|
29867
|
-
? "convertPullRequestToDraft"
|
|
29868
|
-
: "markPullRequestReadyForReview";
|
|
29875
|
+
const mutation_name = args.draft ? "convertPullRequestToDraft" : "markPullRequestReadyForReview";
|
|
29869
29876
|
let query = `
|
|
29870
29877
|
mutation($id: ID!) {
|
|
29871
29878
|
${mutation_name}(input: { pullRequestId: $id }) {
|
|
@@ -29884,9 +29891,7 @@ async function pr_draft(args) {
|
|
|
29884
29891
|
const state = Store.getState();
|
|
29885
29892
|
const cache_pr = state.pr[args.branch];
|
|
29886
29893
|
invariant(cache_pr, "cache_pr must exist");
|
|
29887
|
-
const command_parts = [
|
|
29888
|
-
`gh api graphql -F id="${cache_pr.id}" -f query='${query}'`,
|
|
29889
|
-
];
|
|
29894
|
+
const command_parts = [`gh api graphql -F id="${cache_pr.id}" -f query='${query}'`];
|
|
29890
29895
|
const command = command_parts.join(" ");
|
|
29891
29896
|
const cli_result = await cli(command);
|
|
29892
29897
|
if (cli_result.code !== 0) {
|
|
@@ -30346,6 +30351,8 @@ function DirtyCheck(props) {
|
|
|
30346
30351
|
switch (state.status) {
|
|
30347
30352
|
case "done":
|
|
30348
30353
|
return props.children;
|
|
30354
|
+
case "stash":
|
|
30355
|
+
return (reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow }), message: "\uD83D\uDCE6 Stashing uncommitted changes\u2026" }));
|
|
30349
30356
|
case "prompt":
|
|
30350
30357
|
return (reactExports.createElement(Box, { flexDirection: "column" },
|
|
30351
30358
|
reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow }), message: "\u26A0\uFE0F Uncommitted changes detected. {git_stack} needs a clean working tree.", values: {
|
|
@@ -30355,8 +30362,10 @@ function DirtyCheck(props) {
|
|
|
30355
30362
|
reactExports.createElement(YesNoPrompt, { message: reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow }), message: "{git_stash} changes to proceed?", values: {
|
|
30356
30363
|
git_stash: reactExports.createElement(Command, null, "git stash"),
|
|
30357
30364
|
} }), onYes: async () => {
|
|
30365
|
+
patch({ status: "stash" });
|
|
30358
30366
|
await cli("git stash --include-untracked");
|
|
30359
|
-
actions.output(reactExports.createElement(Text,
|
|
30367
|
+
actions.output(reactExports.createElement(Text, { color: colors.yellow },
|
|
30368
|
+
reactExports.createElement(FormatText, { message: "\uD83D\uDCE6 Changes saved to stash" })));
|
|
30360
30369
|
actions.set((state) => {
|
|
30361
30370
|
state.is_dirty_check_stash = true;
|
|
30362
30371
|
});
|
|
@@ -30394,7 +30403,7 @@ function DirtyCheck(props) {
|
|
|
30394
30403
|
}
|
|
30395
30404
|
|
|
30396
30405
|
function GatherMetadata(props) {
|
|
30397
|
-
const fallback =
|
|
30406
|
+
const fallback = reactExports.createElement(Text, { color: colors.yellow }, "Gathering local git information\u2026");
|
|
30398
30407
|
return (reactExports.createElement(Await, { fallback: fallback, function: run$a }, props.children));
|
|
30399
30408
|
}
|
|
30400
30409
|
async function run$a() {
|
|
@@ -30436,8 +30445,7 @@ async function run$a() {
|
|
|
30436
30445
|
return;
|
|
30437
30446
|
}
|
|
30438
30447
|
const head = (await cli("git rev-parse HEAD")).stdout;
|
|
30439
|
-
const merge_base = (await cli(`git merge-base HEAD ${master_branch}`))
|
|
30440
|
-
.stdout;
|
|
30448
|
+
const merge_base = (await cli(`git merge-base HEAD ${master_branch}`)).stdout;
|
|
30441
30449
|
// handle when there are no detected changes
|
|
30442
30450
|
if (head === merge_base) {
|
|
30443
30451
|
actions.newline();
|
|
@@ -30531,7 +30539,6 @@ async function run$9() {
|
|
|
30531
30539
|
|
|
30532
30540
|
function HandleCtrlCSigint() {
|
|
30533
30541
|
const actions = Store.useActions();
|
|
30534
|
-
const [exiting, set_exiting] = reactExports.useState(false);
|
|
30535
30542
|
useInput((input, key) => {
|
|
30536
30543
|
handle_input().catch((err) => {
|
|
30537
30544
|
// eslint-disable-next-line no-console
|
|
@@ -30542,22 +30549,17 @@ function HandleCtrlCSigint() {
|
|
|
30542
30549
|
actions.clear();
|
|
30543
30550
|
actions.output(reactExports.createElement(Text, { color: colors.red },
|
|
30544
30551
|
reactExports.createElement(FormatText, { message: "\uD83D\uDEA8 Ctrl+C detected" })));
|
|
30545
|
-
set_exiting(true);
|
|
30546
30552
|
await sleep(1);
|
|
30547
30553
|
actions.exit(235);
|
|
30548
30554
|
}
|
|
30549
30555
|
}
|
|
30550
30556
|
});
|
|
30551
|
-
if (exiting) {
|
|
30552
|
-
return (reactExports.createElement(Text, { color: colors.red },
|
|
30553
|
-
reactExports.createElement(FormatText, { message: "\uD83D\uDEA8 Exiting\u2026" })));
|
|
30554
|
-
}
|
|
30555
30557
|
return null;
|
|
30556
30558
|
}
|
|
30557
30559
|
|
|
30558
30560
|
function LocalCommitStatus(props) {
|
|
30559
30561
|
const argv = Store.useState((state) => state.argv);
|
|
30560
|
-
const fallback =
|
|
30562
|
+
const fallback = reactExports.createElement(Text, { color: colors.yellow }, "Fetching PR status from Github\u2026");
|
|
30561
30563
|
if (argv["mock-metadata"]) {
|
|
30562
30564
|
return (reactExports.createElement(Await, { fallback: fallback, function: mock_metadata }, props.children));
|
|
30563
30565
|
}
|
|
@@ -30797,8 +30799,7 @@ async function run$7() {
|
|
|
30797
30799
|
const temp_branch_name = `${branch_name}_${short_id()}`;
|
|
30798
30800
|
try {
|
|
30799
30801
|
// get latest merge_base relative to local master
|
|
30800
|
-
const merge_base = (await cli(`git merge-base HEAD ${master_branch}`))
|
|
30801
|
-
.stdout;
|
|
30802
|
+
const merge_base = (await cli(`git merge-base HEAD ${master_branch}`)).stdout;
|
|
30802
30803
|
// immediately paint all commit to preserve selected commit ranges
|
|
30803
30804
|
let commit_range = await range(commit_map);
|
|
30804
30805
|
// reverse group list to ensure we create git revise in correct order
|
|
@@ -31094,6 +31095,7 @@ async function run$6() {
|
|
|
31094
31095
|
});
|
|
31095
31096
|
actions.output(reactExports.createElement(StatusTable, null));
|
|
31096
31097
|
actions.output(reactExports.createElement(Text, null, "\u2705 Everything up to date."));
|
|
31098
|
+
actions.exit(0);
|
|
31097
31099
|
}
|
|
31098
31100
|
|
|
31099
31101
|
function PreLocalMergeRebase() {
|
|
@@ -31154,7 +31156,7 @@ async function run$5() {
|
|
|
31154
31156
|
state.pr_templates = pr_templates;
|
|
31155
31157
|
if (pr_templates.length > 0) {
|
|
31156
31158
|
actions.output(reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow }), message: "{count} queryable templates found under {dir}, but not supported.", values: {
|
|
31157
|
-
count:
|
|
31159
|
+
count: reactExports.createElement(Text, { color: colors.blue }, pr_templates.length),
|
|
31158
31160
|
dir: reactExports.createElement(Brackets, null, PR_TEMPLATE.TemplateDir("")),
|
|
31159
31161
|
} }));
|
|
31160
31162
|
}
|
|
@@ -31816,7 +31818,7 @@ const RE = {
|
|
|
31816
31818
|
};
|
|
31817
31819
|
|
|
31818
31820
|
function SyncGithub() {
|
|
31819
|
-
return
|
|
31821
|
+
return reactExports.createElement(Await, { fallback: reactExports.createElement(Text, { color: colors.yellow }, "Syncing\u2026"), function: run$3 });
|
|
31820
31822
|
}
|
|
31821
31823
|
async function run$3() {
|
|
31822
31824
|
const state = Store.getState();
|
|
@@ -32151,7 +32153,7 @@ function RebaseCheck(props) {
|
|
|
32151
32153
|
}
|
|
32152
32154
|
|
|
32153
32155
|
function VerboseDebugInfo(props) {
|
|
32154
|
-
const fallback =
|
|
32156
|
+
const fallback = reactExports.createElement(Text, { color: colors.yellow }, "Logging verbose debug information\u2026");
|
|
32155
32157
|
return (reactExports.createElement(Await, { fallback: fallback, function: run$2 }, props.children));
|
|
32156
32158
|
}
|
|
32157
32159
|
async function run$2() {
|
|
@@ -32214,8 +32216,7 @@ async function run$1() {
|
|
|
32214
32216
|
// Calculate commit SHA based on the relative commit number
|
|
32215
32217
|
const adjusted_number = Number(relative_number) - 1;
|
|
32216
32218
|
// get the commit SHA of the target commit
|
|
32217
|
-
const commit_sha = (await cli(`git rev-parse HEAD~${adjusted_number}`))
|
|
32218
|
-
.stdout;
|
|
32219
|
+
const commit_sha = (await cli(`git rev-parse HEAD~${adjusted_number}`)).stdout;
|
|
32219
32220
|
actions.output(reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.yellow }), message: "\uD83D\uDEE0\uFE0F fixup {relative_number} {commit_sha}", values: {
|
|
32220
32221
|
commit_sha: reactExports.createElement(Parens, null, commit_sha),
|
|
32221
32222
|
relative_number: relative_number,
|
|
@@ -32229,7 +32230,8 @@ async function run$1() {
|
|
|
32229
32230
|
if (diff_cmd.code) {
|
|
32230
32231
|
save_stash = true;
|
|
32231
32232
|
await cli("git stash --include-untracked");
|
|
32232
|
-
actions.output(reactExports.createElement(Text,
|
|
32233
|
+
actions.output(reactExports.createElement(Text, { color: colors.yellow },
|
|
32234
|
+
reactExports.createElement(FormatText, { message: "\uD83D\uDCE6 Changes saved to stash" })));
|
|
32233
32235
|
}
|
|
32234
32236
|
try {
|
|
32235
32237
|
// rebase target needs to account for new commit created above
|
|
@@ -32282,13 +32284,7 @@ async function run(args) {
|
|
|
32282
32284
|
// commit subject - 80 characters wide, truncated
|
|
32283
32285
|
const subject_format = `%<(60,trunc)%s`;
|
|
32284
32286
|
// combine all the above formats into one
|
|
32285
|
-
const format = [
|
|
32286
|
-
sha_format,
|
|
32287
|
-
date_format,
|
|
32288
|
-
author_format,
|
|
32289
|
-
decoration_format,
|
|
32290
|
-
subject_format,
|
|
32291
|
-
].join(" ");
|
|
32287
|
+
const format = [sha_format, date_format, author_format, decoration_format, subject_format].join(" ");
|
|
32292
32288
|
// view the SHA, description and history graph of last 20 commits
|
|
32293
32289
|
const rest_args = process_argv.slice(3).join(" ");
|
|
32294
32290
|
const command = [
|
|
@@ -32300,6 +32296,58 @@ async function run(args) {
|
|
|
32300
32296
|
actions.output(result.stdout);
|
|
32301
32297
|
}
|
|
32302
32298
|
|
|
32299
|
+
/* eslint-disable no-console */
|
|
32300
|
+
class ErrorBoundary extends reactExports.Component {
|
|
32301
|
+
constructor(props) {
|
|
32302
|
+
super(props);
|
|
32303
|
+
this.state = {
|
|
32304
|
+
error: null,
|
|
32305
|
+
component_stack: "",
|
|
32306
|
+
};
|
|
32307
|
+
}
|
|
32308
|
+
static getDerivedStateFromError(error) {
|
|
32309
|
+
return { error };
|
|
32310
|
+
}
|
|
32311
|
+
componentDidCatch(_error, error_info) {
|
|
32312
|
+
let component_stack = error_info.componentStack;
|
|
32313
|
+
if (component_stack) {
|
|
32314
|
+
// remove first line of component_stack
|
|
32315
|
+
component_stack = component_stack.split("\n").slice(1).join("\n");
|
|
32316
|
+
this.setState({ component_stack });
|
|
32317
|
+
}
|
|
32318
|
+
}
|
|
32319
|
+
render() {
|
|
32320
|
+
if (!this.state.error) {
|
|
32321
|
+
return this.props.children;
|
|
32322
|
+
}
|
|
32323
|
+
const message = this.state.error.message;
|
|
32324
|
+
return (reactExports.createElement(Box, { flexDirection: "column", gap: 0 },
|
|
32325
|
+
reactExports.createElement(Text, { color: colors.red },
|
|
32326
|
+
reactExports.createElement(FormatText, { message: "\uD83D\uDEA8 Unhandled error {message}", values: {
|
|
32327
|
+
message: reactExports.createElement(Text, { color: colors.gray }, message),
|
|
32328
|
+
} })),
|
|
32329
|
+
this._render_verbose()));
|
|
32330
|
+
}
|
|
32331
|
+
_render_verbose() {
|
|
32332
|
+
const store_state = Store.getState();
|
|
32333
|
+
if (store_state.argv.verbose) {
|
|
32334
|
+
return reactExports.createElement(Text, { color: colors.gray }, this.state.component_stack);
|
|
32335
|
+
}
|
|
32336
|
+
return (reactExports.createElement(Text, { color: colors.gray },
|
|
32337
|
+
reactExports.createElement(FormatText, { message: "Try again with `--verbose` to see more information." })));
|
|
32338
|
+
}
|
|
32339
|
+
}
|
|
32340
|
+
|
|
32341
|
+
function ExitingGate(props) {
|
|
32342
|
+
const is_exiting = Store.useState((state) => state.is_exiting);
|
|
32343
|
+
if (!is_exiting) {
|
|
32344
|
+
return props.children;
|
|
32345
|
+
}
|
|
32346
|
+
return (reactExports.createElement(Box, { flexDirection: "column" },
|
|
32347
|
+
reactExports.createElement(Text, { color: colors.red },
|
|
32348
|
+
reactExports.createElement(FormatText, { message: "\uD83D\uDEA8 Exiting\u2026" }))));
|
|
32349
|
+
}
|
|
32350
|
+
|
|
32303
32351
|
function App() {
|
|
32304
32352
|
const actions = Store.useActions();
|
|
32305
32353
|
const ink = Store.useState((state) => state.ink);
|
|
@@ -32316,19 +32364,21 @@ function App() {
|
|
|
32316
32364
|
// </React.Fragment>
|
|
32317
32365
|
// );
|
|
32318
32366
|
return (reactExports.createElement(Providers, null,
|
|
32319
|
-
reactExports.createElement(
|
|
32320
|
-
|
|
32321
|
-
|
|
32322
|
-
|
|
32323
|
-
|
|
32324
|
-
|
|
32325
|
-
|
|
32326
|
-
|
|
32327
|
-
|
|
32328
|
-
reactExports.createElement(
|
|
32329
|
-
reactExports.createElement(
|
|
32330
|
-
reactExports.createElement(
|
|
32331
|
-
|
|
32367
|
+
reactExports.createElement(ErrorBoundary, null,
|
|
32368
|
+
reactExports.createElement(Debug, null),
|
|
32369
|
+
reactExports.createElement(Output, null),
|
|
32370
|
+
reactExports.createElement(ExitingGate, null,
|
|
32371
|
+
reactExports.createElement(AutoUpdate, { name: "git-stack-cli", verbose: argv.verbose || argv.update, timeoutMs: argv.update ? 30 * 1000 : 2 * 1000, onOutput: actions.output, onDone: () => {
|
|
32372
|
+
if (argv.update) {
|
|
32373
|
+
actions.exit(0);
|
|
32374
|
+
}
|
|
32375
|
+
} },
|
|
32376
|
+
reactExports.createElement(VerboseDebugInfo, null,
|
|
32377
|
+
reactExports.createElement(DependencyCheck, null,
|
|
32378
|
+
reactExports.createElement(RebaseCheck, null,
|
|
32379
|
+
reactExports.createElement(CherryPickCheck, null,
|
|
32380
|
+
reactExports.createElement(MaybeMain, null)))))),
|
|
32381
|
+
reactExports.createElement(HandleCtrlCSigint, null)))));
|
|
32332
32382
|
}
|
|
32333
32383
|
function MaybeMain() {
|
|
32334
32384
|
const argv = Store.useState((state) => state.argv);
|
|
@@ -32344,12 +32394,13 @@ function MaybeMain() {
|
|
|
32344
32394
|
reactExports.createElement(LocalCommitStatus, null,
|
|
32345
32395
|
reactExports.createElement(Rebase, null))));
|
|
32346
32396
|
}
|
|
32347
|
-
return (reactExports.createElement(
|
|
32397
|
+
return (reactExports.createElement(reactExports.Fragment, null,
|
|
32348
32398
|
!argv.verbose ? null : reactExports.createElement(GithubApiError, null),
|
|
32349
32399
|
reactExports.createElement(GatherMetadata, null,
|
|
32350
|
-
reactExports.createElement(
|
|
32351
|
-
reactExports.createElement(
|
|
32352
|
-
reactExports.createElement(
|
|
32400
|
+
reactExports.createElement(DirtyCheck, null,
|
|
32401
|
+
reactExports.createElement(LocalCommitStatus, null,
|
|
32402
|
+
reactExports.createElement(DetectInitialPR, null,
|
|
32403
|
+
reactExports.createElement(Main, null)))))));
|
|
32353
32404
|
}
|
|
32354
32405
|
|
|
32355
32406
|
const align = {
|
|
@@ -37670,10 +37721,9 @@ async function command() {
|
|
|
37670
37721
|
.wrap(123)
|
|
37671
37722
|
// disallow unknown options
|
|
37672
37723
|
.strict()
|
|
37673
|
-
.version("1.15.
|
|
37724
|
+
.version("1.15.1" )
|
|
37674
37725
|
.showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`")
|
|
37675
|
-
.help("help", "Show usage via `git stack help`")
|
|
37676
|
-
.argv;
|
|
37726
|
+
.help("help", "Show usage via `git stack help`").argv;
|
|
37677
37727
|
}
|
|
37678
37728
|
const GlobalOptions = {
|
|
37679
37729
|
verbose: {
|
|
@@ -37758,9 +37808,22 @@ const FixupOptions = {
|
|
|
37758
37808
|
},
|
|
37759
37809
|
};
|
|
37760
37810
|
|
|
37811
|
+
/* eslint-disable no-console */
|
|
37761
37812
|
(async function main() {
|
|
37762
37813
|
try {
|
|
37763
37814
|
const argv = await command();
|
|
37815
|
+
process.on("uncaughtException", (error) => {
|
|
37816
|
+
console.error("🚨 uncaughtException");
|
|
37817
|
+
console.error(error);
|
|
37818
|
+
maybe_verbose_help();
|
|
37819
|
+
process.exit(237);
|
|
37820
|
+
});
|
|
37821
|
+
process.on("unhandledRejection", (reason, _promise) => {
|
|
37822
|
+
console.error("🚨 unhandledRejection");
|
|
37823
|
+
console.error(reason);
|
|
37824
|
+
maybe_verbose_help();
|
|
37825
|
+
process.exit(238);
|
|
37826
|
+
});
|
|
37764
37827
|
const ink = render(reactExports.createElement(App, null), {
|
|
37765
37828
|
// If true, each update will be rendered as a separate output, without replacing the previous one.
|
|
37766
37829
|
// debug: true,
|
|
@@ -37777,14 +37840,18 @@ const FixupOptions = {
|
|
|
37777
37840
|
});
|
|
37778
37841
|
Store.getState().actions.debug(pretty_json(argv));
|
|
37779
37842
|
await ink.waitUntilExit();
|
|
37843
|
+
function maybe_verbose_help() {
|
|
37844
|
+
if (!argv.verbose) {
|
|
37845
|
+
console.error();
|
|
37846
|
+
console.error("Try again with `--verbose` to see more information.");
|
|
37847
|
+
}
|
|
37848
|
+
}
|
|
37780
37849
|
}
|
|
37781
37850
|
catch (err) {
|
|
37782
|
-
// eslint-disable-next-line no-console
|
|
37783
37851
|
console.error(err);
|
|
37784
|
-
process.exit(
|
|
37852
|
+
process.exit(236);
|
|
37785
37853
|
}
|
|
37786
37854
|
})().catch((err) => {
|
|
37787
|
-
// eslint-disable-next-line no-console
|
|
37788
37855
|
console.error(err);
|
|
37789
37856
|
});
|
|
37790
37857
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-stack-cli",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "magus",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"dev": "npm run build -- --watch",
|
|
25
25
|
"build": "rollup -c rollup.config.js",
|
|
26
26
|
"build:standalone": "GIT_STACK_STANDALONE=true bun run scripts/build-standalone.ts",
|
|
27
|
+
"link": "bun run scripts/link.ts",
|
|
27
28
|
"release:npm": "bun run scripts/release-npm.ts",
|
|
28
29
|
"release:github": "bun run scripts/release-github.ts",
|
|
29
30
|
"release:brew": "bun run scripts/release-brew.ts",
|
package/scripts/link.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
|
|
3
|
+
import { spawn } from "~/core/spawn";
|
|
4
|
+
|
|
5
|
+
const SCRIPT_DIR = import.meta.dir;
|
|
6
|
+
const PROJECT_DIR = path.join(SCRIPT_DIR, "..");
|
|
7
|
+
|
|
8
|
+
process.chdir(PROJECT_DIR);
|
|
9
|
+
|
|
10
|
+
await spawn.sync("npm unlink git-stack-cli");
|
|
11
|
+
await spawn.sync("npm link");
|
|
12
|
+
|
|
13
|
+
console.debug();
|
|
14
|
+
console.debug("✅", "linked");
|
package/src/app/App.tsx
CHANGED
|
@@ -19,6 +19,8 @@ import { VerboseDebugInfo } from "~/app/VerboseDebugInfo";
|
|
|
19
19
|
import { Fixup } from "~/commands/Fixup";
|
|
20
20
|
import { Log } from "~/commands/Log";
|
|
21
21
|
import { Rebase } from "~/commands/Rebase";
|
|
22
|
+
import { ErrorBoundary } from "~/components/ErrorBoundary";
|
|
23
|
+
import { ExitingGate } from "~/components/ExitingGate";
|
|
22
24
|
|
|
23
25
|
export function App() {
|
|
24
26
|
const actions = Store.useActions();
|
|
@@ -42,32 +44,36 @@ export function App() {
|
|
|
42
44
|
|
|
43
45
|
return (
|
|
44
46
|
<Providers>
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
+
<ErrorBoundary>
|
|
48
|
+
<Debug />
|
|
49
|
+
<Output />
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
51
|
+
<ExitingGate>
|
|
52
|
+
<AutoUpdate
|
|
53
|
+
name="git-stack-cli"
|
|
54
|
+
verbose={argv.verbose || argv.update}
|
|
55
|
+
timeoutMs={argv.update ? 30 * 1000 : 2 * 1000}
|
|
56
|
+
onOutput={actions.output}
|
|
57
|
+
onDone={() => {
|
|
58
|
+
if (argv.update) {
|
|
59
|
+
actions.exit(0);
|
|
60
|
+
}
|
|
61
|
+
}}
|
|
62
|
+
>
|
|
63
|
+
<VerboseDebugInfo>
|
|
64
|
+
<DependencyCheck>
|
|
65
|
+
<RebaseCheck>
|
|
66
|
+
<CherryPickCheck>
|
|
67
|
+
<MaybeMain />
|
|
68
|
+
</CherryPickCheck>
|
|
69
|
+
</RebaseCheck>
|
|
70
|
+
</DependencyCheck>
|
|
71
|
+
</VerboseDebugInfo>
|
|
72
|
+
</AutoUpdate>
|
|
69
73
|
|
|
70
|
-
|
|
74
|
+
<HandleCtrlCSigint />
|
|
75
|
+
</ExitingGate>
|
|
76
|
+
</ErrorBoundary>
|
|
71
77
|
</Providers>
|
|
72
78
|
);
|
|
73
79
|
}
|
|
@@ -91,16 +97,18 @@ function MaybeMain() {
|
|
|
91
97
|
}
|
|
92
98
|
|
|
93
99
|
return (
|
|
94
|
-
<
|
|
100
|
+
<React.Fragment>
|
|
95
101
|
{!argv.verbose ? null : <GithubApiError />}
|
|
96
102
|
|
|
97
103
|
<GatherMetadata>
|
|
98
|
-
<
|
|
99
|
-
<
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
104
|
+
<DirtyCheck>
|
|
105
|
+
<LocalCommitStatus>
|
|
106
|
+
<DetectInitialPR>
|
|
107
|
+
<Main />
|
|
108
|
+
</DetectInitialPR>
|
|
109
|
+
</LocalCommitStatus>
|
|
110
|
+
</DirtyCheck>
|
|
103
111
|
</GatherMetadata>
|
|
104
|
-
</
|
|
112
|
+
</React.Fragment>
|
|
105
113
|
);
|
|
106
114
|
}
|
package/src/app/AutoUpdate.tsx
CHANGED
|
@@ -67,14 +67,10 @@ export function AutoUpdate(props: Props) {
|
|
|
67
67
|
|
|
68
68
|
async function auto_update() {
|
|
69
69
|
if (props_ref.current.verbose) {
|
|
70
|
-
handle_output(
|
|
71
|
-
<Ink.Text key="init">Checking for latest version...</Ink.Text>
|
|
72
|
-
);
|
|
70
|
+
handle_output(<Ink.Text key="init">Checking for latest version...</Ink.Text>);
|
|
73
71
|
}
|
|
74
72
|
|
|
75
|
-
const timeout_ms = is_finite_value(props.timeoutMs)
|
|
76
|
-
? props.timeoutMs
|
|
77
|
-
: 2 * 1000;
|
|
73
|
+
const timeout_ms = is_finite_value(props.timeoutMs) ? props.timeoutMs : 2 * 1000;
|
|
78
74
|
|
|
79
75
|
const npm_json = await Promise.race([
|
|
80
76
|
fetch_json(`https://registry.npmjs.org/${props.name}`),
|
|
@@ -94,12 +90,7 @@ export function AutoUpdate(props: Props) {
|
|
|
94
90
|
const script_dir = path.dirname(script_path);
|
|
95
91
|
|
|
96
92
|
// dist/ts/index.js
|
|
97
|
-
const package_json_path = path.join(
|
|
98
|
-
script_dir,
|
|
99
|
-
"..",
|
|
100
|
-
"..",
|
|
101
|
-
"package.json"
|
|
102
|
-
);
|
|
93
|
+
const package_json_path = path.join(script_dir, "..", "..", "package.json");
|
|
103
94
|
|
|
104
95
|
type PackageJson = { version: string };
|
|
105
96
|
const package_json = await read_json<PackageJson>(package_json_path);
|
|
@@ -121,7 +112,7 @@ export function AutoUpdate(props: Props) {
|
|
|
121
112
|
latest_version: <Brackets>{latest_version}</Brackets>,
|
|
122
113
|
local_version: <Brackets>{local_version}</Brackets>,
|
|
123
114
|
}}
|
|
124
|
-
|
|
115
|
+
/>,
|
|
125
116
|
);
|
|
126
117
|
}
|
|
127
118
|
|
|
@@ -134,7 +125,7 @@ export function AutoUpdate(props: Props) {
|
|
|
134
125
|
if (semver_result === -1) {
|
|
135
126
|
// latest version is less than or equal to local version, skip auto update
|
|
136
127
|
throw new Error(
|
|
137
|
-
`latest version < local_version, skipping auto update [${latest_version} < ${local_version}]
|
|
128
|
+
`latest version < local_version, skipping auto update [${latest_version} < ${local_version}]`,
|
|
138
129
|
);
|
|
139
130
|
}
|
|
140
131
|
|
|
@@ -156,7 +147,7 @@ export function AutoUpdate(props: Props) {
|
|
|
156
147
|
handle_output(
|
|
157
148
|
<Ink.Text key="error" color={colors.red}>
|
|
158
149
|
{error?.message}
|
|
159
|
-
</Ink.Text
|
|
150
|
+
</Ink.Text>,
|
|
160
151
|
);
|
|
161
152
|
}
|
|
162
153
|
})
|
|
@@ -185,16 +176,10 @@ export function AutoUpdate(props: Props) {
|
|
|
185
176
|
wrapper={<Ink.Text />}
|
|
186
177
|
message="Installing {name}@{version}..."
|
|
187
178
|
values={{
|
|
188
|
-
name:
|
|
189
|
-
|
|
190
|
-
),
|
|
191
|
-
version: (
|
|
192
|
-
<Ink.Text color={colors.blue}>
|
|
193
|
-
{state.latest_version}
|
|
194
|
-
</Ink.Text>
|
|
195
|
-
),
|
|
179
|
+
name: <Ink.Text color={colors.yellow}>{props.name}</Ink.Text>,
|
|
180
|
+
version: <Ink.Text color={colors.blue}>{state.latest_version}</Ink.Text>,
|
|
196
181
|
}}
|
|
197
|
-
|
|
182
|
+
/>,
|
|
198
183
|
);
|
|
199
184
|
|
|
200
185
|
patch({ status: "install" });
|