mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:50:43 +00:00
fix: tolerate runtime deps temp cleanup races
This commit is contained in:
@@ -261,6 +261,63 @@ describe("installBundledRuntimeDeps", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("does not fail an isolated runtime deps install when temp cleanup races", () => {
|
||||
const installRoot = makeTempDir();
|
||||
const installExecutionRoot = makeTempDir();
|
||||
const realRmSync = fs.rmSync.bind(fs);
|
||||
let blockedCleanup = false;
|
||||
vi.spyOn(fs, "rmSync").mockImplementation((target, options) => {
|
||||
if (
|
||||
!blockedCleanup &&
|
||||
path.basename(String(target)).startsWith(".openclaw-runtime-deps-copy-")
|
||||
) {
|
||||
blockedCleanup = true;
|
||||
const error = new Error("Directory not empty") as NodeJS.ErrnoException;
|
||||
error.code = "ENOTEMPTY";
|
||||
throw error;
|
||||
}
|
||||
return realRmSync(target, options);
|
||||
});
|
||||
spawnSyncMock.mockImplementation((_command, _args, options) => {
|
||||
const cwd = String(options?.cwd ?? "");
|
||||
fs.mkdirSync(path.join(cwd, "node_modules", "tokenjuice"), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(cwd, "node_modules", "tokenjuice", "package.json"),
|
||||
JSON.stringify({ name: "tokenjuice", version: "0.6.1" }),
|
||||
);
|
||||
return {
|
||||
pid: 123,
|
||||
output: [],
|
||||
stdout: "",
|
||||
stderr: "",
|
||||
signal: null,
|
||||
status: 0,
|
||||
};
|
||||
});
|
||||
|
||||
expect(() =>
|
||||
installBundledRuntimeDeps({
|
||||
installRoot,
|
||||
installExecutionRoot,
|
||||
missingSpecs: ["tokenjuice@0.6.1"],
|
||||
env: {},
|
||||
}),
|
||||
).not.toThrow();
|
||||
|
||||
expect(blockedCleanup).toBe(true);
|
||||
expect(
|
||||
JSON.parse(
|
||||
fs.readFileSync(
|
||||
path.join(installRoot, "node_modules", "tokenjuice", "package.json"),
|
||||
"utf8",
|
||||
),
|
||||
),
|
||||
).toEqual({
|
||||
name: "tokenjuice",
|
||||
version: "0.6.1",
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects invalid install specs before spawning npm", () => {
|
||||
expect(() =>
|
||||
createBundledRuntimeDepsInstallArgs(["tokenjuice@https://evil.example/t.tgz"]),
|
||||
|
||||
@@ -382,7 +382,12 @@ function replaceNodeModulesDir(targetDir: string, sourceDir: string): void {
|
||||
fs.rmSync(targetDir, { recursive: true, force: true });
|
||||
fs.renameSync(stagedDir, targetDir);
|
||||
} finally {
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
try {
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
} catch {
|
||||
// Stale temp dirs are swept at the next runtime-deps pass. Do not fail
|
||||
// a node_modules replacement on a transient cleanup race.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user