git-stack-cli 2.2.5 → 2.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,8 @@
1
- # git-stack-cli
1
+ <p align="center">
2
+ <img src="https://github.com/user-attachments/assets/3fba8b2d-2cb2-446b-8bf4-523643636565" alt="Logo" height=240>
3
+ </p>
4
+
5
+ # `git stack`
2
6
 
3
7
  - ✨ **[Stacked diffs](https://graphite.dev/guides/stacked-diffs) for `git`**
4
8
  - 🚀 **Simple one-branch workflow**
package/dist/js/index.js CHANGED
@@ -37974,16 +37974,6 @@ function CheckGitRevise(props) {
37974
37974
  var React25 = __toESM(require_react(), 1);
37975
37975
  var import_cloneDeep = __toESM(require_cloneDeep(), 1);
37976
37976
 
37977
- // src/core/safe_quote.ts
37978
- function safe_quote(value) {
37979
- let result = value;
37980
- result = result.replace(RE2.all_double_quote, "\\\"");
37981
- return result;
37982
- }
37983
- var RE2 = {
37984
- all_double_quote: /"/g
37985
- };
37986
-
37987
37977
  // src/core/Metadata.ts
37988
37978
  function write(message, values) {
37989
37979
  let result = message;
@@ -37994,17 +37984,16 @@ function write(message, values) {
37994
37984
  }
37995
37985
  let new_message = line_list.join(`
37996
37986
  `);
37997
- new_message = safe_quote(new_message);
37998
37987
  return new_message;
37999
37988
  }
38000
37989
  function read(message) {
38001
37990
  const values = { id: null, title: null };
38002
- const match_id = message.match(RE3.stack_id);
37991
+ const match_id = message.match(RE2.stack_id);
38003
37992
  if (match_id?.groups) {
38004
37993
  values.id = match_id.groups["id"];
38005
37994
  invariant(values.id, "id must exist");
38006
37995
  }
38007
- const match_title = message.match(RE3.group_title);
37996
+ const match_title = message.match(RE2.group_title);
38008
37997
  if (match_title?.groups) {
38009
37998
  values.title = match_title.groups["title"];
38010
37999
  }
@@ -38012,8 +38001,8 @@ function read(message) {
38012
38001
  }
38013
38002
  function remove(message) {
38014
38003
  let result = message;
38015
- result = result.replace(new RegExp(RE3.stack_id, "gmi"), "");
38016
- result = result.replace(new RegExp(RE3.group_title, "gmi"), "");
38004
+ result = result.replace(new RegExp(RE2.stack_id, "gmi"), "");
38005
+ result = result.replace(new RegExp(RE2.group_title, "gmi"), "");
38017
38006
  result = result.trimEnd();
38018
38007
  return result;
38019
38008
  }
@@ -38025,7 +38014,7 @@ var TEMPLATE = {
38025
38014
  return `git-stack-title: ${title}`;
38026
38015
  }
38027
38016
  };
38028
- var RE3 = {
38017
+ var RE2 = {
38029
38018
  stack_id: new RegExp(`${TEMPLATE.stack_id("(?<id>[^\\s]+)")}`, "i"),
38030
38019
  group_title: new RegExp(TEMPLATE.group_title("(?<title>[^\\n^\\r]+)"), "i")
38031
38020
  };
@@ -38046,6 +38035,20 @@ async function get_tmp_dir() {
38046
38035
  return dir;
38047
38036
  }
38048
38037
 
38038
+ // src/core/safe_quote.ts
38039
+ function safe_quote(value) {
38040
+ let result = value;
38041
+ result = result.replace(RE3.all_backslash, "\\\\");
38042
+ result = result.replace(RE3.all_double_quote, "\\\"");
38043
+ result = result.replace(RE3.all_backtick, "\\`");
38044
+ return result;
38045
+ }
38046
+ var RE3 = {
38047
+ all_double_quote: /"/g,
38048
+ all_backtick: /`/g,
38049
+ all_backslash: /\\/g
38050
+ };
38051
+
38049
38052
  // src/core/github.tsx
38050
38053
  async function pr_list() {
38051
38054
  const state = Store.getState();
@@ -38391,7 +38394,6 @@ GitReviseTodo.todo = function todo(args) {
38391
38394
  const metadata = { id, title };
38392
38395
  const unsafe_message_with_id = write(commit2.full_message, metadata);
38393
38396
  let message_with_id = unsafe_message_with_id;
38394
- message_with_id = message_with_id.replace(/[^\\]"/g, "\\\"");
38395
38397
  const sha = commit2.sha.slice(0, 12);
38396
38398
  const entry_lines = [`++ pick ${sha}`, message_with_id];
38397
38399
  const entry = entry_lines.join(`
@@ -38404,7 +38406,6 @@ GitReviseTodo.todo = function todo(args) {
38404
38406
  return todo2;
38405
38407
  };
38406
38408
  GitReviseTodo.execute = async function grt_execute(args) {
38407
- const tmp_git_sequence_editor_path = path7.join(await get_tmp_dir(), "git-sequence-editor.sh");
38408
38409
  const GIT_SEQUENCE_EDITOR_SCRIPT = `#!/bin/sh
38409
38410
 
38410
38411
  # Example
@@ -38424,30 +38425,44 @@ echo "CLI=$0 $*"
38424
38425
  echo "PWD=$(pwd)"
38425
38426
 
38426
38427
  # ensure \\\`GIT_REVISE_TODO\\\` is not empty
38427
- if [ -z "$GIT_REVISE_TODO" ]; then
38428
- echo "\uD83D\uDEA8 GIT_REVISE_TODO environment variable is empty" >&2
38428
+ if [ ! -f "$GIT_REVISE_TODO" ]; then
38429
+ echo "\uD83D\uDEA8 GIT_REVISE_TODO file must exist" >&2
38429
38430
  exit 1
38430
38431
  fi
38431
38432
 
38432
38433
  # first argument into git sequence editor is git-revise-todo file
38433
38434
  git_revise_todo_path="$1"
38434
38435
 
38435
- # debug print git-revise-todo file passed into command
38436
- echo "$git_revise_todo_path"
38436
+ # print content of git-revise-todo file passed into command
38437
+ echo
38438
+ echo "BEFORE git_revise_todo_path=$git_revise_todo_path"
38437
38439
  echo "----- START -----"
38438
38440
  cat "$git_revise_todo_path"
38441
+ echo
38439
38442
  echo "------ END ------"
38443
+ echo
38444
+
38445
+ # copy content of file at \\\`GIT_REVISE_TODO\\\` env variable to \\\`git_revise_todo_path\\\`
38446
+ cp "$GIT_REVISE_TODO" "$git_revise_todo_path"
38440
38447
 
38441
- # write content of \\\`GIT_REVISE_TODO\\\` env variable to \\\`git_revise_todo_path\\\`
38442
- echo "$GIT_REVISE_TODO" > "$git_revise_todo_path"
38448
+ # print content of git-revise-todo file after copy above
38449
+ echo
38450
+ echo "AFTER git_revise_todo_path=$git_revise_todo_path"
38451
+ echo "----- START -----"
38452
+ cat "$git_revise_todo_path"
38453
+ echo
38454
+ echo "------ END ------"
38455
+ echo
38443
38456
  `;
38444
38457
  invariant(GIT_SEQUENCE_EDITOR_SCRIPT, "GIT_SEQUENCE_EDITOR_SCRIPT must exist");
38458
+ const tmp_git_sequence_editor_path = path7.join(await get_tmp_dir(), "git-sequence-editor.sh");
38445
38459
  await fs10.writeFile(tmp_git_sequence_editor_path, GIT_SEQUENCE_EDITOR_SCRIPT);
38446
38460
  await fs10.chmod(tmp_git_sequence_editor_path, "755");
38447
- const git_revise_todo = GitReviseTodo(args);
38461
+ const tmp_path_git_revise_todo = path7.join(await get_tmp_dir(), "git-revise-todo.txt");
38462
+ await fs10.writeFile(tmp_path_git_revise_todo, GitReviseTodo(args));
38448
38463
  const command = [
38449
38464
  `GIT_EDITOR="${tmp_git_sequence_editor_path}"`,
38450
- `GIT_REVISE_TODO="${git_revise_todo}"`,
38465
+ `GIT_REVISE_TODO="${tmp_path_git_revise_todo}"`,
38451
38466
  `git`,
38452
38467
  `revise --edit -i ${args.rebase_merge_base}`
38453
38468
  ];
@@ -40024,7 +40039,8 @@ function SelectCommitRangesInternal(props) {
40024
40039
  let branch_prefix = "";
40025
40040
  if (argv["branch-prefix"]) {
40026
40041
  branch_prefix = argv["branch-prefix"];
40027
- } else if ("") {
40042
+ } else if (process.env.GIT_STACK_BRANCH_PREFIX) {
40043
+ branch_prefix = process.env.GIT_STACK_BRANCH_PREFIX;
40028
40044
  }
40029
40045
  return `${branch_prefix}${gs_short_id()}`;
40030
40046
  }
@@ -45646,7 +45662,7 @@ var yargs_default = Yargs;
45646
45662
 
45647
45663
  // src/command.ts
45648
45664
  async function command2() {
45649
- 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.2.5").showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`").help("help", "Show usage via `git stack help`").argv;
45665
+ 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.2.7").showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`").help("help", "Show usage via `git stack help`").argv;
45650
45666
  }
45651
45667
  var GlobalOptions = {
45652
45668
  verbose: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-stack-cli",
3
- "version": "2.2.5",
3
+ "version": "2.2.7",
4
4
  "description": "",
5
5
  "author": "magus",
6
6
  "license": "MIT",
@@ -24,36 +24,43 @@ const parsed_args = util.parseArgs({
24
24
  const WATCH = parsed_args.values.watch;
25
25
  const VERBOSE = parsed_args.values.verbose;
26
26
 
27
- console.debug("📦 bundle", WATCH ? "watch" : "build");
27
+ function log(...args: any[]) {
28
+ const timestamp = new Date().toISOString();
29
+ console.debug(`[${timestamp}]`, ...args);
30
+ }
31
+
32
+ log("📦 bundle", WATCH ? "watch" : "build");
28
33
 
29
34
  if (VERBOSE) {
30
- console.debug(parsed_args);
35
+ log(parsed_args);
31
36
  }
32
37
 
33
38
  const REPO_ROOT = (await spawn.sync("git rev-parse --show-toplevel")).stdout;
34
39
 
35
- const PACKAGE_JSON = await file.read_json(path.join(REPO_ROOT, "package.json"));
36
- const GIT_SEQUENCE_EDITOR_SCRIPT_PATH = path.join(REPO_ROOT, "scripts", "git-sequence-editor.sh");
37
- const UNSAFE_GIT_SEQUENCE_EDITOR_SCRIPT = await file.read_text(GIT_SEQUENCE_EDITOR_SCRIPT_PATH);
38
- const GIT_SEQUENCE_EDITOR_SCRIPT = UNSAFE_GIT_SEQUENCE_EDITOR_SCRIPT.replace(/`/g, "\\`");
39
-
40
- let GITIGNORE = (await file.read_text(path.join(REPO_ROOT, ".gitignore"))).split("\n");
41
- GITIGNORE = GITIGNORE.filter((line) => line.trim() && !line.startsWith("#"));
42
- GITIGNORE.push(".git");
40
+ async function get_define() {
41
+ const PACKAGE_JSON = await file.read_json(path.join(REPO_ROOT, "package.json"));
42
+ const GIT_SEQUENCE_EDITOR_SCRIPT_PATH = path.join(REPO_ROOT, "scripts", "git-sequence-editor.sh");
43
+ const UNSAFE_GIT_SEQUENCE_EDITOR_SCRIPT = await file.read_text(GIT_SEQUENCE_EDITOR_SCRIPT_PATH);
44
+ const GIT_SEQUENCE_EDITOR_SCRIPT = UNSAFE_GIT_SEQUENCE_EDITOR_SCRIPT.replace(/`/g, "\\`");
43
45
 
44
- const define = {
45
- "process.env.NODE_ENV": JSON.stringify("production"),
46
- "process.env.CLI_VERSION": JSON.stringify(String(PACKAGE_JSON.version)),
47
- "process.env.GIT_SEQUENCE_EDITOR_SCRIPT": JSON.stringify(GIT_SEQUENCE_EDITOR_SCRIPT),
48
- };
46
+ const define = {
47
+ "process.env.NODE_ENV": JSON.stringify("production"),
48
+ "process.env.CLI_VERSION": JSON.stringify(String(PACKAGE_JSON.version)),
49
+ "process.env.GIT_SEQUENCE_EDITOR_SCRIPT": JSON.stringify(GIT_SEQUENCE_EDITOR_SCRIPT),
50
+ };
49
51
 
50
- if (VERBOSE) {
51
- console.debug({ define });
52
+ return define;
52
53
  }
53
54
 
54
55
  async function run_build() {
55
56
  const start = Date.now();
56
57
 
58
+ const define = await get_define();
59
+
60
+ if (VERBOSE) {
61
+ log({ define });
62
+ }
63
+
57
64
  const result = await Bun.build({
58
65
  entrypoints: ["./src/index.tsx"],
59
66
  outdir: "./dist/js",
@@ -65,10 +72,10 @@ async function run_build() {
65
72
 
66
73
  const duration_ms = Date.now() - start;
67
74
 
68
- console.debug(`✅ Build (${duration_ms}ms)`);
75
+ log(`✅ Build (${duration_ms}ms)`);
69
76
 
70
77
  if (VERBOSE) {
71
- console.debug({ result });
78
+ log({ result });
72
79
  }
73
80
  }
74
81
 
@@ -77,11 +84,15 @@ if (!WATCH) {
77
84
  } else {
78
85
  await run_build();
79
86
 
80
- console.debug("👀 Watching for changes…");
87
+ let GITIGNORE = (await file.read_text(path.join(REPO_ROOT, ".gitignore"))).split("\n");
88
+ GITIGNORE = GITIGNORE.filter((line) => line.trim() && !line.startsWith("#"));
89
+ GITIGNORE.push(".git");
81
90
 
82
- const { signal } = new AbortController();
91
+ log("👀 Watching for changes…");
83
92
 
93
+ const { signal } = new AbortController();
84
94
  const watcher = fs.watch(REPO_ROOT, { recursive: true, signal });
95
+
85
96
  for await (const event of watcher) {
86
97
  const filename = event.filename;
87
98
 
@@ -100,10 +111,10 @@ if (!WATCH) {
100
111
  continue;
101
112
  }
102
113
 
103
- console.debug(`⚠️ Change ${filename}`);
114
+ log(`⚠️ Change ${filename}`);
104
115
 
105
116
  if (VERBOSE) {
106
- console.debug({ ignored, filename, event });
117
+ log({ ignored, filename, event });
107
118
  }
108
119
 
109
120
  await run_build();
@@ -17,19 +17,31 @@ echo "CLI=$0 $*"
17
17
  echo "PWD=$(pwd)"
18
18
 
19
19
  # ensure `GIT_REVISE_TODO` is not empty
20
- if [ -z "$GIT_REVISE_TODO" ]; then
21
- echo "🚨 GIT_REVISE_TODO environment variable is empty" >&2
20
+ if [ ! -f "$GIT_REVISE_TODO" ]; then
21
+ echo "🚨 GIT_REVISE_TODO file must exist" >&2
22
22
  exit 1
23
23
  fi
24
24
 
25
25
  # first argument into git sequence editor is git-revise-todo file
26
26
  git_revise_todo_path="$1"
27
27
 
28
- # debug print git-revise-todo file passed into command
29
- echo "$git_revise_todo_path"
28
+ # print content of git-revise-todo file passed into command
29
+ echo
30
+ echo "BEFORE git_revise_todo_path=$git_revise_todo_path"
30
31
  echo "----- START -----"
31
32
  cat "$git_revise_todo_path"
33
+ echo
32
34
  echo "------ END ------"
35
+ echo
33
36
 
34
- # write content of `GIT_REVISE_TODO` env variable to `git_revise_todo_path`
35
- echo "$GIT_REVISE_TODO" > "$git_revise_todo_path"
37
+ # copy content of file at `GIT_REVISE_TODO` env variable to `git_revise_todo_path`
38
+ cp "$GIT_REVISE_TODO" "$git_revise_todo_path"
39
+
40
+ # print content of git-revise-todo file after copy above
41
+ echo
42
+ echo "AFTER git_revise_todo_path=$git_revise_todo_path"
43
+ echo "----- START -----"
44
+ cat "$git_revise_todo_path"
45
+ echo
46
+ echo "------ END ------"
47
+ echo
@@ -19,7 +19,9 @@ process.chdir(REPO_ROOT);
19
19
  // require clean git status besides changes to package.json version
20
20
  const git_status = await spawn.sync("git status --porcelain");
21
21
  if (!/^M\s+package.json/.test(git_status.stdout)) {
22
- console.error("please commit local changes before running release");
22
+ console.error(
23
+ "please commit local changes and only update package.json version before running release",
24
+ );
23
25
  process.exit(4);
24
26
  }
25
27
 
@@ -91,8 +91,6 @@ GitReviseTodo.todo = function todo(args: CommitListArgs) {
91
91
 
92
92
  let message_with_id = unsafe_message_with_id;
93
93
 
94
- message_with_id = message_with_id.replace(/[^\\]"/g, '\\"');
95
-
96
94
  // get first 12 characters of commit sha
97
95
  const sha = commit.sha.slice(0, 12);
98
96
 
@@ -108,27 +106,25 @@ GitReviseTodo.todo = function todo(args: CommitListArgs) {
108
106
  };
109
107
 
110
108
  GitReviseTodo.execute = async function grt_execute(args: ExecuteArgs) {
111
- // generate temporary directory and drop sequence editor script
112
- const tmp_git_sequence_editor_path = path.join(await get_tmp_dir(), "git-sequence-editor.sh");
113
-
114
109
  // replaced at build time with literal contents of `scripts/git-sequence-editor.sh`
115
110
  const GIT_SEQUENCE_EDITOR_SCRIPT = process.env.GIT_SEQUENCE_EDITOR_SCRIPT;
116
-
117
111
  invariant(GIT_SEQUENCE_EDITOR_SCRIPT, "GIT_SEQUENCE_EDITOR_SCRIPT must exist");
118
112
 
119
- // write script to temporary path
113
+ // generate temporary directory and drop sequence editor script
114
+ // write script to temporary path and ensure script is executable
115
+ const tmp_git_sequence_editor_path = path.join(await get_tmp_dir(), "git-sequence-editor.sh");
120
116
  await fs.writeFile(tmp_git_sequence_editor_path, GIT_SEQUENCE_EDITOR_SCRIPT);
121
-
122
- // ensure script is executable
123
117
  await fs.chmod(tmp_git_sequence_editor_path, "755");
124
118
 
125
- const git_revise_todo = GitReviseTodo(args);
119
+ // write git revise todo to a temp path for use by sequence editor script
120
+ const tmp_path_git_revise_todo = path.join(await get_tmp_dir(), "git-revise-todo.txt");
121
+ await fs.writeFile(tmp_path_git_revise_todo, GitReviseTodo(args));
126
122
 
127
123
  // execute cli with temporary git sequence editor script
128
124
  // revise from merge base to pick correct commits
129
125
  const command = [
130
126
  `GIT_EDITOR="${tmp_git_sequence_editor_path}"`,
131
- `GIT_REVISE_TODO="${git_revise_todo}"`,
127
+ `GIT_REVISE_TODO="${tmp_path_git_revise_todo}"`,
132
128
  `git`,
133
129
  `revise --edit -i ${args.rebase_merge_base}`,
134
130
  ];
@@ -1,5 +1,4 @@
1
1
  import { invariant } from "~/core/invariant";
2
- import { safe_quote } from "~/core/safe_quote";
3
2
 
4
3
  type InputMetadataValues = {
5
4
  id: string;
@@ -25,8 +24,6 @@ export function write(message: string, values: InputMetadataValues) {
25
24
 
26
25
  let new_message = line_list.join("\n");
27
26
 
28
- new_message = safe_quote(new_message);
29
-
30
27
  return new_message;
31
28
  }
32
29
 
@@ -1,10 +1,14 @@
1
1
  // escape double-quote for cli
2
2
  export function safe_quote(value: string) {
3
3
  let result = value;
4
+ result = result.replace(RE.all_backslash, "\\\\");
4
5
  result = result.replace(RE.all_double_quote, '\\"');
6
+ result = result.replace(RE.all_backtick, "\\`");
5
7
  return result;
6
8
  }
7
9
 
8
10
  const RE = {
9
11
  all_double_quote: /"/g,
12
+ all_backtick: /`/g,
13
+ all_backslash: /\\/g,
10
14
  };