git-stack-cli 0.5.2 → 0.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/README.md CHANGED
@@ -16,5 +16,5 @@ git stack
16
16
  npm run dev
17
17
  npm link
18
18
 
19
- git stack --debug
19
+ git stack --verbose
20
20
  ```
@@ -5,40 +5,16 @@ export const METADATA = {
5
5
  "invalid": false,
6
6
  "group_list": [
7
7
  {
8
- "id": "79402548-a996-4c2a-a338-86633040358e",
9
- "pr": {
10
- "baseRefName": "d9fc206e-70ce-4b1c-b950-1f54cf1fe112",
11
- "commits": [
12
- {
13
- "authoredDate": "2023-10-29T21:58:16Z",
14
- "authors": [
15
- {
16
- "email": "noah@iamnoah.com",
17
- "id": "MDQ6VXNlcjI5MDA4NA==",
18
- "login": "magus",
19
- "name": "magus"
20
- }
21
- ],
22
- "committedDate": "2023-11-17T10:43:34Z",
23
- "messageBody": "git-multi-diff-id: 79402548-a996-4c2a-a338-86633040358e",
24
- "messageHeadline": "orange color",
25
- "oid": "3dcc44fbe1f293d0c212e71dfcd459e9d88879a8"
26
- }
27
- ],
28
- "headRefName": "79402548-a996-4c2a-a338-86633040358e",
29
- "number": 32,
30
- "state": "OPEN",
31
- "title": "orange color",
32
- "url": "https://github.com/magus/git-multi-diff-playground/pull/32"
33
- },
34
- "base": "d9fc206e-70ce-4b1c-b950-1f54cf1fe112",
35
- "dirty": false,
8
+ "id": "unassigned",
9
+ "pr": null,
10
+ "base": null,
11
+ "dirty": true,
36
12
  "commits": [
37
13
  {
38
14
  "sha": "3dcc44fbe1f293d0c212e71dfcd459e9d88879a8",
39
15
  "message": "orange color",
40
- "raw_message": "orange color\n\ngit-multi-diff-id: 79402548-a996-4c2a-a338-86633040358e",
41
- "branch_id": "79402548-a996-4c2a-a338-86633040358e"
16
+ "raw_message": "orange color",
17
+ "branch_id": null
42
18
  }
43
19
  ]
44
20
  },
@@ -422,6 +398,7 @@ export const METADATA = {
422
398
  "branch_id": "79402548-a996-4c2a-a338-86633040358e"
423
399
  }
424
400
  ],
401
+ "pr_lookup": {},
425
402
  "UNASSIGNED": "unassigned"
426
403
  },
427
404
  "pr": {
@@ -3,6 +3,7 @@ import fs from "node:fs";
3
3
  import path from "node:path";
4
4
  import * as Ink from "ink";
5
5
  import { cli } from "../core/cli.js";
6
+ import { colors } from "../core/colors.js";
6
7
  import { fetch_json } from "../core/fetch_json.js";
7
8
  import { read_json } from "../core/read_json.js";
8
9
  import { semver_compare } from "../core/semver_compare.js";
@@ -87,7 +88,7 @@ export function AutoUpdate(props) {
87
88
  patch({ status, error, local_version, latest_version });
88
89
  onError(error);
89
90
  if (props_ref.current.verbose) {
90
- handle_output(React.createElement(Ink.Text, { key: "error", dimColor: true, color: "red" }, error?.message));
91
+ handle_output(React.createElement(Ink.Text, { key: "error", dimColor: true, color: colors.red }, error?.message));
91
92
  }
92
93
  });
93
94
  }, []);
@@ -96,10 +97,10 @@ export function AutoUpdate(props) {
96
97
  case "init":
97
98
  return null;
98
99
  case "prompt":
99
- return (React.createElement(YesNoPrompt, { message: React.createElement(Ink.Text, { color: "yellow" }, "New version available, would you like to update?"), onYes: async () => {
100
+ return (React.createElement(YesNoPrompt, { message: React.createElement(Ink.Text, { color: colors.yellow }, "New version available, would you like to update?"), onYes: async () => {
100
101
  handle_output(React.createElement(FormatText, { key: "install", wrapper: React.createElement(Ink.Text, null), message: "Installing {name}@{version}...", values: {
101
- name: React.createElement(Ink.Text, { color: "yellow" }, props.name),
102
- version: (React.createElement(Ink.Text, { color: "#38bdf8" }, state.latest_version)),
102
+ name: (React.createElement(Ink.Text, { color: colors.yellow }, props.name)),
103
+ version: (React.createElement(Ink.Text, { color: colors.blue }, state.latest_version)),
103
104
  } }));
104
105
  patch({ status: "install" });
105
106
  await cli(`npm install -g ${props.name}@latest`);
@@ -1,8 +1,9 @@
1
1
  import * as React from "react";
2
2
  import * as Ink from "ink";
3
+ import { colors } from "../core/colors.js";
3
4
  export function Brackets(props) {
4
- const color = "#f97316";
5
- const text_color = "#38bdf8";
5
+ const color = colors.orange;
6
+ const text_color = colors.blue;
6
7
  return (React.createElement(Ink.Text, { color: text_color },
7
8
  React.createElement(Ink.Text, { color: color }, "["),
8
9
  props.children,
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
2
  import * as Ink from "ink";
3
+ import { colors } from "../core/colors.js";
3
4
  export function Command(props) {
4
- const text_color = "#f97316";
5
+ const text_color = colors.orange;
5
6
  return (React.createElement(Ink.Text, { bold: true, color: text_color }, props.children));
6
7
  }
package/dist/app/Debug.js CHANGED
@@ -2,6 +2,7 @@ import * as React from "react";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
4
  import * as Ink from "ink";
5
+ import { colors } from "../core/colors.js";
5
6
  import { invariant } from "../core/invariant.js";
6
7
  import * as json from "../core/json.js";
7
8
  import { Store } from "./Store.js";
@@ -12,7 +13,7 @@ export function Debug() {
12
13
  const debug = Store.useState((state) => state.select.debug(state));
13
14
  React.useEffect(function debugMessageOnce() {
14
15
  if (debug) {
15
- actions.output(React.createElement(Ink.Text, { color: "yellow" }, "Debug mode enabled"));
16
+ actions.output(React.createElement(Ink.Text, { color: colors.yellow }, "Debug mode enabled"));
16
17
  }
17
18
  }, [argv]);
18
19
  React.useEffect(function syncStateJson() {
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
2
  import * as Ink from "ink";
3
3
  import { cli } from "../core/cli.js";
4
+ import { colors } from "../core/colors.js";
4
5
  import { is_command_available } from "../core/is_command_available.js";
5
6
  import { match_group } from "../core/match_group.js";
6
7
  import { semver_compare } from "../core/semver_compare.js";
@@ -11,19 +12,19 @@ import { Store } from "./Store.js";
11
12
  import { Url } from "./Url.js";
12
13
  export function DependencyCheck(props) {
13
14
  const actions = Store.useActions();
14
- return (React.createElement(Await, { fallback: React.createElement(Ink.Text, { color: "yellow" },
15
+ return (React.createElement(Await, { fallback: React.createElement(Ink.Text, { color: colors.yellow },
15
16
  "Checking ",
16
17
  React.createElement(Command, null, "git"),
17
18
  " install..."), function: async () => {
18
19
  if (is_command_available("git")) {
19
20
  return;
20
21
  }
21
- actions.output(React.createElement(Ink.Text, { color: "yellow" },
22
+ actions.output(React.createElement(Ink.Text, { color: colors.yellow },
22
23
  React.createElement(Command, null, "git"),
23
24
  " must be installed."));
24
25
  actions.exit(2);
25
26
  } },
26
- React.createElement(Await, { fallback: React.createElement(Ink.Text, { color: "yellow" },
27
+ React.createElement(Await, { fallback: React.createElement(Ink.Text, { color: colors.yellow },
27
28
  "Checking ",
28
29
  React.createElement(Command, null, "node"),
29
30
  " install..."), function: async () => {
@@ -32,12 +33,12 @@ export function DependencyCheck(props) {
32
33
  if (semver_result >= 0) {
33
34
  return;
34
35
  }
35
- actions.output(React.createElement(Ink.Text, { color: "yellow" },
36
+ actions.output(React.createElement(Ink.Text, { color: colors.yellow },
36
37
  React.createElement(Command, null, "node"),
37
38
  " must be installed."));
38
39
  actions.exit(2);
39
40
  } },
40
- React.createElement(Await, { fallback: React.createElement(Ink.Text, { color: "yellow" },
41
+ React.createElement(Await, { fallback: React.createElement(Ink.Text, { color: colors.yellow },
41
42
  React.createElement(Ink.Text, null,
42
43
  "Checking ",
43
44
  React.createElement(Command, null, "gh"),
@@ -45,10 +46,10 @@ export function DependencyCheck(props) {
45
46
  if (is_command_available("gh")) {
46
47
  return;
47
48
  }
48
- actions.output(React.createElement(Ink.Text, { color: "yellow" },
49
+ actions.output(React.createElement(Ink.Text, { color: colors.yellow },
49
50
  React.createElement(Command, null, "gh"),
50
51
  " must be installed."));
51
- actions.output(React.createElement(Ink.Text, { color: "yellow" },
52
+ actions.output(React.createElement(Ink.Text, { color: colors.yellow },
52
53
  React.createElement(Ink.Text, null, "Visit "),
53
54
  React.createElement(Url, null, "https://cli.github.com"),
54
55
  React.createElement(Ink.Text, null, " to install the github cli "),
@@ -56,7 +57,7 @@ export function DependencyCheck(props) {
56
57
  React.createElement(Command, null, "gh"))));
57
58
  actions.exit(3);
58
59
  } },
59
- React.createElement(Await, { fallback: React.createElement(Ink.Text, { color: "yellow" },
60
+ React.createElement(Await, { fallback: React.createElement(Ink.Text, { color: colors.yellow },
60
61
  React.createElement(Ink.Text, null,
61
62
  "Checking ",
62
63
  React.createElement(Command, null, "gh auth status"),
@@ -71,7 +72,7 @@ export function DependencyCheck(props) {
71
72
  });
72
73
  return;
73
74
  }
74
- actions.output(React.createElement(Ink.Text, { color: "yellow" },
75
+ actions.output(React.createElement(Ink.Text, { color: colors.yellow },
75
76
  React.createElement(Command, null, "gh"),
76
77
  React.createElement(Ink.Text, null, " requires login, please run "),
77
78
  React.createElement(Command, null, "gh auth login")));
@@ -1,33 +1,60 @@
1
1
  import * as React from "react";
2
2
  import * as Ink from "ink";
3
3
  import { cli } from "../core/cli.js";
4
+ import { colors } from "../core/colors.js";
4
5
  import { invariant } from "../core/invariant.js";
5
6
  import { match_group } from "../core/match_group.js";
6
7
  import { Await } from "./Await.js";
8
+ import { Brackets } from "./Brackets.js";
9
+ import { FormatText } from "./FormatText.js";
7
10
  import { Store } from "./Store.js";
8
11
  export function GatherMetadata(props) {
9
12
  const argv = Store.useState((state) => state.argv);
10
13
  invariant(argv, "argv must exist");
11
- const fallback = (React.createElement(Ink.Text, { color: "yellow" }, "Gathering local git information..."));
14
+ const fallback = (React.createElement(Ink.Text, { color: colors.yellow }, "Gathering local git information..."));
12
15
  return (React.createElement(Await, { fallback: fallback, function: gather_metadata }, props.children));
13
16
  }
14
17
  async function gather_metadata() {
15
18
  const actions = Store.getState().actions;
19
+ const argv = Store.getState().argv;
20
+ invariant(argv, "argv must exist");
16
21
  try {
22
+ // default to master branch, fallback to main
23
+ let master_branch;
24
+ if (argv.branch) {
25
+ actions.debug(React.createElement(FormatText, { message: "Setting master branch to {branch}", values: {
26
+ branch: React.createElement(Brackets, null, argv.branch),
27
+ } }));
28
+ master_branch = argv.branch;
29
+ }
30
+ else {
31
+ const detect_master = await cli(`git branch --list "${BRANCH.master}" --color=never`);
32
+ if (detect_master.stdout !== "") {
33
+ master_branch = BRANCH.master;
34
+ }
35
+ else {
36
+ actions.debug(React.createElement(FormatText, { message: "Could not find {master} branch, falling back to {main}", values: {
37
+ master: React.createElement(Brackets, null, BRANCH.master),
38
+ main: React.createElement(Brackets, null, BRANCH.main),
39
+ } }));
40
+ master_branch = BRANCH.main;
41
+ }
42
+ }
17
43
  const branch_name = (await cli("git rev-parse --abbrev-ref HEAD")).stdout;
18
44
  // handle when there are no detected changes
19
- if (branch_name === "master") {
45
+ if (branch_name === master_branch) {
20
46
  actions.newline();
21
47
  actions.error("Must run within a branch.");
22
48
  actions.exit(0);
23
49
  return;
24
50
  }
25
51
  const head = (await cli("git rev-parse HEAD")).stdout;
26
- const merge_base = (await cli("git merge-base HEAD master")).stdout;
52
+ const merge_base = (await cli(`git merge-base HEAD ${master_branch}`))
53
+ .stdout;
27
54
  // handle when there are no detected changes
28
55
  if (head === merge_base) {
29
56
  actions.newline();
30
- actions.output(React.createElement(Ink.Text, { color: "gray" }, "No changes detected."));
57
+ actions.output(React.createElement(Ink.Text, { color: colors.gray }, "No changes detected."));
31
58
  actions.exit(0);
32
59
  return;
33
60
  }
@@ -37,6 +64,7 @@ async function gather_metadata() {
37
64
  const repo_path = match_group(origin_url, RE.repo_path, "repo_path");
38
65
  Store.setState((state) => {
39
66
  state.repo_path = repo_path;
67
+ state.master_branch = master_branch;
40
68
  state.head = head;
41
69
  state.merge_base = merge_base;
42
70
  state.branch_name = branch_name;
@@ -49,6 +77,7 @@ async function gather_metadata() {
49
77
  actions.error(err.message);
50
78
  }
51
79
  }
80
+ actions.exit(7);
52
81
  }
53
82
  }
54
83
  const RE = {
@@ -56,3 +85,7 @@ const RE = {
56
85
  // https://github.com/magus/git-multi-diff-playground.git
57
86
  repo_path: /(?<repo_path>[^:^/]+\/[^/]+)\.git/,
58
87
  };
88
+ const BRANCH = {
89
+ master: "master",
90
+ main: "main",
91
+ };
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
2
  import * as Ink from "ink";
3
3
  import { cli } from "../core/cli.js";
4
+ import { colors } from "../core/colors.js";
4
5
  import * as date from "../core/date.js";
5
6
  import { invariant } from "../core/invariant.js";
6
7
  import { Await } from "./Await.js";
@@ -41,9 +42,9 @@ async function run() {
41
42
  React.createElement(Ink.Text, null, "/"),
42
43
  React.createElement(Ink.Text, null, limit)),
43
44
  React.createElement(Ink.Text, null, " will reset at "),
44
- React.createElement(Ink.Text, { bold: true, color: "yellow" }, reset_time),
45
+ React.createElement(Ink.Text, { bold: true, color: colors.yellow }, reset_time),
45
46
  React.createElement(Ink.Text, null, " "),
46
47
  React.createElement(Parens, null,
47
48
  React.createElement(Ink.Text, null, "in "),
48
- React.createElement(Ink.Text, { bold: true, color: "yellow" }, time_until))));
49
+ React.createElement(Ink.Text, { bold: true, color: colors.yellow }, time_until))));
49
50
  }
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
2
  import * as Ink from "ink";
3
3
  import * as CommitMetadata from "../core/CommitMetadata.js";
4
+ import { colors } from "../core/colors.js";
4
5
  import { invariant } from "../core/invariant.js";
5
6
  import * as json from "../core/json.js";
6
7
  import { Await } from "./Await.js";
@@ -8,7 +9,7 @@ import { Store } from "./Store.js";
8
9
  export function LocalCommitStatus(props) {
9
10
  const argv = Store.useState((state) => state.argv);
10
11
  invariant(argv, "argv must exist");
11
- const fallback = (React.createElement(Ink.Text, { color: "yellow" }, "Fetching PR status from Github..."));
12
+ const fallback = (React.createElement(Ink.Text, { color: colors.yellow }, "Fetching PR status from Github..."));
12
13
  if (argv["mock-metadata"]) {
13
14
  return (React.createElement(Await, { fallback: fallback, function: mock_metadata }, props.children));
14
15
  }
@@ -3,6 +3,7 @@ import * as Ink from "ink";
3
3
  import * as CommitMetadata from "../core/CommitMetadata.js";
4
4
  import * as Metadata from "../core/Metadata.js";
5
5
  import { cli } from "../core/cli.js";
6
+ import { colors } from "../core/colors.js";
6
7
  import { invariant } from "../core/invariant.js";
7
8
  import { short_id } from "../core/short_id.js";
8
9
  import { Await } from "./Await.js";
@@ -11,32 +12,33 @@ import { FormatText } from "./FormatText.js";
11
12
  import { Parens } from "./Parens.js";
12
13
  import { Store } from "./Store.js";
13
14
  export function LocalMergeRebase() {
14
- return (React.createElement(Await, { fallback: React.createElement(Ink.Text, { color: "yellow" }, "Rebasing commits..."), function: run }));
15
+ return (React.createElement(Await, { fallback: React.createElement(Ink.Text, { color: colors.yellow }, "Rebasing commits..."), function: run }));
15
16
  }
16
17
  async function run() {
17
18
  const state = Store.getState();
18
19
  const actions = state.actions;
19
20
  const branch_name = state.branch_name;
20
21
  const commit_range = state.commit_range;
22
+ const master_branch = state.master_branch;
21
23
  invariant(branch_name, "branch_name must exist");
22
24
  invariant(commit_range, "commit_range must exist");
23
25
  // always listen for SIGINT event and restore git state
24
26
  process.once("SIGINT", handle_exit);
25
27
  const temp_branch_name = `${branch_name}_${short_id()}`;
26
28
  try {
27
- await cli(`git fetch --no-tags -v origin master:master`);
28
- const master_sha = (await cli(`git rev-parse master`)).stdout;
29
+ await cli(`git fetch --no-tags -v origin ${master_branch}:${master_branch}`);
30
+ const master_sha = (await cli(`git rev-parse ${master_branch}`)).stdout;
29
31
  const rebase_merge_base = master_sha;
30
32
  // create temporary branch based on merge base
31
33
  await cli(`git checkout -b ${temp_branch_name} ${rebase_merge_base}`);
32
34
  for (let i = 0; i < commit_range.commit_list.length; i++) {
33
35
  const commit = commit_range.commit_list[i];
34
- const commit_pr = commit_range.pr_map.get(commit.branch_id || "");
36
+ const commit_pr = commit_range.pr_lookup[commit.branch_id || ""];
35
37
  // drop commits that are in groups of merged PRs
36
38
  const merged_pr = commit_pr?.state === "MERGED";
37
39
  if (merged_pr) {
38
40
  if (actions.isDebug()) {
39
- actions.output(React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: "yellow", wrap: "truncate-end" }), message: "Dropping {commit_message} {pr_status}", values: {
41
+ actions.output(React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: colors.yellow, wrap: "truncate-end" }), message: "Dropping {commit_message} {pr_status}", values: {
40
42
  commit_message: React.createElement(Brackets, null, commit.message),
41
43
  pr_status: React.createElement(Parens, null, "MERGED"),
42
44
  } }));
@@ -45,14 +47,14 @@ async function run() {
45
47
  }
46
48
  // cherry-pick and amend commits one by one
47
49
  if (actions.isDebug()) {
48
- actions.output(React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: "yellow", wrap: "truncate-end" }), message: "Picking {commit_message}", values: {
50
+ actions.output(React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: colors.yellow, wrap: "truncate-end" }), message: "Picking {commit_message}", values: {
49
51
  commit_message: React.createElement(Brackets, null, commit.message),
50
52
  } }));
51
53
  }
52
54
  await cli(`git cherry-pick ${commit.sha}`);
53
55
  if (commit.branch_id && !commit_pr) {
54
56
  if (actions.isDebug()) {
55
- actions.output(React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: "yellow", wrap: "truncate-end" }), message: "Cleaning up unused group {group}", values: {
57
+ actions.output(React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: colors.yellow, wrap: "truncate-end" }), message: "Cleaning up unused group {group}", values: {
56
58
  group: React.createElement(Brackets, null, commit.branch_id),
57
59
  } }));
58
60
  }
@@ -99,15 +101,15 @@ async function run() {
99
101
  }
100
102
  }
101
103
  function handle_exit() {
102
- actions.output(React.createElement(Ink.Text, { color: "yellow" },
104
+ actions.output(React.createElement(Ink.Text, { color: colors.yellow },
103
105
  "Restoring ",
104
106
  React.createElement(Brackets, null, branch_name),
105
107
  "..."));
106
108
  restore_git();
107
- actions.output(React.createElement(Ink.Text, { color: "yellow" },
109
+ actions.output(React.createElement(Ink.Text, { color: colors.yellow },
108
110
  "Restored ",
109
111
  React.createElement(Brackets, null, branch_name),
110
112
  "."));
111
- actions.exit(5);
113
+ actions.exit(6);
112
114
  }
113
115
  }
@@ -2,7 +2,9 @@ import * as React from "react";
2
2
  import * as Ink from "ink";
3
3
  import * as CommitMetadata from "../core/CommitMetadata.js";
4
4
  import * as Metadata from "../core/Metadata.js";
5
+ import * as StackSummaryTable from "../core/StackSummaryTable.js";
5
6
  import { cli } from "../core/cli.js";
7
+ import { colors } from "../core/colors.js";
6
8
  import * as github from "../core/github.js";
7
9
  import { invariant } from "../core/invariant.js";
8
10
  import { short_id } from "../core/short_id.js";
@@ -11,7 +13,7 @@ import { Brackets } from "./Brackets.js";
11
13
  import { FormatText } from "./FormatText.js";
12
14
  import { Store } from "./Store.js";
13
15
  export function ManualRebase(props) {
14
- return (React.createElement(Await, { fallback: React.createElement(Ink.Text, { color: "yellow" }, "Rebasing commits..."), function: () => run(props) }));
16
+ return (React.createElement(Await, { fallback: React.createElement(Ink.Text, { color: colors.yellow }, "Rebasing commits..."), function: () => run(props) }));
15
17
  }
16
18
  async function run(props) {
17
19
  const state = Store.getState();
@@ -59,19 +61,27 @@ async function run(props) {
59
61
  await cli(`git commit --amend -m "${new_message}"`);
60
62
  }
61
63
  }
62
- actions.output(React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: "yellow", wrap: "truncate-end" }), message: "Syncing {group}\u2026", values: {
64
+ actions.output(React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: colors.yellow, wrap: "truncate-end" }), message: "Syncing {group}\u2026", values: {
63
65
  group: (React.createElement(Brackets, null, group.pr?.title || group.title || group.id)),
64
66
  } }));
65
67
  if (!props.skipSync) {
66
68
  // push to origin since github requires commit shas to line up perfectly
67
69
  const git_push_command = [`git push -f origin HEAD:${group.id}`];
68
- if (argv["no-verify"]) {
70
+ if (argv.verify === false) {
69
71
  git_push_command.push("--no-verify");
70
72
  }
71
73
  await cli(git_push_command.join(" "));
72
74
  if (group.pr) {
73
75
  // ensure base matches pr in github
74
- await github.pr_base(group.id, group.base);
76
+ await github.pr_edit({
77
+ branch: group.id,
78
+ base: group.base,
79
+ body: StackSummaryTable.write({
80
+ body: group.pr.body,
81
+ commit_range,
82
+ selected_group_id: group.id,
83
+ }),
84
+ });
75
85
  }
76
86
  else {
77
87
  // delete local group branch if leftover
@@ -83,6 +93,11 @@ async function run(props) {
83
93
  branch: group.id,
84
94
  base: group.base,
85
95
  title: group.title,
96
+ body: StackSummaryTable.write({
97
+ body: "",
98
+ commit_range,
99
+ selected_group_id: group.id,
100
+ }),
86
101
  });
87
102
  // move back to temp branch
88
103
  await cli(`git checkout ${temp_branch_name}`);
@@ -125,12 +140,12 @@ async function run(props) {
125
140
  }
126
141
  }
127
142
  function handle_exit() {
128
- actions.output(React.createElement(Ink.Text, { color: "yellow" },
143
+ actions.output(React.createElement(Ink.Text, { color: colors.yellow },
129
144
  "Restoring ",
130
145
  React.createElement(Brackets, null, branch_name),
131
146
  "..."));
132
147
  restore_git();
133
- actions.output(React.createElement(Ink.Text, { color: "yellow" },
148
+ actions.output(React.createElement(Ink.Text, { color: colors.yellow },
134
149
  "Restored ",
135
150
  React.createElement(Brackets, null, branch_name),
136
151
  "."));
@@ -1,6 +1,7 @@
1
1
  import * as React from "react";
2
2
  import * as Ink from "ink";
3
3
  import { clamp } from "../core/clamp.js";
4
+ import { colors } from "../core/colors.js";
4
5
  import { wrap_index } from "../core/wrap_index.js";
5
6
  export function MultiSelect(props) {
6
7
  const [selected_set, select] = React.useReducer((state, value) => {
@@ -52,12 +53,13 @@ export function MultiSelect(props) {
52
53
  // console.debug({ item, selected, state });
53
54
  props.onSelect({ item, selected, state });
54
55
  }, [selected_set]);
55
- Ink.useInput((_input, key) => {
56
+ Ink.useInput((input, key) => {
56
57
  if (props.disabled) {
57
58
  // console.debug("[MultiSelect] disabled, ignoring input");
58
59
  return;
59
60
  }
60
- if (key.return) {
61
+ const space = input === " ";
62
+ if (key.return || space) {
61
63
  selectRef.current = true;
62
64
  const item = props.items[index];
63
65
  if (!item.disabled) {
@@ -100,7 +102,7 @@ function ItemRow(props) {
100
102
  let underline;
101
103
  let dimColor;
102
104
  if (props.active) {
103
- color = "#38bdf8";
105
+ color = colors.blue;
104
106
  underline = true;
105
107
  }
106
108
  if (props.selected) {
@@ -125,7 +127,7 @@ function Radio(props) {
125
127
  if (props.selected) {
126
128
  // display = "✓";
127
129
  display = "◉";
128
- color = "green";
130
+ color = colors.green;
129
131
  }
130
132
  else {
131
133
  // display = " ";
@@ -133,7 +135,7 @@ function Radio(props) {
133
135
  color = "";
134
136
  }
135
137
  if (props.disabled) {
136
- color = "gray";
138
+ color = colors.gray;
137
139
  dimColor = true;
138
140
  }
139
141
  return (React.createElement(Ink.Text, { bold: props.selected, color: color, dimColor: dimColor }, display));
@@ -1,7 +1,8 @@
1
1
  import * as React from "react";
2
2
  import * as Ink from "ink";
3
+ import { colors } from "../core/colors.js";
3
4
  export function Parens(props) {
4
- const color = "#38bdf8";
5
+ const color = colors.blue;
5
6
  return (React.createElement(Ink.Text, null,
6
7
  React.createElement(Ink.Text, { color: color }, "("),
7
8
  props.children,
@@ -1,5 +1,6 @@
1
1
  import * as React from "react";
2
2
  import * as Ink from "ink";
3
+ import { colors } from "../core/colors.js";
3
4
  import { invariant } from "../core/invariant.js";
4
5
  import { short_id } from "../core/short_id.js";
5
6
  import { wrap_index } from "../core/wrap_index.js";
@@ -72,7 +73,7 @@ function SelectCommitRangesInternal(props) {
72
73
  state.commit_map = {};
73
74
  for (const [sha, id] of commit_map.entries()) {
74
75
  if (id) {
75
- const group = new_group_list.find((g) => g.id === id);
76
+ const group = group_list.find((g) => g.id === id);
76
77
  // console.debug({ sha, id, group });
77
78
  if (group) {
78
79
  state.commit_map[sha] = group;
@@ -155,37 +156,37 @@ function SelectCommitRangesInternal(props) {
155
156
  React.createElement(Ink.Text, { wrap: "truncate-end" }, group.title)),
156
157
  React.createElement(Ink.Text, null, right_arrow)),
157
158
  React.createElement(Ink.Box, { height: 1 }),
158
- unassigned_count > 0 ? (React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: "gray" }), message: "{count} unassigned commits, press {c} to {create} a new group", values: {
159
- count: (React.createElement(Ink.Text, { color: "#3b82f6", bold: true }, unassigned_count)),
160
- c: (React.createElement(Ink.Text, { bold: true, color: "#22c55e" }, "c")),
161
- create: (React.createElement(Ink.Text, { bold: true, color: "#22c55e" },
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 },
162
163
  React.createElement(Parens, null, "c"),
163
164
  "reate")),
164
165
  } })) : (React.createElement(React.Fragment, null,
165
166
  React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, null), message: "\uD83C\uDF89 Done! Press {s} to {sync} the commits to Github", values: {
166
- s: (React.createElement(Ink.Text, { bold: true, color: "#22c55e" }, "s")),
167
- sync: (React.createElement(Ink.Text, { bold: true, color: "#22c55e" },
167
+ s: (React.createElement(Ink.Text, { bold: true, color: colors.green }, "s")),
168
+ sync: (React.createElement(Ink.Text, { bold: true, color: colors.green },
168
169
  React.createElement(Parens, null, "s"),
169
170
  "ync")),
170
171
  } }))),
171
172
  !group_input ? null : (React.createElement(React.Fragment, null,
172
173
  React.createElement(Ink.Box, { height: 1 }),
173
- React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: "gray" }), message: "Enter a title for the PR {note}", values: {
174
+ React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: colors.gray }), message: "Enter a title for the PR {note}", values: {
174
175
  note: (React.createElement(Parens, null,
175
176
  React.createElement(FormatText, { message: "press {enter} to submit", values: {
176
- enter: (React.createElement(Ink.Text, { bold: true, color: "#22c55e" }, SYMBOL.enter)),
177
+ enter: (React.createElement(Ink.Text, { bold: true, color: colors.green }, SYMBOL.enter)),
177
178
  } }))),
178
179
  } }),
179
180
  React.createElement(TextInput, { onSubmit: submit_group_input }),
180
181
  React.createElement(Ink.Box, { height: 1 }))),
181
182
  React.createElement(Ink.Box, null,
182
- React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: "gray" }), message: "Press {left} and {right} to view PR groups", values: {
183
- left: (React.createElement(Ink.Text, { bold: true, color: "#22c55e" }, SYMBOL.left)),
184
- right: (React.createElement(Ink.Text, { bold: true, color: "#22c55e" }, SYMBOL.right)),
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)),
185
186
  } })),
186
187
  React.createElement(Ink.Box, null,
187
- React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: "gray" }), message: "Press {enter} to toggle commit selection", values: {
188
- enter: (React.createElement(Ink.Text, { bold: true, color: "#22c55e" }, SYMBOL.enter)),
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)),
189
190
  } }))));
190
191
  function submit_group_input(title) {
191
192
  const id = short_id();