repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
pi/agent/skillz/lnx/linux-userland/scripts/backup.test.mjs
Rawimport assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { lstatSync, mkdtempSync, readFileSync, readdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { test } from "node:test";
const doc = readFileSync(new URL("../SKILL.md", import.meta.url), "utf8");
const snippet = doc.match(/## Safe Edit Pattern[\s\S]*?```bash\n([\s\S]*?)```/)[1];
for (const symlink of [false, true]) {
test(`backup and rollback preserve ${symlink ? "symlinked" : "regular"} config`, { skip: process.platform !== "linux" }, () => {
const dir = mkdtempSync(join(tmpdir(), "linux-userland-backup-"));
try {
const target = join(dir, "config target");
const file = symlink ? join(dir, "config link") : target;
writeFileSync(target, "original\n");
if (symlink) symlinkSync(target, file);
const script = snippet
.replace("/path/to/file", '"$CONFIG_FILE"')
.replace('# edit "$file"', 'printf "changed\\n" > "$file"')
.replace("# run validator/reload", 'test "$(cat "$backup")" = original || exit 1')
.replace("# rollback if bad: ", "");
const result = spawnSync("sh", ["-eu", "-c", script], {
env: { ...process.env, CONFIG_FILE: file },
encoding: "utf8",
});
assert.equal(result.status, 0, result.stderr);
assert.equal(readFileSync(target, "utf8"), "original\n");
assert.equal(lstatSync(file).isSymbolicLink(), symlink);
const backups = readdirSync(dir).filter((name) => name.includes(".bak."));
assert.equal(backups.length, 1);
assert.ok(lstatSync(join(dir, backups[0])).isFile());
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
}
for (const kind of ["missing", "dangling symlink", "directory"]) {
test(`refuse ${kind} without creating a backup`, { skip: process.platform !== "linux" }, () => {
const dir = mkdtempSync(join(tmpdir(), "linux-userland-backup-"));
try {
const file = kind === "directory" ? dir : join(dir, "config");
if (kind === "dangling symlink") symlinkSync(join(dir, "missing"), file);
const before = readdirSync(dir);
const result = spawnSync("sh", ["-eu", "-c", snippet.replace("/path/to/file", '"$CONFIG_FILE"')], {
env: { ...process.env, CONFIG_FILE: file },
encoding: "utf8",
});
assert.equal(result.status, 1, result.stderr);
assert.deepEqual(readdirSync(dir), before);
} finally {
rmSync(dir, { recursive: true, force: true });
}
});
}