fix(backup): exclude snapshots from recovery copy, harden change walk

Migration recovery backups no longer re-copy Folio-Backups (up to 21x bloat). bookChangedSince tracks visited dev:ino so a symlink loop in the book cannot wedge the main-process interval tick. Snapshot toggle check aligned to === false; drop dead home-shortening branch in Settings.
This commit is contained in:
avi 2026-09-19 17:20:31 -05:00
commit b80aa798b2
4 changed files with 49 additions and 4 deletions

View file

@ -27,6 +27,9 @@ const {
createSnapshot,
pruneSnapshots,
bookChangedSince,
ensureRecoveryBackup,
getRecoveryRoot,
_resetSessionBackupGuard,
SNAPSHOT_DIR_NAME,
} = backup;
@ -88,9 +91,35 @@ settings.delete("snapshotLocation");
// missing dir -> null, no throw
ok(createSnapshot(path.join(dir, "nope"), 5) === null, "missing book returns null");
// symlink loop inside the book must not hang the change check
try {
fs.symlinkSync(dir, path.join(dir, "chapters", "loop"), "dir");
const t0 = Date.now();
const changed = bookChangedSince(dir, Date.now() + 60_000);
ok(changed === false && Date.now() - t0 < 5000, "symlink loop terminates without false positive");
} catch {
ok(true, "symlink loop test skipped (no symlink permission)");
}
// migration recovery backup excludes the snapshot dir (no 21x bloat)
const home = fs.mkdtempSync(path.join(os.tmpdir(), "folio-fakehome-"));
const origHome = process.env.HOME;
process.env.HOME = home;
try {
_resetSessionBackupGuard();
const dest = ensureRecoveryBackup(dir);
ok(typeof dest === "string" && fs.existsSync(dest), "recovery backup created");
ok(fs.existsSync(path.join(dest, "folio.json")), "recovery backup contains folio.json");
ok(!fs.existsSync(path.join(dest, SNAPSHOT_DIR_NAME)), "recovery backup excludes snapshots");
ok(getRecoveryRoot().startsWith(home), "recovery root honors HOME");
} finally {
process.env.HOME = origHome;
}
// cleanup
fs.rmSync(dir, { recursive: true, force: true });
fs.rmSync(custom, { recursive: true, force: true });
fs.rmSync(home, { recursive: true, force: true });
cleanupProj();
cleanupChap();
cleanupBackup();