git-stack-cli 2.1.0-beta → 2.1.1-beta
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 +58 -37
- package/package.json +2 -1
- package/src/app/DetectInitialPR.tsx +2 -2
- package/src/core/GitReviseTodo.ts +2 -2
- package/src/core/get_tmp_dir.ts +12 -0
- package/src/core/github.tsx +19 -10
- package/src/index.tsx +7 -0
package/dist/js/index.js
CHANGED
|
@@ -28099,6 +28099,7 @@ var require_last = __commonJS((exports, module) => {
|
|
|
28099
28099
|
|
|
28100
28100
|
// src/index.tsx
|
|
28101
28101
|
var React55 = __toESM(require_react(), 1);
|
|
28102
|
+
import fs14 from "node:fs/promises";
|
|
28102
28103
|
|
|
28103
28104
|
// node_modules/.pnpm/ink-cjs@4.4.1_@types+react@18.2.33_react-devtools-core@4.19.1_react@18.2.0/node_modules/ink-cjs/build/render.js
|
|
28104
28105
|
import { Stream } from "node:stream";
|
|
@@ -38015,9 +38016,21 @@ var RE3 = {
|
|
|
38015
38016
|
|
|
38016
38017
|
// src/core/github.tsx
|
|
38017
38018
|
var React24 = __toESM(require_react(), 1);
|
|
38019
|
+
import crypto from "node:crypto";
|
|
38020
|
+
import fs9 from "node:fs/promises";
|
|
38021
|
+
import path6 from "node:path";
|
|
38022
|
+
|
|
38023
|
+
// src/core/get_tmp_dir.ts
|
|
38018
38024
|
import fs8 from "node:fs/promises";
|
|
38019
38025
|
import os2 from "node:os";
|
|
38020
38026
|
import path5 from "node:path";
|
|
38027
|
+
async function get_tmp_dir() {
|
|
38028
|
+
const dir = path5.join(os2.tmpdir(), "git-stack-cli");
|
|
38029
|
+
await fs8.mkdir(dir, { recursive: true });
|
|
38030
|
+
return dir;
|
|
38031
|
+
}
|
|
38032
|
+
|
|
38033
|
+
// src/core/github.tsx
|
|
38021
38034
|
async function pr_list() {
|
|
38022
38035
|
const state = Store.getState();
|
|
38023
38036
|
const actions = state.actions;
|
|
@@ -38146,15 +38159,21 @@ async function pr_draft(args) {
|
|
|
38146
38159
|
}
|
|
38147
38160
|
var JSON_FIELDS = "--json id,number,state,baseRefName,headRefName,commits,title,body,url,isDraft";
|
|
38148
38161
|
async function gh_json(command) {
|
|
38149
|
-
|
|
38162
|
+
let hash = crypto.createHash("md5").update(command).digest("hex");
|
|
38163
|
+
let tmp_filename = safe_filename(`gh_json-${hash}`);
|
|
38164
|
+
const tmp_pr_json = path6.join(await get_tmp_dir(), `${tmp_filename}.json`);
|
|
38150
38165
|
const options = { ignoreExitCode: true };
|
|
38151
38166
|
const cli_result = await cli(`gh ${command} > ${tmp_pr_json}`, options);
|
|
38152
38167
|
if (cli_result.code !== 0) {
|
|
38153
38168
|
return new Error(cli_result.output);
|
|
38154
38169
|
}
|
|
38155
|
-
const json_str = await
|
|
38156
|
-
|
|
38157
|
-
|
|
38170
|
+
const json_str = String(await fs9.readFile(tmp_pr_json));
|
|
38171
|
+
try {
|
|
38172
|
+
const json = JSON.parse(json_str);
|
|
38173
|
+
return json;
|
|
38174
|
+
} catch (error) {
|
|
38175
|
+
return new Error(`gh_json JSON.parse: ${error}`);
|
|
38176
|
+
}
|
|
38158
38177
|
}
|
|
38159
38178
|
function handle_error(output) {
|
|
38160
38179
|
const state = Store.getState();
|
|
@@ -38166,14 +38185,15 @@ function handle_error(output) {
|
|
|
38166
38185
|
}
|
|
38167
38186
|
async function write_body_file(args) {
|
|
38168
38187
|
invariant(args.body, "args.body must exist");
|
|
38169
|
-
|
|
38170
|
-
|
|
38171
|
-
temp_filename = temp_filename.replace(RE4.non_alphanumeric_dash, "-");
|
|
38172
|
-
const temp_path = path5.join(temp_dir, temp_filename);
|
|
38188
|
+
let tmp_filename = safe_filename(`git-stack-body-${args.base}`);
|
|
38189
|
+
const temp_path = path6.join(await get_tmp_dir(), tmp_filename);
|
|
38173
38190
|
await safe_rm(temp_path);
|
|
38174
|
-
await
|
|
38191
|
+
await fs9.writeFile(temp_path, args.body);
|
|
38175
38192
|
return temp_path;
|
|
38176
38193
|
}
|
|
38194
|
+
function safe_filename(value) {
|
|
38195
|
+
return value.replace(RE4.non_alphanumeric_dash, "-");
|
|
38196
|
+
}
|
|
38177
38197
|
var RE4 = {
|
|
38178
38198
|
non_alphanumeric_dash: /[^a-zA-Z0-9_-]+/g
|
|
38179
38199
|
};
|
|
@@ -38327,9 +38347,8 @@ function lines(value) {
|
|
|
38327
38347
|
var UNASSIGNED = "unassigned";
|
|
38328
38348
|
|
|
38329
38349
|
// src/core/GitReviseTodo.ts
|
|
38330
|
-
import
|
|
38331
|
-
import
|
|
38332
|
-
import path6 from "node:path";
|
|
38350
|
+
import fs10 from "node:fs/promises";
|
|
38351
|
+
import path7 from "node:path";
|
|
38333
38352
|
function GitReviseTodo(args) {
|
|
38334
38353
|
const commit_list = [];
|
|
38335
38354
|
const group_list = args.commit_range.group_list;
|
|
@@ -38365,7 +38384,7 @@ GitReviseTodo.todo = function todo(args) {
|
|
|
38365
38384
|
return todo2;
|
|
38366
38385
|
};
|
|
38367
38386
|
GitReviseTodo.execute = async function grt_execute(args) {
|
|
38368
|
-
const tmp_git_sequence_editor_path =
|
|
38387
|
+
const tmp_git_sequence_editor_path = path7.join(await get_tmp_dir(), "git-sequence-editor.sh");
|
|
38369
38388
|
const GIT_SEQUENCE_EDITOR_SCRIPT = `#!/bin/sh
|
|
38370
38389
|
|
|
38371
38390
|
# Example
|
|
@@ -38403,8 +38422,8 @@ echo "------ END ------"
|
|
|
38403
38422
|
echo "$GIT_REVISE_TODO" > "$git_revise_todo_path"
|
|
38404
38423
|
`;
|
|
38405
38424
|
invariant(GIT_SEQUENCE_EDITOR_SCRIPT, "GIT_SEQUENCE_EDITOR_SCRIPT must exist");
|
|
38406
|
-
await
|
|
38407
|
-
await
|
|
38425
|
+
await fs10.writeFile(tmp_git_sequence_editor_path, GIT_SEQUENCE_EDITOR_SCRIPT);
|
|
38426
|
+
await fs10.chmod(tmp_git_sequence_editor_path, "755");
|
|
38408
38427
|
const git_revise_todo = GitReviseTodo(args);
|
|
38409
38428
|
const command = [
|
|
38410
38429
|
`GIT_EDITOR="${tmp_git_sequence_editor_path}"`,
|
|
@@ -38481,7 +38500,7 @@ function DetectInitialPR(props) {
|
|
|
38481
38500
|
const branch_name2 = Store.getState().branch_name;
|
|
38482
38501
|
const commit_range = Store.getState().commit_range;
|
|
38483
38502
|
invariant(branch_name2, "branch_name must exist");
|
|
38484
|
-
invariant(commit_range, "
|
|
38503
|
+
invariant(commit_range, "commit_range must exist");
|
|
38485
38504
|
try {
|
|
38486
38505
|
let has_existing_metadata = false;
|
|
38487
38506
|
for (const commit2 of commit_range.commit_list) {
|
|
@@ -38513,7 +38532,7 @@ function DetectInitialPR(props) {
|
|
|
38513
38532
|
const branch_name2 = Store.getState().branch_name;
|
|
38514
38533
|
const commit_range = import_cloneDeep.default(Store.getState().commit_range);
|
|
38515
38534
|
invariant(branch_name2, "branch_name must exist");
|
|
38516
|
-
invariant(commit_range, "
|
|
38535
|
+
invariant(commit_range, "commit_range must exist");
|
|
38517
38536
|
for (const group of commit_range.group_list) {
|
|
38518
38537
|
group.id = branch_name2;
|
|
38519
38538
|
group.title = state.pr?.title || "-";
|
|
@@ -38845,16 +38864,16 @@ var React32 = __toESM(require_react(), 1);
|
|
|
38845
38864
|
|
|
38846
38865
|
// src/commands/Rebase.tsx
|
|
38847
38866
|
var React31 = __toESM(require_react(), 1);
|
|
38848
|
-
import
|
|
38867
|
+
import fs11 from "node:fs";
|
|
38849
38868
|
|
|
38850
38869
|
// src/core/short_id.ts
|
|
38851
|
-
import
|
|
38870
|
+
import crypto2 from "node:crypto";
|
|
38852
38871
|
function short_id() {
|
|
38853
38872
|
const timestamp = Date.now();
|
|
38854
38873
|
const js_max_bits = 53;
|
|
38855
38874
|
const timestamp_bits = Math.floor(Math.log2(timestamp)) + 1;
|
|
38856
38875
|
const padding_bits = js_max_bits - timestamp_bits;
|
|
38857
|
-
const random =
|
|
38876
|
+
const random = crypto2.randomInt(0, Math.pow(2, padding_bits));
|
|
38858
38877
|
const combined = interleave_bits(timestamp, random);
|
|
38859
38878
|
return encode(combined);
|
|
38860
38879
|
}
|
|
@@ -38998,7 +39017,7 @@ Rebase.run = async function run4() {
|
|
|
38998
39017
|
cli.sync(`git clean -df`, spawn_options);
|
|
38999
39018
|
cli.sync(`git checkout ${branch_name}`, spawn_options);
|
|
39000
39019
|
cli.sync(`git branch -D ${temp_branch_name}`, spawn_options);
|
|
39001
|
-
if (
|
|
39020
|
+
if (fs11.existsSync(cwd2)) {
|
|
39002
39021
|
process.chdir(cwd2);
|
|
39003
39022
|
}
|
|
39004
39023
|
cli.sync(`pwd`, spawn_options);
|
|
@@ -39021,7 +39040,7 @@ function LocalMergeRebase() {
|
|
|
39021
39040
|
|
|
39022
39041
|
// src/app/ManualRebase.tsx
|
|
39023
39042
|
var React33 = __toESM(require_react(), 1);
|
|
39024
|
-
import
|
|
39043
|
+
import fs12 from "node:fs";
|
|
39025
39044
|
function ManualRebase() {
|
|
39026
39045
|
return /* @__PURE__ */ React33.createElement(Await, {
|
|
39027
39046
|
fallback: /* @__PURE__ */ React33.createElement(Text, {
|
|
@@ -39121,7 +39140,7 @@ async function run5() {
|
|
|
39121
39140
|
cli.sync(`git clean -df`, spawn_options);
|
|
39122
39141
|
cli.sync(`git checkout ${branch_name}`, spawn_options);
|
|
39123
39142
|
cli.sync(`git branch -D ${temp_branch_name}`, spawn_options);
|
|
39124
|
-
if (
|
|
39143
|
+
if (fs12.existsSync(cwd2)) {
|
|
39125
39144
|
process.chdir(cwd2);
|
|
39126
39145
|
}
|
|
39127
39146
|
cli.sync(`pwd`, spawn_options);
|
|
@@ -39380,8 +39399,8 @@ function PreLocalMergeRebase() {
|
|
|
39380
39399
|
|
|
39381
39400
|
// src/app/PreManualRebase.tsx
|
|
39382
39401
|
var React38 = __toESM(require_react(), 1);
|
|
39383
|
-
import
|
|
39384
|
-
import
|
|
39402
|
+
import fs13 from "node:fs/promises";
|
|
39403
|
+
import path8 from "node:path";
|
|
39385
39404
|
function PreManualRebase() {
|
|
39386
39405
|
return /* @__PURE__ */ React38.createElement(Await, {
|
|
39387
39406
|
fallback: null,
|
|
@@ -39403,7 +39422,7 @@ async function run7() {
|
|
|
39403
39422
|
for (const key of PR_TEMPLATE_KEY_LIST) {
|
|
39404
39423
|
const pr_template_fn = PR_TEMPLATE[key];
|
|
39405
39424
|
if (await safe_exists(pr_template_fn(repo_root))) {
|
|
39406
|
-
pr_template_body = await
|
|
39425
|
+
pr_template_body = await fs13.readFile(pr_template_fn(repo_root), "utf-8");
|
|
39407
39426
|
actions.output(/* @__PURE__ */ React38.createElement(FormatText, {
|
|
39408
39427
|
wrapper: /* @__PURE__ */ React38.createElement(Text, {
|
|
39409
39428
|
color: colors.yellow
|
|
@@ -39418,7 +39437,7 @@ async function run7() {
|
|
|
39418
39437
|
}
|
|
39419
39438
|
let pr_templates = [];
|
|
39420
39439
|
if (await safe_exists(PR_TEMPLATE.TemplateDir(repo_root))) {
|
|
39421
|
-
pr_templates = await
|
|
39440
|
+
pr_templates = await fs13.readdir(PR_TEMPLATE.TemplateDir(repo_root));
|
|
39422
39441
|
}
|
|
39423
39442
|
actions.set((state2) => {
|
|
39424
39443
|
state2.pr_template_body = pr_template_body;
|
|
@@ -39441,10 +39460,10 @@ async function run7() {
|
|
|
39441
39460
|
});
|
|
39442
39461
|
}
|
|
39443
39462
|
var PR_TEMPLATE = Object.freeze({
|
|
39444
|
-
Github: (root) =>
|
|
39445
|
-
Root: (root) =>
|
|
39446
|
-
Docs: (root) =>
|
|
39447
|
-
TemplateDir: (root) =>
|
|
39463
|
+
Github: (root) => path8.join(root, ".github", "pull_request_template.md"),
|
|
39464
|
+
Root: (root) => path8.join(root, "pull_request_template.md"),
|
|
39465
|
+
Docs: (root) => path8.join(root, "docs", "pull_request_template.md"),
|
|
39466
|
+
TemplateDir: (root) => path8.join(root, ".github", "PULL_REQUEST_TEMPLATE")
|
|
39448
39467
|
});
|
|
39449
39468
|
var PR_TEMPLATE_KEY_LIST = Object.keys(PR_TEMPLATE);
|
|
39450
39469
|
|
|
@@ -40426,7 +40445,7 @@ function Providers(props) {
|
|
|
40426
40445
|
|
|
40427
40446
|
// src/app/RebaseCheck.tsx
|
|
40428
40447
|
var React48 = __toESM(require_react(), 1);
|
|
40429
|
-
import
|
|
40448
|
+
import path9 from "node:path";
|
|
40430
40449
|
function reducer5(state, patch) {
|
|
40431
40450
|
return { ...state, ...patch };
|
|
40432
40451
|
}
|
|
@@ -40464,8 +40483,8 @@ function RebaseCheck(props) {
|
|
|
40464
40483
|
try {
|
|
40465
40484
|
const git_dir = (await cli(`git rev-parse --absolute-git-dir`)).stdout;
|
|
40466
40485
|
let is_rebase = false;
|
|
40467
|
-
is_rebase ||= await safe_exists(
|
|
40468
|
-
is_rebase ||= await safe_exists(
|
|
40486
|
+
is_rebase ||= await safe_exists(path9.join(git_dir, "rebase-apply"));
|
|
40487
|
+
is_rebase ||= await safe_exists(path9.join(git_dir, "rebase-merge"));
|
|
40469
40488
|
const status = is_rebase ? "prompt" : "done";
|
|
40470
40489
|
patch({ status });
|
|
40471
40490
|
} catch (err) {
|
|
@@ -42021,9 +42040,9 @@ var parser = new YargsParser({
|
|
|
42021
42040
|
format,
|
|
42022
42041
|
normalize,
|
|
42023
42042
|
resolve: resolve2,
|
|
42024
|
-
require: (
|
|
42043
|
+
require: (path10) => {
|
|
42025
42044
|
if (true) {
|
|
42026
|
-
return __require(
|
|
42045
|
+
return __require(path10);
|
|
42027
42046
|
} else
|
|
42028
42047
|
;
|
|
42029
42048
|
}
|
|
@@ -45606,7 +45625,7 @@ var yargs_default = Yargs;
|
|
|
45606
45625
|
|
|
45607
45626
|
// src/command.ts
|
|
45608
45627
|
async function command2() {
|
|
45609
|
-
return yargs_default(hideBin(process.argv)).usage("Usage: git stack [command] [options]").command("$0", "Sync commit ranges to Github", (yargs) => yargs.options(DefaultOptions)).command("fixup [commit]", "Amend staged changes to a specific commit in history", (yargs) => yargs.positional("commit", FixupOptions.commit)).command("log [args...]", "Print an abbreviated log with numbered commits, useful for git stack fixup", (yargs) => yargs.strict(false)).command("rebase", "Update local branch via rebase with latest changes from origin master branch", (yargs) => yargs).option("verbose", GlobalOptions.verbose).wrap(123).strict().version("2.1.
|
|
45628
|
+
return yargs_default(hideBin(process.argv)).usage("Usage: git stack [command] [options]").command("$0", "Sync commit ranges to Github", (yargs) => yargs.options(DefaultOptions)).command("fixup [commit]", "Amend staged changes to a specific commit in history", (yargs) => yargs.positional("commit", FixupOptions.commit)).command("log [args...]", "Print an abbreviated log with numbered commits, useful for git stack fixup", (yargs) => yargs.strict(false)).command("rebase", "Update local branch via rebase with latest changes from origin master branch", (yargs) => yargs).option("verbose", GlobalOptions.verbose).wrap(123).strict().version("2.1.1-beta").showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`").help("help", "Show usage via `git stack help`").argv;
|
|
45610
45629
|
}
|
|
45611
45630
|
var GlobalOptions = {
|
|
45612
45631
|
verbose: {
|
|
@@ -45715,6 +45734,8 @@ var FixupOptions = {
|
|
|
45715
45734
|
maybe_verbose_help();
|
|
45716
45735
|
process.exit(238);
|
|
45717
45736
|
});
|
|
45737
|
+
const tmp_dir = await get_tmp_dir();
|
|
45738
|
+
await fs14.rm(tmp_dir, { recursive: true });
|
|
45718
45739
|
const ink = render_default(/* @__PURE__ */ React55.createElement(App2, null), {
|
|
45719
45740
|
exitOnCtrlC: false
|
|
45720
45741
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-stack-cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1-beta",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "magus",
|
|
6
6
|
"license": "MIT",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"zustand": "^4.4.4"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
+
"@oven/bun-darwin-aarch64": "1.1.42",
|
|
55
56
|
"@types/chalk": "^2.2.0",
|
|
56
57
|
"@types/lodash": "^4.17.7",
|
|
57
58
|
"@types/luxon": "^3.4.2",
|
|
@@ -108,7 +108,7 @@ export function DetectInitialPR(props: Props) {
|
|
|
108
108
|
const commit_range = Store.getState().commit_range;
|
|
109
109
|
|
|
110
110
|
invariant(branch_name, "branch_name must exist");
|
|
111
|
-
invariant(commit_range, "
|
|
111
|
+
invariant(commit_range, "commit_range must exist");
|
|
112
112
|
|
|
113
113
|
try {
|
|
114
114
|
let has_existing_metadata = false;
|
|
@@ -149,7 +149,7 @@ export function DetectInitialPR(props: Props) {
|
|
|
149
149
|
const commit_range = cloneDeep(Store.getState().commit_range);
|
|
150
150
|
|
|
151
151
|
invariant(branch_name, "branch_name must exist");
|
|
152
|
-
invariant(commit_range, "
|
|
152
|
+
invariant(commit_range, "commit_range must exist");
|
|
153
153
|
|
|
154
154
|
for (const group of commit_range.group_list) {
|
|
155
155
|
group.id = branch_name;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
|
-
import os from "node:os";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
|
|
5
4
|
import * as Metadata from "~/core/Metadata";
|
|
6
5
|
import { cli } from "~/core/cli";
|
|
6
|
+
import { get_tmp_dir } from "~/core/get_tmp_dir";
|
|
7
7
|
import { invariant } from "~/core/invariant";
|
|
8
8
|
import { safe_rm } from "~/core/safe_rm";
|
|
9
9
|
|
|
@@ -109,7 +109,7 @@ GitReviseTodo.todo = function todo(args: CommitListArgs) {
|
|
|
109
109
|
|
|
110
110
|
GitReviseTodo.execute = async function grt_execute(args: ExecuteArgs) {
|
|
111
111
|
// generate temporary directory and drop sequence editor script
|
|
112
|
-
const tmp_git_sequence_editor_path = path.join(
|
|
112
|
+
const tmp_git_sequence_editor_path = path.join(await get_tmp_dir(), "git-sequence-editor.sh");
|
|
113
113
|
|
|
114
114
|
// replaced at build time with literal contents of `scripts/git-sequence-editor.sh`
|
|
115
115
|
const GIT_SEQUENCE_EDITOR_SCRIPT = process.env.GIT_SEQUENCE_EDITOR_SCRIPT;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
export async function get_tmp_dir(): Promise<string> {
|
|
6
|
+
const dir = path.join(os.tmpdir(), "git-stack-cli");
|
|
7
|
+
|
|
8
|
+
// ensure tmp directory exists
|
|
9
|
+
await fs.mkdir(dir, { recursive: true });
|
|
10
|
+
|
|
11
|
+
return dir;
|
|
12
|
+
}
|
package/src/core/github.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
|
|
3
|
+
import crypto from "node:crypto";
|
|
3
4
|
import fs from "node:fs/promises";
|
|
4
|
-
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
|
|
7
7
|
import * as Ink from "ink-cjs";
|
|
@@ -10,6 +10,7 @@ import { Brackets } from "~/app/Brackets";
|
|
|
10
10
|
import { Store } from "~/app/Store";
|
|
11
11
|
import { cli } from "~/core/cli";
|
|
12
12
|
import { colors } from "~/core/colors";
|
|
13
|
+
import { get_tmp_dir } from "~/core/get_tmp_dir";
|
|
13
14
|
import { invariant } from "~/core/invariant";
|
|
14
15
|
import { safe_quote } from "~/core/safe_quote";
|
|
15
16
|
import { safe_rm } from "~/core/safe_rm";
|
|
@@ -228,7 +229,10 @@ const JSON_FIELDS = "--json id,number,state,baseRefName,headRefName,commits,titl
|
|
|
228
229
|
// consistent handle gh cli commands returning json
|
|
229
230
|
// redirect to tmp file to avoid scrollback overflow causing scrollback to be cleared
|
|
230
231
|
async function gh_json<T>(command: string): Promise<T | Error> {
|
|
231
|
-
|
|
232
|
+
// hash command for unique short string
|
|
233
|
+
let hash = crypto.createHash("md5").update(command).digest("hex");
|
|
234
|
+
let tmp_filename = safe_filename(`gh_json-${hash}`);
|
|
235
|
+
const tmp_pr_json = path.join(await get_tmp_dir(), `${tmp_filename}.json`);
|
|
232
236
|
|
|
233
237
|
const options = { ignoreExitCode: true };
|
|
234
238
|
const cli_result = await cli(`gh ${command} > ${tmp_pr_json}`, options);
|
|
@@ -238,9 +242,13 @@ async function gh_json<T>(command: string): Promise<T | Error> {
|
|
|
238
242
|
}
|
|
239
243
|
|
|
240
244
|
// read from file
|
|
241
|
-
const json_str = await fs.readFile(tmp_pr_json
|
|
242
|
-
|
|
243
|
-
|
|
245
|
+
const json_str = String(await fs.readFile(tmp_pr_json));
|
|
246
|
+
try {
|
|
247
|
+
const json = JSON.parse(json_str);
|
|
248
|
+
return json;
|
|
249
|
+
} catch (error) {
|
|
250
|
+
return new Error(`gh_json JSON.parse: ${error}`);
|
|
251
|
+
}
|
|
244
252
|
}
|
|
245
253
|
|
|
246
254
|
function handle_error(output: string): never {
|
|
@@ -258,15 +266,12 @@ function handle_error(output: string): never {
|
|
|
258
266
|
async function write_body_file(args: EditPullRequestArgs) {
|
|
259
267
|
invariant(args.body, "args.body must exist");
|
|
260
268
|
|
|
261
|
-
const temp_dir = os.tmpdir();
|
|
262
|
-
|
|
263
269
|
// ensure unique filename is safe for filesystem
|
|
264
270
|
// base (group id) might contain slashes, e.g. dev/magus/gs-3cmrMBSUj
|
|
265
271
|
// the flashes would mess up the filesystem path to this file
|
|
266
|
-
let
|
|
267
|
-
temp_filename = temp_filename.replace(RE.non_alphanumeric_dash, "-");
|
|
272
|
+
let tmp_filename = safe_filename(`git-stack-body-${args.base}`);
|
|
268
273
|
|
|
269
|
-
const temp_path = path.join(
|
|
274
|
+
const temp_path = path.join(await get_tmp_dir(), tmp_filename);
|
|
270
275
|
|
|
271
276
|
await safe_rm(temp_path);
|
|
272
277
|
|
|
@@ -275,6 +280,10 @@ async function write_body_file(args: EditPullRequestArgs) {
|
|
|
275
280
|
return temp_path;
|
|
276
281
|
}
|
|
277
282
|
|
|
283
|
+
function safe_filename(value: string): string {
|
|
284
|
+
return value.replace(RE.non_alphanumeric_dash, "-");
|
|
285
|
+
}
|
|
286
|
+
|
|
278
287
|
type Commit = {
|
|
279
288
|
authoredDate: string; // "2023-10-22T23:13:35Z"
|
|
280
289
|
authors: [
|
package/src/index.tsx
CHANGED
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
import * as React from "react";
|
|
6
6
|
|
|
7
|
+
import fs from "node:fs/promises";
|
|
8
|
+
|
|
7
9
|
import * as Ink from "ink-cjs";
|
|
8
10
|
|
|
9
11
|
import { App } from "~/app/App";
|
|
10
12
|
import { Store } from "~/app/Store";
|
|
11
13
|
import { command } from "~/command";
|
|
14
|
+
import { get_tmp_dir } from "~/core/get_tmp_dir";
|
|
12
15
|
import { pretty_json } from "~/core/pretty_json";
|
|
13
16
|
|
|
14
17
|
(async function main() {
|
|
@@ -33,6 +36,10 @@ import { pretty_json } from "~/core/pretty_json";
|
|
|
33
36
|
process.exit(238);
|
|
34
37
|
});
|
|
35
38
|
|
|
39
|
+
// cleanup leftover temporary files from previous run
|
|
40
|
+
const tmp_dir = await get_tmp_dir();
|
|
41
|
+
await fs.rm(tmp_dir, { recursive: true });
|
|
42
|
+
|
|
36
43
|
const ink = Ink.render(<App />, {
|
|
37
44
|
// If true, each update will be rendered as a separate output, without replacing the previous one.
|
|
38
45
|
// debug: true,
|