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 +1 -1
- package/dist/__fixtures__/metadata.js +7 -30
- package/dist/app/AutoUpdate.js +5 -4
- package/dist/app/Brackets.js +3 -2
- package/dist/app/Command.js +2 -1
- package/dist/app/Debug.js +2 -1
- package/dist/app/DependencyCheck.js +10 -9
- package/dist/app/GatherMetadata.js +37 -4
- package/dist/app/GithubApiError.js +3 -2
- package/dist/app/LocalCommitStatus.js +2 -1
- package/dist/app/LocalMergeRebase.js +12 -10
- package/dist/app/ManualRebase.js +21 -6
- package/dist/app/MultiSelect.js +7 -5
- package/dist/app/Parens.js +2 -1
- package/dist/app/SelectCommitRanges.js +15 -14
- package/dist/app/Status.js +4 -3
- package/dist/app/StatusTable.js +29 -21
- package/dist/app/Store.js +3 -1
- package/dist/app/Table.js +10 -8
- package/dist/app/TextInput.js +16 -2
- package/dist/app/Url.js +2 -2
- package/dist/app/YesNoPrompt.js +5 -4
- package/dist/command.js +12 -1
- package/dist/core/CommitMetadata.js +6 -4
- package/dist/core/Metadata copy.js +37 -0
- package/dist/core/Metadata.js +0 -1
- package/dist/core/StackSummaryTable.js +35 -0
- package/dist/core/StackTable.js +38 -0
- package/dist/core/SummaryTable.js +38 -0
- package/dist/core/chalk.js +83 -0
- package/dist/core/colors.js +15 -0
- package/dist/core/github.js +23 -7
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -5,40 +5,16 @@ export const METADATA = {
|
|
|
5
5
|
"invalid": false,
|
|
6
6
|
"group_list": [
|
|
7
7
|
{
|
|
8
|
-
"id": "
|
|
9
|
-
"pr":
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
41
|
-
"branch_id":
|
|
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": {
|
package/dist/app/AutoUpdate.js
CHANGED
|
@@ -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:
|
|
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:
|
|
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:
|
|
102
|
-
version: (React.createElement(Ink.Text, { color:
|
|
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`);
|
package/dist/app/Brackets.js
CHANGED
|
@@ -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 =
|
|
5
|
-
const text_color =
|
|
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,
|
package/dist/app/Command.js
CHANGED
|
@@ -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 =
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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 ===
|
|
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(
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
28
|
-
const master_sha = (await cli(`git rev-parse
|
|
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.
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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(
|
|
113
|
+
actions.exit(6);
|
|
112
114
|
}
|
|
113
115
|
}
|
package/dist/app/ManualRebase.js
CHANGED
|
@@ -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:
|
|
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:
|
|
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
|
|
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.
|
|
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:
|
|
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:
|
|
148
|
+
actions.output(React.createElement(Ink.Text, { color: colors.yellow },
|
|
134
149
|
"Restored ",
|
|
135
150
|
React.createElement(Brackets, null, branch_name),
|
|
136
151
|
"."));
|
package/dist/app/MultiSelect.js
CHANGED
|
@@ -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((
|
|
56
|
+
Ink.useInput((input, key) => {
|
|
56
57
|
if (props.disabled) {
|
|
57
58
|
// console.debug("[MultiSelect] disabled, ignoring input");
|
|
58
59
|
return;
|
|
59
60
|
}
|
|
60
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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));
|
package/dist/app/Parens.js
CHANGED
|
@@ -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 =
|
|
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 =
|
|
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:
|
|
159
|
-
count: (React.createElement(Ink.Text, { color:
|
|
160
|
-
c: (React.createElement(Ink.Text, { bold: true, color:
|
|
161
|
-
create: (React.createElement(Ink.Text, { bold: true, color:
|
|
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:
|
|
167
|
-
sync: (React.createElement(Ink.Text, { bold: true, color:
|
|
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:
|
|
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:
|
|
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:
|
|
183
|
-
left: (React.createElement(Ink.Text, { bold: true, color:
|
|
184
|
-
right: (React.createElement(Ink.Text, { bold: true, color:
|
|
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:
|
|
188
|
-
enter: (React.createElement(Ink.Text, { bold: true, color:
|
|
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();
|