@wrongstack/tools 0.313.0 → 0.313.1
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/audit.js +10 -4055
- package/dist/bash.js +9 -2308
- package/dist/batch-tool-use.js +2 -187
- package/dist/browser/index.js +25 -1339
- package/dist/builtin.js +69 -33949
- package/dist/chunk-2CTB3UK5.js +197 -0
- package/dist/chunk-2ME7ZWDD.js +1272 -0
- package/dist/chunk-2TFQDEPU.js +113 -0
- package/dist/chunk-2ZCJNKFE.js +315 -0
- package/dist/chunk-3PVYQFRQ.js +472 -0
- package/dist/chunk-3QMQBO5Z.js +89 -0
- package/dist/chunk-42AKKX7O.js +385 -0
- package/dist/chunk-42SKEETB.js +113 -0
- package/dist/chunk-4BHUSMNL.js +104 -0
- package/dist/chunk-4I4LWFOO.js +431 -0
- package/dist/chunk-553IQUMO.js +478 -0
- package/dist/chunk-55KF77OK.js +1944 -0
- package/dist/chunk-6HLZK37X.js +359 -0
- package/dist/chunk-6RNIFLG4.js +305 -0
- package/dist/chunk-A6BRWIXN.js +317 -0
- package/dist/chunk-AHHDWNXC.js +200 -0
- package/dist/chunk-B2CIOKWP.js +899 -0
- package/dist/chunk-BTSFTGIL.js +7 -0
- package/dist/chunk-D33S4RQG.js +222 -0
- package/dist/chunk-DIJKHSUO.js +134 -0
- package/dist/chunk-DPL47QGS.js +3515 -0
- package/dist/chunk-EMRGN4KM.js +170 -0
- package/dist/chunk-FGOABE4Z.js +955 -0
- package/dist/chunk-FW65TP4G.js +520 -0
- package/dist/chunk-GOIZNNOA.js +221 -0
- package/dist/chunk-H5MJUAA6.js +295 -0
- package/dist/chunk-H5OHH6F4.js +223 -0
- package/dist/chunk-HC5RM4WY.js +199 -0
- package/dist/chunk-HEQFMLZ7.js +190 -0
- package/dist/chunk-HFXSNKCV.js +196 -0
- package/dist/chunk-HXSBQ2SE.js +1723 -0
- package/dist/chunk-ILESNGNM.js +163 -0
- package/dist/chunk-INF5CGAO.js +137 -0
- package/dist/chunk-IWDFZ6XR.js +337 -0
- package/dist/chunk-IXMNTNW5.js +238 -0
- package/dist/chunk-J4SRJKBW.js +428 -0
- package/dist/chunk-J5SKD6LN.js +235 -0
- package/dist/chunk-JRJJX3L5.js +424 -0
- package/dist/chunk-KXNDHMUB.js +366 -0
- package/dist/chunk-LIJQMYYX.js +59 -0
- package/dist/chunk-MAN26PZ5.js +260 -0
- package/dist/chunk-MKRQMLZA.js +474 -0
- package/dist/chunk-NBDZMMG2.js +169 -0
- package/dist/chunk-NHA6BEIH.js +101 -0
- package/dist/chunk-OA6YJIWL.js +4412 -0
- package/dist/chunk-OZC255IC.js +2830 -0
- package/dist/chunk-PUR6WU2B.js +154 -0
- package/dist/chunk-Q5JPPCZC.js +12 -0
- package/dist/chunk-QBV725YG.js +128 -0
- package/dist/chunk-QHVW4AAM.js +892 -0
- package/dist/chunk-QNJ7AQ4B.js +1000 -0
- package/dist/chunk-RGISBZBD.js +231 -0
- package/dist/chunk-RJZQWEMS.js +84 -0
- package/dist/chunk-RP2ZA47V.js +15 -0
- package/dist/chunk-RXISBFR5.js +315 -0
- package/dist/chunk-S5CCLZL3.js +99 -0
- package/dist/chunk-TVTCSBJF.js +122 -0
- package/dist/chunk-U4D5S3VQ.js +21 -0
- package/dist/chunk-U4VAATKP.js +193 -0
- package/dist/chunk-UKU2ZX4C.js +203 -0
- package/dist/chunk-UNSKG6DC.js +159 -0
- package/dist/chunk-URFKEIHM.js +1091 -0
- package/dist/chunk-UTV7YAW7.js +178 -0
- package/dist/chunk-V43EQ6VR.js +68 -0
- package/dist/chunk-VB3MJGCV.js +610 -0
- package/dist/chunk-WHIIIREL.js +223 -0
- package/dist/chunk-XMIFYKUT.js +1371 -0
- package/dist/chunk-YF2RSV34.js +54 -0
- package/dist/chunk-Z6DAKQ3U.js +1 -0
- package/dist/chunk-ZIGAZFWE.js +522 -0
- package/dist/circuit-breaker.js +3 -191
- package/dist/codebase-index/index.js +84 -13688
- package/dist/codebase-index/parser-worker-script.js +8 -3995
- package/dist/codebase-index/project-server.js +60 -8548
- package/dist/codebase-index/worker.js +20 -8416
- package/dist/design.js +2 -299
- package/dist/diff.js +4 -256
- package/dist/document.js +4 -222
- package/dist/e2e.js +5 -476
- package/dist/edit.js +14 -10200
- package/dist/exec.js +16 -3131
- package/dist/fetch.js +8 -398
- package/dist/format.js +10 -3750
- package/dist/generic-parser-VUXDIAOZ.js +13 -0
- package/dist/git.js +4 -380
- package/dist/glob.js +6 -280
- package/dist/go-parser-6CA77WZ4.js +469 -0
- package/dist/grep.js +7 -604
- package/dist/index.js +318 -35387
- package/dist/install.js +10 -4091
- package/dist/json-parser-7YMDJSBJ.js +213 -0
- package/dist/json.js +4 -665
- package/dist/kanban.js +3 -2096
- package/dist/languages/index.js +23 -4664
- package/dist/legacy-bridge-7UKZT46G.js +18 -0
- package/dist/lint.js +10 -3706
- package/dist/logs.js +4 -287
- package/dist/memory.js +6 -215
- package/dist/mode.js +3 -99
- package/dist/outdated.js +4 -5170
- package/dist/pack.js +65 -33897
- package/dist/parser-dispatch-VPOFDO2U.js +14 -0
- package/dist/patch.js +13 -9935
- package/dist/plan.js +5 -3286
- package/dist/process-registry.js +8 -651
- package/dist/ps-slash.js +12 -1439
- package/dist/py-parser-GPM5VYRG.js +16 -0
- package/dist/read.js +13 -9816
- package/dist/replace.js +15 -10014
- package/dist/rs-parser-WVQ4KYCX.js +81 -0
- package/dist/scaffold.js +4 -253
- package/dist/search.js +5 -585
- package/dist/session-kanban.js +30 -972
- package/dist/skill.js +2 -215
- package/dist/task.js +5 -3410
- package/dist/test.js +10 -3773
- package/dist/todo.js +4 -2891
- package/dist/tool-help.js +3 -123
- package/dist/tool-search.js +3 -79
- package/dist/tool-tier.js +68 -33984
- package/dist/tool-use.js +2 -93
- package/dist/tree-sitter-parser-YCILHGZD.js +17 -0
- package/dist/tree.js +4 -288
- package/dist/ts-parser-YH4ZMWMH.js +232 -0
- package/dist/typecheck.js +10 -3753
- package/dist/win32.js +6 -60
- package/dist/write.js +14 -9882
- package/dist/yaml-parser-GFAOKV53.js +157 -0
- package/package.json +5 -5
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// src/_output-spool.ts
|
|
2
|
+
import { createWriteStream, mkdirSync } from "node:fs";
|
|
3
|
+
import * as fsp from "node:fs/promises";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { wstackGlobalRoot } from "@wrongstack/core/utils";
|
|
6
|
+
var SPOOL_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
7
|
+
var SPOOL_WRITE_HWM_BYTES = 4 * 1024 * 1024;
|
|
8
|
+
var sweepStarted = false;
|
|
9
|
+
function toolOutputDir() {
|
|
10
|
+
return path.join(wstackGlobalRoot(), "tool-output");
|
|
11
|
+
}
|
|
12
|
+
function sweepOldSpoolFiles(dir) {
|
|
13
|
+
if (sweepStarted) return;
|
|
14
|
+
sweepStarted = true;
|
|
15
|
+
void (async () => {
|
|
16
|
+
try {
|
|
17
|
+
const now = Date.now();
|
|
18
|
+
for (const name of await fsp.readdir(dir)) {
|
|
19
|
+
if (!name.endsWith(".log")) continue;
|
|
20
|
+
const p = path.join(dir, name);
|
|
21
|
+
try {
|
|
22
|
+
const st = await fsp.stat(p);
|
|
23
|
+
if (now - st.mtimeMs > SPOOL_RETENTION_MS) await fsp.unlink(p);
|
|
24
|
+
} catch {
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
} catch {
|
|
28
|
+
}
|
|
29
|
+
})();
|
|
30
|
+
}
|
|
31
|
+
function spoolNote(info) {
|
|
32
|
+
const dropped = info.droppedBytes > 0 ? `, ~${info.droppedBytes} bytes dropped under backpressure` : "";
|
|
33
|
+
return `
|
|
34
|
+
[output truncated \u2014 full ${info.bytes} bytes at ${info.path}${dropped}; read/grep that file selectively instead of re-running with more output]`;
|
|
35
|
+
}
|
|
36
|
+
function createOutputSpool(opts) {
|
|
37
|
+
const threshold = opts.thresholdBytes ?? 32768;
|
|
38
|
+
const safeTool = opts.tool.replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 40) || "tool";
|
|
39
|
+
let head = "";
|
|
40
|
+
let headBytes = 0;
|
|
41
|
+
let totalBytes = 0;
|
|
42
|
+
let droppedBytes = 0;
|
|
43
|
+
let stream = null;
|
|
44
|
+
let filePath = null;
|
|
45
|
+
let failed = false;
|
|
46
|
+
let finalized = false;
|
|
47
|
+
const open = () => {
|
|
48
|
+
if (stream || failed) return;
|
|
49
|
+
try {
|
|
50
|
+
const dir = toolOutputDir();
|
|
51
|
+
mkdirSync(dir, { recursive: true });
|
|
52
|
+
sweepOldSpoolFiles(dir);
|
|
53
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
54
|
+
const rand = Math.random().toString(36).slice(2, 6);
|
|
55
|
+
filePath = path.join(dir, `${stamp}-${safeTool}-${rand}.log`);
|
|
56
|
+
stream = createWriteStream(filePath, { flags: "w", encoding: "utf8" });
|
|
57
|
+
stream.on("error", () => {
|
|
58
|
+
failed = true;
|
|
59
|
+
stream = null;
|
|
60
|
+
filePath = null;
|
|
61
|
+
});
|
|
62
|
+
stream.write(head);
|
|
63
|
+
} catch {
|
|
64
|
+
failed = true;
|
|
65
|
+
stream = null;
|
|
66
|
+
filePath = null;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
write(text) {
|
|
71
|
+
if (finalized || !text) return;
|
|
72
|
+
const textBytes = Buffer.byteLength(text, "utf8");
|
|
73
|
+
totalBytes += textBytes;
|
|
74
|
+
if (!stream && !failed) {
|
|
75
|
+
if (headBytes + textBytes <= threshold) {
|
|
76
|
+
head += text;
|
|
77
|
+
headBytes += textBytes;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
head += text;
|
|
81
|
+
open();
|
|
82
|
+
head = "";
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (stream) {
|
|
86
|
+
if (stream.writableLength > SPOOL_WRITE_HWM_BYTES) {
|
|
87
|
+
droppedBytes += textBytes;
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
stream.write(text);
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
finalize() {
|
|
94
|
+
if (finalized) {
|
|
95
|
+
return filePath ? { path: filePath, bytes: totalBytes, droppedBytes } : null;
|
|
96
|
+
}
|
|
97
|
+
finalized = true;
|
|
98
|
+
head = "";
|
|
99
|
+
if (!stream || !filePath) return null;
|
|
100
|
+
try {
|
|
101
|
+
stream.end();
|
|
102
|
+
} catch {
|
|
103
|
+
}
|
|
104
|
+
return { path: filePath, bytes: totalBytes, droppedBytes };
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export {
|
|
110
|
+
spoolNote,
|
|
111
|
+
createOutputSpool
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=chunk-2TFQDEPU.js.map
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import {
|
|
2
|
+
enqueueReindex
|
|
3
|
+
} from "./chunk-2ME7ZWDD.js";
|
|
4
|
+
import {
|
|
5
|
+
resolveRealInsideRoot,
|
|
6
|
+
safeResolveReal,
|
|
7
|
+
sha256hex
|
|
8
|
+
} from "./chunk-D33S4RQG.js";
|
|
9
|
+
|
|
10
|
+
// src/patch.ts
|
|
11
|
+
import { spawn } from "node:child_process";
|
|
12
|
+
import * as fs from "node:fs/promises";
|
|
13
|
+
import * as os from "node:os";
|
|
14
|
+
import * as path from "node:path";
|
|
15
|
+
import { buildChildEnv, toErrorMessage } from "@wrongstack/core/utils";
|
|
16
|
+
var patchTool = {
|
|
17
|
+
name: "patch",
|
|
18
|
+
category: "Filesystem",
|
|
19
|
+
description: "Apply a unified diff (patch) to the project. This is the correct tool when you have a diff that needs to be applied precisely, including handling of rejects.",
|
|
20
|
+
usageHint: "Best used when you already have a diff (from generation, external source, or previous step).\n- Use `dry_run: true` to see what would happen without modifying files.\n- Applied with `--merge`: a conflicting hunk writes git-style conflict\n markers (<<<<<<< / ======= / >>>>>>>) INTO the file and reports failure.\n It does NOT create .rej/.orig files. `files` lists what changed on disk\n even when the patch failed, so read those back before retrying.\nOften cleaner than many small `edit` operations for larger changes.",
|
|
21
|
+
selection: {
|
|
22
|
+
doNotUseWhen: "you do not already have a unified diff or only need one precise replacement.",
|
|
23
|
+
useInstead: ["edit"]
|
|
24
|
+
},
|
|
25
|
+
permission: "confirm",
|
|
26
|
+
// WS-046: gives permission decisions something to key on.
|
|
27
|
+
// The target directory. The patch body itself is unstable (every diff
|
|
28
|
+
// differs), so it could never re-match its own stored rule.
|
|
29
|
+
subjectKey: "directory",
|
|
30
|
+
mutating: true,
|
|
31
|
+
capabilities: ["fs.write"],
|
|
32
|
+
icon: "edit",
|
|
33
|
+
timeoutMs: 3e4,
|
|
34
|
+
inputSchema: {
|
|
35
|
+
type: "object",
|
|
36
|
+
properties: {
|
|
37
|
+
patch: { type: "string", description: "Unified diff patch content" },
|
|
38
|
+
directory: { type: "string", description: "Root directory for patch (default: cwd)" },
|
|
39
|
+
strip: { type: "integer", description: "Strip leading path components (default: 1)" },
|
|
40
|
+
dry_run: { type: "boolean", description: "Preview without applying" }
|
|
41
|
+
},
|
|
42
|
+
required: ["patch"]
|
|
43
|
+
},
|
|
44
|
+
async execute(input, ctx, opts) {
|
|
45
|
+
if (!input?.patch) throw new Error("patch: patch content is required");
|
|
46
|
+
const strip = Math.max(1, input.strip ?? 1);
|
|
47
|
+
const dryRun = input.dry_run ?? false;
|
|
48
|
+
const refuse = (message) => ({
|
|
49
|
+
applied: 0,
|
|
50
|
+
rejected: 1,
|
|
51
|
+
files: [],
|
|
52
|
+
dry_run: dryRun,
|
|
53
|
+
message
|
|
54
|
+
});
|
|
55
|
+
let dir;
|
|
56
|
+
try {
|
|
57
|
+
dir = input.directory ? await safeResolveReal(input.directory, ctx) : ctx.cwd;
|
|
58
|
+
} catch (err) {
|
|
59
|
+
return refuse(`patch refused: ${toErrorMessage(err)}`);
|
|
60
|
+
}
|
|
61
|
+
const realRoot = await fs.realpath(ctx.projectRoot).catch(() => path.resolve(ctx.projectRoot));
|
|
62
|
+
const targets = extractDiffTargets(input.patch);
|
|
63
|
+
const resolvedTargets = [];
|
|
64
|
+
for (const t of targets) {
|
|
65
|
+
const stripped = stripPathComponents(t.raw, strip);
|
|
66
|
+
if (!stripped) continue;
|
|
67
|
+
if (path.isAbsolute(stripped)) {
|
|
68
|
+
return refuse(`patch refused: target "${t.raw}" strips to absolute path`);
|
|
69
|
+
}
|
|
70
|
+
const candidate = path.resolve(dir, stripped);
|
|
71
|
+
let real;
|
|
72
|
+
try {
|
|
73
|
+
real = await resolveRealInsideRoot(candidate, ctx);
|
|
74
|
+
} catch (err) {
|
|
75
|
+
return refuse(`patch refused: target "${t.raw}" ${toErrorMessage(err)}`);
|
|
76
|
+
}
|
|
77
|
+
const rel = path.relative(realRoot, real);
|
|
78
|
+
if (rel.startsWith("..") || path.isAbsolute(rel)) {
|
|
79
|
+
return refuse(`patch refused: target "${t.raw}" resolves outside project root`);
|
|
80
|
+
}
|
|
81
|
+
resolvedTargets.push({ raw: t.raw, deleted: t.deleted, abs: real });
|
|
82
|
+
}
|
|
83
|
+
const beforeContents = /* @__PURE__ */ new Map();
|
|
84
|
+
const beforeExisted = /* @__PURE__ */ new Set();
|
|
85
|
+
if (!dryRun) {
|
|
86
|
+
for (const target of resolvedTargets) {
|
|
87
|
+
const existed = (await fs.stat(target.abs).catch(() => null))?.isFile() ?? false;
|
|
88
|
+
if (existed) beforeExisted.add(target.abs);
|
|
89
|
+
beforeContents.set(target.abs, await readTextForTracking(target.abs));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), ".wstack_patch_"));
|
|
93
|
+
try {
|
|
94
|
+
await fs.chmod(tmpDir, 448).catch(() => {
|
|
95
|
+
});
|
|
96
|
+
const patchFile = path.join(tmpDir, "in.diff");
|
|
97
|
+
await fs.writeFile(patchFile, input.patch, { mode: 384 });
|
|
98
|
+
const args = [`-p${strip}`, "--merge", ...dryRun ? ["--dry-run"] : [], "-i", patchFile];
|
|
99
|
+
const result = await runPatch(args, dir, opts.signal, {
|
|
100
|
+
patchFile,
|
|
101
|
+
strip,
|
|
102
|
+
dryRun
|
|
103
|
+
});
|
|
104
|
+
const touched = [];
|
|
105
|
+
if (!dryRun) {
|
|
106
|
+
for (const target of resolvedTargets) {
|
|
107
|
+
const abs = target.abs;
|
|
108
|
+
const before = beforeContents.get(abs) ?? null;
|
|
109
|
+
const stat2 = await fs.stat(abs).catch(() => null);
|
|
110
|
+
if (!stat2?.isFile()) {
|
|
111
|
+
if (beforeExisted.has(abs)) {
|
|
112
|
+
touched.push(abs);
|
|
113
|
+
ctx.session?.recordFileChange?.({
|
|
114
|
+
path: abs,
|
|
115
|
+
action: "deleted",
|
|
116
|
+
before,
|
|
117
|
+
after: null
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const after = await readTextForTracking(abs);
|
|
123
|
+
if (after === null || after === before) continue;
|
|
124
|
+
touched.push(abs);
|
|
125
|
+
ctx.recordRead?.(abs, stat2.mtimeMs, "write", sha256hex(after));
|
|
126
|
+
ctx.session?.recordFileChange?.({
|
|
127
|
+
path: abs,
|
|
128
|
+
action: before === null ? "created" : "modified",
|
|
129
|
+
before,
|
|
130
|
+
after
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
if (touched.length > 0) {
|
|
134
|
+
try {
|
|
135
|
+
enqueueReindex({ projectRoot: ctx.projectRoot, files: touched });
|
|
136
|
+
} catch {
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (result.exitCode !== 0) {
|
|
141
|
+
if (!dryRun) {
|
|
142
|
+
const partial = touched.length > 0 ? ` ${touched.length} file(s) were still modified on disk and have been recorded for rewind: ${touched.map((p) => path.relative(realRoot, p) || p).join(", ")}.` : "";
|
|
143
|
+
return {
|
|
144
|
+
applied: touched.length,
|
|
145
|
+
rejected: 1,
|
|
146
|
+
// Normalize to relative-to-realRoot for API consistency with the
|
|
147
|
+
// success path (which returns GNU patch's dir-relative names).
|
|
148
|
+
// `touched` entries are realpaths from resolveRealInsideRoot, and
|
|
149
|
+
// realRoot is also a realpath, so path.relative is like-for-like.
|
|
150
|
+
files: touched.map((p) => path.relative(realRoot, p) || p),
|
|
151
|
+
dry_run: dryRun,
|
|
152
|
+
message: `patch failed: ${result.stderr || result.stdout}${partial}`
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
const wouldPatch = extractPatchedFiles(result.stdout);
|
|
156
|
+
return {
|
|
157
|
+
applied: wouldPatch.length,
|
|
158
|
+
rejected: 1,
|
|
159
|
+
files: wouldPatch,
|
|
160
|
+
dry_run: dryRun,
|
|
161
|
+
message: `patch preview: would conflict \u2014 ${result.stderr || result.stdout}`
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
const patched = result.engine === "git" ? [
|
|
165
|
+
...new Set(
|
|
166
|
+
resolvedTargets.map((target) => path.relative(dir, target.abs) || target.abs)
|
|
167
|
+
)
|
|
168
|
+
] : extractPatchedFiles(result.stdout);
|
|
169
|
+
return {
|
|
170
|
+
applied: patched.length,
|
|
171
|
+
rejected: 0,
|
|
172
|
+
files: patched,
|
|
173
|
+
dry_run: dryRun,
|
|
174
|
+
message: result.stdout || "patch applied"
|
|
175
|
+
};
|
|
176
|
+
} finally {
|
|
177
|
+
await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => {
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
var MAX_TRACKING_BYTES = 5 * 1024 * 1024;
|
|
183
|
+
async function readTextForTracking(absPath) {
|
|
184
|
+
try {
|
|
185
|
+
const stat2 = await fs.stat(absPath);
|
|
186
|
+
if (!stat2.isFile() || stat2.size > MAX_TRACKING_BYTES) return null;
|
|
187
|
+
const buf = await fs.readFile(absPath);
|
|
188
|
+
if (buf.includes(0)) return null;
|
|
189
|
+
return buf.toString("utf8");
|
|
190
|
+
} catch {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function extractDiffTargets(patch) {
|
|
195
|
+
const out = [];
|
|
196
|
+
const clean = (raw) => {
|
|
197
|
+
if (!raw) return "";
|
|
198
|
+
return (raw.length > 4096 ? raw.slice(0, 4096) : raw).trim();
|
|
199
|
+
};
|
|
200
|
+
let lastOld;
|
|
201
|
+
let inHunk = false;
|
|
202
|
+
let oldLinesLeft = 0;
|
|
203
|
+
let newLinesLeft = 0;
|
|
204
|
+
for (const line of patch.split(/\r?\n/)) {
|
|
205
|
+
const hunkMatch = /^@@ -\d+(?:,(\d+))? \+\d+(?:,(\d+))? @@/.exec(line);
|
|
206
|
+
if (hunkMatch) {
|
|
207
|
+
inHunk = true;
|
|
208
|
+
oldLinesLeft = hunkMatch[1] ? Number(hunkMatch[1]) : 1;
|
|
209
|
+
newLinesLeft = hunkMatch[2] ? Number(hunkMatch[2]) : 1;
|
|
210
|
+
lastOld = void 0;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (inHunk) {
|
|
214
|
+
const ch = line[0];
|
|
215
|
+
if (ch === "-") oldLinesLeft--;
|
|
216
|
+
else if (ch === "+") newLinesLeft--;
|
|
217
|
+
else if (ch === " " || ch === void 0) {
|
|
218
|
+
oldLinesLeft--;
|
|
219
|
+
newLinesLeft--;
|
|
220
|
+
}
|
|
221
|
+
if (oldLinesLeft <= 0 && newLinesLeft <= 0) inHunk = false;
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
const oldMatch = /^---\s+([^\t\r\n]+)/.exec(line);
|
|
225
|
+
if (oldMatch) {
|
|
226
|
+
lastOld = clean(oldMatch[1]);
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
const newMatch = /^\+\+\+\s+([^\t\r\n]+)/.exec(line);
|
|
230
|
+
if (!newMatch) continue;
|
|
231
|
+
const newTarget = clean(newMatch[1]);
|
|
232
|
+
if (newTarget && newTarget !== "/dev/null") {
|
|
233
|
+
out.push({ raw: newTarget, deleted: false });
|
|
234
|
+
} else if (lastOld && lastOld !== "/dev/null") {
|
|
235
|
+
out.push({ raw: lastOld, deleted: true });
|
|
236
|
+
}
|
|
237
|
+
lastOld = void 0;
|
|
238
|
+
}
|
|
239
|
+
return out;
|
|
240
|
+
}
|
|
241
|
+
function stripPathComponents(p, strip) {
|
|
242
|
+
const s = p.replace(/\\/g, "/");
|
|
243
|
+
let idx = 0;
|
|
244
|
+
for (let i = 0; i < strip; i++) {
|
|
245
|
+
while (idx < s.length && s[idx] !== "/") idx++;
|
|
246
|
+
let hadSlash = false;
|
|
247
|
+
while (idx < s.length && s[idx] === "/") {
|
|
248
|
+
idx++;
|
|
249
|
+
hadSlash = true;
|
|
250
|
+
}
|
|
251
|
+
if (!hadSlash) return void 0;
|
|
252
|
+
}
|
|
253
|
+
return s.slice(idx) || void 0;
|
|
254
|
+
}
|
|
255
|
+
function runPatch(args, cwd, signal, fallback) {
|
|
256
|
+
return runPatchProcess("patch", args, cwd, signal).then(async (result) => {
|
|
257
|
+
if (!result.unavailable) return { ...result, engine: "patch" };
|
|
258
|
+
const gitArgs = [
|
|
259
|
+
"apply",
|
|
260
|
+
"--unsafe-paths",
|
|
261
|
+
`-p${fallback.strip}`,
|
|
262
|
+
"--verbose",
|
|
263
|
+
...fallback.dryRun ? ["--check"] : [],
|
|
264
|
+
fallback.patchFile
|
|
265
|
+
];
|
|
266
|
+
const gitResult = await runPatchProcess("git", gitArgs, cwd, signal);
|
|
267
|
+
return { ...gitResult, engine: "git" };
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
function runPatchProcess(command, args, cwd, signal) {
|
|
271
|
+
return new Promise((resolve2) => {
|
|
272
|
+
let stdout = "";
|
|
273
|
+
let stderr = "";
|
|
274
|
+
const env = { ...buildChildEnv(), LANG: "C", LC_ALL: "C" };
|
|
275
|
+
const child = spawn(command, args, {
|
|
276
|
+
cwd,
|
|
277
|
+
signal,
|
|
278
|
+
env,
|
|
279
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
280
|
+
windowsHide: true
|
|
281
|
+
});
|
|
282
|
+
child.stdout?.on("data", (c) => {
|
|
283
|
+
stdout += c.toString();
|
|
284
|
+
});
|
|
285
|
+
child.stderr?.on("data", (c) => {
|
|
286
|
+
stderr += c.toString();
|
|
287
|
+
});
|
|
288
|
+
child.on(
|
|
289
|
+
"close",
|
|
290
|
+
(code) => resolve2({ exitCode: code ?? 1, stdout, stderr, unavailable: false })
|
|
291
|
+
);
|
|
292
|
+
child.on(
|
|
293
|
+
"error",
|
|
294
|
+
(e) => resolve2({
|
|
295
|
+
exitCode: 1,
|
|
296
|
+
stdout: "",
|
|
297
|
+
stderr: e.message,
|
|
298
|
+
unavailable: e.code === "ENOENT"
|
|
299
|
+
})
|
|
300
|
+
);
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
function extractPatchedFiles(output) {
|
|
304
|
+
const files = [];
|
|
305
|
+
const re = /(?:patching|checking) file (.+)/gi;
|
|
306
|
+
for (const m of output.matchAll(re)) {
|
|
307
|
+
if (m[1]) files.push(m[1]);
|
|
308
|
+
}
|
|
309
|
+
return files;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export {
|
|
313
|
+
patchTool
|
|
314
|
+
};
|
|
315
|
+
//# sourceMappingURL=chunk-2ZCJNKFE.js.map
|