git-stack-cli 1.0.4 → 1.0.6

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
@@ -44,7 +44,7 @@ Often pushing all your commits to a single pull request is the simplest and fast
44
44
  This comes at a price, your teammates have to review larger, less related pieces of code and you will lose some of your atomic commit history if you "Squash and merge".
45
45
 
46
46
  When you decide to break changes up into multiple diffs that depend on one another this process is commonly referred to as **[stacked diffs](https://graphite.dev/guides/stacked-diffs)** (pull requests that depend on other pull requests).
47
- This appraoch is popular at many major comparnies such as Twitter, Facebook, etc.
47
+ This approach is popular at many major companies such as Twitter, Facebook, etc.
48
48
  Managing stacked diffs manually involves managing multiple local branches, jumping between them, rebasing, etc.
49
49
  This process gets even more complicated when you start getting feedback in code review and have to update individual branches.
50
50
  Managing even a few stacked diffs requires a relatively strong knowledge of `git`, even with tricks like [`--update-refs`](https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---update-refs).
@@ -26846,6 +26846,30 @@ function match_group(value, re, group) {
26846
26846
  invariant(result, `match.groups must contain [${group}] ${debug}`);
26847
26847
  return result;
26848
26848
  }
26849
+ match_group.safe = (value, re, group) => {
26850
+ try {
26851
+ return match_group(value, re, group);
26852
+ }
26853
+ catch (err) {
26854
+ return null;
26855
+ }
26856
+ };
26857
+
26858
+ function auth_status(output) {
26859
+ let username;
26860
+ username = match_group.safe(output, RE$4.logged_in_as, "username");
26861
+ if (username)
26862
+ return username;
26863
+ username = match_group.safe(output, RE$4.logged_in_account, "username");
26864
+ if (username)
26865
+ return username;
26866
+ return null;
26867
+ }
26868
+ const RE$4 = {
26869
+ // Logged in to github.com as magus
26870
+ logged_in_as: /Logged in to github.com as (?<username>[^\s]+)/,
26871
+ logged_in_account: /Logged in to github.com account (?<username>[^\s]+)/,
26872
+ };
26849
26873
 
26850
26874
  function DependencyCheck(props) {
26851
26875
  const actions = Store.useActions();
@@ -26903,15 +26927,19 @@ function DependencyCheck(props) {
26903
26927
  "Checking ",
26904
26928
  reactExports.createElement(Command, null, "gh auth status"),
26905
26929
  "...")), function: async () => {
26906
- const auth_status = await cli(`gh auth status`, {
26907
- ignoreExitCode: true,
26908
- });
26909
- if (auth_status.code === 0) {
26910
- const username = match_group(auth_status.stdout, RE$4.auth_username, "username");
26911
- actions.set((state) => {
26912
- state.username = username;
26913
- });
26914
- return;
26930
+ const options = { ignoreExitCode: true };
26931
+ const auth_status$1 = await cli(`gh auth status`, options);
26932
+ if (auth_status$1.code === 0) {
26933
+ const username = auth_status(auth_status$1.stdout);
26934
+ if (username) {
26935
+ actions.set((state) => {
26936
+ state.username = username;
26937
+ });
26938
+ return;
26939
+ }
26940
+ }
26941
+ if (actions.isDebug()) {
26942
+ actions.error("gh auth status could not find username");
26915
26943
  }
26916
26944
  actions.output(reactExports.createElement(Text, { color: colors.yellow },
26917
26945
  reactExports.createElement(Command, null, "gh"),
@@ -26920,10 +26948,6 @@ function DependencyCheck(props) {
26920
26948
  actions.exit(4);
26921
26949
  } }, props.children)))));
26922
26950
  }
26923
- const RE$4 = {
26924
- // Logged in to github.com as magus
26925
- auth_username: /Logged in to github.com as (?<username>[^\s]+)/,
26926
- };
26927
26951
 
26928
26952
  function GatherMetadata(props) {
26929
26953
  const argv = Store.useState((state) => state.argv);
@@ -34080,7 +34104,7 @@ async function command() {
34080
34104
  .wrap(null)
34081
34105
  // disallow unknown options
34082
34106
  .strict()
34083
- .version("1.0.4" )
34107
+ .version("1.0.6" )
34084
34108
  .showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`")
34085
34109
  .help("help", "Show usage via `git stack help`").argv);
34086
34110
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-stack-cli",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "",
5
5
  "author": "magus",
6
6
  "license": "MIT",
@@ -27,6 +27,7 @@
27
27
  "release:npm": "bun run scripts/release-npm.ts",
28
28
  "release:github": "bun run scripts/release-github.ts",
29
29
  "release:brew": "bun run scripts/release-brew.ts",
30
+ "release": "npm run release:npm && npm run release:github && npm run release:brew",
30
31
  "lint:check": "eslint . --cache",
31
32
  "lint": "npm run lint:check -- --fix",
32
33
  "prettier:check": "prettier ./src --check --cache",
@@ -32,5 +32,9 @@ export async function exists(filepath: string) {
32
32
  }
33
33
 
34
34
  export async function rm(filepath: string) {
35
- await fs.rm(filepath);
35
+ return fs.rm(filepath);
36
+ }
37
+
38
+ export async function mv(source: string, destination: string) {
39
+ return fs.rename(source, destination);
36
40
  }
@@ -17,6 +17,47 @@ const package_json = await file.read_json(
17
17
 
18
18
  const version = package_json.version;
19
19
 
20
+ process.chdir(HOMEBREW_DIR);
21
+
22
+ // before creating new formula, mv the previous into a versioned formula name
23
+ const previous_formula_path = path.join(
24
+ HOMEBREW_DIR,
25
+ "Formula",
26
+ "git-stack.rb"
27
+ );
28
+
29
+ // match either version format from core or tap formula
30
+ //
31
+ // version "1.0.4"
32
+ // version = "1.0.4"
33
+ //
34
+ let previous_formula = await file.read_text(previous_formula_path);
35
+ const re_version = /version(?: =)? "(?<version>\d+\.\d+\.\d+)"/m;
36
+ const previous_version_match = previous_formula.match(re_version);
37
+
38
+ if (!previous_version_match?.groups) {
39
+ console.error("previous version missing in formula", previous_formula_path);
40
+ process.exit(3);
41
+ }
42
+
43
+ const previous_version = previous_version_match.groups.version;
44
+ // convert `1.0.4` to `104`
45
+ const not_dot_version = previous_version.replace(/\./g, "");
46
+ const previous_class = `GitStackAt${not_dot_version}`;
47
+ previous_formula = previous_formula.replace(
48
+ "class GitStack",
49
+ `class ${previous_class}`
50
+ );
51
+
52
+ await file.write_text(
53
+ path.join(HOMEBREW_DIR, "Formula", `git-stack@${previous_version}.rb`),
54
+ previous_formula
55
+ );
56
+
57
+ process.chdir(PROJECT_DIR);
58
+
59
+ await spawn(`npm run build:standalone`);
60
+
20
61
  process.chdir(STANDALONE_DIR);
21
62
 
22
63
  const linux_asset = await create_asset("git-stack-cli-linux", { version });
@@ -29,41 +70,51 @@ const re_token = (name: string) => new RegExp(`{{ ${name} }}`, "g");
29
70
 
30
71
  process.chdir(HOMEBREW_DIR);
31
72
 
32
- let formula = await file.read_text("git-stack.rb.template");
33
-
34
- formula = formula.replace(re_token("version"), version);
35
- formula = formula.replace(re_token("mac_bin"), macos_asset.filepath);
36
- formula = formula.replace(re_token("mac_sha256"), macos_asset.sha256);
37
- formula = formula.replace(re_token("linux_bin"), linux_asset.filepath);
38
- formula = formula.replace(re_token("linux_sha256"), linux_asset.sha256);
39
-
40
- await file.write_text("git-stack.rb", formula);
41
-
42
- await spawn.sync(`git commit -a -m ${version}`);
43
- await spawn.sync(`git push`);
73
+ let tap = await file.read_text(
74
+ path.join("templates", "git-stack.tap.rb.template")
75
+ );
44
76
 
45
- process.chdir(PROJECT_DIR);
77
+ tap = tap.replace(re_token("version"), version);
78
+ tap = tap.replace(re_token("mac_bin"), macos_asset.filepath);
79
+ tap = tap.replace(re_token("mac_sha256"), macos_asset.sha256);
80
+ tap = tap.replace(re_token("linux_bin"), linux_asset.filepath);
81
+ tap = tap.replace(re_token("linux_sha256"), linux_asset.sha256);
46
82
 
47
- await spawn(`npm i`);
83
+ await file.write_text(path.join("Formula", "git-stack.rb"), tap);
48
84
 
49
- await spawn.sync(`git commit -a -m ${version}`);
50
- await spawn.sync(`git push`);
85
+ let core = await file.read_text(
86
+ path.join("templates", "git-stack.core.rb.template")
87
+ );
51
88
 
52
- // -a: create tag on last commit
53
- // -m: message
54
- await spawn.sync(`git tag -a ${version} -m ${version}`);
55
- await spawn.sync(`git push origin ${version}`);
89
+ core = core.replace(re_token("version"), version);
90
+ core = core.replace(re_token("mac_bin"), macos_asset.filepath);
91
+ core = core.replace(re_token("mac_sha256"), macos_asset.sha256);
92
+ core = core.replace(re_token("linux_bin"), linux_asset.filepath);
93
+ core = core.replace(re_token("linux_sha256"), linux_asset.sha256);
56
94
 
57
- await spawn.sync(`gh release create ${version} -t ${version} --generate-notes`);
95
+ await file.write_text(path.join("Formula", "git-stack.core.rb"), core);
58
96
 
97
+ // finally upload the assets to the github release
59
98
  process.chdir(STANDALONE_DIR);
60
-
61
99
  await spawn.sync(`gh release upload ${version} ${linux_asset.filepath}`);
62
100
  await spawn.sync(`gh release upload ${version} ${macos_asset.filepath}`);
63
101
  await spawn.sync(`gh release upload ${version} ${win_asset.filepath}`);
64
102
 
103
+ // commit homebrew repo changes
104
+ process.chdir(HOMEBREW_DIR);
105
+ await spawn.sync(`git add .`);
106
+ await spawn.sync(`git commit -m ${version}`);
107
+ await spawn.sync(`git push`);
108
+
109
+ // commmit changes to main repo
110
+ process.chdir(PROJECT_DIR);
111
+ await spawn.sync(`git commit -a -m "homebrew-git-stack ${version}"`);
112
+ await spawn.sync(`git push`);
113
+
65
114
  console.debug();
66
115
  console.debug("✅", "published", version);
67
116
  console.debug();
68
117
  console.debug("https://github.com/magus/homebrew-git-stack");
69
118
  console.debug();
119
+ console.debug("https://github.com/magus/git-stack-cli/releases");
120
+ console.debug();
@@ -10,8 +10,8 @@ import { Url } from "~/app/Url";
10
10
  import { cli } from "~/core/cli";
11
11
  import { colors } from "~/core/colors";
12
12
  import { is_command_available } from "~/core/is_command_available";
13
- import { match_group } from "~/core/match_group";
14
13
  import { semver_compare } from "~/core/semver_compare";
14
+ import * as gh from "~/github/gh";
15
15
 
16
16
  type Props = {
17
17
  children: React.ReactNode;
@@ -112,22 +112,23 @@ export function DependencyCheck(props: Props) {
112
112
  </Ink.Text>
113
113
  }
114
114
  function={async () => {
115
- const auth_status = await cli(`gh auth status`, {
116
- ignoreExitCode: true,
117
- });
115
+ const options = { ignoreExitCode: true };
116
+ const auth_status = await cli(`gh auth status`, options);
118
117
 
119
118
  if (auth_status.code === 0) {
120
- const username = match_group(
121
- auth_status.stdout,
122
- RE.auth_username,
123
- "username"
124
- );
119
+ const username = gh.auth_status(auth_status.stdout);
125
120
 
126
- actions.set((state) => {
127
- state.username = username;
128
- });
121
+ if (username) {
122
+ actions.set((state) => {
123
+ state.username = username;
124
+ });
129
125
 
130
- return;
126
+ return;
127
+ }
128
+ }
129
+
130
+ if (actions.isDebug()) {
131
+ actions.error("gh auth status could not find username");
131
132
  }
132
133
 
133
134
  actions.output(
@@ -148,8 +149,3 @@ export function DependencyCheck(props: Props) {
148
149
  </Await>
149
150
  );
150
151
  }
151
-
152
- const RE = {
153
- // Logged in to github.com as magus
154
- auth_username: /Logged in to github.com as (?<username>[^\s]+)/,
155
- };
@@ -8,3 +8,11 @@ export function match_group(value: string, re: RegExp, group: string) {
8
8
  invariant(result, `match.groups must contain [${group}] ${debug}`);
9
9
  return result;
10
10
  }
11
+
12
+ match_group.safe = (value: string, re: RegExp, group: string) => {
13
+ try {
14
+ return match_group(value, re, group);
15
+ } catch (err) {
16
+ return null;
17
+ }
18
+ };
@@ -0,0 +1,24 @@
1
+ import { test, expect } from "bun:test";
2
+
3
+ import * as gh from "./gh";
4
+
5
+ test("logged in as", () => {
6
+ const username = gh.auth_status(
7
+ " ✓ Logged in to github.com as magus (keyring)\n"
8
+ );
9
+
10
+ expect(username).toBe("magus");
11
+ });
12
+
13
+ test("logged in without as", () => {
14
+ const username = gh.auth_status(
15
+ "✓ Logged in to github.com account xoxohorses (keyring)"
16
+ );
17
+
18
+ expect(username).toBe("xoxohorses");
19
+ });
20
+
21
+ test("returns null when no match is found", () => {
22
+ const username = gh.auth_status("this should not match anything");
23
+ expect(username).toBe(null);
24
+ });
@@ -0,0 +1,19 @@
1
+ import { match_group } from "~/core/match_group";
2
+
3
+ export function auth_status(output: string) {
4
+ let username;
5
+
6
+ username = match_group.safe(output, RE.logged_in_as, "username");
7
+ if (username) return username;
8
+
9
+ username = match_group.safe(output, RE.logged_in_account, "username");
10
+ if (username) return username;
11
+
12
+ return null;
13
+ }
14
+
15
+ const RE = {
16
+ // Logged in to github.com as magus
17
+ logged_in_as: /Logged in to github.com as (?<username>[^\s]+)/,
18
+ logged_in_account: /Logged in to github.com account (?<username>[^\s]+)/,
19
+ };