git-stack-cli 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/__fixtures__/metadata.js +763 -0
- package/dist/__fixtures__/metadata.json +186 -0
- package/dist/app/App.js +30 -0
- package/dist/app/ArgCheck.js +21 -0
- package/dist/app/Await.js +45 -0
- package/dist/app/Brackets.js +10 -0
- package/dist/app/Counter.js +19 -0
- package/dist/app/Debug.js +31 -0
- package/dist/app/DependencyCheck.js +52 -0
- package/dist/app/Exit.js +14 -0
- package/dist/app/GatherMetadata copy.js +54 -0
- package/dist/app/GatherMetadata.js +54 -0
- package/dist/app/GithubApiError.js +49 -0
- package/dist/app/InitMetadata.js +14 -0
- package/dist/app/KeepAlive.js +11 -0
- package/dist/app/Main copy.js +200 -0
- package/dist/app/ManualRebase.js +126 -0
- package/dist/app/MultiSelect copy.js +76 -0
- package/dist/app/MultiSelect.js +136 -0
- package/dist/app/Output.js +9 -0
- package/dist/app/Parens copy.js +9 -0
- package/dist/app/Parens.js +9 -0
- package/dist/app/PostRebaseStatus copy.js +23 -0
- package/dist/app/PostRebaseStatus.js +23 -0
- package/dist/app/PreSelectCommitRanges copy.js +29 -0
- package/dist/app/PreSelectCommitRanges.js +11 -0
- package/dist/app/SelectCommitRange.js +1 -0
- package/dist/app/SelectCommitRanges.js +182 -0
- package/dist/app/Status copy.js +46 -0
- package/dist/app/Status.js +45 -0
- package/dist/app/StatusTable.js +94 -0
- package/dist/app/Store.js +73 -0
- package/dist/app/Waterfall.js +20 -0
- package/dist/app/YesNoPrompt copy.js +24 -0
- package/dist/app/YesNoPrompt.js +23 -0
- package/dist/app/main.js +31 -0
- package/dist/cli.js +9 -0
- package/dist/command.js +22 -0
- package/dist/core/CommitMetadata.js +143 -0
- package/dist/core/Metadata.js +36 -0
- package/dist/core/ZustandStore.js +23 -0
- package/dist/core/assertNever.js +4 -0
- package/dist/core/cache.js +39 -0
- package/dist/core/capitalize.js +5 -0
- package/dist/core/clamp.js +6 -0
- package/dist/core/cli copy.js +44 -0
- package/dist/core/cli.js +44 -0
- package/dist/core/color.js +83 -0
- package/dist/core/date.js +18 -0
- package/dist/core/dependency_check.js +27 -0
- package/dist/core/exit.js +4 -0
- package/dist/core/get_commit_metadata.js +61 -0
- package/dist/core/github.js +45 -0
- package/dist/core/invariant.js +5 -0
- package/dist/core/is_command_available.js +15 -0
- package/dist/core/json.js +35 -0
- package/dist/core/match_group.js +9 -0
- package/dist/core/serialize_json.js +17 -0
- package/dist/core/sleep.js +3 -0
- package/dist/core/wrap_index.js +10 -0
- package/dist/index.js +13 -0
- package/dist/main copy.js +266 -0
- package/dist/main.backup.js +266 -0
- package/dist/main.js +265 -0
- package/package.json +51 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
{
|
|
2
|
+
"head": "cc09b96b823d9dde77188e675d3090be7c1d625a",
|
|
3
|
+
"merge_base": "9528176b12abf81c779bc5244afc7d760f6fa422",
|
|
4
|
+
"branch_name": "dev/noah/a-test",
|
|
5
|
+
"commit_range": {
|
|
6
|
+
"invalid": true,
|
|
7
|
+
"group_map": {},
|
|
8
|
+
"commit_list": [
|
|
9
|
+
{
|
|
10
|
+
"sha": "a28f1ef080b56b56699bc420b200968e793702a9",
|
|
11
|
+
"message": "more remove",
|
|
12
|
+
"raw_message": "more remove\n\ngit-multi-diff-id: 14e097a1-fa9b-45af-8f7d-b77df9d91fe6",
|
|
13
|
+
"pr": {
|
|
14
|
+
"baseRefName": "master",
|
|
15
|
+
"commits": [
|
|
16
|
+
{
|
|
17
|
+
"authoredDate": "2023-10-22T23:13:20Z",
|
|
18
|
+
"authors": [
|
|
19
|
+
{
|
|
20
|
+
"email": "noah@iamnoah.com",
|
|
21
|
+
"id": "MDQ6VXNlcjI5MDA4NA==",
|
|
22
|
+
"login": "magus",
|
|
23
|
+
"name": "magus"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"committedDate": "2023-10-28T19:16:29Z",
|
|
27
|
+
"messageBody": "git-multi-diff-id: 14e097a1-fa9b-45af-8f7d-b77df9d91fe6",
|
|
28
|
+
"messageHeadline": "more remove",
|
|
29
|
+
"oid": "a28f1ef080b56b56699bc420b200968e793702a9"
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"headRefName": "14e097a1-fa9b-45af-8f7d-b77df9d91fe6",
|
|
33
|
+
"number": 28,
|
|
34
|
+
"state": "OPEN",
|
|
35
|
+
"title": "more remove",
|
|
36
|
+
"url": "https://github.com/magus/git-multi-diff-playground/pull/28"
|
|
37
|
+
},
|
|
38
|
+
"metadata": {
|
|
39
|
+
"id": "14e097a1-fa9b-45af-8f7d-b77df9d91fe6"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"sha": "7454ce81940f2a0964ff06c7a98c7fa1892f82bf",
|
|
44
|
+
"message": "remove num",
|
|
45
|
+
"raw_message": "remove num\n\ngit-multi-diff-id: 3d1d890d-11c9-4569-83c3-e3aff6426e37",
|
|
46
|
+
"pr": {
|
|
47
|
+
"baseRefName": "14e097a1-fa9b-45af-8f7d-b77df9d91fe6",
|
|
48
|
+
"commits": [
|
|
49
|
+
{
|
|
50
|
+
"authoredDate": "2023-10-22T23:13:14Z",
|
|
51
|
+
"authors": [
|
|
52
|
+
{
|
|
53
|
+
"email": "noah@iamnoah.com",
|
|
54
|
+
"id": "MDQ6VXNlcjI5MDA4NA==",
|
|
55
|
+
"login": "magus",
|
|
56
|
+
"name": "magus"
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
"committedDate": "2023-10-28T19:16:33Z",
|
|
60
|
+
"messageBody": "git-multi-diff-id: 3d1d890d-11c9-4569-83c3-e3aff6426e37",
|
|
61
|
+
"messageHeadline": "remove num",
|
|
62
|
+
"oid": "7454ce81940f2a0964ff06c7a98c7fa1892f82bf"
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"headRefName": "3d1d890d-11c9-4569-83c3-e3aff6426e37",
|
|
66
|
+
"number": 27,
|
|
67
|
+
"state": "OPEN",
|
|
68
|
+
"title": "remove num",
|
|
69
|
+
"url": "https://github.com/magus/git-multi-diff-playground/pull/27"
|
|
70
|
+
},
|
|
71
|
+
"metadata": {
|
|
72
|
+
"id": "3d1d890d-11c9-4569-83c3-e3aff6426e37"
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"sha": "a339f9cc4d8c10b691fef2c2425bf4a67c8c70f0",
|
|
77
|
+
"message": "strawberry",
|
|
78
|
+
"raw_message": "strawberry\n\ngit-multi-diff-id: 53d15f9a-2451-492c-a831-642d41ad3ef4",
|
|
79
|
+
"pr": {
|
|
80
|
+
"baseRefName": "3d1d890d-11c9-4569-83c3-e3aff6426e37",
|
|
81
|
+
"commits": [
|
|
82
|
+
{
|
|
83
|
+
"authoredDate": "2023-10-25T09:29:30Z",
|
|
84
|
+
"authors": [
|
|
85
|
+
{
|
|
86
|
+
"email": "noah@iamnoah.com",
|
|
87
|
+
"id": "MDQ6VXNlcjI5MDA4NA==",
|
|
88
|
+
"login": "magus",
|
|
89
|
+
"name": "magus"
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
"committedDate": "2023-10-28T19:16:37Z",
|
|
93
|
+
"messageBody": "git-multi-diff-id: 53d15f9a-2451-492c-a831-642d41ad3ef4",
|
|
94
|
+
"messageHeadline": "strawberry",
|
|
95
|
+
"oid": "a339f9cc4d8c10b691fef2c2425bf4a67c8c70f0"
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
"headRefName": "53d15f9a-2451-492c-a831-642d41ad3ef4",
|
|
99
|
+
"number": 30,
|
|
100
|
+
"state": "OPEN",
|
|
101
|
+
"title": "strawberry",
|
|
102
|
+
"url": "https://github.com/magus/git-multi-diff-playground/pull/30"
|
|
103
|
+
},
|
|
104
|
+
"metadata": {
|
|
105
|
+
"id": "53d15f9a-2451-492c-a831-642d41ad3ef4"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"sha": "24fa3301563d40b42f698bff92b8a805412a4a69",
|
|
110
|
+
"message": "orange color",
|
|
111
|
+
"raw_message": "orange color",
|
|
112
|
+
"pr": null,
|
|
113
|
+
"metadata": {
|
|
114
|
+
"id": null
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"sha": "dea1b85bdbcec0b27f1c5b2cc675e47fd9f51005",
|
|
119
|
+
"message": "cantaloupe",
|
|
120
|
+
"raw_message": "cantaloupe\nline2 changed\nline3 'abc'\nline4\nline5 \"hello world\"\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\ngit-multi-diff-id: 398c0ead-77ad-41a4-af6e-280f99998c28",
|
|
121
|
+
"pr": {
|
|
122
|
+
"baseRefName": "53d15f9a-2451-492c-a831-642d41ad3ef4",
|
|
123
|
+
"commits": [
|
|
124
|
+
{
|
|
125
|
+
"authoredDate": "2023-10-22T23:13:35Z",
|
|
126
|
+
"authors": [
|
|
127
|
+
{
|
|
128
|
+
"email": "noah@iamnoah.com",
|
|
129
|
+
"id": "MDQ6VXNlcjI5MDA4NA==",
|
|
130
|
+
"login": "magus",
|
|
131
|
+
"name": "magus"
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
"committedDate": "2023-10-28T19:16:40Z",
|
|
135
|
+
"messageBody": "line2 changed\nline3 'abc'\nline4\nline5 \"hello world\"\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\ngit-multi-diff-id: 398c0ead-77ad-41a4-af6e-280f99998c28",
|
|
136
|
+
"messageHeadline": "cantaloupe",
|
|
137
|
+
"oid": "86d0b3cf5dcbd94963f2839818734c3b0e13d2fc"
|
|
138
|
+
}
|
|
139
|
+
],
|
|
140
|
+
"headRefName": "398c0ead-77ad-41a4-af6e-280f99998c28",
|
|
141
|
+
"number": 29,
|
|
142
|
+
"state": "OPEN",
|
|
143
|
+
"title": "cantaloupe line2 line3 'abc' line4 line5 \"hello world\" Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
|
|
144
|
+
"url": "https://github.com/magus/git-multi-diff-playground/pull/29"
|
|
145
|
+
},
|
|
146
|
+
"metadata": {
|
|
147
|
+
"id": "398c0ead-77ad-41a4-af6e-280f99998c28"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"sha": "cc09b96b823d9dde77188e675d3090be7c1d625a",
|
|
152
|
+
"message": "pineapple",
|
|
153
|
+
"raw_message": "pineapple\n\ngit-multi-diff-id: 53d15f9a-2451-492c-a831-642d41ad3ef4",
|
|
154
|
+
"pr": {
|
|
155
|
+
"baseRefName": "3d1d890d-11c9-4569-83c3-e3aff6426e37",
|
|
156
|
+
"commits": [
|
|
157
|
+
{
|
|
158
|
+
"authoredDate": "2023-10-25T09:29:30Z",
|
|
159
|
+
"authors": [
|
|
160
|
+
{
|
|
161
|
+
"email": "noah@iamnoah.com",
|
|
162
|
+
"id": "MDQ6VXNlcjI5MDA4NA==",
|
|
163
|
+
"login": "magus",
|
|
164
|
+
"name": "magus"
|
|
165
|
+
}
|
|
166
|
+
],
|
|
167
|
+
"committedDate": "2023-10-28T19:16:37Z",
|
|
168
|
+
"messageBody": "git-multi-diff-id: 53d15f9a-2451-492c-a831-642d41ad3ef4",
|
|
169
|
+
"messageHeadline": "strawberry",
|
|
170
|
+
"oid": "a339f9cc4d8c10b691fef2c2425bf4a67c8c70f0"
|
|
171
|
+
}
|
|
172
|
+
],
|
|
173
|
+
"headRefName": "53d15f9a-2451-492c-a831-642d41ad3ef4",
|
|
174
|
+
"number": 30,
|
|
175
|
+
"state": "OPEN",
|
|
176
|
+
"title": "strawberry",
|
|
177
|
+
"url": "https://github.com/magus/git-multi-diff-playground/pull/30"
|
|
178
|
+
},
|
|
179
|
+
"metadata": {
|
|
180
|
+
"id": "53d15f9a-2451-492c-a831-642d41ad3ef4"
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
],
|
|
184
|
+
"UNASSIGNED": "unassigned"
|
|
185
|
+
}
|
|
186
|
+
}
|
package/dist/app/App.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Debug } from "./Debug.js";
|
|
3
|
+
import { DependencyCheck } from "./DependencyCheck.js";
|
|
4
|
+
import { GatherMetadata } from "./GatherMetadata.js";
|
|
5
|
+
import { GithubApiError } from "./GithubApiError.js";
|
|
6
|
+
import { Main } from "./Main.js";
|
|
7
|
+
import { Output } from "./Output.js";
|
|
8
|
+
import { Store } from "./Store.js";
|
|
9
|
+
export function App() {
|
|
10
|
+
const ink = Store.useState((state) => state.ink);
|
|
11
|
+
const argv = Store.useState((state) => state.argv);
|
|
12
|
+
if (!ink || !argv) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
// // debug component
|
|
16
|
+
// return (
|
|
17
|
+
// <React.Fragment>
|
|
18
|
+
// <Debug />
|
|
19
|
+
// <Output />
|
|
20
|
+
// <GithubApiError />
|
|
21
|
+
// </React.Fragment>
|
|
22
|
+
// );
|
|
23
|
+
return (React.createElement(React.Fragment, null,
|
|
24
|
+
React.createElement(Debug, null),
|
|
25
|
+
React.createElement(Output, null),
|
|
26
|
+
!argv.debug ? null : React.createElement(GithubApiError, null),
|
|
27
|
+
React.createElement(DependencyCheck, null,
|
|
28
|
+
React.createElement(GatherMetadata, null,
|
|
29
|
+
React.createElement(Main, null)))));
|
|
30
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { invariant } from "../core/invariant.js";
|
|
3
|
+
import { GithubApiError } from "./GithubApiError.js";
|
|
4
|
+
import { Store } from "./Store.js";
|
|
5
|
+
export function ArgCheck(props) {
|
|
6
|
+
const argv = Store.useState((state) => state.argv);
|
|
7
|
+
invariant(argv, "argv must exist");
|
|
8
|
+
// if (argv.debug) {
|
|
9
|
+
// return (
|
|
10
|
+
// <Await
|
|
11
|
+
// fallback={<Ink.Text>Checking Github API quota...</Ink.Text>}
|
|
12
|
+
// function={github_quota}
|
|
13
|
+
// >
|
|
14
|
+
// {props.children}
|
|
15
|
+
// </Await>
|
|
16
|
+
// );
|
|
17
|
+
// }
|
|
18
|
+
return (React.createElement(React.Fragment, null,
|
|
19
|
+
React.createElement(GithubApiError, null),
|
|
20
|
+
props.children));
|
|
21
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cache } from "../core/cache.js";
|
|
3
|
+
import { invariant } from "../core/invariant.js";
|
|
4
|
+
export function Await(props) {
|
|
5
|
+
const [display_fallback, set_display_fallback] = React.useState(false);
|
|
6
|
+
// const id = React.useId();
|
|
7
|
+
const cacheRef = React.useRef(null);
|
|
8
|
+
if (!cacheRef.current) {
|
|
9
|
+
// console.debug("setting cacheRef.current", { id });
|
|
10
|
+
cacheRef.current = cache(props.function);
|
|
11
|
+
}
|
|
12
|
+
let delayFallbackMs;
|
|
13
|
+
if ("delayFallbackMs" in props && typeof props.delayFallbackMs === "number") {
|
|
14
|
+
delayFallbackMs = props.delayFallbackMs;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
delayFallbackMs = 1000;
|
|
18
|
+
}
|
|
19
|
+
React.useEffect(() => {
|
|
20
|
+
const cache = cacheRef.current;
|
|
21
|
+
if (!cache) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
let timeoutId;
|
|
25
|
+
timeoutId = setTimeout(() => {
|
|
26
|
+
// only display fallback if we are still pending
|
|
27
|
+
if (cache.check() === "pending") {
|
|
28
|
+
set_display_fallback(true);
|
|
29
|
+
}
|
|
30
|
+
}, delayFallbackMs);
|
|
31
|
+
return function cleanup() {
|
|
32
|
+
clearTimeout(timeoutId);
|
|
33
|
+
};
|
|
34
|
+
}, [delayFallbackMs]);
|
|
35
|
+
invariant(cacheRef.current, "cache must exist");
|
|
36
|
+
if ("fallback" in props) {
|
|
37
|
+
return (React.createElement(React.Suspense, { fallback: !display_fallback ? null : props.fallback },
|
|
38
|
+
React.createElement(ReadCache, { cache: cacheRef.current }, props.children)));
|
|
39
|
+
}
|
|
40
|
+
return React.createElement(ReadCache, { cache: cacheRef.current });
|
|
41
|
+
}
|
|
42
|
+
function ReadCache(props) {
|
|
43
|
+
props.cache.read();
|
|
44
|
+
return props.children;
|
|
45
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as Ink from "ink";
|
|
3
|
+
export function Brackets(props) {
|
|
4
|
+
const color = "#f97316";
|
|
5
|
+
const text_color = "#06b6d4";
|
|
6
|
+
return (React.createElement(Ink.Text, { color: text_color },
|
|
7
|
+
React.createElement(Ink.Text, { color: color }, "["),
|
|
8
|
+
props.children,
|
|
9
|
+
React.createElement(Ink.Text, { color: color }, "]")));
|
|
10
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as Ink from "ink";
|
|
3
|
+
export function Counter() {
|
|
4
|
+
const { isFocused } = Ink.useFocus();
|
|
5
|
+
const [counter, setCounter] = React.useState(0);
|
|
6
|
+
React.useEffect(() => {
|
|
7
|
+
const timer = setInterval(() => {
|
|
8
|
+
setCounter((prevCounter) => prevCounter + 1);
|
|
9
|
+
}, 100);
|
|
10
|
+
return () => {
|
|
11
|
+
clearInterval(timer);
|
|
12
|
+
};
|
|
13
|
+
}, []);
|
|
14
|
+
return (React.createElement(Ink.Text, { color: "green" },
|
|
15
|
+
counter,
|
|
16
|
+
" tests passed (focus:",
|
|
17
|
+
String(isFocused),
|
|
18
|
+
")"));
|
|
19
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
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 { invariant } from "../core/invariant.js";
|
|
6
|
+
import * as json from "../core/json.js";
|
|
7
|
+
import { Store } from "./Store.js";
|
|
8
|
+
export function Debug() {
|
|
9
|
+
const actions = Store.useActions();
|
|
10
|
+
const state = Store.useState((state) => state);
|
|
11
|
+
const debug = Store.useState((state) => state.argv?.debug);
|
|
12
|
+
React.useEffect(function debugMessageOnce() {
|
|
13
|
+
if (debug) {
|
|
14
|
+
actions.output(React.createElement(Ink.Text, { color: "yellow" }, "Debug mode enabled"));
|
|
15
|
+
}
|
|
16
|
+
}, [debug]);
|
|
17
|
+
React.useEffect(function syncStateJson() {
|
|
18
|
+
invariant(state.cwd, "state.cwd must exist");
|
|
19
|
+
if (!debug) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const output_file = path.join(state.cwd, "git-multi-diff-state.json");
|
|
23
|
+
if (fs.existsSync(output_file)) {
|
|
24
|
+
fs.rmSync(output_file);
|
|
25
|
+
}
|
|
26
|
+
const serialized = json.serialize(state);
|
|
27
|
+
const content = JSON.stringify(serialized, null, 2);
|
|
28
|
+
fs.writeFileSync(output_file, content);
|
|
29
|
+
}, [debug, state]);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as Ink from "ink";
|
|
3
|
+
import { cli } from "../core/cli.js";
|
|
4
|
+
import { is_command_available } from "../core/is_command_available.js";
|
|
5
|
+
import { Await } from "./Await.js";
|
|
6
|
+
import { Store } from "./Store.js";
|
|
7
|
+
export function DependencyCheck(props) {
|
|
8
|
+
const actions = Store.useActions();
|
|
9
|
+
return (React.createElement(Await, { fallback: React.createElement(Ink.Box, null,
|
|
10
|
+
React.createElement(Ink.Text, null, "Checking git install...")), function: async () => {
|
|
11
|
+
if (is_command_available("git")) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
actions.output(React.createElement(Ink.Text, null,
|
|
15
|
+
React.createElement(Ink.Text, { color: "yellow" }, "git"),
|
|
16
|
+
" must be installed."));
|
|
17
|
+
actions.exit(2);
|
|
18
|
+
} },
|
|
19
|
+
React.createElement(Await, { fallback: React.createElement(Ink.Box, null,
|
|
20
|
+
React.createElement(Ink.Text, null, "Checking gh install...")), function: async () => {
|
|
21
|
+
if (is_command_available("gh")) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
actions.output(React.createElement(Ink.Text, null,
|
|
25
|
+
React.createElement(Ink.Text, { color: "yellow" }, "gh"),
|
|
26
|
+
" must be installed."));
|
|
27
|
+
actions.output(React.createElement(Ink.Box, { flexDirection: "row", gap: 1 },
|
|
28
|
+
React.createElement(Ink.Text, null, "Visit"),
|
|
29
|
+
React.createElement(Ink.Text, { color: "#38bdf8" }, "https://cli.github.com"),
|
|
30
|
+
React.createElement(Ink.Text, null, "to install the github cli"),
|
|
31
|
+
React.createElement(Ink.Text, null,
|
|
32
|
+
"(",
|
|
33
|
+
React.createElement(Ink.Text, { color: "yellow" }, "gh"),
|
|
34
|
+
")")));
|
|
35
|
+
actions.exit(3);
|
|
36
|
+
} },
|
|
37
|
+
React.createElement(Await, { fallback: React.createElement(Ink.Box, null,
|
|
38
|
+
React.createElement(Ink.Text, null, "Checking gh auth status...")), function: async () => {
|
|
39
|
+
const gh_auth_status_cli = await cli(`gh auth status`, {
|
|
40
|
+
ignoreExitCode: true,
|
|
41
|
+
});
|
|
42
|
+
if (gh_auth_status_cli.code === 0) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
actions.output(React.createElement(Ink.Box, { flexDirection: "row", gap: 1 },
|
|
46
|
+
React.createElement(Ink.Text, { color: "yellow" }, "gh"),
|
|
47
|
+
React.createElement(Ink.Text, null, "requires login, please run"),
|
|
48
|
+
React.createElement(Ink.Text, null,
|
|
49
|
+
React.createElement(Ink.Text, { color: "yellow" }, "gh auth login"))));
|
|
50
|
+
actions.exit(4);
|
|
51
|
+
} }, props.children))));
|
|
52
|
+
}
|
package/dist/app/Exit.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Store } from "./Store.js";
|
|
3
|
+
export function Exit(props) {
|
|
4
|
+
const actions = Store.useActions();
|
|
5
|
+
React.useEffect(() => {
|
|
6
|
+
if (props.clear) {
|
|
7
|
+
actions.clear();
|
|
8
|
+
}
|
|
9
|
+
actions.unmount();
|
|
10
|
+
process.exitCode = props.code;
|
|
11
|
+
process.exit();
|
|
12
|
+
}, [props.clear, props.code]);
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as Ink from "ink";
|
|
3
|
+
import * as CommitMetadata from "../core/CommitMetadata.js";
|
|
4
|
+
import { cli } from "../core/cli.js";
|
|
5
|
+
import { invariant } from "../core/invariant.js";
|
|
6
|
+
import * as json from "../core/json.js";
|
|
7
|
+
import { Await } from "./Await.js";
|
|
8
|
+
import { Store } from "./Store.js";
|
|
9
|
+
export function GatherMetadata(props) {
|
|
10
|
+
const argv = Store.useState((state) => state.argv);
|
|
11
|
+
invariant(argv, "argv must exist");
|
|
12
|
+
const fallback = (React.createElement(Ink.Text, { color: "yellow" }, "Fetching PR status from Github..."));
|
|
13
|
+
if (argv["mock-metadata"]) {
|
|
14
|
+
return (React.createElement(Await, { fallback: fallback, function: mock_metadata }, props.children));
|
|
15
|
+
}
|
|
16
|
+
return (React.createElement(Await, { fallback: fallback, function: gather_metadata }, props.children));
|
|
17
|
+
}
|
|
18
|
+
async function mock_metadata() {
|
|
19
|
+
const module = await import("../__fixtures__/metadata.js");
|
|
20
|
+
const deserialized = json.deserialize(module.METADATA);
|
|
21
|
+
Store.setState((state) => {
|
|
22
|
+
Object.assign(state, deserialized);
|
|
23
|
+
state.step = "status";
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
async function gather_metadata() {
|
|
27
|
+
const actions = Store.getState().actions;
|
|
28
|
+
const head = (await cli("git rev-parse HEAD")).stdout;
|
|
29
|
+
const merge_base = (await cli("git merge-base HEAD master")).stdout;
|
|
30
|
+
// handle when there are no detected changes
|
|
31
|
+
if (head === merge_base) {
|
|
32
|
+
actions.newline();
|
|
33
|
+
actions.output(React.createElement(Ink.Text, { color: "gray" }, "No changes detected."));
|
|
34
|
+
actions.exit(0);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const branch_name = (await cli("git rev-parse --abbrev-ref HEAD")).stdout;
|
|
38
|
+
try {
|
|
39
|
+
const commit_range = await CommitMetadata.range();
|
|
40
|
+
Store.setState((state) => {
|
|
41
|
+
state.head = head;
|
|
42
|
+
state.merge_base = merge_base;
|
|
43
|
+
state.branch_name = branch_name;
|
|
44
|
+
state.commit_range = commit_range;
|
|
45
|
+
state.step = "status";
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
actions.output(React.createElement(Ink.Text, { color: "#ef4444" }, "Error gathering metadata."));
|
|
50
|
+
if (err instanceof Error) {
|
|
51
|
+
actions.debug(React.createElement(Ink.Text, { color: "#ef4444" }, err.message));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as Ink from "ink";
|
|
3
|
+
import * as CommitMetadata from "../core/CommitMetadata.js";
|
|
4
|
+
import { cli } from "../core/cli.js";
|
|
5
|
+
import { invariant } from "../core/invariant.js";
|
|
6
|
+
import * as json from "../core/json.js";
|
|
7
|
+
import { Await } from "./Await.js";
|
|
8
|
+
import { Store } from "./Store.js";
|
|
9
|
+
export function GatherMetadata(props) {
|
|
10
|
+
const argv = Store.useState((state) => state.argv);
|
|
11
|
+
invariant(argv, "argv must exist");
|
|
12
|
+
const fallback = (React.createElement(Ink.Text, { color: "yellow" }, "Fetching PR status from Github..."));
|
|
13
|
+
if (argv["mock-metadata"]) {
|
|
14
|
+
return (React.createElement(Await, { fallback: fallback, function: mock_metadata }, props.children));
|
|
15
|
+
}
|
|
16
|
+
return (React.createElement(Await, { fallback: fallback, function: gather_metadata }, props.children));
|
|
17
|
+
}
|
|
18
|
+
async function mock_metadata() {
|
|
19
|
+
const module = await import("../__fixtures__/metadata.js");
|
|
20
|
+
const deserialized = json.deserialize(module.METADATA);
|
|
21
|
+
Store.setState((state) => {
|
|
22
|
+
Object.assign(state, deserialized);
|
|
23
|
+
state.step = "status";
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
async function gather_metadata() {
|
|
27
|
+
const actions = Store.getState().actions;
|
|
28
|
+
const head = (await cli("git rev-parse HEAD")).stdout;
|
|
29
|
+
const merge_base = (await cli("git merge-base HEAD master")).stdout;
|
|
30
|
+
// handle when there are no detected changes
|
|
31
|
+
if (head === merge_base) {
|
|
32
|
+
actions.newline();
|
|
33
|
+
actions.output(React.createElement(Ink.Text, { color: "gray" }, "No changes detected."));
|
|
34
|
+
actions.exit(0);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const branch_name = (await cli("git rev-parse --abbrev-ref HEAD")).stdout;
|
|
38
|
+
try {
|
|
39
|
+
const commit_range = await CommitMetadata.range();
|
|
40
|
+
Store.setState((state) => {
|
|
41
|
+
state.head = head;
|
|
42
|
+
state.merge_base = merge_base;
|
|
43
|
+
state.branch_name = branch_name;
|
|
44
|
+
state.commit_range = commit_range;
|
|
45
|
+
state.step = "status";
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
actions.output(React.createElement(Ink.Text, { color: "#ef4444" }, "Error gathering metadata."));
|
|
50
|
+
if (err instanceof Error) {
|
|
51
|
+
actions.debug(React.createElement(Ink.Text, { color: "#ef4444" }, err.message));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as Ink from "ink";
|
|
3
|
+
import { cli } from "../core/cli.js";
|
|
4
|
+
import * as date from "../core/date.js";
|
|
5
|
+
import { invariant } from "../core/invariant.js";
|
|
6
|
+
import { Await } from "./Await.js";
|
|
7
|
+
import { Brackets } from "./Brackets.js";
|
|
8
|
+
import { Parens } from "./Parens.js";
|
|
9
|
+
import { Store } from "./Store.js";
|
|
10
|
+
export function GithubApiError() {
|
|
11
|
+
const argv = Store.useState((state) => state.argv);
|
|
12
|
+
invariant(argv, "argv must exist");
|
|
13
|
+
return React.createElement(Await, { fallback: null, function: run });
|
|
14
|
+
}
|
|
15
|
+
async function run() {
|
|
16
|
+
const actions = Store.getState().actions;
|
|
17
|
+
const res = await cli(`gh api https://api.github.com/rate_limit`);
|
|
18
|
+
const res_json = JSON.parse(res.stdout);
|
|
19
|
+
const resources_graphql = res_json.resources.graphql;
|
|
20
|
+
const used = resources_graphql.used;
|
|
21
|
+
const limit = resources_graphql.limit;
|
|
22
|
+
const reset_date = new Date(resources_graphql.reset * 1000);
|
|
23
|
+
// calculate the time remaining in minutes
|
|
24
|
+
const now = new Date();
|
|
25
|
+
const diff_seconds = (reset_date.getTime() - now.getTime()) / 1000;
|
|
26
|
+
const diff_minutes = Math.round(diff_seconds / 60);
|
|
27
|
+
const reset_time = date.format_time(reset_date);
|
|
28
|
+
let time_until;
|
|
29
|
+
if (diff_minutes < 0) {
|
|
30
|
+
time_until = `${diff_seconds} seconds`;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
time_until = `${diff_minutes} minutes`;
|
|
34
|
+
}
|
|
35
|
+
actions.output(React.createElement(Ink.Text, { dimColor: true },
|
|
36
|
+
React.createElement(Ink.Text, null, "Github "),
|
|
37
|
+
React.createElement(Brackets, null, "graphql"),
|
|
38
|
+
React.createElement(Ink.Text, null, " API rate limit "),
|
|
39
|
+
React.createElement(Brackets, null,
|
|
40
|
+
React.createElement(Ink.Text, null, used),
|
|
41
|
+
React.createElement(Ink.Text, null, "/"),
|
|
42
|
+
React.createElement(Ink.Text, null, limit)),
|
|
43
|
+
React.createElement(Ink.Text, null, " will reset at "),
|
|
44
|
+
React.createElement(Ink.Text, { bold: true, color: "yellow" }, reset_time),
|
|
45
|
+
React.createElement(Ink.Text, null, " "),
|
|
46
|
+
React.createElement(Parens, null,
|
|
47
|
+
React.createElement(Ink.Text, null, "in "),
|
|
48
|
+
React.createElement(Ink.Text, { bold: true, color: "yellow" }, time_until))));
|
|
49
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cli } from "../core/cli.js";
|
|
3
|
+
import { Await } from "./Await.js";
|
|
4
|
+
import { Store } from "./Store.js";
|
|
5
|
+
export function InitMetadata() {
|
|
6
|
+
return (React.createElement(Await, { function: async () => {
|
|
7
|
+
const head = (await cli("git rev-parse HEAD")).stdout;
|
|
8
|
+
const merge_base = (await cli("git merge-base HEAD master")).stdout;
|
|
9
|
+
Store.setState((state) => {
|
|
10
|
+
state.head = head;
|
|
11
|
+
state.merge_base = merge_base;
|
|
12
|
+
});
|
|
13
|
+
} }));
|
|
14
|
+
}
|