git-stack-cli 0.8.7 → 1.0.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.
Files changed (105) hide show
  1. package/README.md +32 -3
  2. package/dist/cjs/index.cjs +34770 -0
  3. package/package.json +21 -7
  4. package/dist/__fixtures__/metadata.js +0 -666
  5. package/dist/__fixtures__/metadata.json +0 -186
  6. package/dist/app/App copy.js +0 -30
  7. package/dist/app/App.js +0 -42
  8. package/dist/app/ArgCheck.js +0 -21
  9. package/dist/app/AutoUpdate.js +0 -128
  10. package/dist/app/Await.js +0 -45
  11. package/dist/app/Brackets copy.js +0 -10
  12. package/dist/app/Brackets.js +0 -11
  13. package/dist/app/Command.js +0 -7
  14. package/dist/app/Counter.js +0 -19
  15. package/dist/app/Debug.js +0 -33
  16. package/dist/app/DependencyCheck.js +0 -89
  17. package/dist/app/Exit.js +0 -14
  18. package/dist/app/FormatText.js +0 -9
  19. package/dist/app/GatherMetadata copy.js +0 -91
  20. package/dist/app/GatherMetadata.js +0 -100
  21. package/dist/app/GithubApiError.js +0 -50
  22. package/dist/app/InitMetadata.js +0 -14
  23. package/dist/app/Input.js +0 -15
  24. package/dist/app/KeepAlive.js +0 -11
  25. package/dist/app/LocalCommitStatus.js +0 -43
  26. package/dist/app/LocalMergeRebase.js +0 -157
  27. package/dist/app/Main copy.js +0 -200
  28. package/dist/app/ManualRebase copy.js +0 -127
  29. package/dist/app/ManualRebase.js +0 -220
  30. package/dist/app/MultiSelect copy.js +0 -76
  31. package/dist/app/MultiSelect.js +0 -143
  32. package/dist/app/NPMAutoUpdate.js +0 -34
  33. package/dist/app/Output.js +0 -19
  34. package/dist/app/Parens copy.js +0 -9
  35. package/dist/app/Parens.js +0 -10
  36. package/dist/app/PostRebaseStatus copy.js +0 -23
  37. package/dist/app/PostRebaseStatus.js +0 -23
  38. package/dist/app/PreLocalMergeRebase.js +0 -21
  39. package/dist/app/PreSelectCommitRanges copy.js +0 -21
  40. package/dist/app/PreSelectCommitRanges.js +0 -21
  41. package/dist/app/Providers.js +0 -5
  42. package/dist/app/RebaseCheck.js +0 -56
  43. package/dist/app/SelectCommitRange.js +0 -1
  44. package/dist/app/SelectCommitRanges.js +0 -207
  45. package/dist/app/Status copy.js +0 -46
  46. package/dist/app/Status.js +0 -61
  47. package/dist/app/StatusTable.js +0 -115
  48. package/dist/app/Store.js +0 -136
  49. package/dist/app/Table.js +0 -65
  50. package/dist/app/TextInput.js +0 -51
  51. package/dist/app/Url copy.js +0 -6
  52. package/dist/app/Url.js +0 -6
  53. package/dist/app/Waterfall.js +0 -20
  54. package/dist/app/YesNoPrompt copy.js +0 -24
  55. package/dist/app/YesNoPrompt.js +0 -40
  56. package/dist/app/main.js +0 -39
  57. package/dist/cli.js +0 -9
  58. package/dist/command.js +0 -60
  59. package/dist/core/CommitMetadata.js +0 -159
  60. package/dist/core/Metadata copy.js +0 -37
  61. package/dist/core/Metadata.js +0 -36
  62. package/dist/core/Metadata.test.js +0 -34
  63. package/dist/core/StackSummaryTable.js +0 -86
  64. package/dist/core/StackSummaryTable.test.js +0 -134
  65. package/dist/core/StackTable.js +0 -38
  66. package/dist/core/SummaryTable.js +0 -38
  67. package/dist/core/ZustandStore.js +0 -23
  68. package/dist/core/assertNever.js +0 -4
  69. package/dist/core/cache.js +0 -39
  70. package/dist/core/capitalize.js +0 -5
  71. package/dist/core/chalk.js +0 -83
  72. package/dist/core/clamp.js +0 -6
  73. package/dist/core/cli copy.js +0 -44
  74. package/dist/core/cli.js +0 -86
  75. package/dist/core/color.js +0 -83
  76. package/dist/core/colors.js +0 -15
  77. package/dist/core/date.js +0 -18
  78. package/dist/core/dependency_check.js +0 -27
  79. package/dist/core/env.js +0 -4
  80. package/dist/core/exit.js +0 -4
  81. package/dist/core/fetch_json.js +0 -24
  82. package/dist/core/get_commit_metadata.js +0 -61
  83. package/dist/core/github.js +0 -118
  84. package/dist/core/id.js +0 -61
  85. package/dist/core/invariant copy.js +0 -5
  86. package/dist/core/invariant.js +0 -5
  87. package/dist/core/isFiniteValue.js +0 -3
  88. package/dist/core/is_command_available.js +0 -15
  89. package/dist/core/is_dev.js +0 -1
  90. package/dist/core/is_finite_value.js +0 -3
  91. package/dist/core/json.js +0 -35
  92. package/dist/core/match_group.js +0 -9
  93. package/dist/core/readJson.js +0 -3
  94. package/dist/core/read_json.js +0 -12
  95. package/dist/core/safe_quote.js +0 -9
  96. package/dist/core/semver_compare.js +0 -26
  97. package/dist/core/serialize_json.js +0 -17
  98. package/dist/core/short_id.js +0 -60
  99. package/dist/core/sleep copy.js +0 -3
  100. package/dist/core/sleep.js +0 -3
  101. package/dist/core/wrap_index.js +0 -10
  102. package/dist/index.js +0 -13
  103. package/dist/main copy.js +0 -266
  104. package/dist/main.backup.js +0 -266
  105. package/dist/main.js +0 -265
@@ -1,143 +0,0 @@
1
- import * as React from "react";
2
- import * as Ink from "ink";
3
- import { clamp } from "../core/clamp.js";
4
- import { colors } from "../core/colors.js";
5
- import { is_finite_value } from "../core/is_finite_value.js";
6
- import { wrap_index } from "../core/wrap_index.js";
7
- export function MultiSelect(props) {
8
- const [selected_set, select] = React.useReducer((state, value) => {
9
- const next = new Set(state);
10
- if (next.has(value)) {
11
- next.delete(value);
12
- }
13
- else {
14
- next.add(value);
15
- }
16
- return next;
17
- }, new Set(), (set) => {
18
- props.items.forEach((item, i) => {
19
- if (item.selected) {
20
- set.add(i);
21
- }
22
- });
23
- return set;
24
- });
25
- // clamp index to keep in item range
26
- const [index, set_index] = React.useReducer((_, value) => {
27
- return clamp(value, 0, props.items.length - 1);
28
- }, 0, function find_initial_index() {
29
- let last_enabled;
30
- for (let i = props.items.length - 1; i >= 0; i--) {
31
- const item = props.items[i];
32
- if (!item.disabled) {
33
- last_enabled = i;
34
- }
35
- if (!item.selected && !item.disabled) {
36
- return i;
37
- }
38
- }
39
- if (is_finite_value(last_enabled)) {
40
- return last_enabled;
41
- }
42
- return 0;
43
- });
44
- const selectRef = React.useRef(false);
45
- React.useEffect(() => {
46
- if (!selectRef.current) {
47
- // console.debug("[MultiSelect]", "skip onSelect before selectRef");
48
- return;
49
- }
50
- const item = props.items[index].value;
51
- const selected_list = Array.from(selected_set);
52
- const selected = selected_set.has(index);
53
- const state = selected_list.map((index) => props.items[index].value);
54
- // console.debug({ item, selected, state });
55
- props.onSelect({ item, selected, state });
56
- }, [selected_set]);
57
- Ink.useInput((input, key) => {
58
- if (props.disabled) {
59
- // console.debug("[MultiSelect] disabled, ignoring input");
60
- return;
61
- }
62
- const space = input === " ";
63
- if (key.return || space) {
64
- selectRef.current = true;
65
- const item = props.items[index];
66
- if (!item.disabled) {
67
- return select(index);
68
- }
69
- }
70
- if (key.upArrow) {
71
- let check = index;
72
- for (let i = 0; i < props.items.length; i++) {
73
- check = wrap_index(check - 1, props.items);
74
- // console.debug("up", { check, i, index });
75
- const item = props.items[check];
76
- if (!item.disabled) {
77
- return set_index(check);
78
- }
79
- }
80
- }
81
- if (key.downArrow) {
82
- let check = index;
83
- for (let i = 0; i < props.items.length; i++) {
84
- check = wrap_index(check + 1, props.items);
85
- // console.debug("down", { check, i, index });
86
- const item = props.items[check];
87
- if (!item.disabled) {
88
- return set_index(check);
89
- }
90
- }
91
- }
92
- });
93
- return (React.createElement(Ink.Box, { flexDirection: "column" }, props.items.map((item, i) => {
94
- const active = i === index;
95
- const selected = selected_set.has(i);
96
- const disabled = item.disabled || false;
97
- return (React.createElement(ItemRow, { key: i, label: item.label, active: active, selected: selected, disabled: disabled, maxWidth: props.maxWidth }));
98
- })));
99
- }
100
- function ItemRow(props) {
101
- let color;
102
- let bold;
103
- let underline;
104
- let dimColor;
105
- if (props.active) {
106
- color = colors.blue;
107
- underline = true;
108
- }
109
- if (props.selected) {
110
- // color = "";
111
- bold = true;
112
- }
113
- if (props.disabled) {
114
- color = "";
115
- bold = false;
116
- underline = false;
117
- dimColor = true;
118
- }
119
- return (React.createElement(Ink.Box, { flexDirection: "row", gap: 1 },
120
- React.createElement(Radio, { selected: props.selected, disabled: props.disabled }),
121
- React.createElement(Ink.Box, { width: props.maxWidth },
122
- React.createElement(Ink.Text, { bold: bold, underline: underline, color: color, dimColor: dimColor, wrap: "truncate-end" }, props.label))));
123
- }
124
- function Radio(props) {
125
- let display;
126
- let color;
127
- let dimColor;
128
- if (props.selected) {
129
- // display = "✓";
130
- display = "◉";
131
- color = colors.green;
132
- }
133
- else {
134
- // display = " ";
135
- display = "◯";
136
- color = "";
137
- }
138
- if (props.disabled) {
139
- color = colors.gray;
140
- dimColor = true;
141
- }
142
- return (React.createElement(Ink.Text, { bold: props.selected, color: color, dimColor: dimColor }, display));
143
- }
@@ -1,34 +0,0 @@
1
- import * as React from "react";
2
- import fs from "node:fs";
3
- import * as Ink from "ink";
4
- export function AutoUpdate(props) {
5
- const props_ref = React.useRef(props);
6
- props_ref.current = props;
7
- React.useEffect(() => {
8
- async function auto_update() {
9
- try {
10
- const npm_res = await fetch(`https://registry.npmjs.org/${props.name}`);
11
- const npm_json = await npm_res.json();
12
- const latest = npm_json["dist-tags"].latest;
13
- console.debug({ latest });
14
- const script_path = process.argv[1];
15
- const path_list = [process.argv[1]];
16
- const real_path_list = path_list.map((p) => fs.realpathSync(p));
17
- console.debug({ real_path_list, path_list });
18
- // const winner = await Promise.race([
19
- // sleep(Math.random() * 5000).then(() => "a"),
20
- // sleep(Math.random() * 5000).then(() => "b"),
21
- // ]);
22
- // console.debug({ winner });
23
- }
24
- catch (err) {
25
- console.debug({ err });
26
- // handled by catch below
27
- throw err;
28
- }
29
- }
30
- const onError = props_ref.current.onError || (() => { });
31
- auto_update().catch(onError);
32
- }, []);
33
- return React.createElement(Ink.Text, { color: "yellow" }, "Checking for latest version...");
34
- }
@@ -1,19 +0,0 @@
1
- import * as React from "react";
2
- import * as Ink from "ink";
3
- import { Store } from "./Store.js";
4
- export function Output() {
5
- const output = Store.useState((state) => state.output);
6
- const pending_output = Store.useState((state) => state.pending_output);
7
- const pending_output_items = Object.values(pending_output);
8
- return (React.createElement(React.Fragment, null,
9
- React.createElement(Ink.Static, { items: output }, (node, i) => {
10
- return React.createElement(Ink.Box, { key: i }, node);
11
- }),
12
- pending_output_items.map((node_list, i) => {
13
- return (React.createElement(Ink.Box, { key: i },
14
- React.createElement(Ink.Text, null, node_list.map((text, j) => {
15
- return (React.createElement(React.Fragment, { key: j },
16
- React.createElement(Ink.Text, null, text)));
17
- }))));
18
- })));
19
- }
@@ -1,9 +0,0 @@
1
- import * as React from "react";
2
- import * as Ink from "ink";
3
- export function Parens(props) {
4
- const color = "#38bdf8";
5
- return (React.createElement(Ink.Text, null,
6
- React.createElement(Ink.Text, { color: color }, "("),
7
- props.children,
8
- React.createElement(Ink.Text, { color: color }, ")")));
9
- }
@@ -1,10 +0,0 @@
1
- import * as React from "react";
2
- import * as Ink from "ink";
3
- import { colors } from "../core/colors.js";
4
- export function Parens(props) {
5
- const color = colors.blue;
6
- return (React.createElement(Ink.Text, null,
7
- React.createElement(Ink.Text, { color: color }, "("),
8
- props.children,
9
- React.createElement(Ink.Text, { color: color }, ")")));
10
- }
@@ -1,23 +0,0 @@
1
- import * as React from "react";
2
- import * as Ink from "ink";
3
- import * as CommitMetadata from "../core/CommitMetadata.js";
4
- import { invariant } from "../core/invariant.js";
5
- import { Await } from "./Await.js";
6
- import { StatusTable } from "./StatusTable.js";
7
- import { Store } from "./Store.js";
8
- export function PostRebaseStatus() {
9
- const argv = Store.useState((state) => state.argv);
10
- invariant(argv, "argv must exist");
11
- return React.createElement(Await, { fallback: null, function: run });
12
- }
13
- async function run() {
14
- const actions = Store.getState().actions;
15
- // reset github pr cache before refreshing via commit range below
16
- actions.reset_pr();
17
- const commit_range = await CommitMetadata.range();
18
- actions.set((state) => {
19
- state.commit_range = commit_range;
20
- });
21
- actions.output(React.createElement(StatusTable, null));
22
- actions.output(React.createElement(Ink.Text, null, "\u2705 Everything up to date."));
23
- }
@@ -1,23 +0,0 @@
1
- import * as React from "react";
2
- import * as Ink from "ink";
3
- import * as CommitMetadata from "../core/CommitMetadata.js";
4
- import { invariant } from "../core/invariant.js";
5
- import { Await } from "./Await.js";
6
- import { StatusTable } from "./StatusTable.js";
7
- import { Store } from "./Store.js";
8
- export function PostRebaseStatus() {
9
- const argv = Store.useState((state) => state.argv);
10
- invariant(argv, "argv must exist");
11
- return React.createElement(Await, { fallback: null, function: run });
12
- }
13
- async function run() {
14
- const actions = Store.getState().actions;
15
- // reset github pr cache before refreshing via commit range below
16
- actions.reset_pr();
17
- const commit_range = await CommitMetadata.range();
18
- actions.set((state) => {
19
- state.commit_range = commit_range;
20
- });
21
- actions.output(React.createElement(StatusTable, null));
22
- actions.output(React.createElement(Ink.Text, null, "\u2705 Everything up to date."));
23
- }
@@ -1,21 +0,0 @@
1
- import * as React from "react";
2
- import { invariant } from "../core/invariant.js";
3
- import { Store } from "./Store.js";
4
- import { YesNoPrompt } from "./YesNoPrompt.js";
5
- export function PreLocalMergeRebase() {
6
- const actions = Store.useActions();
7
- const argv = Store.useState((state) => state.argv);
8
- invariant(argv, "argv must exist");
9
- React.useEffect(() => {
10
- if (argv.force) {
11
- Store.setState((state) => {
12
- state.step = "local-merge-rebase";
13
- });
14
- }
15
- }, [argv]);
16
- return (React.createElement(YesNoPrompt, { message: "Local branch needs to be rebased, would you like to rebase to update your local branch?", onYes: () => {
17
- actions.set((state) => {
18
- state.step = "local-merge-rebase";
19
- });
20
- }, onNo: () => actions.exit(0) }));
21
- }
@@ -1,21 +0,0 @@
1
- import * as React from "react";
2
- import { invariant } from "../core/invariant.js";
3
- import { Store } from "./Store.js";
4
- import { YesNoPrompt } from "./YesNoPrompt.js";
5
- export function PreSelectCommitRanges() {
6
- const actions = Store.useActions();
7
- const argv = Store.useState((state) => state.argv);
8
- invariant(argv, "argv must exist");
9
- React.useEffect(() => {
10
- if (argv.force) {
11
- Store.setState((state) => {
12
- state.step = "select-commit-ranges";
13
- });
14
- }
15
- }, [argv]);
16
- return (React.createElement(YesNoPrompt, { message: "Some commits are new or outdated, would you like to select new commit ranges?", onYes: () => {
17
- actions.set((state) => {
18
- state.step = "select-commit-ranges";
19
- });
20
- }, onNo: () => actions.exit(0) }));
21
- }
@@ -1,21 +0,0 @@
1
- import * as React from "react";
2
- import { invariant } from "../core/invariant.js";
3
- import { Store } from "./Store.js";
4
- import { YesNoPrompt } from "./YesNoPrompt.js";
5
- export function PreSelectCommitRanges() {
6
- const actions = Store.useActions();
7
- const argv = Store.useState((state) => state.argv);
8
- invariant(argv, "argv must exist");
9
- React.useEffect(() => {
10
- if (argv.force) {
11
- Store.setState((state) => {
12
- state.step = "select-commit-ranges";
13
- });
14
- }
15
- }, [argv]);
16
- return (React.createElement(YesNoPrompt, { message: "Some commits are new or outdated, would you like to select new commit ranges?", onYes: () => {
17
- actions.set((state) => {
18
- state.step = "select-commit-ranges";
19
- });
20
- }, onNo: () => actions.exit(0) }));
21
- }
@@ -1,5 +0,0 @@
1
- import * as React from "react";
2
- import { IntlProvider } from "react-intl";
3
- export function Providers(props) {
4
- return React.createElement(IntlProvider, { locale: "en" }, props.children);
5
- }
@@ -1,56 +0,0 @@
1
- import * as React from "react";
2
- import fs from "node:fs";
3
- import path from "node:path";
4
- import * as Ink from "ink";
5
- import { cli } from "../core/cli.js";
6
- import { colors } from "../core/colors.js";
7
- import { invariant } from "../core/invariant.js";
8
- import { Await } from "./Await.js";
9
- import { Store } from "./Store.js";
10
- import { YesNoPrompt } from "./YesNoPrompt.js";
11
- function reducer(state, patch) {
12
- return { ...state, ...patch };
13
- }
14
- export function RebaseCheck(props) {
15
- const actions = Store.useActions();
16
- const argv = Store.useState((state) => state.argv);
17
- invariant(argv, "argv must exist");
18
- const [state, patch] = React.useReducer(reducer, {
19
- status: "init",
20
- });
21
- switch (state.status) {
22
- case "done":
23
- return props.children;
24
- case "prompt":
25
- return (React.createElement(YesNoPrompt, { message: React.createElement(Ink.Text, { color: colors.yellow }, "Rebase detected, would you like to abort it?"), onYes: async () => {
26
- await cli(`git rebase --abort`);
27
- patch({ status: "done" });
28
- }, onNo: async () => {
29
- actions.exit(0);
30
- } }));
31
- default:
32
- return (React.createElement(Await, { fallback: React.createElement(Ink.Text, { color: colors.yellow }, "Checking for rebase..."), function: rebase_check }));
33
- }
34
- async function rebase_check() {
35
- const actions = Store.getState().actions;
36
- const argv = Store.getState().argv;
37
- invariant(argv, "argv must exist");
38
- try {
39
- const repo_root = (await cli(`git rev-parse --absolute-git-dir`)).stdout;
40
- let is_rebase = false;
41
- is_rebase ||= fs.existsSync(path.join(repo_root, "rebase-apply"));
42
- is_rebase ||= fs.existsSync(path.join(repo_root, "rebase-merge"));
43
- const status = is_rebase ? "prompt" : "done";
44
- patch({ status });
45
- }
46
- catch (err) {
47
- actions.error("Unable to check for rebase.");
48
- if (err instanceof Error) {
49
- if (actions.isDebug()) {
50
- actions.error(err.message);
51
- }
52
- }
53
- actions.exit(9);
54
- }
55
- }
56
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,207 +0,0 @@
1
- import * as React from "react";
2
- import * as Ink from "ink";
3
- import { colors } from "../core/colors.js";
4
- import { invariant } from "../core/invariant.js";
5
- import { short_id } from "../core/short_id.js";
6
- import { wrap_index } from "../core/wrap_index.js";
7
- import { Brackets } from "./Brackets.js";
8
- import { FormatText } from "./FormatText.js";
9
- import { MultiSelect } from "./MultiSelect.js";
10
- import { Parens } from "./Parens.js";
11
- import { Store } from "./Store.js";
12
- import { TextInput } from "./TextInput.js";
13
- export function SelectCommitRanges() {
14
- const commit_range = Store.useState((state) => state.commit_range);
15
- invariant(commit_range, "commit_range must exist");
16
- return React.createElement(SelectCommitRangesInternal, { commit_range: commit_range });
17
- }
18
- function SelectCommitRangesInternal(props) {
19
- const actions = Store.useActions();
20
- const [selected_group_id, set_selected_group_id] = React.useState(props.commit_range.UNASSIGNED);
21
- const [group_input, set_group_input] = React.useState(false);
22
- const [new_group_list, create_group] = React.useReducer((group_list, group) => {
23
- return group_list.concat(group);
24
- }, []);
25
- const [commit_map, update_commit_map] = React.useReducer((map, args) => {
26
- map.set(args.key, args.value);
27
- // console.debug("update_commit_map", map, args);
28
- return new Map(map);
29
- }, new Map(), (map) => {
30
- for (const commit of props.commit_range.commit_list) {
31
- map.set(commit.sha, commit.branch_id);
32
- }
33
- return new Map(map);
34
- });
35
- const group_list = [];
36
- // detect if there are unassigned commits
37
- let unassigned_count = 0;
38
- for (const [, group_id] of commit_map.entries()) {
39
- if (group_id === null) {
40
- // console.debug("unassigned commit detected", sha);
41
- unassigned_count++;
42
- }
43
- }
44
- group_list.push(...new_group_list);
45
- const total_group_count = new_group_list.length + props.commit_range.group_list.length;
46
- for (const group of props.commit_range.group_list) {
47
- if (group.pr?.state === "MERGED")
48
- continue;
49
- if (group.id === props.commit_range.UNASSIGNED) {
50
- // only include unassigned group when there are no other groups
51
- if (total_group_count === 1) {
52
- group_list.push({
53
- id: group.id,
54
- title: "Unassigned",
55
- });
56
- }
57
- continue;
58
- }
59
- group_list.push({
60
- id: group.id,
61
- title: group.pr?.title || group.id,
62
- });
63
- }
64
- let current_index = group_list.findIndex((g) => g.id === selected_group_id);
65
- if (current_index === -1) {
66
- current_index = 0;
67
- }
68
- Ink.useInput((input, key) => {
69
- const inputLower = input.toLowerCase();
70
- const hasUnassignedCommits = unassigned_count > 0;
71
- if (!hasUnassignedCommits && inputLower === "s") {
72
- actions.set((state) => {
73
- state.commit_map = {};
74
- for (const [sha, id] of commit_map.entries()) {
75
- if (id) {
76
- const group = group_list.find((g) => g.id === id);
77
- // console.debug({ sha, id, group });
78
- if (group) {
79
- state.commit_map[sha] = group;
80
- }
81
- }
82
- }
83
- switch (inputLower) {
84
- case "s":
85
- state.step = "manual-rebase";
86
- break;
87
- }
88
- });
89
- return;
90
- }
91
- // only allow create when on unassigned group
92
- if (hasUnassignedCommits && inputLower === "c") {
93
- set_group_input(true);
94
- return;
95
- }
96
- if (key.leftArrow) {
97
- const new_index = wrap_index(current_index - 1, group_list);
98
- const next_group = group_list[new_index];
99
- return set_selected_group_id(next_group.id);
100
- }
101
- if (key.rightArrow) {
102
- const new_index = wrap_index(current_index + 1, group_list);
103
- const next_group = group_list[new_index];
104
- return set_selected_group_id(next_group.id);
105
- }
106
- });
107
- const group = group_list[current_index];
108
- const items = props.commit_range.commit_list.map((commit) => {
109
- const commit_metadata_id = commit_map.get(commit.sha);
110
- const selected = commit_metadata_id !== null;
111
- let disabled;
112
- if (group.id === props.commit_range.UNASSIGNED) {
113
- disabled = true;
114
- }
115
- else {
116
- disabled = Boolean(selected && commit_metadata_id !== group.id);
117
- }
118
- return {
119
- label: commit.subject_line,
120
- value: commit,
121
- selected,
122
- disabled,
123
- };
124
- });
125
- items.reverse();
126
- // <- (2/4) #742 Title A ->
127
- const left_arrow = `${SYMBOL.left} `;
128
- const right_arrow = ` ${SYMBOL.right}`;
129
- const group_position = `(${current_index + 1}/${group_list.length}) `;
130
- const max_group_label_width = 80;
131
- let group_title_width = max_group_label_width;
132
- group_title_width -= group_position.length;
133
- group_title_width -= left_arrow.length + right_arrow.length;
134
- group_title_width = Math.min(group.title.length, group_title_width);
135
- let max_item_width = max_group_label_width;
136
- max_item_width -= left_arrow.length + right_arrow.length;
137
- return (React.createElement(Ink.Box, { flexDirection: "column" },
138
- React.createElement(Ink.Box, { height: 1 }),
139
- React.createElement(MultiSelect, { key: group.id, items: items, maxWidth: max_item_width, disabled: group_input, onSelect: (args) => {
140
- // console.debug("onSelect", args);
141
- const key = args.item.sha;
142
- let value;
143
- if (args.selected) {
144
- value = group.id;
145
- }
146
- else {
147
- value = null;
148
- }
149
- update_commit_map({ key, value });
150
- } }),
151
- React.createElement(Ink.Box, { height: 1 }),
152
- React.createElement(Ink.Box, { width: max_group_label_width, flexDirection: "row" },
153
- React.createElement(Ink.Text, null, left_arrow),
154
- React.createElement(Ink.Text, null, group_position),
155
- React.createElement(Ink.Box, { width: group_title_width, justifyContent: "center" },
156
- React.createElement(Ink.Text, { wrap: "truncate-end" }, group.title)),
157
- React.createElement(Ink.Text, null, right_arrow)),
158
- React.createElement(Ink.Box, { height: 1 }),
159
- unassigned_count > 0 ? (React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: colors.gray }), message: "{count} unassigned commits, press {c} to {create} a new group", values: {
160
- count: (React.createElement(Ink.Text, { color: colors.yellow, bold: true }, unassigned_count)),
161
- c: (React.createElement(Ink.Text, { bold: true, color: colors.green }, "c")),
162
- create: (React.createElement(Ink.Text, { bold: true, color: colors.green },
163
- React.createElement(Parens, null, "c"),
164
- "reate")),
165
- } })) : (React.createElement(React.Fragment, null,
166
- React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, null), message: "\uD83C\uDF89 Done! Press {s} to {sync} the commits to Github", values: {
167
- s: (React.createElement(Ink.Text, { bold: true, color: colors.green }, "s")),
168
- sync: (React.createElement(Ink.Text, { bold: true, color: colors.green },
169
- React.createElement(Parens, null, "s"),
170
- "ync")),
171
- } }))),
172
- !group_input ? null : (React.createElement(React.Fragment, null,
173
- React.createElement(Ink.Box, { height: 1 }),
174
- React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: colors.gray }), message: "Enter a title for the PR {note}", values: {
175
- note: (React.createElement(Parens, null,
176
- React.createElement(FormatText, { message: "press {enter} to submit", values: {
177
- enter: (React.createElement(Ink.Text, { bold: true, color: colors.green }, SYMBOL.enter)),
178
- } }))),
179
- } }),
180
- React.createElement(TextInput, { onSubmit: submit_group_input }),
181
- React.createElement(Ink.Box, { height: 1 }))),
182
- React.createElement(Ink.Box, null,
183
- React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: colors.gray }), message: "Press {left} and {right} to view PR groups", values: {
184
- left: (React.createElement(Ink.Text, { bold: true, color: colors.green }, SYMBOL.left)),
185
- right: (React.createElement(Ink.Text, { bold: true, color: colors.green }, SYMBOL.right)),
186
- } })),
187
- React.createElement(Ink.Box, null,
188
- React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: colors.gray }), message: "Press {enter} to toggle commit selection", values: {
189
- enter: (React.createElement(Ink.Text, { bold: true, color: colors.green }, SYMBOL.enter)),
190
- } }))));
191
- function submit_group_input(title) {
192
- const id = short_id();
193
- actions.output(React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { dimColor: true }), message: "Created new group {group} {note}", values: {
194
- group: React.createElement(Brackets, null, title),
195
- note: React.createElement(Parens, null, id),
196
- } }));
197
- // console.debug("submit_group_input", { title, id });
198
- create_group({ id, title });
199
- set_selected_group_id(id);
200
- set_group_input(false);
201
- }
202
- }
203
- const SYMBOL = {
204
- left: "←",
205
- right: "→",
206
- enter: "Enter",
207
- };
@@ -1,46 +0,0 @@
1
- import * as React from "react";
2
- import * as Ink from "ink";
3
- import { invariant } from "../core/invariant.js";
4
- import { Await } from "./Await.js";
5
- import { StatusTable } from "./StatusTable.js";
6
- import { Store } from "./Store.js";
7
- export function Status() {
8
- const argv = Store.useState((state) => state.argv);
9
- invariant(argv, "argv must exist");
10
- return React.createElement(Await, { fallback: null, function: () => run({ argv }) });
11
- }
12
- async function run(args) {
13
- const actions = Store.getState().actions;
14
- const commit_range = Store.getState().commit_range;
15
- invariant(commit_range, "commit_range must exist");
16
- actions.output(React.createElement(StatusTable, null));
17
- let needs_update = false;
18
- for (const group of commit_range.group_list) {
19
- if (group.dirty) {
20
- needs_update = true;
21
- break;
22
- }
23
- }
24
- if (args.argv.check) {
25
- actions.exit(0);
26
- }
27
- else if (args.argv.force) {
28
- Store.setState((state) => {
29
- state.step = "select-commit-ranges";
30
- });
31
- }
32
- else if (needs_update) {
33
- Store.setState((state) => {
34
- state.step = "pre-select-commit-ranges";
35
- });
36
- }
37
- else {
38
- actions.newline();
39
- actions.output(React.createElement(Ink.Text, null, "\u2705 Everything up to date."));
40
- actions.output(React.createElement(Ink.Text, { color: "gray" },
41
- React.createElement(Ink.Text, null, "Run with"),
42
- React.createElement(Ink.Text, { bold: true, color: "yellow" }, ` --force `),
43
- React.createElement(Ink.Text, null, "to force update all pull requests.")));
44
- actions.exit(0);
45
- }
46
- }