git-stack-cli 0.7.5 → 0.7.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/dist/app/DependencyCheck.js +4 -0
- package/dist/app/LocalMergeRebase.js +17 -3
- package/dist/app/ManualRebase.js +11 -7
- package/dist/app/Output.js +13 -3
- package/dist/app/Store.js +43 -11
- package/dist/core/cli.js +24 -13
- package/package.json +1 -1
|
@@ -16,6 +16,10 @@ export function DependencyCheck(props) {
|
|
|
16
16
|
"Checking ",
|
|
17
17
|
React.createElement(Command, null, "git"),
|
|
18
18
|
" install..."), function: async () => {
|
|
19
|
+
// await Promise.all([
|
|
20
|
+
// cli(`for i in $(seq 1 5); do echo $i; sleep 1; done`),
|
|
21
|
+
// cli(`for i in $(seq 5 1); do printf "$i "; sleep 1; done; echo`),
|
|
22
|
+
// ]);
|
|
19
23
|
if (is_command_available("git")) {
|
|
20
24
|
return;
|
|
21
25
|
}
|
|
@@ -53,11 +53,22 @@ async function run() {
|
|
|
53
53
|
commit_message: React.createElement(Brackets, null, commit.message),
|
|
54
54
|
} }));
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
await cli(`git format-patch -1 ${commit.sha} --stdout > ${PATCH_FILE}`);
|
|
57
|
+
await cli(`git apply ${PATCH_FILE}`);
|
|
58
|
+
await cli(`rm ${PATCH_FILE}`);
|
|
59
|
+
await cli(`git add --all`);
|
|
60
|
+
let new_message;
|
|
61
|
+
if (commit.branch_id) {
|
|
62
|
+
new_message = await Metadata.write(commit.message, commit.branch_id);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
new_message = commit.message;
|
|
66
|
+
}
|
|
67
|
+
const git_commit_comand = [`git commit -m "${new_message}"`];
|
|
57
68
|
if (argv.verify === false) {
|
|
58
|
-
|
|
69
|
+
git_commit_comand.push("--no-verify");
|
|
59
70
|
}
|
|
60
|
-
await cli(
|
|
71
|
+
await cli(git_commit_comand);
|
|
61
72
|
if (commit.branch_id && !commit_pr) {
|
|
62
73
|
if (actions.isDebug()) {
|
|
63
74
|
actions.output(React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: colors.yellow, wrap: "truncate-end" }), message: "Cleaning up unused group {group}", values: {
|
|
@@ -95,6 +106,8 @@ async function run() {
|
|
|
95
106
|
// trying to use `await cli(...)` here will silently fail since
|
|
96
107
|
// all children processes receive the SIGINT signal
|
|
97
108
|
const spawn_options = { ignoreExitCode: true };
|
|
109
|
+
// always clean up any patch files
|
|
110
|
+
cli.sync(`rm ${PATCH_FILE}`, spawn_options);
|
|
98
111
|
// always put self back in original branch
|
|
99
112
|
cli.sync(`git checkout ${branch_name}`, spawn_options);
|
|
100
113
|
// ...and cleanup temporary branch
|
|
@@ -119,3 +132,4 @@ async function run() {
|
|
|
119
132
|
actions.exit(6);
|
|
120
133
|
}
|
|
121
134
|
}
|
|
135
|
+
const PATCH_FILE = "mypatch.patch";
|
package/dist/app/ManualRebase.js
CHANGED
|
@@ -57,15 +57,16 @@ async function run(props) {
|
|
|
57
57
|
const selected_url = get_group_url(group);
|
|
58
58
|
// cherry-pick and amend commits one by one
|
|
59
59
|
for (const commit of group.commits) {
|
|
60
|
-
|
|
60
|
+
await cli(`git format-patch -1 ${commit.sha} --stdout > ${PATCH_FILE}`);
|
|
61
|
+
await cli(`git apply ${PATCH_FILE}`);
|
|
62
|
+
await cli(`rm ${PATCH_FILE}`);
|
|
63
|
+
await cli(`git add --all`);
|
|
64
|
+
const new_message = await Metadata.write(commit.message, group.id);
|
|
65
|
+
const git_commit_comand = [`git commit -m "${new_message}"`];
|
|
61
66
|
if (argv.verify === false) {
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
await cli(git_cherry_pick_command);
|
|
65
|
-
if (commit.branch_id !== group.id) {
|
|
66
|
-
const new_message = await Metadata.write(commit.message, group.id);
|
|
67
|
-
await cli(`git commit --amend -m "${new_message}"`);
|
|
67
|
+
git_commit_comand.push("--no-verify");
|
|
68
68
|
}
|
|
69
|
+
await cli(git_commit_comand);
|
|
69
70
|
}
|
|
70
71
|
actions.output(React.createElement(FormatText, { wrapper: React.createElement(Ink.Text, { color: colors.yellow, wrap: "truncate-end" }), message: "Syncing {group}\u2026", values: {
|
|
71
72
|
group: (React.createElement(Brackets, null, group.pr?.title || group.title || group.id)),
|
|
@@ -164,6 +165,8 @@ async function run(props) {
|
|
|
164
165
|
// trying to use `await cli(...)` here will silently fail since
|
|
165
166
|
// all children processes receive the SIGINT signal
|
|
166
167
|
const spawn_options = { ignoreExitCode: true };
|
|
168
|
+
// always clean up any patch files
|
|
169
|
+
cli.sync(`rm ${PATCH_FILE}`, spawn_options);
|
|
167
170
|
// always put self back in original branch
|
|
168
171
|
cli.sync(`git checkout ${branch_name}`, spawn_options);
|
|
169
172
|
// ...and cleanup temporary branch
|
|
@@ -189,3 +192,4 @@ async function run(props) {
|
|
|
189
192
|
}
|
|
190
193
|
}
|
|
191
194
|
const get_group_url = (group) => group.pr?.url || group.id;
|
|
195
|
+
const PATCH_FILE = "mypatch.patch";
|
package/dist/app/Output.js
CHANGED
|
@@ -3,7 +3,17 @@ import * as Ink from "ink";
|
|
|
3
3
|
import { Store } from "./Store.js";
|
|
4
4
|
export function Output() {
|
|
5
5
|
const output = Store.useState((state) => state.output);
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
const pending_output = Store.useState((state) => state.pending_output);
|
|
7
|
+
const pending_output_items = Object.values(pending_output);
|
|
8
|
+
return (React.createElement(React.Fragment, null,
|
|
9
|
+
React.createElement(Ink.Static, { items: output }, (node, i) => {
|
|
10
|
+
return React.createElement(Ink.Box, { key: i }, node);
|
|
11
|
+
}),
|
|
12
|
+
pending_output_items.map((node_list, i) => {
|
|
13
|
+
return (React.createElement(Ink.Box, { key: i },
|
|
14
|
+
React.createElement(Ink.Text, null, node_list.map((text, j) => {
|
|
15
|
+
return (React.createElement(React.Fragment, { key: j },
|
|
16
|
+
React.createElement(Ink.Text, null, text)));
|
|
17
|
+
}))));
|
|
18
|
+
})));
|
|
9
19
|
}
|
package/dist/app/Store.js
CHANGED
|
@@ -18,11 +18,13 @@ const BaseStore = createStore()(immer((set, get) => ({
|
|
|
18
18
|
commit_map: null,
|
|
19
19
|
step: "loading",
|
|
20
20
|
output: [],
|
|
21
|
+
pending_output: {},
|
|
21
22
|
pr: {},
|
|
22
23
|
actions: {
|
|
23
24
|
exit(code, clear = true) {
|
|
24
25
|
set((state) => {
|
|
25
|
-
|
|
26
|
+
const node = React.createElement(Exit, { clear: clear, code: code });
|
|
27
|
+
state.mutate.output(state, { node });
|
|
26
28
|
});
|
|
27
29
|
},
|
|
28
30
|
clear() {
|
|
@@ -33,28 +35,37 @@ const BaseStore = createStore()(immer((set, get) => ({
|
|
|
33
35
|
},
|
|
34
36
|
newline() {
|
|
35
37
|
set((state) => {
|
|
36
|
-
|
|
38
|
+
const node = "";
|
|
39
|
+
state.mutate.output(state, { node });
|
|
37
40
|
});
|
|
38
41
|
},
|
|
39
42
|
json(value) {
|
|
40
43
|
set((state) => {
|
|
41
|
-
|
|
44
|
+
const node = JSON.stringify(value, null, 2);
|
|
45
|
+
state.mutate.output(state, { node });
|
|
42
46
|
});
|
|
43
47
|
},
|
|
44
48
|
error(message) {
|
|
45
49
|
set((state) => {
|
|
46
|
-
|
|
50
|
+
const node = React.createElement(Ink.Text, { color: colors.red }, message);
|
|
51
|
+
state.mutate.output(state, { node });
|
|
47
52
|
});
|
|
48
53
|
},
|
|
49
54
|
output(node) {
|
|
50
55
|
set((state) => {
|
|
51
|
-
state.mutate.output(state, node);
|
|
56
|
+
state.mutate.output(state, { node });
|
|
52
57
|
});
|
|
53
58
|
},
|
|
54
|
-
debug(node) {
|
|
59
|
+
debug(node, id) {
|
|
55
60
|
if (get().actions.isDebug()) {
|
|
61
|
+
const debug = true;
|
|
56
62
|
set((state) => {
|
|
57
|
-
|
|
63
|
+
if (id) {
|
|
64
|
+
state.mutate.pending_output(state, { id, node, debug });
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
state.mutate.output(state, { node, debug });
|
|
68
|
+
}
|
|
58
69
|
});
|
|
59
70
|
}
|
|
60
71
|
},
|
|
@@ -74,15 +85,36 @@ const BaseStore = createStore()(immer((set, get) => ({
|
|
|
74
85
|
},
|
|
75
86
|
},
|
|
76
87
|
mutate: {
|
|
77
|
-
output(state,
|
|
78
|
-
switch (typeof node) {
|
|
88
|
+
output(state, args) {
|
|
89
|
+
switch (typeof args.node) {
|
|
79
90
|
case "boolean":
|
|
80
91
|
case "number":
|
|
81
92
|
case "string":
|
|
82
|
-
state.output.push(React.createElement(Ink.Text,
|
|
93
|
+
state.output.push(React.createElement(Ink.Text, { dimColor: args.debug }, String(args.node)));
|
|
83
94
|
return;
|
|
84
95
|
}
|
|
85
|
-
state.output.push(node);
|
|
96
|
+
state.output.push(args.node);
|
|
97
|
+
},
|
|
98
|
+
pending_output(state, args) {
|
|
99
|
+
const { id } = args;
|
|
100
|
+
if (!id) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (!state.pending_output[id]) {
|
|
104
|
+
state.pending_output[id] = [];
|
|
105
|
+
}
|
|
106
|
+
switch (typeof args.node) {
|
|
107
|
+
case "boolean":
|
|
108
|
+
case "number":
|
|
109
|
+
case "string": {
|
|
110
|
+
state.pending_output[id].push(React.createElement(Ink.Text, { dimColor: args.debug }, String(args.node)));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
state.pending_output[id].push(args.node);
|
|
115
|
+
},
|
|
116
|
+
end_pending_output(state, id) {
|
|
117
|
+
delete state.pending_output[id];
|
|
86
118
|
},
|
|
87
119
|
},
|
|
88
120
|
select: {
|
package/dist/core/cli.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as child from "node:child_process";
|
|
2
2
|
import { Store } from "../app/Store.js";
|
|
3
|
+
let i = 0;
|
|
3
4
|
export async function cli(unsafe_command, unsafe_options) {
|
|
4
5
|
const state = Store.getState();
|
|
5
6
|
const options = Object.assign({}, unsafe_options);
|
|
@@ -15,28 +16,38 @@ export async function cli(unsafe_command, unsafe_options) {
|
|
|
15
16
|
let stdout = "";
|
|
16
17
|
let stderr = "";
|
|
17
18
|
let output = "";
|
|
19
|
+
const id = `${++i}-${command}`;
|
|
20
|
+
state.actions.debug(`[start] ${command}`);
|
|
21
|
+
state.actions.debug(`[start] ${command}\n`, id);
|
|
22
|
+
function write_output(value) {
|
|
23
|
+
output += value;
|
|
24
|
+
state.actions.debug(value, id);
|
|
25
|
+
}
|
|
18
26
|
childProcess.stdout?.on("data", (data) => {
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
const value = String(data);
|
|
28
|
+
stdout += value;
|
|
29
|
+
write_output(value);
|
|
21
30
|
});
|
|
22
31
|
childProcess.stderr?.on("data", (data) => {
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
const value = String(data);
|
|
33
|
+
stderr += value;
|
|
34
|
+
write_output(value);
|
|
25
35
|
});
|
|
26
36
|
childProcess.on("close", (code) => {
|
|
37
|
+
const result = {
|
|
38
|
+
command,
|
|
39
|
+
code: code || 0,
|
|
40
|
+
stdout: stdout.trimEnd(),
|
|
41
|
+
stderr: stderr.trimEnd(),
|
|
42
|
+
output: output.trimEnd(),
|
|
43
|
+
};
|
|
44
|
+
state.actions.set((state) => state.mutate.end_pending_output(state, id));
|
|
45
|
+
state.actions.debug(`[end] ${command}`);
|
|
46
|
+
state.actions.debug(result.output);
|
|
27
47
|
if (!options.ignoreExitCode && code !== 0) {
|
|
28
48
|
reject(new Error(`[${command}] (${code})`));
|
|
29
49
|
}
|
|
30
50
|
else {
|
|
31
|
-
const result = {
|
|
32
|
-
command,
|
|
33
|
-
code: code || 0,
|
|
34
|
-
stdout: stdout.trimEnd(),
|
|
35
|
-
stderr: stderr.trimEnd(),
|
|
36
|
-
output: output.trimEnd(),
|
|
37
|
-
};
|
|
38
|
-
state.actions.debug(`$ ${command}`);
|
|
39
|
-
state.actions.debug(result.output);
|
|
40
51
|
resolve(result);
|
|
41
52
|
}
|
|
42
53
|
});
|