git-stack-cli 2.2.6 → 2.2.8
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 +5 -1
- package/dist/js/index.js +465 -448
- package/package.json +1 -1
- package/scripts/bun-build.ts +34 -23
- package/scripts/git-sequence-editor.sh +18 -6
- package/scripts/release-brew.ts +2 -0
- package/src/command.ts +1 -0
- package/src/commands/Rebase.tsx +6 -2
- package/src/core/GitReviseTodo.ts +7 -11
- package/src/core/Metadata.ts +0 -3
- package/src/core/safe_quote.ts +4 -0
package/package.json
CHANGED
package/scripts/bun-build.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
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
|
-
|
|
75
|
+
log(`✅ Build (${duration_ms}ms)`);
|
|
69
76
|
|
|
70
77
|
if (VERBOSE) {
|
|
71
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
114
|
+
log(`⚠️ Change ${filename}`);
|
|
104
115
|
|
|
105
116
|
if (VERBOSE) {
|
|
106
|
-
|
|
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 [ -
|
|
21
|
-
echo "🚨 GIT_REVISE_TODO
|
|
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
|
-
#
|
|
29
|
-
echo
|
|
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
|
-
#
|
|
35
|
-
|
|
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
|
package/scripts/release-brew.ts
CHANGED
|
@@ -66,6 +66,8 @@ const re_token = (name: string) => new RegExp(`{{ ${name} }}`, "g");
|
|
|
66
66
|
process.chdir(HOMEBREW_DIR);
|
|
67
67
|
await spawn.sync(`git reset --hard`);
|
|
68
68
|
await spawn.sync(`git checkout master`);
|
|
69
|
+
await spawn.sync("git fetch --prune");
|
|
70
|
+
await spawn.sync("git reset --hard origin/master");
|
|
69
71
|
|
|
70
72
|
// homebrew tap formula (binaries)
|
|
71
73
|
|
package/src/command.ts
CHANGED
|
@@ -9,6 +9,7 @@ export async function command() {
|
|
|
9
9
|
// https://yargs.js.org/docs/#api-reference-optionkey-opt
|
|
10
10
|
return (
|
|
11
11
|
yargs(hideBin(process.argv))
|
|
12
|
+
.scriptName("git stack")
|
|
12
13
|
.usage("Usage: git stack [command] [options]")
|
|
13
14
|
|
|
14
15
|
.command("$0", "Sync commit ranges to Github", (yargs) => yargs.options(DefaultOptions))
|
package/src/commands/Rebase.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import { Await } from "~/app/Await";
|
|
|
8
8
|
import { Brackets } from "~/app/Brackets";
|
|
9
9
|
import { FormatText } from "~/app/FormatText";
|
|
10
10
|
import { Parens } from "~/app/Parens";
|
|
11
|
+
import { Status } from "~/app/Status";
|
|
11
12
|
import { Store } from "~/app/Store";
|
|
12
13
|
import * as CommitMetadata from "~/core/CommitMetadata";
|
|
13
14
|
import { cli } from "~/core/cli";
|
|
@@ -128,7 +129,7 @@ Rebase.run = async function run() {
|
|
|
128
129
|
message="✅ {branch_name} in sync with {origin_branch}"
|
|
129
130
|
values={{
|
|
130
131
|
branch_name: <Brackets>{branch_name}</Brackets>,
|
|
131
|
-
origin_branch: <Brackets>{
|
|
132
|
+
origin_branch: <Brackets>{master_branch}</Brackets>,
|
|
132
133
|
}}
|
|
133
134
|
/>,
|
|
134
135
|
);
|
|
@@ -137,8 +138,11 @@ Rebase.run = async function run() {
|
|
|
137
138
|
|
|
138
139
|
actions.set((state) => {
|
|
139
140
|
state.commit_range = next_commit_range;
|
|
140
|
-
state.step = "status";
|
|
141
141
|
});
|
|
142
|
+
|
|
143
|
+
actions.output(<Status />);
|
|
144
|
+
|
|
145
|
+
actions.exit(0);
|
|
142
146
|
} catch (err) {
|
|
143
147
|
actions.error("Unable to rebase.");
|
|
144
148
|
|
|
@@ -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
|
-
//
|
|
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
|
-
|
|
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="${
|
|
127
|
+
`GIT_REVISE_TODO="${tmp_path_git_revise_todo}"`,
|
|
132
128
|
`git`,
|
|
133
129
|
`revise --edit -i ${args.rebase_merge_base}`,
|
|
134
130
|
];
|
package/src/core/Metadata.ts
CHANGED
|
@@ -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
|
|
package/src/core/safe_quote.ts
CHANGED
|
@@ -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
|
};
|