@wrongstack/tools 0.8.5 → 0.9.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/dist/builtin.js +67 -42
- package/dist/builtin.js.map +1 -1
- package/dist/git.js +38 -13
- package/dist/git.js.map +1 -1
- package/dist/index.js +67 -42
- package/dist/index.js.map +1 -1
- package/dist/pack.js +67 -42
- package/dist/pack.js.map +1 -1
- package/package.json +2 -2
package/dist/git.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { statSync } from 'node:fs';
|
|
3
|
-
import { dirname } from 'node:path';
|
|
3
|
+
import { resolve, sep, dirname } from 'node:path';
|
|
4
4
|
import { buildChildEnv } from '@wrongstack/core';
|
|
5
5
|
|
|
6
6
|
// src/git.ts
|
|
@@ -82,6 +82,10 @@ var gitTool = {
|
|
|
82
82
|
truncated: false
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
|
+
if (input.command === "worktree") {
|
|
86
|
+
const guard = validateWorktreeInput(input, ctx.projectRoot);
|
|
87
|
+
if (guard) return guard;
|
|
88
|
+
}
|
|
85
89
|
const gitDir = findGitDir(ctx.cwd, ctx.projectRoot);
|
|
86
90
|
if (!gitDir) {
|
|
87
91
|
return {
|
|
@@ -96,13 +100,34 @@ var gitTool = {
|
|
|
96
100
|
return await runGit(args, gitDir, opts.signal);
|
|
97
101
|
}
|
|
98
102
|
};
|
|
103
|
+
function validateWorktreeInput(input, projectRoot) {
|
|
104
|
+
const reject = (stderr) => ({
|
|
105
|
+
command: "worktree",
|
|
106
|
+
stdout: "",
|
|
107
|
+
stderr,
|
|
108
|
+
exitCode: 1,
|
|
109
|
+
truncated: false
|
|
110
|
+
});
|
|
111
|
+
if (input.branch?.startsWith("-")) return reject(`unsafe branch name: ${input.branch}`);
|
|
112
|
+
if (input.worktreePath?.startsWith("-")) {
|
|
113
|
+
return reject(`unsafe worktree path: ${input.worktreePath}`);
|
|
114
|
+
}
|
|
115
|
+
if ((input.worktreeAction === "add" || input.worktreeAction === "remove") && input.worktreePath) {
|
|
116
|
+
const root = resolve(projectRoot);
|
|
117
|
+
const abs = resolve(root, input.worktreePath);
|
|
118
|
+
if (abs !== root && !abs.startsWith(root + sep)) {
|
|
119
|
+
return reject(`unsafe worktree path (escapes project root): ${input.worktreePath}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
99
124
|
function findGitDir(cwd, projectRoot) {
|
|
100
125
|
const root = projectRoot;
|
|
101
126
|
let dir = cwd;
|
|
102
127
|
for (let i = 0; i < 20; i++) {
|
|
103
128
|
try {
|
|
104
129
|
const stat = statSync(`${dir}/.git`);
|
|
105
|
-
if (stat.isDirectory()) return dir;
|
|
130
|
+
if (stat.isDirectory() || stat.isFile()) return dir;
|
|
106
131
|
} catch {
|
|
107
132
|
}
|
|
108
133
|
if (dir === root) break;
|
|
@@ -158,14 +183,14 @@ function buildArgs(input) {
|
|
|
158
183
|
switch (input.worktreeAction) {
|
|
159
184
|
case "list":
|
|
160
185
|
return ["worktree", "list"];
|
|
161
|
-
case "add":
|
|
162
|
-
return [
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
186
|
+
case "add": {
|
|
187
|
+
if (!input.worktreePath) return ["worktree", "list"];
|
|
188
|
+
const add = ["worktree", "add"];
|
|
189
|
+
if (input.newBranch && input.branch) add.push("-b", input.branch);
|
|
190
|
+
add.push(input.worktreePath);
|
|
191
|
+
if (!input.newBranch && input.branch) add.push(input.branch);
|
|
192
|
+
return add;
|
|
193
|
+
}
|
|
169
194
|
case "remove":
|
|
170
195
|
return [
|
|
171
196
|
"worktree",
|
|
@@ -183,7 +208,7 @@ function buildArgs(input) {
|
|
|
183
208
|
}
|
|
184
209
|
}
|
|
185
210
|
function runGit(args, cwd, signal) {
|
|
186
|
-
return new Promise((
|
|
211
|
+
return new Promise((resolve2) => {
|
|
187
212
|
let stdout = "";
|
|
188
213
|
let stderr = "";
|
|
189
214
|
const child = spawn("git", args, {
|
|
@@ -203,7 +228,7 @@ function runGit(args, cwd, signal) {
|
|
|
203
228
|
}
|
|
204
229
|
});
|
|
205
230
|
child.on("error", (err) => {
|
|
206
|
-
|
|
231
|
+
resolve2({
|
|
207
232
|
command: args[0],
|
|
208
233
|
stdout,
|
|
209
234
|
stderr: err.message,
|
|
@@ -212,7 +237,7 @@ function runGit(args, cwd, signal) {
|
|
|
212
237
|
});
|
|
213
238
|
});
|
|
214
239
|
child.on("close", (code) => {
|
|
215
|
-
|
|
240
|
+
resolve2({
|
|
216
241
|
command: args[0],
|
|
217
242
|
stdout: stdout.slice(0, MAX_OUTPUT),
|
|
218
243
|
stderr: stderr.slice(0, MAX_OUTPUT),
|
package/dist/git.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/git.ts"],"names":[],"mappings":";;;;;;AAkDA,IAAM,UAAA,GAAa,GAAA;AACnB,IAAM,UAAA,GAAa,GAAA;AAEZ,IAAM,OAAA,GAAqC;AAAA,EAChD,IAAA,EAAM,KAAA;AAAA,EACN,QAAA,EAAU,KAAA;AAAA,EACV,WAAA,EACE,oIAAA;AAAA,EACF,SAAA,EACE,mKAAA;AAAA,EACF,UAAA,EAAY,SAAA;AAAA;AAAA;AAAA;AAAA,EAIZ,QAAA,EAAU,IAAA;AAAA,EACV,SAAA,EAAW,UAAA;AAAA,EACX,WAAA,EAAa;AAAA,IACX,IAAA,EAAM,QAAA;AAAA,IACN,UAAA,EAAY;AAAA,MACV,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,QAAA;AAAA,QACN,IAAA,EAAM;AAAA,UACJ,QAAA;AAAA,UACA,KAAA;AAAA,UACA,MAAA;AAAA,UACA,QAAA;AAAA,UACA,QAAA;AAAA,UACA,UAAA;AAAA,UACA,OAAA;AAAA,UACA,MAAA;AAAA,UACA,MAAA;AAAA,UACA,OAAA;AAAA,UACA,OAAA;AAAA,UACA;AAAA,SACF;AAAA,QACA,WAAA,EAAa;AAAA,OACf;AAAA,MACA,KAAA,EAAO;AAAA,QACL,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EACE;AAAA,OACJ;AAAA,MACA,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,sCAAA,EAAuC;AAAA,MAC/E,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,iCAAA,EAAkC;AAAA,MACzE,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,QAAA;AAAA,QACN,IAAA,EAAM,CAAC,OAAA,EAAS,SAAA,EAAW,QAAQ,OAAO,CAAA;AAAA,QAC1C,WAAA,EAAa;AAAA,OACf;AAAA,MACA,KAAA,EAAO,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,6BAAA,EAA8B;AAAA,MACrE,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,aAAa,0CAAA,EAA2C;AAAA,MACpF,cAAA,EAAgB;AAAA,QACd,IAAA,EAAM,QAAA;AAAA,QACN,IAAA,EAAM,CAAC,MAAA,EAAQ,KAAA,EAAO,UAAU,OAAO,CAAA;AAAA,QACvC,WAAA,EAAa;AAAA,OACf;AAAA,MACA,YAAA,EAAc;AAAA,QACZ,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa;AAAA,OACf;AAAA,MACA,SAAA,EAAW;AAAA,QACT,IAAA,EAAM,SAAA;AAAA,QACN,WAAA,EAAa;AAAA,OACf;AAAA,MACA,KAAA,EAAO;AAAA,QACL,IAAA,EAAM,SAAA;AAAA,QACN,WAAA,EAAa;AAAA;AACf,KACF;AAAA,IACA,QAAA,EAAU,CAAC,SAAS;AAAA,GACtB;AAAA,EACA,MAAM,OAAA,CAAQ,KAAA,EAAO,GAAA,EAAK,IAAA,EAAM;AAC9B,IAAA,IAAI,CAAC,KAAA,EAAO,OAAA,EAAS,MAAM,IAAI,MAAM,0BAA0B,CAAA;AAE/D,IAAA,IAAI,KAAA,CAAM,OAAA,KAAY,QAAA,IAAY,CAAC,MAAM,OAAA,EAAS;AAChD,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,QAAA;AAAA,QACT,MAAA,EAAQ,EAAA;AAAA,QACR,MAAA,EAAQ,yCAAA;AAAA,QACR,QAAA,EAAU,CAAA;AAAA,QACV,SAAA,EAAW;AAAA,OACb;AAAA,IACF;AAIA,IAAA,MAAM,MAAA,GAAS,UAAA,CAAW,GAAA,CAAI,GAAA,EAAK,IAAI,WAAW,CAAA;AAClD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,OAAO;AAAA,QACL,SAAS,KAAA,CAAM,OAAA;AAAA,QACf,MAAA,EAAQ,EAAA;AAAA,QACR,MAAA,EAAQ,+CAAA;AAAA,QACR,QAAA,EAAU,GAAA;AAAA,QACV,SAAA,EAAW;AAAA,OACb;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,GAAO,UAAU,KAAK,CAAA;AAC5B,IAAA,OAAO,MAAM,MAAA,CAAO,IAAA,EAAM,MAAA,EAAQ,KAAK,MAAM,CAAA;AAAA,EAC/C;AACF;AAEA,SAAS,UAAA,CAAW,KAAa,WAAA,EAAoC;AACnE,EAAA,MAAM,IAAA,GAAO,WAAA;AACb,EAAA,IAAI,GAAA,GAAM,GAAA;AACV,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,EAAA,EAAI,CAAA,EAAA,EAAK;AAC3B,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,QAAA,CAAS,CAAA,EAAG,GAAG,CAAA,KAAA,CAAO,CAAA;AACnC,MAAA,IAAI,IAAA,CAAK,WAAA,EAAY,EAAG,OAAO,GAAA;AAAA,IACjC,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,IAAI,QAAQ,IAAA,EAAM;AAClB,IAAA,MAAM,MAAA,GAAS,QAAQ,GAAG,CAAA;AAC1B,IAAA,IAAI,WAAW,GAAA,EAAK;AACpB,IAAA,GAAA,GAAM,MAAA;AAAA,EACR;AACA,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,UAAU,KAAA,EAA2B;AAC5C,EAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,IAAS,EAAA;AAC7B,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,GAAA,CACf,KAAA,CAAM,OAAA,CAAQ,MAAM,KAAK,CAAA,GAAI,KAAA,CAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,MAAM,GAAG,CAAA,EAC9D,GAAA,CAAI,CAAC,CAAA,KAAc,CAAA,CAAE,IAAA,EAAM,CAAA,CAC3B,MAAA,CAAO,OAAO,CAAA,GACjB,EAAC;AAEL,EAAA,QAAQ,MAAM,OAAA;AAAS,IACrB,KAAK,QAAA;AACH,MAAA,OAAO,CAAC,QAAA,EAAU,GAAI,KAAA,CAAM,MAAA,GAAS,CAAC,IAAA,EAAM,GAAG,KAAK,CAAA,GAAI,EAAG,CAAA;AAAA,IAC7D,KAAK,KAAA;AACH,MAAA,OAAO;AAAA,QACL,KAAA;AAAA,QACA,eAAe,KAAK,CAAA,CAAA;AAAA,QACpB,GAAI,KAAA,CAAM,MAAA,KAAW,YAAY,CAAC,WAAW,IAAI,EAAC;AAAA,QAClD,GAAI,KAAA,CAAM,MAAA,KAAW,SAAS,CAAC,QAAQ,IAAI,EAAC;AAAA,QAC5C,GAAI,MAAM,MAAA,KAAW,OAAA,GAAU,CAAC,WAAA,EAAa,SAAA,EAAW,YAAY,CAAA,GAAI,EAAC;AAAA,QACzE,GAAI,MAAM,MAAA,KAAW,OAAA,IAAW,CAAC,KAAA,CAAM,MAAA,GAAS,EAAC,GAAI;AAAC,OACxD;AAAA,IACF,KAAK,MAAA;AACH,MAAA,OAAO,CAAC,MAAA,EAAQ,YAAA,EAAc,GAAI,KAAA,CAAM,MAAA,GAAS,CAAC,IAAA,EAAM,GAAG,KAAK,CAAA,GAAI,EAAG,CAAA;AAAA,IACzE,KAAK,QAAA;AACH,MAAA,OAAO;AAAA,QACL,QAAA;AAAA,QACA,GAAI,KAAA,CAAM,OAAA,GAAU,CAAC,WAAA,EAAa,aAAa,IAAI,EAAC;AAAA,QACpD,GAAI,MAAM,OAAA,GAAU,CAAC,MAAM,KAAA,CAAM,OAAO,IAAI,EAAC;AAAA,QAC7C,GAAI,MAAM,MAAA,GAAS,CAAC,MAAM,GAAG,KAAK,IAAI;AAAC,OACzC;AAAA,IACF,KAAK,QAAA;AAEH,MAAA,OAAO,MAAM,MAAA,GACT,CAAC,UAAU,GAAI,KAAA,CAAM,OAAO,UAAA,CAAW,GAAG,CAAA,GAAI,KAAK,CAAC,KAAA,CAAM,MAAM,CAAE,CAAA,GAClE,CAAC,QAAQ,CAAA;AAAA,IACf,KAAK,UAAA;AACH,MAAA,OAAO;AAAA,QACL,UAAA;AAAA,QACA,GAAI,MAAM,MAAA,GAAS,CAAC,MAAM,KAAA,CAAM,MAAM,IAAI,EAAC;AAAA,QAC3C,GAAI,MAAM,MAAA,GAAS,CAAC,MAAM,GAAG,KAAK,IAAI;AAAC,OACzC;AAAA,IACF,KAAK,OAAA;AACH,MAAA,OAAO,KAAA,CAAM,OAAA,GAAU,CAAC,OAAA,EAAS,MAAA,EAAQ,IAAA,EAAM,KAAA,CAAM,OAAO,CAAA,GAAI,CAAC,OAAA,EAAS,MAAM,CAAA;AAAA,IAClF,KAAK,MAAA;AACH,MAAA,OAAO,CAAC,MAAM,CAAA;AAAA,IAChB,KAAK,MAAA;AACH,MAAA,OAAO,CAAC,MAAM,CAAA;AAAA,IAChB,KAAK,OAAA;AACH,MAAA,OAAO,CAAC,OAAA,EAAS,GAAI,KAAA,CAAM,MAAA,GAAS,CAAC,KAAA,CAAM,MAAM,CAAA,GAAI,CAAC,OAAO,CAAE,CAAA;AAAA,IACjE,KAAK,OAAA;AACH,MAAA,OAAO,CAAC,OAAO,CAAA;AAAA,IACjB,KAAK,UAAA;AACH,MAAA,QAAQ,MAAM,cAAA;AAAgB,QAC5B,KAAK,MAAA;AACH,UAAA,OAAO,CAAC,YAAY,MAAM,CAAA;AAAA,QAC5B,KAAK,KAAA;AACH,UAAA,OAAO;AAAA,YACL,UAAA;AAAA,YACA,KAAA;AAAA,YACA,GAAI,KAAA,CAAM,SAAA,GAAY,CAAC,IAAI,IAAI,EAAC;AAAA,YAChC,GAAI,KAAA,CAAM,MAAA,GAAS,CAAC,KAAA,CAAM,MAAM,IAAI,EAAC;AAAA,YACrC,MAAM,YAAA,IAAgB;AAAA,WACxB,CAAE,OAAO,OAAO,CAAA;AAAA,QAClB,KAAK,QAAA;AACH,UAAA,OAAO;AAAA,YACL,UAAA;AAAA,YACA,QAAA;AAAA,YACA,GAAI,KAAA,CAAM,KAAA,GAAQ,CAAC,SAAS,IAAI,EAAC;AAAA,YACjC,MAAM,YAAA,IAAgB;AAAA,WACxB,CAAE,OAAO,OAAO,CAAA;AAAA,QAClB,KAAK,OAAA;AACH,UAAA,OAAO,CAAC,YAAY,OAAO,CAAA;AAAA,QAC7B;AACE,UAAA,OAAO,CAAC,YAAY,MAAM,CAAA;AAAA;AAC9B,IACF;AACE,MAAA,OAAO,CAAC,MAAM,OAAO,CAAA;AAAA;AAE3B;AAEA,SAAS,MAAA,CAAO,IAAA,EAAgB,GAAA,EAAa,MAAA,EAAyC;AACpF,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI,MAAA,GAAS,EAAA;AAEb,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,EAAO,IAAA,EAAM;AAAA,MAC/B,GAAA;AAAA,MACA,MAAA;AAAA,MACA,KAAK,aAAA,EAAc;AAAA,MACnB,KAAA,EAAO,CAAC,QAAA,EAAU,MAAA,EAAQ,MAAM;AAAA,KACjC,CAAA;AAED,IAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,KAAA,KAAkB;AAC1C,MAAA,IAAI,MAAA,CAAO,SAAS,UAAA,EAAY;AAC9B,QAAA,MAAA,IAAU,MAAM,QAAA,EAAS;AAAA,MAC3B;AAAA,IACF,CAAC,CAAA;AAED,IAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,KAAA,KAAkB;AAC1C,MAAA,IAAI,MAAA,CAAO,SAAS,UAAA,EAAY;AAC9B,QAAA,MAAA,IAAU,MAAM,QAAA,EAAS;AAAA,MAC3B;AAAA,IACF,CAAC,CAAA;AAED,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AACzB,MAAA,OAAA,CAAQ;AAAA,QACN,OAAA,EAAS,KAAK,CAAC,CAAA;AAAA,QACf,MAAA;AAAA,QACA,QAAQ,GAAA,CAAI,OAAA;AAAA,QACZ,QAAA,EAAU,CAAA;AAAA,QACV,SAAA,EAAW,OAAO,MAAA,IAAU;AAAA,OAC7B,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AAC1B,MAAA,OAAA,CAAQ;AAAA,QACN,OAAA,EAAS,KAAK,CAAC,CAAA;AAAA,QACf,MAAA,EAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA;AAAA,QAClC,MAAA,EAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,UAAU,CAAA;AAAA,QAClC,UAAU,IAAA,IAAQ,CAAA;AAAA,QAClB,SAAA,EAAW,MAAA,CAAO,MAAA,IAAU,UAAA,IAAc,OAAO,MAAA,IAAU;AAAA,OAC5D,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH","file":"git.js","sourcesContent":["import { spawn } from 'node:child_process';\nimport { statSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { buildChildEnv } from '@wrongstack/core';\nimport type { Tool } from '@wrongstack/core';\n\ntype GitSubcommand =\n | 'status'\n | 'log'\n | 'diff'\n | 'commit'\n | 'branch'\n | 'checkout'\n | 'stash'\n | 'push'\n | 'pull'\n | 'fetch'\n | 'reset'\n | 'worktree';\n\ninterface GitInput {\n command: GitSubcommand;\n files?: string | string[];\n dry_run?: boolean;\n /** commit message for `commit` subcommand */\n message?: string;\n /** branch name for `checkout` / `branch` */\n branch?: string;\n /** pass --graph, --oneline, --stat for `log` */\n format?: 'short' | 'oneline' | 'stat' | 'graph';\n /** limit for `log` */\n limit?: number;\n /** worktree action: list, add, remove, prune */\n worktreeAction?: 'list' | 'add' | 'remove' | 'prune';\n /** path for worktree add/remove (e.g. \"../wt-feature-xyz\") */\n worktreePath?: string;\n /** create new branch when adding worktree */\n newBranch?: boolean;\n /** force operation (e.g. worktree remove --force) */\n force?: boolean;\n}\n\ninterface GitOutput {\n command: GitSubcommand;\n stdout: string;\n stderr: string;\n exitCode: number;\n truncated: boolean;\n}\n\nconst TIMEOUT_MS = 30_000;\nconst MAX_OUTPUT = 100_000;\n\nexport const gitTool: Tool<GitInput, GitOutput> = {\n name: 'git',\n category: 'Git',\n description:\n 'Run git commands. Wraps common operations: status, log, diff, commit, branch, checkout, stash, push, pull, fetch, reset, worktree.',\n usageHint:\n 'Prefer built-in subcommands over raw args. `command` is required. `message` for commits. `branch` for checkout/branch. `files` for status/diff. `format` for log.',\n permission: 'confirm',\n // Conservative: any of these may mutate. The non-mutating commands\n // (status/log/diff/branch/fetch) are still gated on `permission: 'confirm'`\n // and `MUTATING_SUBCOMMANDS` is consulted at runtime for per-call checks.\n mutating: true,\n timeoutMs: TIMEOUT_MS,\n inputSchema: {\n type: 'object',\n properties: {\n command: {\n type: 'string',\n enum: [\n 'status',\n 'log',\n 'diff',\n 'commit',\n 'branch',\n 'checkout',\n 'stash',\n 'push',\n 'pull',\n 'fetch',\n 'reset',\n 'worktree',\n ],\n description: 'Git subcommand',\n },\n files: {\n type: 'string',\n description:\n 'File(s) for status/diff: single path, comma-separated list, or \"**/*.ts\" glob',\n },\n message: { type: 'string', description: 'Commit message (required for commit)' },\n branch: { type: 'string', description: 'Branch name for checkout/branch' },\n format: {\n type: 'string',\n enum: ['short', 'oneline', 'stat', 'graph'],\n description: 'Log format (default: short)',\n },\n limit: { type: 'integer', description: 'Limit for log (default: 20)' },\n dry_run: { type: 'boolean', description: 'For commit: show what would be committed' },\n worktreeAction: {\n type: 'string',\n enum: ['list', 'add', 'remove', 'prune'],\n description: 'Worktree action: list, add, remove, prune',\n },\n worktreePath: {\n type: 'string',\n description: 'Path for worktree add/remove (e.g. \"../wt-feature-xyz\")',\n },\n newBranch: {\n type: 'boolean',\n description: 'Create new branch when adding worktree',\n },\n force: {\n type: 'boolean',\n description: 'Force operation (e.g. worktree remove --force)',\n },\n },\n required: ['command'],\n },\n async execute(input, ctx, opts) {\n if (!input?.command) throw new Error('git: command is required');\n\n if (input.command === 'commit' && !input.message) {\n return {\n command: 'commit',\n stdout: '',\n stderr: 'git commit requires a message (-m flag)',\n exitCode: 1,\n truncated: false,\n };\n }\n\n // Bound the search at projectRoot so a non-git project doesn't drift\n // into a parent repo (e.g. ~/repos/.git) and operate on the wrong tree.\n const gitDir = findGitDir(ctx.cwd, ctx.projectRoot);\n if (!gitDir) {\n return {\n command: input.command,\n stdout: '',\n stderr: 'Not in a git repository (within project root)',\n exitCode: 128,\n truncated: false,\n };\n }\n\n const args = buildArgs(input);\n return await runGit(args, gitDir, opts.signal);\n },\n};\n\nfunction findGitDir(cwd: string, projectRoot: string): string | null {\n const root = projectRoot;\n let dir = cwd;\n for (let i = 0; i < 20; i++) {\n try {\n const stat = statSync(`${dir}/.git`);\n if (stat.isDirectory()) return dir;\n } catch {\n // continue\n }\n if (dir === root) break;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\nfunction buildArgs(input: GitInput): string[] {\n const limit = input.limit ?? 20;\n const files = input.files\n ? (Array.isArray(input.files) ? input.files : input.files.split(','))\n .map((s: string) => s.trim())\n .filter(Boolean)\n : [];\n\n switch (input.command) {\n case 'status':\n return ['status', ...(files.length ? ['--', ...files] : [])];\n case 'log':\n return [\n 'log',\n `--max-count=${limit}`,\n ...(input.format === 'oneline' ? ['--oneline'] : []),\n ...(input.format === 'stat' ? ['--stat'] : []),\n ...(input.format === 'graph' ? ['--oneline', '--graph', '--decorate'] : []),\n ...(input.format === 'short' || !input.format ? [] : []),\n ];\n case 'diff':\n return ['diff', '--no-color', ...(files.length ? ['--', ...files] : [])];\n case 'commit':\n return [\n 'commit',\n ...(input.dry_run ? ['--dry-run', '--porcelain'] : []),\n ...(input.message ? ['-m', input.message] : []),\n ...(files.length ? ['--', ...files] : []),\n ];\n case 'branch':\n // Validate branch name: reject names starting with '-' (flag injection).\n return input.branch\n ? ['branch', ...(input.branch.startsWith('-') ? [] : [input.branch])]\n : ['branch'];\n case 'checkout':\n return [\n 'checkout',\n ...(input.branch ? ['--', input.branch] : []),\n ...(files.length ? ['--', ...files] : []),\n ];\n case 'stash':\n return input.message ? ['stash', 'push', '-m', input.message] : ['stash', 'push'];\n case 'push':\n return ['push'];\n case 'pull':\n return ['pull'];\n case 'fetch':\n return ['fetch', ...(input.branch ? [input.branch] : ['--all'])];\n case 'reset':\n return ['reset'];\n case 'worktree':\n switch (input.worktreeAction) {\n case 'list':\n return ['worktree', 'list'];\n case 'add':\n return [\n 'worktree',\n 'add',\n ...(input.newBranch ? ['-b'] : []),\n ...(input.branch ? [input.branch] : []),\n input.worktreePath ?? '',\n ].filter(Boolean);\n case 'remove':\n return [\n 'worktree',\n 'remove',\n ...(input.force ? ['--force'] : []),\n input.worktreePath ?? '',\n ].filter(Boolean);\n case 'prune':\n return ['worktree', 'prune'];\n default:\n return ['worktree', 'list'];\n }\n default:\n return [input.command];\n }\n}\n\nfunction runGit(args: string[], cwd: string, signal: AbortSignal): Promise<GitOutput> {\n return new Promise((resolve) => {\n let stdout = '';\n let stderr = '';\n\n const child = spawn('git', args, {\n cwd,\n signal,\n env: buildChildEnv(),\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n child.stdout?.on('data', (chunk: Buffer) => {\n if (stdout.length < MAX_OUTPUT) {\n stdout += chunk.toString();\n }\n });\n\n child.stderr?.on('data', (chunk: Buffer) => {\n if (stderr.length < MAX_OUTPUT) {\n stderr += chunk.toString();\n }\n });\n\n child.on('error', (err) => {\n resolve({\n command: args[0] as GitSubcommand,\n stdout,\n stderr: err.message,\n exitCode: 1,\n truncated: stdout.length >= MAX_OUTPUT,\n });\n });\n\n child.on('close', (code) => {\n resolve({\n command: args[0] as GitSubcommand,\n stdout: stdout.slice(0, MAX_OUTPUT),\n stderr: stderr.slice(0, MAX_OUTPUT),\n exitCode: code ?? 1,\n truncated: stdout.length >= MAX_OUTPUT || stderr.length >= MAX_OUTPUT,\n });\n });\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/git.ts"],"names":["resolve"],"mappings":"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","file":"git.js","sourcesContent":["import { spawn } from 'node:child_process';\nimport { statSync } from 'node:fs';\nimport { dirname, resolve, sep } from 'node:path';\nimport { buildChildEnv } from '@wrongstack/core';\nimport type { Tool } from '@wrongstack/core';\n\ntype GitSubcommand =\n | 'status'\n | 'log'\n | 'diff'\n | 'commit'\n | 'branch'\n | 'checkout'\n | 'stash'\n | 'push'\n | 'pull'\n | 'fetch'\n | 'reset'\n | 'worktree';\n\ninterface GitInput {\n command: GitSubcommand;\n files?: string | string[];\n dry_run?: boolean;\n /** commit message for `commit` subcommand */\n message?: string;\n /** branch name for `checkout` / `branch` */\n branch?: string;\n /** pass --graph, --oneline, --stat for `log` */\n format?: 'short' | 'oneline' | 'stat' | 'graph';\n /** limit for `log` */\n limit?: number;\n /** worktree action: list, add, remove, prune */\n worktreeAction?: 'list' | 'add' | 'remove' | 'prune';\n /** path for worktree add/remove (e.g. \"../wt-feature-xyz\") */\n worktreePath?: string;\n /** create new branch when adding worktree */\n newBranch?: boolean;\n /** force operation (e.g. worktree remove --force) */\n force?: boolean;\n}\n\ninterface GitOutput {\n command: GitSubcommand;\n stdout: string;\n stderr: string;\n exitCode: number;\n truncated: boolean;\n}\n\nconst TIMEOUT_MS = 30_000;\nconst MAX_OUTPUT = 100_000;\n\nexport const gitTool: Tool<GitInput, GitOutput> = {\n name: 'git',\n category: 'Git',\n description:\n 'Run git commands. Wraps common operations: status, log, diff, commit, branch, checkout, stash, push, pull, fetch, reset, worktree.',\n usageHint:\n 'Prefer built-in subcommands over raw args. `command` is required. `message` for commits. `branch` for checkout/branch. `files` for status/diff. `format` for log.',\n permission: 'confirm',\n // Conservative: any of these may mutate. The non-mutating commands\n // (status/log/diff/branch/fetch) are still gated on `permission: 'confirm'`\n // and `MUTATING_SUBCOMMANDS` is consulted at runtime for per-call checks.\n mutating: true,\n timeoutMs: TIMEOUT_MS,\n inputSchema: {\n type: 'object',\n properties: {\n command: {\n type: 'string',\n enum: [\n 'status',\n 'log',\n 'diff',\n 'commit',\n 'branch',\n 'checkout',\n 'stash',\n 'push',\n 'pull',\n 'fetch',\n 'reset',\n 'worktree',\n ],\n description: 'Git subcommand',\n },\n files: {\n type: 'string',\n description:\n 'File(s) for status/diff: single path, comma-separated list, or \"**/*.ts\" glob',\n },\n message: { type: 'string', description: 'Commit message (required for commit)' },\n branch: { type: 'string', description: 'Branch name for checkout/branch' },\n format: {\n type: 'string',\n enum: ['short', 'oneline', 'stat', 'graph'],\n description: 'Log format (default: short)',\n },\n limit: { type: 'integer', description: 'Limit for log (default: 20)' },\n dry_run: { type: 'boolean', description: 'For commit: show what would be committed' },\n worktreeAction: {\n type: 'string',\n enum: ['list', 'add', 'remove', 'prune'],\n description: 'Worktree action: list, add, remove, prune',\n },\n worktreePath: {\n type: 'string',\n description: 'Path for worktree add/remove (e.g. \"../wt-feature-xyz\")',\n },\n newBranch: {\n type: 'boolean',\n description: 'Create new branch when adding worktree',\n },\n force: {\n type: 'boolean',\n description: 'Force operation (e.g. worktree remove --force)',\n },\n },\n required: ['command'],\n },\n async execute(input, ctx, opts) {\n if (!input?.command) throw new Error('git: command is required');\n\n if (input.command === 'commit' && !input.message) {\n return {\n command: 'commit',\n stdout: '',\n stderr: 'git commit requires a message (-m flag)',\n exitCode: 1,\n truncated: false,\n };\n }\n\n // Validate worktree paths/branches before touching the filesystem: reject\n // flag injection and any path that escapes the project root.\n if (input.command === 'worktree') {\n const guard = validateWorktreeInput(input, ctx.projectRoot);\n if (guard) return guard;\n }\n\n // Bound the search at projectRoot so a non-git project doesn't drift\n // into a parent repo (e.g. ~/repos/.git) and operate on the wrong tree.\n const gitDir = findGitDir(ctx.cwd, ctx.projectRoot);\n if (!gitDir) {\n return {\n command: input.command,\n stdout: '',\n stderr: 'Not in a git repository (within project root)',\n exitCode: 128,\n truncated: false,\n };\n }\n\n const args = buildArgs(input);\n return await runGit(args, gitDir, opts.signal);\n },\n};\n\n/**\n * Reject worktree inputs that could inject git flags or escape the project\n * root. Returns a `GitOutput` describing the rejection, or `null` if safe.\n */\nfunction validateWorktreeInput(input: GitInput, projectRoot: string): GitOutput | null {\n const reject = (stderr: string): GitOutput => ({\n command: 'worktree',\n stdout: '',\n stderr,\n exitCode: 1,\n truncated: false,\n });\n\n // Flag injection: a leading '-' would be parsed as a git option.\n if (input.branch?.startsWith('-')) return reject(`unsafe branch name: ${input.branch}`);\n if (input.worktreePath?.startsWith('-')) {\n return reject(`unsafe worktree path: ${input.worktreePath}`);\n }\n\n // Path escape: add/remove targets must resolve inside the project root.\n if (\n (input.worktreeAction === 'add' || input.worktreeAction === 'remove') &&\n input.worktreePath\n ) {\n const root = resolve(projectRoot);\n const abs = resolve(root, input.worktreePath);\n if (abs !== root && !abs.startsWith(root + sep)) {\n return reject(`unsafe worktree path (escapes project root): ${input.worktreePath}`);\n }\n }\n\n return null;\n}\n\nfunction findGitDir(cwd: string, projectRoot: string): string | null {\n const root = projectRoot;\n let dir = cwd;\n for (let i = 0; i < 20; i++) {\n try {\n const stat = statSync(`${dir}/.git`);\n // A normal repo has a `.git` directory; a linked worktree has a `.git`\n // *file* (gitlink pointing at the main repo). Accept both so the tool\n // operates inside a worktree when a subagent's cwd is a worktree dir.\n if (stat.isDirectory() || stat.isFile()) return dir;\n } catch {\n // continue\n }\n if (dir === root) break;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\nfunction buildArgs(input: GitInput): string[] {\n const limit = input.limit ?? 20;\n const files = input.files\n ? (Array.isArray(input.files) ? input.files : input.files.split(','))\n .map((s: string) => s.trim())\n .filter(Boolean)\n : [];\n\n switch (input.command) {\n case 'status':\n return ['status', ...(files.length ? ['--', ...files] : [])];\n case 'log':\n return [\n 'log',\n `--max-count=${limit}`,\n ...(input.format === 'oneline' ? ['--oneline'] : []),\n ...(input.format === 'stat' ? ['--stat'] : []),\n ...(input.format === 'graph' ? ['--oneline', '--graph', '--decorate'] : []),\n ...(input.format === 'short' || !input.format ? [] : []),\n ];\n case 'diff':\n return ['diff', '--no-color', ...(files.length ? ['--', ...files] : [])];\n case 'commit':\n return [\n 'commit',\n ...(input.dry_run ? ['--dry-run', '--porcelain'] : []),\n ...(input.message ? ['-m', input.message] : []),\n ...(files.length ? ['--', ...files] : []),\n ];\n case 'branch':\n // Validate branch name: reject names starting with '-' (flag injection).\n return input.branch\n ? ['branch', ...(input.branch.startsWith('-') ? [] : [input.branch])]\n : ['branch'];\n case 'checkout':\n return [\n 'checkout',\n ...(input.branch ? ['--', input.branch] : []),\n ...(files.length ? ['--', ...files] : []),\n ];\n case 'stash':\n return input.message ? ['stash', 'push', '-m', input.message] : ['stash', 'push'];\n case 'push':\n return ['push'];\n case 'pull':\n return ['pull'];\n case 'fetch':\n return ['fetch', ...(input.branch ? [input.branch] : ['--all'])];\n case 'reset':\n return ['reset'];\n case 'worktree':\n switch (input.worktreeAction) {\n case 'list':\n return ['worktree', 'list'];\n case 'add': {\n // git worktree add [-b <new-branch>] <path> [<commit-ish>]\n // The path comes BEFORE the branch/commit-ish. With --newBranch the\n // branch is the name to create (`-b <branch> <path>`); without it the\n // branch is an existing branch/commit to check out (`<path> <branch>`).\n if (!input.worktreePath) return ['worktree', 'list'];\n const add = ['worktree', 'add'];\n if (input.newBranch && input.branch) add.push('-b', input.branch);\n add.push(input.worktreePath);\n if (!input.newBranch && input.branch) add.push(input.branch);\n return add;\n }\n case 'remove':\n return [\n 'worktree',\n 'remove',\n ...(input.force ? ['--force'] : []),\n input.worktreePath ?? '',\n ].filter(Boolean);\n case 'prune':\n return ['worktree', 'prune'];\n default:\n return ['worktree', 'list'];\n }\n default:\n return [input.command];\n }\n}\n\nfunction runGit(args: string[], cwd: string, signal: AbortSignal): Promise<GitOutput> {\n return new Promise((resolve) => {\n let stdout = '';\n let stderr = '';\n\n const child = spawn('git', args, {\n cwd,\n signal,\n env: buildChildEnv(),\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n child.stdout?.on('data', (chunk: Buffer) => {\n if (stdout.length < MAX_OUTPUT) {\n stdout += chunk.toString();\n }\n });\n\n child.stderr?.on('data', (chunk: Buffer) => {\n if (stderr.length < MAX_OUTPUT) {\n stderr += chunk.toString();\n }\n });\n\n child.on('error', (err) => {\n resolve({\n command: args[0] as GitSubcommand,\n stdout,\n stderr: err.message,\n exitCode: 1,\n truncated: stdout.length >= MAX_OUTPUT,\n });\n });\n\n child.on('close', (code) => {\n resolve({\n command: args[0] as GitSubcommand,\n stdout: stdout.slice(0, MAX_OUTPUT),\n stderr: stderr.slice(0, MAX_OUTPUT),\n exitCode: code ?? 1,\n truncated: stdout.length >= MAX_OUTPUT || stderr.length >= MAX_OUTPUT,\n });\n });\n });\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs4 from 'node:fs/promises';
|
|
2
2
|
import { stat } from 'node:fs/promises';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
|
-
import { dirname } from 'node:path';
|
|
4
|
+
import { resolve, sep, dirname } from 'node:path';
|
|
5
5
|
import { atomicWrite, unifiedDiff, detectNewlineStyle, normalizeToLf, toStyle, compileGlob, buildChildEnv, stripAnsi, loadPlan, emptyPlan, clearPlan, savePlan, getPlanTemplate, addPlanItem, deriveTodosFromPlanItem, removePlanItem, setPlanItemStatus, formatPlan } from '@wrongstack/core';
|
|
6
6
|
import { spawn, execFileSync, spawnSync } from 'node:child_process';
|
|
7
7
|
import * as os from 'node:os';
|
|
@@ -466,13 +466,13 @@ async function globFiles(pattern, base, extraGlob) {
|
|
|
466
466
|
return await globNative(pattern, base, extraGlob);
|
|
467
467
|
}
|
|
468
468
|
function checkRg() {
|
|
469
|
-
return new Promise((
|
|
469
|
+
return new Promise((resolve7) => {
|
|
470
470
|
try {
|
|
471
471
|
const p = spawn("rg", ["--version"], { env: buildChildEnv(), stdio: "ignore" });
|
|
472
|
-
p.on("error", () =>
|
|
473
|
-
p.on("close", (code) =>
|
|
472
|
+
p.on("error", () => resolve7(false));
|
|
473
|
+
p.on("close", (code) => resolve7(code === 0));
|
|
474
474
|
} catch {
|
|
475
|
-
|
|
475
|
+
resolve7(false);
|
|
476
476
|
}
|
|
477
477
|
});
|
|
478
478
|
}
|
|
@@ -484,10 +484,10 @@ function spawnRgFind(pattern, base) {
|
|
|
484
484
|
buf += chunk.toString();
|
|
485
485
|
});
|
|
486
486
|
return {
|
|
487
|
-
promise: new Promise((
|
|
487
|
+
promise: new Promise((resolve7, reject) => {
|
|
488
488
|
child.on("error", reject);
|
|
489
489
|
child.on("close", () => {
|
|
490
|
-
|
|
490
|
+
resolve7(buf.split("\n").filter(Boolean));
|
|
491
491
|
});
|
|
492
492
|
})
|
|
493
493
|
};
|
|
@@ -656,13 +656,13 @@ var grepTool = {
|
|
|
656
656
|
}
|
|
657
657
|
};
|
|
658
658
|
async function detectRg(signal) {
|
|
659
|
-
return new Promise((
|
|
659
|
+
return new Promise((resolve7) => {
|
|
660
660
|
try {
|
|
661
661
|
const p = spawn("rg", ["--version"], { env: buildChildEnv(), stdio: "ignore", signal });
|
|
662
|
-
p.on("error", () =>
|
|
663
|
-
p.on("close", (code) =>
|
|
662
|
+
p.on("error", () => resolve7(false));
|
|
663
|
+
p.on("close", (code) => resolve7(code === 0));
|
|
664
664
|
} catch {
|
|
665
|
-
|
|
665
|
+
resolve7(false);
|
|
666
666
|
}
|
|
667
667
|
});
|
|
668
668
|
}
|
|
@@ -1373,10 +1373,10 @@ var bashTool = {
|
|
|
1373
1373
|
queue.push(c);
|
|
1374
1374
|
}
|
|
1375
1375
|
};
|
|
1376
|
-
const next = () => new Promise((
|
|
1376
|
+
const next = () => new Promise((resolve7) => {
|
|
1377
1377
|
const c = queue.shift();
|
|
1378
|
-
if (c)
|
|
1379
|
-
else resolveNext =
|
|
1378
|
+
if (c) resolve7(c);
|
|
1379
|
+
else resolveNext = resolve7;
|
|
1380
1380
|
});
|
|
1381
1381
|
let lastFlush = Date.now();
|
|
1382
1382
|
const flush = () => {
|
|
@@ -1626,7 +1626,7 @@ var execTool = {
|
|
|
1626
1626
|
}
|
|
1627
1627
|
};
|
|
1628
1628
|
function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
|
|
1629
|
-
return new Promise((
|
|
1629
|
+
return new Promise((resolve7) => {
|
|
1630
1630
|
let stdout = "";
|
|
1631
1631
|
let stderr = "";
|
|
1632
1632
|
let killed = false;
|
|
@@ -1660,7 +1660,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
|
|
|
1660
1660
|
const durationMs = Date.now() - startedAt;
|
|
1661
1661
|
const exitCode = killed ? 124 : code ?? 1;
|
|
1662
1662
|
registry.afterCall(durationMs, exitCode !== 0);
|
|
1663
|
-
|
|
1663
|
+
resolve7({
|
|
1664
1664
|
command: cmd,
|
|
1665
1665
|
args,
|
|
1666
1666
|
stdout: stdout.slice(0, MAX_OUTPUT2),
|
|
@@ -1674,7 +1674,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
|
|
|
1674
1674
|
clearTimeout(timer);
|
|
1675
1675
|
if (typeof pid === "number") registry.unregister(pid);
|
|
1676
1676
|
registry.afterCall(Date.now() - startedAt, true);
|
|
1677
|
-
|
|
1677
|
+
resolve7({
|
|
1678
1678
|
command: cmd,
|
|
1679
1679
|
args,
|
|
1680
1680
|
stdout: stdout.slice(0, MAX_OUTPUT2),
|
|
@@ -2498,6 +2498,10 @@ var gitTool = {
|
|
|
2498
2498
|
truncated: false
|
|
2499
2499
|
};
|
|
2500
2500
|
}
|
|
2501
|
+
if (input.command === "worktree") {
|
|
2502
|
+
const guard = validateWorktreeInput(input, ctx.projectRoot);
|
|
2503
|
+
if (guard) return guard;
|
|
2504
|
+
}
|
|
2501
2505
|
const gitDir = findGitDir(ctx.cwd, ctx.projectRoot);
|
|
2502
2506
|
if (!gitDir) {
|
|
2503
2507
|
return {
|
|
@@ -2512,13 +2516,34 @@ var gitTool = {
|
|
|
2512
2516
|
return await runGit(args, gitDir, opts.signal);
|
|
2513
2517
|
}
|
|
2514
2518
|
};
|
|
2519
|
+
function validateWorktreeInput(input, projectRoot) {
|
|
2520
|
+
const reject = (stderr) => ({
|
|
2521
|
+
command: "worktree",
|
|
2522
|
+
stdout: "",
|
|
2523
|
+
stderr,
|
|
2524
|
+
exitCode: 1,
|
|
2525
|
+
truncated: false
|
|
2526
|
+
});
|
|
2527
|
+
if (input.branch?.startsWith("-")) return reject(`unsafe branch name: ${input.branch}`);
|
|
2528
|
+
if (input.worktreePath?.startsWith("-")) {
|
|
2529
|
+
return reject(`unsafe worktree path: ${input.worktreePath}`);
|
|
2530
|
+
}
|
|
2531
|
+
if ((input.worktreeAction === "add" || input.worktreeAction === "remove") && input.worktreePath) {
|
|
2532
|
+
const root = resolve(projectRoot);
|
|
2533
|
+
const abs = resolve(root, input.worktreePath);
|
|
2534
|
+
if (abs !== root && !abs.startsWith(root + sep)) {
|
|
2535
|
+
return reject(`unsafe worktree path (escapes project root): ${input.worktreePath}`);
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
return null;
|
|
2539
|
+
}
|
|
2515
2540
|
function findGitDir(cwd, projectRoot) {
|
|
2516
2541
|
const root = projectRoot;
|
|
2517
2542
|
let dir = cwd;
|
|
2518
2543
|
for (let i = 0; i < 20; i++) {
|
|
2519
2544
|
try {
|
|
2520
2545
|
const stat11 = statSync(`${dir}/.git`);
|
|
2521
|
-
if (stat11.isDirectory()) return dir;
|
|
2546
|
+
if (stat11.isDirectory() || stat11.isFile()) return dir;
|
|
2522
2547
|
} catch {
|
|
2523
2548
|
}
|
|
2524
2549
|
if (dir === root) break;
|
|
@@ -2574,14 +2599,14 @@ function buildArgs(input) {
|
|
|
2574
2599
|
switch (input.worktreeAction) {
|
|
2575
2600
|
case "list":
|
|
2576
2601
|
return ["worktree", "list"];
|
|
2577
|
-
case "add":
|
|
2578
|
-
return [
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2602
|
+
case "add": {
|
|
2603
|
+
if (!input.worktreePath) return ["worktree", "list"];
|
|
2604
|
+
const add = ["worktree", "add"];
|
|
2605
|
+
if (input.newBranch && input.branch) add.push("-b", input.branch);
|
|
2606
|
+
add.push(input.worktreePath);
|
|
2607
|
+
if (!input.newBranch && input.branch) add.push(input.branch);
|
|
2608
|
+
return add;
|
|
2609
|
+
}
|
|
2585
2610
|
case "remove":
|
|
2586
2611
|
return [
|
|
2587
2612
|
"worktree",
|
|
@@ -2599,7 +2624,7 @@ function buildArgs(input) {
|
|
|
2599
2624
|
}
|
|
2600
2625
|
}
|
|
2601
2626
|
function runGit(args, cwd, signal) {
|
|
2602
|
-
return new Promise((
|
|
2627
|
+
return new Promise((resolve7) => {
|
|
2603
2628
|
let stdout = "";
|
|
2604
2629
|
let stderr = "";
|
|
2605
2630
|
const child = spawn("git", args, {
|
|
@@ -2619,7 +2644,7 @@ function runGit(args, cwd, signal) {
|
|
|
2619
2644
|
}
|
|
2620
2645
|
});
|
|
2621
2646
|
child.on("error", (err) => {
|
|
2622
|
-
|
|
2647
|
+
resolve7({
|
|
2623
2648
|
command: args[0],
|
|
2624
2649
|
stdout,
|
|
2625
2650
|
stderr: err.message,
|
|
@@ -2628,7 +2653,7 @@ function runGit(args, cwd, signal) {
|
|
|
2628
2653
|
});
|
|
2629
2654
|
});
|
|
2630
2655
|
child.on("close", (code) => {
|
|
2631
|
-
|
|
2656
|
+
resolve7({
|
|
2632
2657
|
command: args[0],
|
|
2633
2658
|
stdout: stdout.slice(0, MAX_OUTPUT3),
|
|
2634
2659
|
stderr: stderr.slice(0, MAX_OUTPUT3),
|
|
@@ -2724,7 +2749,7 @@ function stripPathComponents(p, strip) {
|
|
|
2724
2749
|
return parts.slice(strip).join("/");
|
|
2725
2750
|
}
|
|
2726
2751
|
function runPatch(args, cwd, signal) {
|
|
2727
|
-
return new Promise((
|
|
2752
|
+
return new Promise((resolve7) => {
|
|
2728
2753
|
let stdout = "";
|
|
2729
2754
|
let stderr = "";
|
|
2730
2755
|
const env = { ...buildChildEnv(), LANG: "C", LC_ALL: "C" };
|
|
@@ -2735,8 +2760,8 @@ function runPatch(args, cwd, signal) {
|
|
|
2735
2760
|
child.stderr?.on("data", (c) => {
|
|
2736
2761
|
stderr += c.toString();
|
|
2737
2762
|
});
|
|
2738
|
-
child.on("close", (code) =>
|
|
2739
|
-
child.on("error", (e) =>
|
|
2763
|
+
child.on("close", (code) => resolve7({ exitCode: code ?? 1, stdout, stderr }));
|
|
2764
|
+
child.on("error", (e) => resolve7({ exitCode: 1, stdout: "", stderr: e.message }));
|
|
2740
2765
|
});
|
|
2741
2766
|
}
|
|
2742
2767
|
function extractPatchedFiles(output) {
|
|
@@ -2938,7 +2963,7 @@ function findGitDir2(cwd) {
|
|
|
2938
2963
|
return null;
|
|
2939
2964
|
}
|
|
2940
2965
|
function runGit2(args, cwd, signal) {
|
|
2941
|
-
return new Promise((
|
|
2966
|
+
return new Promise((resolve7) => {
|
|
2942
2967
|
let stdout = "";
|
|
2943
2968
|
let stderr = "";
|
|
2944
2969
|
const child = spawn("git", args, { cwd, signal, env: buildChildEnv(), stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -2948,8 +2973,8 @@ function runGit2(args, cwd, signal) {
|
|
|
2948
2973
|
child.stderr?.on("data", (c) => {
|
|
2949
2974
|
stderr += c.toString();
|
|
2950
2975
|
});
|
|
2951
|
-
child.on("close", (code) =>
|
|
2952
|
-
child.on("error", (e) =>
|
|
2976
|
+
child.on("close", (code) => resolve7({ stdout, stderr, exitCode: code ?? 0 }));
|
|
2977
|
+
child.on("error", (e) => resolve7({ stdout: "", stderr: e.message, exitCode: 1 }));
|
|
2953
2978
|
});
|
|
2954
2979
|
}
|
|
2955
2980
|
async function fileDiff(input, ctx, signal) {
|
|
@@ -3200,8 +3225,8 @@ async function* spawnStream(opts) {
|
|
|
3200
3225
|
let spawnFailed = false;
|
|
3201
3226
|
for (; ; ) {
|
|
3202
3227
|
while (queue.length === 0) {
|
|
3203
|
-
await new Promise((
|
|
3204
|
-
waiter =
|
|
3228
|
+
await new Promise((resolve7) => {
|
|
3229
|
+
waiter = resolve7;
|
|
3205
3230
|
});
|
|
3206
3231
|
}
|
|
3207
3232
|
const chunk = queue.shift();
|
|
@@ -3920,7 +3945,7 @@ async function detectManager2(cwd) {
|
|
|
3920
3945
|
return "npm";
|
|
3921
3946
|
}
|
|
3922
3947
|
function runOutdated(manager, args, cwd, signal) {
|
|
3923
|
-
return new Promise((
|
|
3948
|
+
return new Promise((resolve7) => {
|
|
3924
3949
|
let stdout = "";
|
|
3925
3950
|
let stderr = "";
|
|
3926
3951
|
const MAX = 1e5;
|
|
@@ -3933,10 +3958,10 @@ function runOutdated(manager, args, cwd, signal) {
|
|
|
3933
3958
|
});
|
|
3934
3959
|
child.on("close", (code) => {
|
|
3935
3960
|
const result = parseOutdatedOutput(stdout, code ?? 0);
|
|
3936
|
-
|
|
3961
|
+
resolve7(result);
|
|
3937
3962
|
});
|
|
3938
3963
|
child.on("error", (e) => {
|
|
3939
|
-
|
|
3964
|
+
resolve7({
|
|
3940
3965
|
exit_code: 1,
|
|
3941
3966
|
packages: [],
|
|
3942
3967
|
total: 0,
|
|
@@ -4060,7 +4085,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
|
|
|
4060
4085
|
};
|
|
4061
4086
|
}
|
|
4062
4087
|
args.push("--timestamps", service);
|
|
4063
|
-
return new Promise((
|
|
4088
|
+
return new Promise((resolve7) => {
|
|
4064
4089
|
let stdout = "";
|
|
4065
4090
|
let stderr = "";
|
|
4066
4091
|
const MAX = 2e5;
|
|
@@ -4076,7 +4101,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
|
|
|
4076
4101
|
if (settled) return;
|
|
4077
4102
|
settled = true;
|
|
4078
4103
|
clearTimeout(timer);
|
|
4079
|
-
|
|
4104
|
+
resolve7(result);
|
|
4080
4105
|
};
|
|
4081
4106
|
const child = spawn("docker", args, { cwd, signal, env: buildChildEnv(), stdio: ["ignore", "pipe", "pipe"] });
|
|
4082
4107
|
const timer = setTimeout(() => {
|