git-stack-cli 2.9.1 → 2.9.2
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/dist/js/index.js +77 -77
- package/package.json +1 -1
- package/scripts/bun-build.ts +4 -0
- package/scripts/core/get_define.ts +1 -1
- package/src/app/AutoUpdate.tsx +6 -0
- package/src/app/GithubApiError.tsx +6 -1
- package/src/app/PostRebaseStatus.tsx +7 -4
- package/src/app/PreManualRebase.tsx +6 -1
- package/src/app/Status.tsx +6 -1
- package/src/app/Store.tsx +3 -7
- package/src/app/SyncGithub.tsx +20 -7
- package/src/command.ts +5 -1
- package/src/commands/Config.tsx +6 -1
- package/src/commands/Fixup.tsx +6 -1
- package/src/commands/Log.tsx +7 -1
- package/src/core/CommitMetadata.ts +39 -20
- package/src/core/github.tsx +87 -29
package/package.json
CHANGED
package/scripts/bun-build.ts
CHANGED
|
@@ -48,6 +48,10 @@ const REPO_ROOT = (await spawn.sync("git rev-parse --show-toplevel")).stdout;
|
|
|
48
48
|
|
|
49
49
|
const define = await get_define();
|
|
50
50
|
|
|
51
|
+
if (DEV) {
|
|
52
|
+
define["process.env.DEV"] = JSON.stringify("true");
|
|
53
|
+
}
|
|
54
|
+
|
|
51
55
|
const BUILD_CONFIG = {
|
|
52
56
|
entrypoints: ["./src/index.tsx"],
|
|
53
57
|
outdir: "./dist/js",
|
|
@@ -5,7 +5,7 @@ import { spawn } from "~/core/spawn";
|
|
|
5
5
|
|
|
6
6
|
const REPO_ROOT = (await spawn.sync("git rev-parse --show-toplevel")).stdout;
|
|
7
7
|
|
|
8
|
-
export async function get_define() {
|
|
8
|
+
export async function get_define(): Promise<Record<string, string>> {
|
|
9
9
|
const PACKAGE_JSON = await file.read_json(path.join(REPO_ROOT, "package.json"));
|
|
10
10
|
const GIT_SEQUENCE_EDITOR_SCRIPT_PATH = path.join(REPO_ROOT, "scripts", "git-sequence-editor.sh");
|
|
11
11
|
const UNSAFE_GIT_SEQUENCE_EDITOR_SCRIPT = await file.read_text(GIT_SEQUENCE_EDITOR_SCRIPT_PATH);
|
package/src/app/AutoUpdate.tsx
CHANGED
|
@@ -152,6 +152,12 @@ export function AutoUpdate(props: Props) {
|
|
|
152
152
|
init_state().catch(abort);
|
|
153
153
|
|
|
154
154
|
async function init_state() {
|
|
155
|
+
if (process.env.DEV === "true") {
|
|
156
|
+
info(<Ink.Text color={colors.yellow}>Skip AutoUpdate</Ink.Text>);
|
|
157
|
+
patch({ status: "done" });
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
155
161
|
if (state.latest_version !== null) return;
|
|
156
162
|
|
|
157
163
|
const local_version = process.env.CLI_VERSION;
|
|
@@ -15,7 +15,12 @@ type Props = {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
export function GithubApiError(props: Props) {
|
|
18
|
-
return
|
|
18
|
+
return (
|
|
19
|
+
<Await
|
|
20
|
+
fallback={<Ink.Text color={colors.yellow}>Fetching Github API usage…</Ink.Text>}
|
|
21
|
+
function={() => run(props)}
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
async function run(props: Props) {
|
|
@@ -6,17 +6,20 @@ import { Await } from "~/app/Await";
|
|
|
6
6
|
import { StatusTable } from "~/app/StatusTable";
|
|
7
7
|
import { Store } from "~/app/Store";
|
|
8
8
|
import * as CommitMetadata from "~/core/CommitMetadata";
|
|
9
|
+
import { colors } from "~/core/colors";
|
|
9
10
|
|
|
10
11
|
export function PostRebaseStatus() {
|
|
11
|
-
return
|
|
12
|
+
return (
|
|
13
|
+
<Await
|
|
14
|
+
fallback={<Ink.Text color={colors.yellow}>Fetching latest status…</Ink.Text>}
|
|
15
|
+
function={run}
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
12
18
|
}
|
|
13
19
|
|
|
14
20
|
async function run() {
|
|
15
21
|
const actions = Store.getState().actions;
|
|
16
22
|
|
|
17
|
-
// reset github pr cache before refreshing via commit range below
|
|
18
|
-
actions.reset_pr();
|
|
19
|
-
|
|
20
23
|
const commit_range = await CommitMetadata.range();
|
|
21
24
|
|
|
22
25
|
actions.set((state) => {
|
|
@@ -14,7 +14,12 @@ import { invariant } from "~/core/invariant";
|
|
|
14
14
|
import { safe_exists } from "~/core/safe_exists";
|
|
15
15
|
|
|
16
16
|
export function PreManualRebase() {
|
|
17
|
-
return
|
|
17
|
+
return (
|
|
18
|
+
<Await
|
|
19
|
+
fallback={<Ink.Text color={colors.yellow}>Check PR templates…</Ink.Text>}
|
|
20
|
+
function={run}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
async function run() {
|
package/src/app/Status.tsx
CHANGED
|
@@ -9,7 +9,12 @@ import { colors } from "~/core/colors";
|
|
|
9
9
|
import { invariant } from "~/core/invariant";
|
|
10
10
|
|
|
11
11
|
export function Status() {
|
|
12
|
-
return
|
|
12
|
+
return (
|
|
13
|
+
<Await
|
|
14
|
+
fallback={<Ink.Text color={colors.yellow}>Fetching latest status…</Ink.Text>}
|
|
15
|
+
function={run}
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
async function run() {
|
package/src/app/Store.tsx
CHANGED
|
@@ -76,7 +76,9 @@ export type State = {
|
|
|
76
76
|
output: Array<React.ReactNode>;
|
|
77
77
|
pending_output: Record<string, Array<React.ReactNode>>;
|
|
78
78
|
|
|
79
|
+
// cache
|
|
79
80
|
pr: { [branch: string]: PullRequest };
|
|
81
|
+
cache_pr_diff: { [id: number]: string };
|
|
80
82
|
|
|
81
83
|
actions: {
|
|
82
84
|
exit(code: number, args?: ExitArgs): void;
|
|
@@ -90,7 +92,6 @@ export type State = {
|
|
|
90
92
|
|
|
91
93
|
isDebug(): boolean;
|
|
92
94
|
|
|
93
|
-
reset_pr(): void;
|
|
94
95
|
register_abort_handler(abort_handler: AbortHandler): void;
|
|
95
96
|
unregister_abort_handler(): void;
|
|
96
97
|
|
|
@@ -138,6 +139,7 @@ const BaseStore = createStore<State>()(
|
|
|
138
139
|
pending_output: {},
|
|
139
140
|
|
|
140
141
|
pr: {},
|
|
142
|
+
cache_pr_diff: {},
|
|
141
143
|
|
|
142
144
|
actions: {
|
|
143
145
|
exit(code, args) {
|
|
@@ -228,12 +230,6 @@ const BaseStore = createStore<State>()(
|
|
|
228
230
|
return state.select.debug(state);
|
|
229
231
|
},
|
|
230
232
|
|
|
231
|
-
reset_pr() {
|
|
232
|
-
set((state) => {
|
|
233
|
-
state.pr = {};
|
|
234
|
-
});
|
|
235
|
-
},
|
|
236
|
-
|
|
237
233
|
register_abort_handler(abort_handler) {
|
|
238
234
|
set((state) => {
|
|
239
235
|
state.abort_handler = abort_handler;
|
package/src/app/SyncGithub.tsx
CHANGED
|
@@ -160,6 +160,15 @@ async function run() {
|
|
|
160
160
|
actions.unregister_abort_handler();
|
|
161
161
|
|
|
162
162
|
actions.set((state) => {
|
|
163
|
+
// invalidate cache for PRs we pushed
|
|
164
|
+
for (const group of push_group_list) {
|
|
165
|
+
if (group.pr) {
|
|
166
|
+
delete state.pr[group.pr.headRefName];
|
|
167
|
+
delete state.cache_pr_diff[group.pr.number];
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// move to next step
|
|
163
172
|
state.step = "post-rebase-status";
|
|
164
173
|
});
|
|
165
174
|
} catch (err) {
|
|
@@ -185,9 +194,13 @@ async function run() {
|
|
|
185
194
|
|
|
186
195
|
const group = commit_range.group_list[index];
|
|
187
196
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
197
|
+
// skip the unassigned commits group
|
|
198
|
+
if (group.id === commit_range.UNASSIGNED) continue;
|
|
199
|
+
|
|
200
|
+
// if not --force, skip non-dirty master_base groups
|
|
201
|
+
if (group.master_base && !group.dirty && !argv.force) continue;
|
|
202
|
+
|
|
203
|
+
push_group_list.unshift(group);
|
|
191
204
|
}
|
|
192
205
|
|
|
193
206
|
return push_group_list;
|
|
@@ -300,14 +313,14 @@ async function run() {
|
|
|
300
313
|
async function push_master_group(group: CommitMetadataGroup) {
|
|
301
314
|
invariant(repo_root, "repo_root must exist");
|
|
302
315
|
|
|
303
|
-
const
|
|
304
|
-
const
|
|
316
|
+
const repo_rel_worktree_path = `.git/git-stack-worktrees/push_master_group`;
|
|
317
|
+
const worktree_path = path.join(repo_root, repo_rel_worktree_path);
|
|
305
318
|
|
|
306
319
|
// ensure worktree for pushing master groups
|
|
307
|
-
if (!(await safe_exists(
|
|
320
|
+
if (!(await safe_exists(worktree_path))) {
|
|
308
321
|
actions.output(
|
|
309
322
|
<Ink.Text color={colors.white}>
|
|
310
|
-
Creating <Ink.Text color={colors.yellow}>{
|
|
323
|
+
Creating <Ink.Text color={colors.yellow}>{repo_rel_worktree_path}</Ink.Text>
|
|
311
324
|
</Ink.Text>,
|
|
312
325
|
);
|
|
313
326
|
actions.output(
|
package/src/command.ts
CHANGED
|
@@ -60,7 +60,11 @@ export async function command(argv: string[], options: CommandOptions = {}) {
|
|
|
60
60
|
.command(
|
|
61
61
|
"config",
|
|
62
62
|
"Generate a one-time configuration json based on the passed arguments",
|
|
63
|
-
(yargs) =>
|
|
63
|
+
(yargs) => {
|
|
64
|
+
// match options for default command (since we are generating a config for its options)
|
|
65
|
+
let builder = yargs.options(DefaultOptions);
|
|
66
|
+
return builder;
|
|
67
|
+
},
|
|
64
68
|
)
|
|
65
69
|
|
|
66
70
|
.command(
|
package/src/commands/Config.tsx
CHANGED
|
@@ -10,7 +10,12 @@ import { colors } from "~/core/colors";
|
|
|
10
10
|
import { invariant } from "~/core/invariant";
|
|
11
11
|
|
|
12
12
|
export function Config() {
|
|
13
|
-
return
|
|
13
|
+
return (
|
|
14
|
+
<Await
|
|
15
|
+
fallback={<Ink.Text color={colors.yellow}>Generating config…</Ink.Text>}
|
|
16
|
+
function={run}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
14
19
|
|
|
15
20
|
async function run() {
|
|
16
21
|
const state = Store.getState();
|
package/src/commands/Fixup.tsx
CHANGED
|
@@ -10,7 +10,12 @@ import { cli } from "~/core/cli";
|
|
|
10
10
|
import { colors } from "~/core/colors";
|
|
11
11
|
|
|
12
12
|
export function Fixup() {
|
|
13
|
-
return
|
|
13
|
+
return (
|
|
14
|
+
<Await
|
|
15
|
+
fallback={<Ink.Text color={colors.yellow}>Fixing up commits…</Ink.Text>}
|
|
16
|
+
function={run}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
14
19
|
}
|
|
15
20
|
|
|
16
21
|
async function run() {
|
package/src/commands/Log.tsx
CHANGED
|
@@ -5,13 +5,19 @@ import * as Ink from "ink-cjs";
|
|
|
5
5
|
import { Await } from "~/app/Await";
|
|
6
6
|
import { Store } from "~/app/Store";
|
|
7
7
|
import { cli } from "~/core/cli";
|
|
8
|
+
import { colors } from "~/core/colors";
|
|
8
9
|
import { invariant } from "~/core/invariant";
|
|
9
10
|
|
|
10
11
|
export function Log() {
|
|
11
12
|
const { stdout } = Ink.useStdout();
|
|
12
13
|
const available_width = stdout.columns || 80;
|
|
13
14
|
|
|
14
|
-
return
|
|
15
|
+
return (
|
|
16
|
+
<Await
|
|
17
|
+
fallback={<Ink.Text color={colors.yellow}>Generating log…</Ink.Text>}
|
|
18
|
+
function={() => run({ available_width })}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
type Args = {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
|
|
1
3
|
import { Store } from "~/app/Store";
|
|
2
4
|
import * as git from "~/core/git";
|
|
3
5
|
import * as github from "~/core/github";
|
|
@@ -26,6 +28,8 @@ type CommitRangeGroup = {
|
|
|
26
28
|
type CommitGroupMap = { [sha: string]: CommitRangeGroup };
|
|
27
29
|
|
|
28
30
|
export async function range(commit_group_map?: CommitGroupMap) {
|
|
31
|
+
const DEBUG = process.env.DEV && false;
|
|
32
|
+
|
|
29
33
|
// gather all open prs in repo first
|
|
30
34
|
// cheaper query to populate cache
|
|
31
35
|
await github.pr_list();
|
|
@@ -163,7 +167,9 @@ export async function range(commit_group_map?: CommitGroupMap) {
|
|
|
163
167
|
// console.debug(" ", "group.base", group.base);
|
|
164
168
|
}
|
|
165
169
|
|
|
166
|
-
|
|
170
|
+
if (DEBUG) {
|
|
171
|
+
console.debug({ group });
|
|
172
|
+
}
|
|
167
173
|
|
|
168
174
|
if (!group.pr) {
|
|
169
175
|
group.dirty = true;
|
|
@@ -180,13 +186,17 @@ export async function range(commit_group_map?: CommitGroupMap) {
|
|
|
180
186
|
// gh pr diff --color=never 110
|
|
181
187
|
// git --no-pager diff --color=never 00c8fe0~1..00c8fe0
|
|
182
188
|
let diff_github = await github.pr_diff(group.pr.number);
|
|
183
|
-
diff_github =
|
|
189
|
+
diff_github = normalize_diff(diff_github);
|
|
184
190
|
|
|
185
191
|
let diff_local = await git.get_diff(group.commits);
|
|
186
|
-
diff_local =
|
|
192
|
+
diff_local = normalize_diff(diff_local);
|
|
193
|
+
|
|
194
|
+
if (DEBUG) {
|
|
195
|
+
console.debug({ diff_local, diff_github });
|
|
196
|
+
}
|
|
187
197
|
|
|
188
198
|
// find the first differing character index
|
|
189
|
-
let compare_length = Math.
|
|
199
|
+
let compare_length = Math.max(diff_github.length, diff_local.length);
|
|
190
200
|
let diff_index = -1;
|
|
191
201
|
for (let c_i = 0; c_i < compare_length; c_i++) {
|
|
192
202
|
if (diff_github[c_i] !== diff_local[c_i]) {
|
|
@@ -197,23 +207,25 @@ export async function range(commit_group_map?: CommitGroupMap) {
|
|
|
197
207
|
if (diff_index > -1) {
|
|
198
208
|
group.dirty = true;
|
|
199
209
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
210
|
+
if (DEBUG) {
|
|
211
|
+
// print preview at diff_index for both strings
|
|
212
|
+
const preview_radius = 30;
|
|
213
|
+
const start_index = Math.max(0, diff_index - preview_radius);
|
|
214
|
+
const end_index = Math.min(compare_length, diff_index + preview_radius);
|
|
204
215
|
|
|
205
|
-
|
|
206
|
-
|
|
216
|
+
diff_github = diff_github.substring(start_index, end_index);
|
|
217
|
+
diff_github = JSON.stringify(diff_github).slice(1, -1);
|
|
207
218
|
|
|
208
|
-
|
|
209
|
-
|
|
219
|
+
diff_local = diff_local.substring(start_index, end_index);
|
|
220
|
+
diff_local = JSON.stringify(diff_local).slice(1, -1);
|
|
210
221
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
222
|
+
let pointer_indent = " ".repeat(diff_index - start_index + 1);
|
|
223
|
+
console.warn(`⚠️ git diff mismatch`);
|
|
224
|
+
console.warn(` ${pointer_indent}⌄`);
|
|
225
|
+
console.warn(`diff_github …${diff_github}…`);
|
|
226
|
+
console.warn(`diff_local …${diff_local}…`);
|
|
227
|
+
console.warn(` ${pointer_indent}⌃`);
|
|
228
|
+
}
|
|
217
229
|
}
|
|
218
230
|
} else if (!group.master_base && previous_group && previous_group.master_base) {
|
|
219
231
|
// special case
|
|
@@ -280,10 +292,17 @@ export async function range(commit_group_map?: CommitGroupMap) {
|
|
|
280
292
|
|
|
281
293
|
export const UNASSIGNED = "unassigned";
|
|
282
294
|
|
|
283
|
-
function
|
|
284
|
-
|
|
295
|
+
function normalize_diff(diff_text: string) {
|
|
296
|
+
diff_text = diff_text.replace(RE.diff_index_line, "");
|
|
297
|
+
diff_text = diff_text.replace(RE.diff_section_header, "");
|
|
298
|
+
return diff_text;
|
|
285
299
|
}
|
|
286
300
|
|
|
287
301
|
const RE = {
|
|
302
|
+
// index 8b7c5f7b37688..84124e0a677ca 100644
|
|
303
|
+
// https://regex101.com/r/YBwF6P/1
|
|
288
304
|
diff_index_line: /^index [0-9a-f]+\.\.[0-9a-f]+.*?\n/gm,
|
|
305
|
+
// @@ -29,6 +29,7 @@ from caas_cli import cli as caas_cli # type: ignore
|
|
306
|
+
// https://regex101.com/r/ohMeDC/1
|
|
307
|
+
diff_section_header: /^@@ .*? @@(?: .*)?\n/gm,
|
|
289
308
|
};
|
package/src/core/github.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import path from "node:path";
|
|
|
7
7
|
import * as Ink from "ink-cjs";
|
|
8
8
|
|
|
9
9
|
import { Brackets } from "~/app/Brackets";
|
|
10
|
+
import { FormatText } from "~/app/FormatText";
|
|
10
11
|
import { Store } from "~/app/Store";
|
|
11
12
|
import { Timer } from "~/core/Timer";
|
|
12
13
|
import { cli } from "~/core/cli";
|
|
@@ -38,16 +39,19 @@ export async function pr_list(): Promise<Array<PullRequest>> {
|
|
|
38
39
|
|
|
39
40
|
if (actions.isDebug()) {
|
|
40
41
|
actions.output(
|
|
41
|
-
<
|
|
42
|
-
<Ink.Text
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
<FormatText
|
|
43
|
+
wrapper={<Ink.Text dimColor />}
|
|
44
|
+
message="Github cache {count} open PRs from {repo_path} authored by {username}"
|
|
45
|
+
values={{
|
|
46
|
+
count: (
|
|
47
|
+
<Ink.Text bold color={colors.yellow}>
|
|
48
|
+
{result_pr_list.length}
|
|
49
|
+
</Ink.Text>
|
|
50
|
+
),
|
|
51
|
+
repo_path: <Brackets>{repo_path}</Brackets>,
|
|
52
|
+
username: <Brackets>{username}</Brackets>,
|
|
53
|
+
}}
|
|
54
|
+
/>,
|
|
51
55
|
);
|
|
52
56
|
}
|
|
53
57
|
|
|
@@ -76,15 +80,11 @@ export async function pr_status(branch: string): Promise<null | PullRequest> {
|
|
|
76
80
|
if (cache) {
|
|
77
81
|
if (actions.isDebug()) {
|
|
78
82
|
actions.debug(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
</Ink.Text>
|
|
85
|
-
<Ink.Text> </Ink.Text>
|
|
86
|
-
<Ink.Text dimColor>{branch}</Ink.Text>
|
|
87
|
-
</Ink.Text>,
|
|
83
|
+
cache_message({
|
|
84
|
+
hit: true,
|
|
85
|
+
message: "Github pr_status cache",
|
|
86
|
+
extra: branch,
|
|
87
|
+
}),
|
|
88
88
|
);
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -93,15 +93,11 @@ export async function pr_status(branch: string): Promise<null | PullRequest> {
|
|
|
93
93
|
|
|
94
94
|
if (actions.isDebug()) {
|
|
95
95
|
actions.debug(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
</Ink.Text>
|
|
102
|
-
<Ink.Text> </Ink.Text>
|
|
103
|
-
<Ink.Text dimColor>{branch}</Ink.Text>
|
|
104
|
-
</Ink.Text>,
|
|
96
|
+
cache_message({
|
|
97
|
+
hit: false,
|
|
98
|
+
message: "Github pr_status cache",
|
|
99
|
+
extra: branch,
|
|
100
|
+
}),
|
|
105
101
|
);
|
|
106
102
|
}
|
|
107
103
|
|
|
@@ -246,14 +242,46 @@ export async function pr_draft(args: DraftPullRequestArgs) {
|
|
|
246
242
|
}
|
|
247
243
|
|
|
248
244
|
export async function pr_diff(number: number) {
|
|
249
|
-
|
|
245
|
+
const state = Store.getState();
|
|
246
|
+
const actions = state.actions;
|
|
247
|
+
|
|
248
|
+
const maybe_diff = state.cache_pr_diff[number];
|
|
249
|
+
|
|
250
|
+
if (maybe_diff) {
|
|
251
|
+
if (actions.isDebug()) {
|
|
252
|
+
actions.debug(
|
|
253
|
+
cache_message({
|
|
254
|
+
hit: true,
|
|
255
|
+
message: "Github pr_diff cache",
|
|
256
|
+
extra: number,
|
|
257
|
+
}),
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return maybe_diff;
|
|
262
|
+
}
|
|
250
263
|
|
|
264
|
+
if (actions.isDebug()) {
|
|
265
|
+
actions.debug(
|
|
266
|
+
cache_message({
|
|
267
|
+
hit: false,
|
|
268
|
+
message: "Github pr_diff cache",
|
|
269
|
+
extra: number,
|
|
270
|
+
}),
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// https://cli.github.com/manual/gh_pr_diff
|
|
251
275
|
const cli_result = await cli(`gh pr diff --color=never ${number}`);
|
|
252
276
|
|
|
253
277
|
if (cli_result.code !== 0) {
|
|
254
278
|
handle_error(cli_result.output);
|
|
255
279
|
}
|
|
256
280
|
|
|
281
|
+
actions.set((state) => {
|
|
282
|
+
state.cache_pr_diff[number] = cli_result.output;
|
|
283
|
+
});
|
|
284
|
+
|
|
257
285
|
return cli_result.stdout;
|
|
258
286
|
}
|
|
259
287
|
|
|
@@ -321,6 +349,36 @@ function safe_filename(value: string): string {
|
|
|
321
349
|
return value.replace(RE.non_alphanumeric_dash, "-");
|
|
322
350
|
}
|
|
323
351
|
|
|
352
|
+
type CacheMessageArgs = {
|
|
353
|
+
hit: boolean;
|
|
354
|
+
message: React.ReactNode;
|
|
355
|
+
extra: React.ReactNode;
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
function cache_message(args: CacheMessageArgs) {
|
|
359
|
+
const status = args.hit ? (
|
|
360
|
+
<Ink.Text bold color={colors.green}>
|
|
361
|
+
HIT
|
|
362
|
+
</Ink.Text>
|
|
363
|
+
) : (
|
|
364
|
+
<Ink.Text bold color={colors.red}>
|
|
365
|
+
MISS
|
|
366
|
+
</Ink.Text>
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
return (
|
|
370
|
+
<FormatText
|
|
371
|
+
wrapper={<Ink.Text dimColor />}
|
|
372
|
+
message="{message} {status} {extra}"
|
|
373
|
+
values={{
|
|
374
|
+
message: args.message,
|
|
375
|
+
status,
|
|
376
|
+
extra: args.extra,
|
|
377
|
+
}}
|
|
378
|
+
/>
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
|
|
324
382
|
type Commit = {
|
|
325
383
|
authoredDate: string; // "2023-10-22T23:13:35Z"
|
|
326
384
|
authors: [
|