git-stack-cli 1.13.2 → 1.14.0

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
@@ -83,6 +83,19 @@ To update your local branch with the latest changes in the remote branch (e.g. `
83
83
  git stack rebase
84
84
  ```
85
85
 
86
+ ### Customizing branch name
87
+
88
+ By default `git stack` generates a unique branch name such as `gs-3cmrMBSUj`.
89
+
90
+ You can specify a prefix for the generated branch name by using either the environment variable or the command line option.
91
+ In the example below branches would be generated such as `dev/magus/gs-3cmrMBSUj`.
92
+
93
+ ```bash
94
+ GIT_STACK_BRANCH_PREFIX="dev/magus/" git stack
95
+
96
+ git stack --branch-prefix="dev/magus/"
97
+ ```
98
+
86
99
  ## Why?
87
100
 
88
101
  The goal of `git stack` is to combine the **simplicity of developing in a single branch** in order to **preserve your commit history** while also **grouping commits into pull requests for code review**.
@@ -14912,7 +14912,7 @@ var isSafeInteger = hasNativeIsSafeInteger
14912
14912
  // IE11 does not support y and u.
14913
14913
  var REGEX_SUPPORTS_U_AND_Y = true;
14914
14914
  try {
14915
- var re = RE$5('([^\\p{White_Space}\\p{Pattern_Syntax}]*)', 'yu');
14915
+ var re = RE$6('([^\\p{White_Space}\\p{Pattern_Syntax}]*)', 'yu');
14916
14916
  /**
14917
14917
  * legacy Edge or Xbox One browser
14918
14918
  * Unicode flag support: supported
@@ -15009,14 +15009,14 @@ var trimEnd = hasTrimEnd
15009
15009
  return s.replace(SPACE_SEPARATOR_END_REGEX, '');
15010
15010
  };
15011
15011
  // Prevent minifier to translate new RegExp to literal form that might cause syntax error on IE11.
15012
- function RE$5(s, flag) {
15012
+ function RE$6(s, flag) {
15013
15013
  return new RegExp(s, flag);
15014
15014
  }
15015
15015
  // #endregion
15016
15016
  var matchIdentifierAtIndex;
15017
15017
  if (REGEX_SUPPORTS_U_AND_Y) {
15018
15018
  // Native
15019
- var IDENTIFIER_PREFIX_RE_1 = RE$5('([^\\p{White_Space}\\p{Pattern_Syntax}]*)', 'yu');
15019
+ var IDENTIFIER_PREFIX_RE_1 = RE$6('([^\\p{White_Space}\\p{Pattern_Syntax}]*)', 'yu');
15020
15020
  matchIdentifierAtIndex = function matchIdentifierAtIndex(s, index) {
15021
15021
  var _a;
15022
15022
  IDENTIFIER_PREFIX_RE_1.lastIndex = index;
@@ -26941,15 +26941,15 @@ match_group.safe = (value, re, group) => {
26941
26941
 
26942
26942
  function auth_status(output) {
26943
26943
  let username;
26944
- username = match_group.safe(output, RE$4.logged_in_as, "username");
26944
+ username = match_group.safe(output, RE$5.logged_in_as, "username");
26945
26945
  if (username)
26946
26946
  return username;
26947
- username = match_group.safe(output, RE$4.logged_in_account, "username");
26947
+ username = match_group.safe(output, RE$5.logged_in_account, "username");
26948
26948
  if (username)
26949
26949
  return username;
26950
26950
  return null;
26951
26951
  }
26952
- const RE$4 = {
26952
+ const RE$5 = {
26953
26953
  // Logged in to github.com as magus
26954
26954
  logged_in_as: /Logged in to github.com as (?<username>[^\s]+)/,
26955
26955
  logged_in_account: /Logged in to github.com account (?<username>[^\s]+)/,
@@ -29663,10 +29663,10 @@ var cloneDeep$1 = /*@__PURE__*/getDefaultExportFromCjs(cloneDeep_1);
29663
29663
  // escape double-quote for cli
29664
29664
  function safe_quote(value) {
29665
29665
  let result = value;
29666
- result = result.replace(RE$3.all_double_quote, '\\"');
29666
+ result = result.replace(RE$4.all_double_quote, '\\"');
29667
29667
  return result;
29668
29668
  }
29669
- const RE$3 = {
29669
+ const RE$4 = {
29670
29670
  all_double_quote: /"/g,
29671
29671
  };
29672
29672
 
@@ -29684,12 +29684,12 @@ function write$1(message, values) {
29684
29684
  }
29685
29685
  function read(message) {
29686
29686
  const values = { id: null, title: null };
29687
- const match_id = message.match(RE$2.stack_id);
29687
+ const match_id = message.match(RE$3.stack_id);
29688
29688
  if (match_id?.groups) {
29689
29689
  values.id = match_id.groups["id"];
29690
29690
  invariant(values.id, "id must exist");
29691
29691
  }
29692
- const match_title = message.match(RE$2.group_title);
29692
+ const match_title = message.match(RE$3.group_title);
29693
29693
  if (match_title?.groups) {
29694
29694
  values.title = match_title.groups["title"];
29695
29695
  }
@@ -29698,8 +29698,8 @@ function read(message) {
29698
29698
  function remove(message) {
29699
29699
  let result = message;
29700
29700
  // remove metadata
29701
- result = result.replace(new RegExp(RE$2.stack_id, "gmi"), "");
29702
- result = result.replace(new RegExp(RE$2.group_title, "gmi"), "");
29701
+ result = result.replace(new RegExp(RE$3.stack_id, "gmi"), "");
29702
+ result = result.replace(new RegExp(RE$3.group_title, "gmi"), "");
29703
29703
  result = result.trimEnd();
29704
29704
  return result;
29705
29705
  }
@@ -29711,7 +29711,7 @@ const TEMPLATE$1 = {
29711
29711
  return `git-stack-title: ${title}`;
29712
29712
  },
29713
29713
  };
29714
- const RE$2 = {
29714
+ const RE$3 = {
29715
29715
  // https://regex101.com/r/wLmGVq/1
29716
29716
  stack_id: new RegExp(`${TEMPLATE$1.stack_id("(?<id>[^\\s]+)")}`, "i"),
29717
29717
  group_title: new RegExp(TEMPLATE$1.group_title("(?<title>[^\\n^\\r]+)"), "i"),
@@ -29788,11 +29788,17 @@ async function pr_create(args) {
29788
29788
  // pull request create failed: GraphQL: Head sha can't be blank, Base sha can't be blank, No commits between gs-6LAx-On45 and origin/gs-ED2etrzv2, Head ref must be a branch (createPullRequest)
29789
29789
  //
29790
29790
  // https://github.com/cli/cli/issues/5465
29791
- let command = `gh pr create --head refs/heads/${args.branch} --base ${args.base} --title="${title}" --body="${args.body}"`;
29791
+ let command_parts = [
29792
+ "gh pr create",
29793
+ `--head refs/heads/${args.branch}`,
29794
+ `--base ${args.base}`,
29795
+ `--title="${title}"`,
29796
+ `--body="${args.body}"`,
29797
+ ];
29792
29798
  if (args.draft) {
29793
- command += " --draft";
29799
+ command_parts.push("--draft");
29794
29800
  }
29795
- const cli_result = await cli(command);
29801
+ const cli_result = await cli(command_parts);
29796
29802
  if (cli_result.code !== 0) {
29797
29803
  handle_error(cli_result.output);
29798
29804
  return null;
@@ -29805,8 +29811,7 @@ async function pr_edit(args) {
29805
29811
  const body_file = await write_body_file(args);
29806
29812
  command_parts.push(`--body-file="${body_file}"`);
29807
29813
  }
29808
- const command = command_parts.join(" ");
29809
- const cli_result = await cli(command);
29814
+ const cli_result = await cli(command_parts);
29810
29815
  if (cli_result.code !== 0) {
29811
29816
  handle_error(cli_result.output);
29812
29817
  }
@@ -29873,11 +29878,19 @@ function handle_error(output) {
29873
29878
  async function write_body_file(args) {
29874
29879
  invariant(args.body, "args.body must exist");
29875
29880
  const temp_dir = os.tmpdir();
29876
- const temp_path = path.join(temp_dir, `git-stack-body-${args.base}`);
29881
+ // ensure unique filename is safe for filesystem
29882
+ // base (group id) might contain slashes, e.g. dev/magus/gs-3cmrMBSUj
29883
+ // the flashes would mess up the filesystem path to this file
29884
+ let temp_filename = `git-stack-body-${args.base}`;
29885
+ temp_filename = temp_filename.replace(RE$2.non_alphanumeric_dash, "-");
29886
+ const temp_path = path.join(temp_dir, temp_filename);
29877
29887
  await safe_rm(temp_path);
29878
29888
  await fs$1.writeFile(temp_path, args.body);
29879
29889
  return temp_path;
29880
29890
  }
29891
+ const RE$2 = {
29892
+ non_alphanumeric_dash: /[^a-zA-Z0-9_-]+/g,
29893
+ };
29881
29894
 
29882
29895
  async function range(commit_group_map) {
29883
29896
  const master_branch = Store.getState().master_branch;
@@ -31534,8 +31547,20 @@ function SelectCommitRangesInternal(props) {
31534
31547
  reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { color: colors.gray }), message: "Press {enter} to toggle commit selection", values: {
31535
31548
  enter: (reactExports.createElement(Text, { bold: true, color: colors.green }, SYMBOL.enter)),
31536
31549
  } }))));
31550
+ function get_group_id() {
31551
+ let branch_prefix = "";
31552
+ // branch prefix via cli flag or env var
31553
+ // cli flag takes precedence since it is more explicit
31554
+ if (argv["branch-prefix"]) {
31555
+ branch_prefix = argv["branch-prefix"];
31556
+ }
31557
+ else if (process.env.GIT_STACK_BRANCH_PREFIX) {
31558
+ branch_prefix = process.env.GIT_STACK_BRANCH_PREFIX;
31559
+ }
31560
+ return `${branch_prefix}${gs_short_id()}`;
31561
+ }
31537
31562
  function submit_group_input(title) {
31538
- const id = gs_short_id();
31563
+ const id = get_group_id();
31539
31564
  actions.output(reactExports.createElement(FormatText, { wrapper: reactExports.createElement(Text, { dimColor: true }), message: "Created new group {group} {note}", values: {
31540
31565
  group: reactExports.createElement(Brackets, null, title),
31541
31566
  note: reactExports.createElement(Parens, null, id),
@@ -37595,7 +37620,7 @@ async function command() {
37595
37620
  .wrap(123)
37596
37621
  // disallow unknown options
37597
37622
  .strict()
37598
- .version("1.13.2" )
37623
+ .version("1.14.0" )
37599
37624
  .showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`")
37600
37625
  .help("help", "Show usage via `git stack help`")
37601
37626
  .argv;
@@ -37649,17 +37674,22 @@ const DefaultOptions = {
37649
37674
  default: false,
37650
37675
  description: "Open all PRs as drafts",
37651
37676
  },
37652
- "write-state-json": {
37653
- hidden: true,
37654
- type: "boolean",
37655
- default: false,
37656
- description: "Write state to local json file for debugging",
37677
+ "branch-prefix": {
37678
+ type: "string",
37679
+ default: "",
37680
+ description: "Prefix for generated branch names, e.g. dev/magus/",
37657
37681
  },
37658
37682
  "template": {
37659
37683
  type: "boolean",
37660
37684
  default: true,
37661
37685
  description: "Use automatic Github PR template, e.g. .github/pull_request_template.md, disable with --no-template",
37662
37686
  },
37687
+ "write-state-json": {
37688
+ hidden: true,
37689
+ type: "boolean",
37690
+ default: false,
37691
+ description: "Write state to local json file for debugging",
37692
+ },
37663
37693
  "mock-metadata": {
37664
37694
  hidden: true,
37665
37695
  type: "boolean",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-stack-cli",
3
- "version": "1.13.2",
3
+ "version": "1.14.0",
4
4
  "description": "",
5
5
  "author": "magus",
6
6
  "license": "MIT",
@@ -387,8 +387,21 @@ function SelectCommitRangesInternal(props: Props) {
387
387
  </Ink.Box>
388
388
  );
389
389
 
390
+ function get_group_id() {
391
+ let branch_prefix = "";
392
+
393
+ // branch prefix via cli flag or env var
394
+ // cli flag takes precedence since it is more explicit
395
+ if (argv["branch-prefix"]) {
396
+ branch_prefix = argv["branch-prefix"];
397
+ } else if (process.env.GIT_STACK_BRANCH_PREFIX) {
398
+ branch_prefix = process.env.GIT_STACK_BRANCH_PREFIX;
399
+ }
400
+
401
+ return `${branch_prefix}${gs_short_id()}`;
402
+ }
390
403
  function submit_group_input(title: string) {
391
- const id = gs_short_id();
404
+ const id = get_group_id();
392
405
 
393
406
  actions.output(
394
407
  <FormatText
package/src/command.ts CHANGED
@@ -111,11 +111,10 @@ const DefaultOptions = {
111
111
  description: "Open all PRs as drafts",
112
112
  },
113
113
 
114
- "write-state-json": {
115
- hidden: true,
116
- type: "boolean",
117
- default: false,
118
- description: "Write state to local json file for debugging",
114
+ "branch-prefix": {
115
+ type: "string",
116
+ default: "",
117
+ description: "Prefix for generated branch names, e.g. dev/magus/",
119
118
  },
120
119
 
121
120
  "template": {
@@ -125,6 +124,13 @@ const DefaultOptions = {
125
124
  "Use automatic Github PR template, e.g. .github/pull_request_template.md, disable with --no-template",
126
125
  },
127
126
 
127
+ "write-state-json": {
128
+ hidden: true,
129
+ type: "boolean",
130
+ default: false,
131
+ description: "Write state to local json file for debugging",
132
+ },
133
+
128
134
  "mock-metadata": {
129
135
  hidden: true,
130
136
  type: "boolean",
@@ -130,13 +130,19 @@ export async function pr_create(args: CreatePullRequestArgs) {
130
130
  // pull request create failed: GraphQL: Head sha can't be blank, Base sha can't be blank, No commits between gs-6LAx-On45 and origin/gs-ED2etrzv2, Head ref must be a branch (createPullRequest)
131
131
  //
132
132
  // https://github.com/cli/cli/issues/5465
133
- let command = `gh pr create --head refs/heads/${args.branch} --base ${args.base} --title="${title}" --body="${args.body}"`;
133
+ let command_parts = [
134
+ "gh pr create",
135
+ `--head refs/heads/${args.branch}`,
136
+ `--base ${args.base}`,
137
+ `--title="${title}"`,
138
+ `--body="${args.body}"`,
139
+ ];
134
140
 
135
141
  if (args.draft) {
136
- command += " --draft";
142
+ command_parts.push("--draft");
137
143
  }
138
144
 
139
- const cli_result = await cli(command);
145
+ const cli_result = await cli(command_parts);
140
146
 
141
147
  if (cli_result.code !== 0) {
142
148
  handle_error(cli_result.output);
@@ -160,9 +166,7 @@ export async function pr_edit(args: EditPullRequestArgs) {
160
166
  command_parts.push(`--body-file="${body_file}"`);
161
167
  }
162
168
 
163
- const command = command_parts.join(" ");
164
-
165
- const cli_result = await cli(command);
169
+ const cli_result = await cli(command_parts);
166
170
 
167
171
  if (cli_result.code !== 0) {
168
172
  handle_error(cli_result.output);
@@ -254,7 +258,14 @@ async function write_body_file(args: EditPullRequestArgs) {
254
258
  invariant(args.body, "args.body must exist");
255
259
 
256
260
  const temp_dir = os.tmpdir();
257
- const temp_path = path.join(temp_dir, `git-stack-body-${args.base}`);
261
+
262
+ // ensure unique filename is safe for filesystem
263
+ // base (group id) might contain slashes, e.g. dev/magus/gs-3cmrMBSUj
264
+ // the flashes would mess up the filesystem path to this file
265
+ let temp_filename = `git-stack-body-${args.base}`;
266
+ temp_filename = temp_filename.replace(RE.non_alphanumeric_dash, "-");
267
+
268
+ const temp_path = path.join(temp_dir, temp_filename);
258
269
 
259
270
  await safe_rm(temp_path);
260
271
 
@@ -291,3 +302,7 @@ export type PullRequest = {
291
302
  url: string;
292
303
  isDraft: boolean;
293
304
  };
305
+
306
+ const RE = {
307
+ non_alphanumeric_dash: /[^a-zA-Z0-9_-]+/g,
308
+ };
@@ -5,5 +5,6 @@ declare namespace NodeJS {
5
5
  CLI_VERSION?: string;
6
6
  GIT_STACK_STANDALONE?: "true" | "false";
7
7
  GIT_SEQUENCE_EDITOR_SCRIPT?: string;
8
+ GIT_STACK_BRANCH_PREFIX?: string;
8
9
  }
9
10
  }