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 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
- const tmp_pr_json = path5.join(os2.tmpdir(), "git-stack-gh.json");
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 fs8.readFile(tmp_pr_json, "utf-8");
38156
- const json = JSON.parse(json_str);
38157
- return json;
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
- const temp_dir = os2.tmpdir();
38170
- let temp_filename = `git-stack-body-${args.base}`;
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 fs8.writeFile(temp_path, args.body);
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 fs9 from "node:fs/promises";
38331
- import os3 from "node:os";
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 = path6.join(os3.tmpdir(), "git-sequence-editor.sh");
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 fs9.writeFile(tmp_git_sequence_editor_path, GIT_SEQUENCE_EDITOR_SCRIPT);
38407
- await fs9.chmod(tmp_git_sequence_editor_path, "755");
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, "branch_name must exist");
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, "branch_name must exist");
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 fs10 from "node:fs";
38867
+ import fs11 from "node:fs";
38849
38868
 
38850
38869
  // src/core/short_id.ts
38851
- import crypto from "node:crypto";
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 = crypto.randomInt(0, Math.pow(2, padding_bits));
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 (fs10.existsSync(cwd2)) {
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 fs11 from "node:fs";
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 (fs11.existsSync(cwd2)) {
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 fs12 from "node:fs/promises";
39384
- import path7 from "node:path";
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 fs12.readFile(pr_template_fn(repo_root), "utf-8");
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 fs12.readdir(PR_TEMPLATE.TemplateDir(repo_root));
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) => path7.join(root, ".github", "pull_request_template.md"),
39445
- Root: (root) => path7.join(root, "pull_request_template.md"),
39446
- Docs: (root) => path7.join(root, "docs", "pull_request_template.md"),
39447
- TemplateDir: (root) => path7.join(root, ".github", "PULL_REQUEST_TEMPLATE")
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 path8 from "node:path";
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(path8.join(git_dir, "rebase-apply"));
40468
- is_rebase ||= await safe_exists(path8.join(git_dir, "rebase-merge"));
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: (path9) => {
42043
+ require: (path10) => {
42025
42044
  if (true) {
42026
- return __require(path9);
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.0-beta").showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`").help("help", "Show usage via `git stack help`").argv;
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.0-beta",
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, "branch_name must exist");
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, "branch_name must exist");
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(os.tmpdir(), "git-sequence-editor.sh");
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
+ }
@@ -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
- const tmp_pr_json = path.join(os.tmpdir(), "git-stack-gh.json");
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, "utf-8");
242
- const json = JSON.parse(json_str);
243
- return json;
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 temp_filename = `git-stack-body-${args.base}`;
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(temp_dir, temp_filename);
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,