mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:40:44 +00:00
fix: remove plugins from recorded install roots
This commit is contained in:
@@ -801,6 +801,26 @@ describe("uninstallPlugin", () => {
|
||||
});
|
||||
await expect(fs.access(managedDir)).rejects.toThrow();
|
||||
});
|
||||
|
||||
it("deletes tracked installs from a recorded managed extensions root", async () => {
|
||||
const currentExtensionsDir = path.join(tempDir, "current", "extensions");
|
||||
const recordedExtensionsDir = path.join(tempDir, "recorded", "extensions");
|
||||
const installPath = resolvePluginInstallDir("my-plugin", recordedExtensionsDir);
|
||||
await fs.mkdir(installPath, { recursive: true });
|
||||
await fs.writeFile(path.join(installPath, "index.js"), "// plugin");
|
||||
|
||||
const result = await uninstallPlugin({
|
||||
config: createSingleNpmInstallConfig(installPath),
|
||||
pluginId: "my-plugin",
|
||||
deleteFiles: true,
|
||||
extensionsDir: currentExtensionsDir,
|
||||
});
|
||||
|
||||
expectSuccessfulUninstallActions(result, {
|
||||
directory: true,
|
||||
});
|
||||
await expect(fs.access(installPath)).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveUninstallDirectoryTarget", () => {
|
||||
@@ -851,4 +871,27 @@ describe("resolveUninstallDirectoryTarget", () => {
|
||||
}),
|
||||
).toBe(installPath);
|
||||
});
|
||||
|
||||
it("uses configured installPath when it is under the recorded managed extensions root", () => {
|
||||
const currentExtensionsDir = path.join(os.tmpdir(), "openclaw-uninstall-current", "extensions");
|
||||
const recordedExtensionsDir = path.join(
|
||||
os.tmpdir(),
|
||||
"openclaw-uninstall-recorded",
|
||||
"extensions",
|
||||
);
|
||||
const installPath = resolvePluginInstallDir("my-plugin", recordedExtensionsDir);
|
||||
|
||||
expect(
|
||||
resolveUninstallDirectoryTarget({
|
||||
pluginId: "my-plugin",
|
||||
hasInstall: true,
|
||||
installRecord: {
|
||||
source: "npm",
|
||||
spec: "my-plugin@1.0.0",
|
||||
installPath,
|
||||
},
|
||||
extensionsDir: currentExtensionsDir,
|
||||
}),
|
||||
).toBe(installPath);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -61,11 +61,39 @@ export function resolveUninstallDirectoryTarget(params: {
|
||||
return configuredPath;
|
||||
}
|
||||
|
||||
const recordedManagedPath = resolveRecordedManagedInstallPath({
|
||||
pluginId: params.pluginId,
|
||||
installPath: configuredPath,
|
||||
});
|
||||
if (recordedManagedPath) {
|
||||
return recordedManagedPath;
|
||||
}
|
||||
|
||||
// Never trust configured installPath blindly for recursive deletes outside
|
||||
// the managed extensions directory.
|
||||
return defaultPath;
|
||||
}
|
||||
|
||||
function resolveRecordedManagedInstallPath(params: {
|
||||
pluginId: string;
|
||||
installPath: string;
|
||||
}): string | null {
|
||||
const resolvedInstallPath = path.resolve(params.installPath);
|
||||
const recordedExtensionsDir = path.dirname(resolvedInstallPath);
|
||||
if (path.basename(recordedExtensionsDir) !== "extensions") {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const canonicalInstallPath = path.resolve(
|
||||
resolvePluginInstallDir(params.pluginId, recordedExtensionsDir),
|
||||
);
|
||||
return canonicalInstallPath === resolvedInstallPath ? params.installPath : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const SHARED_CHANNEL_CONFIG_KEYS = new Set(["defaults", "modelByChannel"]);
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user