fix: prune stale plugin runtime mirror entries

This commit is contained in:
Shakker
2026-04-28 10:58:06 +01:00
parent 92016b82ae
commit 32c987626b
2 changed files with 50 additions and 9 deletions

View File

@@ -19,13 +19,13 @@ afterEach(() => {
});
describe("refreshBundledPluginRuntimeMirrorRoot", () => {
it("refreshes stale mirrors without deleting the active target root", () => {
it("refreshes stale mirrors without leaving removed source files behind", () => {
const root = makeTempRoot();
const sourceRoot = path.join(root, "source");
const targetRoot = path.join(root, "target");
fs.mkdirSync(sourceRoot, { recursive: true });
fs.mkdirSync(targetRoot, { recursive: true });
fs.writeFileSync(path.join(sourceRoot, "index.js"), "export const value = 'v1';\n", "utf8");
fs.writeFileSync(path.join(sourceRoot, "old.js"), "export const value = 'v1';\n", "utf8");
expect(
refreshBundledPluginRuntimeMirrorRoot({
@@ -35,8 +35,8 @@ describe("refreshBundledPluginRuntimeMirrorRoot", () => {
}),
).toBe(true);
fs.writeFileSync(path.join(sourceRoot, "index.js"), "export const value = 'v2';\n", "utf8");
fs.writeFileSync(path.join(targetRoot, "inflight-import.js"), "still readable\n", "utf8");
fs.rmSync(path.join(sourceRoot, "old.js"));
fs.writeFileSync(path.join(sourceRoot, "new.js"), "export const value = 'v2';\n", "utf8");
expect(
refreshBundledPluginRuntimeMirrorRoot({
@@ -46,9 +46,47 @@ describe("refreshBundledPluginRuntimeMirrorRoot", () => {
}),
).toBe(true);
expect(fs.readFileSync(path.join(targetRoot, "index.js"), "utf8")).toContain("v2");
expect(fs.readFileSync(path.join(targetRoot, "inflight-import.js"), "utf8")).toBe(
"still readable\n",
);
expect(fs.readdirSync(targetRoot).toSorted()).toEqual([
".openclaw-runtime-mirror.json",
"new.js",
]);
expect(fs.readFileSync(path.join(targetRoot, "new.js"), "utf8")).toContain("v2");
expect(
refreshBundledPluginRuntimeMirrorRoot({
pluginId: "demo",
sourceRoot,
targetRoot,
}),
).toBe(false);
});
it("replaces stale target entries when the source changes type", () => {
const root = makeTempRoot();
const sourceRoot = path.join(root, "source");
const targetRoot = path.join(root, "target");
fs.mkdirSync(path.join(sourceRoot, "entry"), { recursive: true });
fs.writeFileSync(path.join(sourceRoot, "entry", "index.js"), "export const value = 1;\n");
expect(
refreshBundledPluginRuntimeMirrorRoot({
pluginId: "demo",
sourceRoot,
targetRoot,
}),
).toBe(true);
fs.rmSync(path.join(sourceRoot, "entry"), { recursive: true, force: true });
fs.writeFileSync(path.join(sourceRoot, "entry"), "export const value = 2;\n");
expect(
refreshBundledPluginRuntimeMirrorRoot({
pluginId: "demo",
sourceRoot,
targetRoot,
}),
).toBe(true);
expect(fs.lstatSync(path.join(targetRoot, "entry")).isFile()).toBe(true);
expect(fs.readFileSync(path.join(targetRoot, "entry"), "utf8")).toContain("2");
});
});

View File

@@ -74,7 +74,10 @@ export function copyBundledPluginRuntimeRoot(sourceRoot: string, targetRoot: str
pruneStaleBundledRuntimeMirrorEntries(targetRoot, mirroredNames);
}
function pruneStaleBundledRuntimeMirrorEntries(targetRoot: string, mirroredNames: Set<string>): void {
function pruneStaleBundledRuntimeMirrorEntries(
targetRoot: string,
mirroredNames: Set<string>,
): void {
for (const entry of fs.readdirSync(targetRoot, { withFileTypes: true })) {
if (shouldIgnoreBundledRuntimeMirrorEntry(entry.name)) {
continue;