




















@@ -0,0 +1,173 @@
1+import { execFileSync } from "node:child_process";
2+import { mkdirSync, rmSync, writeFileSync } from "node:fs";
3+import path from "node:path";
4+import { afterEach, describe, expect, it } from "vitest";
5+import { collectPackagePatchViolations } from "../../scripts/check-package-patches.mjs";
6+import { cleanupTempDirs, makeTempRepoRoot, writeJsonFile } from "../helpers/temp-repo.js";
7+8+const tempDirs: string[] = [];
9+10+const nestedGitEnvKeys = [
11+"GIT_ALTERNATE_OBJECT_DIRECTORIES",
12+"GIT_DIR",
13+"GIT_INDEX_FILE",
14+"GIT_OBJECT_DIRECTORY",
15+"GIT_QUARANTINE_PATH",
16+"GIT_WORK_TREE",
17+] as const;
18+19+function createNestedGitEnv(): NodeJS.ProcessEnv {
20+const env = {
21+ ...process.env,
22+GIT_CONFIG_NOSYSTEM: "1",
23+GIT_TERMINAL_PROMPT: "0",
24+};
25+for (const key of nestedGitEnvKeys) {
26+delete env[key];
27+}
28+return env;
29+}
30+31+function git(cwd: string, args: string[]) {
32+execFileSync("git", args, {
33+ cwd,
34+encoding: "utf8",
35+env: createNestedGitEnv(),
36+});
37+}
38+39+function makeRepo() {
40+const dir = makeTempRepoRoot(tempDirs, "openclaw-package-patches-");
41+git(dir, ["init", "-q", "--initial-branch=main"]);
42+writeJsonFile(path.join(dir, "package.json"), { name: "fixture" });
43+writeFileSync(path.join(dir, "pnpm-workspace.yaml"), "packages:\n - .\n", "utf8");
44+writeFileSync(path.join(dir, "pnpm-lock.yaml"), "lockfileVersion: '9.0'\n", "utf8");
45+git(dir, ["add", "package.json", "pnpm-workspace.yaml", "pnpm-lock.yaml"]);
46+return dir;
47+}
48+49+afterEach(() => {
50+cleanupTempDirs(tempDirs);
51+});
52+53+describe("check-package-patches", () => {
54+it("allows the existing legacy pnpm patches", () => {
55+const dir = makeRepo();
56+mkdirSync(path.join(dir, "patches"), { recursive: true });
57+writeFileSync(
58+path.join(dir, "pnpm-workspace.yaml"),
59+`packages:
60+ - .
61+patchedDependencies:
62+ "baileys@7.0.0-rc11": "patches/baileys@7.0.0-rc11.patch"
63+ "@agentclientprotocol/claude-agent-acp@0.33.1": "patches/@agentclientprotocol__claude-agent-acp@0.33.1.patch"
64+`,
65+"utf8",
66+);
67+writeFileSync(
68+path.join(dir, "pnpm-lock.yaml"),
69+`lockfileVersion: '9.0'
70+patchedDependencies:
71+ '@agentclientprotocol/claude-agent-acp@0.33.1': 3995624bb834cc60fea1461c7ef33f1fcdd8fb58b8f43f2f1490bc689f6e1be2
72+ baileys@7.0.0-rc11: a9aea1790d2c65b1ae543c77faca4119bbfb91ee3b6ca6c38d1cad4f5702ada2
73+`,
74+"utf8",
75+);
76+writeFileSync(path.join(dir, "patches", "baileys@7.0.0-rc11.patch"), "diff\n", "utf8");
77+writeFileSync(
78+path.join(dir, "patches", "@agentclientprotocol__claude-agent-acp@0.33.1.patch"),
79+"diff\n",
80+"utf8",
81+);
82+git(dir, ["add", "pnpm-workspace.yaml", "pnpm-lock.yaml", "patches"]);
83+84+expect(collectPackagePatchViolations(dir)).toEqual([]);
85+});
86+87+it("rejects new workspace patchedDependencies and patch files", () => {
88+const dir = makeRepo();
89+mkdirSync(path.join(dir, "patches"), { recursive: true });
90+mkdirSync(path.join(dir, "fixtures"), { recursive: true });
91+writeFileSync(
92+path.join(dir, "pnpm-workspace.yaml"),
93+`packages:
94+ - .
95+patchedDependencies:
96+ "left-pad@1.3.0": "patches/left-pad@1.3.0.patch"
97+`,
98+"utf8",
99+);
100+writeFileSync(path.join(dir, "patches", "left-pad@1.3.0.patch"), "diff\n", "utf8");
101+writeFileSync(path.join(dir, "fixtures", "fixture.patch"), "diff\n", "utf8");
102+git(dir, ["add", "pnpm-workspace.yaml", "patches", "fixtures"]);
103+104+expect(collectPackagePatchViolations(dir)).toEqual([
105+{
106+file: "pnpm-workspace.yaml",
107+kind: "patchedDependency",
108+detail: "left-pad@1.3.0 -> patches/left-pad@1.3.0.patch",
109+},
110+{
111+file: "fixtures/fixture.patch",
112+kind: "patchFile",
113+detail: "new package patch file",
114+},
115+{
116+file: "patches/left-pad@1.3.0.patch",
117+kind: "patchFile",
118+detail: "new package patch file",
119+},
120+]);
121+});
122+123+it("rejects lockfile-only and package-local patch declarations", () => {
124+const dir = makeRepo();
125+writeJsonFile(path.join(dir, "package.json"), {
126+name: "fixture",
127+pnpm: {
128+patchedDependencies: {
129+"nested@1.0.0": "patches/nested.patch",
130+},
131+},
132+});
133+writeFileSync(
134+path.join(dir, "pnpm-lock.yaml"),
135+`lockfileVersion: '9.0'
136+patchedDependencies:
137+ hidden@1.0.0: abc123
138+`,
139+"utf8",
140+);
141+git(dir, ["add", "package.json", "pnpm-lock.yaml"]);
142+143+expect(collectPackagePatchViolations(dir)).toEqual([
144+{
145+file: "pnpm-lock.yaml",
146+kind: "patchedDependency",
147+detail: "hidden@1.0.0 -> abc123",
148+},
149+{
150+file: "package.json",
151+kind: "packageJsonPatchedDependency",
152+detail: "nested@1.0.0 -> patches/nested.patch",
153+},
154+]);
155+});
156+157+it("skips tracked package manifests deleted in the worktree", () => {
158+const dir = makeRepo();
159+mkdirSync(path.join(dir, "packages", "deleted"), { recursive: true });
160+writeJsonFile(path.join(dir, "packages", "deleted", "package.json"), {
161+name: "deleted",
162+pnpm: {
163+patchedDependencies: {
164+"deleted-only@1.0.0": "patches/deleted-only.patch",
165+},
166+},
167+});
168+git(dir, ["add", "packages/deleted/package.json"]);
169+rmSync(path.join(dir, "packages", "deleted", "package.json"));
170+171+expect(collectPackagePatchViolations(dir)).toEqual([]);
172+});
173+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。