Skip to content

Commit 2fec429

Browse files
kortdriessenclaude
andcommitted
fluxconfig: symlinked legacy lib is not "stranded" — realpath-compare in migration
Real-machine transition state: ~/FluxLib stays behind as a symlink to <FluxConfig>/FluxLib until every old-code session is gone, and old-code ensureFluxLib re-persists fluxLibPath (recreating the capital config dir) on every CLI run. The re-merge handled this but logged a misleading "both libraries exist" warning — now oldLib/target are realpath-compared, so the symlink case is recognized as already-migrated: key dropped, no warning. Gate test covers the full old-code-recreation cycle (t6). Verified on the real machine: recreated ~/.config/Flux re-merged + removed, prefs back to fluxConfigPath-only, no stranded warning. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 39e589d commit 2fec429

2 files changed

Lines changed: 31 additions & 3 deletions

File tree

‎electron/fluxPaths.cjs‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,19 @@ async function migrateFluxLib(cfg, events) {
294294
};
295295
if (fsSync.existsSync(target)) {
296296
if (oldLib !== target && fsSync.existsSync(oldLib)) {
297-
const w = `both ${target} and ${oldLib} exist — leaving both untouched (nothing merged or deleted); resolve by hand`;
298-
console.error(`flux config: WARNING — ${w}`);
299-
events.push({ action: "stranded-fluxlib-warning", detail: w });
297+
// realpath: a transitional symlink (old path -> <cfg>/FluxLib) is the
298+
// SAME tree, not a stranded second library — no warning for it.
299+
let distinct = true;
300+
try {
301+
distinct = fsSync.realpathSync(oldLib) !== fsSync.realpathSync(target);
302+
} catch {
303+
/* unreadable — treat as distinct and warn */
304+
}
305+
if (distinct) {
306+
const w = `both ${target} and ${oldLib} exist — leaving both untouched (nothing merged or deleted); resolve by hand`;
307+
console.error(`flux config: WARNING — ${w}`);
308+
events.push({ action: "stranded-fluxlib-warning", detail: w });
309+
}
300310
}
301311
dropKey();
302312
return;

‎scripts/verify-fluxconfig.ts‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,24 @@ if (process.platform !== "win32") {
178178
await fp.ensureFluxConfig();
179179
assert(fs.existsSync(path.join(f4.home, "FluxConfig", "FluxLib", "library.bib")), "pre-existing empty FluxConfig filled in place");
180180

181+
// -- transitional symlink (old lib path -> <cfg>/FluxLib) is NOT "stranded"
182+
// (the real machine keeps ~/FluxLib as a symlink until every old-code
183+
// session is gone; old code re-persists fluxLibPath, so re-merges recur)
184+
const f6 = freshFixture("t6");
185+
await fp.ensureFluxConfig();
186+
fs.symlinkSync(path.join(f6.home, "FluxConfig", "FluxLib"), path.join(f6.home, "FluxLib"));
187+
fs.mkdirSync(path.join(f6.xdg, "Flux"), { recursive: true }); // flux-cap-ok (old code recreates it)
188+
fs.writeFileSync(
189+
path.join(f6.xdg, "Flux", "preferences.json"), // flux-cap-ok
190+
JSON.stringify({ schemaVersion: "0.1.0", fluxLibPath: path.join(f6.home, "FluxLib") }),
191+
);
192+
const r6 = await fp.ensureFluxConfig();
193+
assert(r6.fluxLibPath === path.join(f6.home, "FluxConfig", "FluxLib"), "re-merge after old-code prefs recreation resolves derived");
194+
const marker6 = JSON.parse(fs.readFileSync(path.join(f6.home, "FluxConfig", ".fluxconfig.json"), "utf8"));
195+
assert(!marker6.events.some((e: { action: string }) => e.action === "stranded-fluxlib-warning"), "symlinked legacy lib is not flagged as stranded");
196+
const prefs6 = JSON.parse(fs.readFileSync(path.join(f6.xdg, "flux", "preferences.json"), "utf8"));
197+
assert(!("fluxLibPath" in prefs6) && prefs6.fluxConfigPath, "re-merge drops the re-persisted fluxLibPath again");
198+
181199
// -- moveFluxConfig (Settings "Move…"): same-fs rename + destination guards
182200
const f5 = freshFixture("t5");
183201
await fp.ensureFluxConfig();

0 commit comments

Comments
 (0)