fix(coding-agent): keep bun/npm routing for regular-file entries on Windows
Bun's global bin entry on Windows is a regular-file .exe shim, not a symlink, so the standalone-binary override would have rerouted a legitimate bun-managed install to in-place binary replacement and clobbered the shim. Gate the override on POSIX, where package-manager bin entries are always symlinks; add a regression test.
This commit is contained in:
@@ -239,12 +239,16 @@ function resolveUpdateMethod(
|
||||
if (miseDataDir && isPathInDirectory(ompPath, path.join(miseDataDir, "shims"))) return "mise";
|
||||
// A plain executable file in a package-manager bin dir is the standalone
|
||||
// binary the installer placed there, not an npm/bun-managed install (those
|
||||
// symlink into node_modules). When the global bin dir overlaps the
|
||||
// symlink into node_modules on POSIX). When the global bin dir overlaps the
|
||||
// installer's default (~/.local/bin), classifying by directory alone routes
|
||||
// a binary install through npm/bun, whose reinstall then collides with the
|
||||
// existing file (npm EEXIST). Fall through to binary replacement instead.
|
||||
if (bunBinDir && isPathInDirectory(ompPath, bunBinDir) && !ompIsRegularFile) return "bun";
|
||||
if ((npmBinDir && isPathInDirectory(ompPath, npmBinDir) && !ompIsRegularFile) || isWindowsScriptLauncher)
|
||||
// Windows is excluded: there package managers write regular-file shims
|
||||
// (bun's .exe launcher, npm's .cmd/.ps1), so a regular file is NOT evidence
|
||||
// of a standalone install and the override would hijack managed installs.
|
||||
const isStandaloneRegularFile = ompIsRegularFile && process.platform !== "win32";
|
||||
if (bunBinDir && isPathInDirectory(ompPath, bunBinDir) && !isStandaloneRegularFile) return "bun";
|
||||
if ((npmBinDir && isPathInDirectory(ompPath, npmBinDir) && !isStandaloneRegularFile) || isWindowsScriptLauncher)
|
||||
return "npm";
|
||||
return "binary";
|
||||
}
|
||||
|
||||
@@ -111,6 +111,26 @@ describe("update-cli install target detection", () => {
|
||||
expect(method).toBe("binary");
|
||||
});
|
||||
|
||||
it("keeps bun update for regular-file entries in the bun global bin dir on Windows, where bun writes .exe shims", () => {
|
||||
// On Windows a bun-managed global install is a regular-file .exe
|
||||
// launcher, not a symlink, so the standalone-binary override must not
|
||||
// apply there — it would clobber the shim with a raw binary. Paths use
|
||||
// forward slashes so the lexical containment check works on the POSIX
|
||||
// host running this suite; the platform gate is what is under test.
|
||||
const platformDescriptor = Object.getOwnPropertyDescriptor(process, "platform");
|
||||
if (!platformDescriptor) throw new Error("process.platform descriptor missing");
|
||||
Object.defineProperty(process, "platform", { ...platformDescriptor, value: "win32" });
|
||||
try {
|
||||
const method = resolveUpdateMethodForTest("C:/Users/test/.bun/bin/omp.exe", "C:/Users/test/.bun/bin", {
|
||||
ompIsRegularFile: true,
|
||||
});
|
||||
|
||||
expect(method).toBe("bun");
|
||||
} finally {
|
||||
Object.defineProperty(process, "platform", platformDescriptor);
|
||||
}
|
||||
});
|
||||
|
||||
it("still uses npm update when the npm global bin entry is a package-manager symlink, not a plain file", () => {
|
||||
const method = resolveUpdateMethodForTest("/home/u/.local/bin/omp", undefined, {
|
||||
npmBinDir: "/home/u/.local/bin",
|
||||
|
||||
Reference in New Issue
Block a user