Spaces:
Running
Running
File size: 7,672 Bytes
31b3c47 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import {
existsSync,
mkdirSync,
mkdtempSync,
readFileSync,
readdirSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { test } from "node:test";
import { handOver, parseWriteAtomicArgs, stagingError } from "./write-atomic.mjs";
import { SCAFFOLD_QUARANTINE } from "./scaffold-quarantine.mjs";
const TEMPLATE_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..");
const SCRIPT = join(TEMPLATE_ROOT, "scripts/write-atomic.mjs");
function makeWorkspace() {
const root = mkdtempSync(join(tmpdir(), "write-atomic-"));
mkdirSync(join(root, "public"), { recursive: true });
mkdirSync(join(root, ".grok"), { recursive: true });
return root;
}
test("parseWriteAtomicArgs needs exactly a staged file and a target", () => {
assert.deepEqual(parseWriteAtomicArgs([".grok/og.tmp", "public/og.jpg"]), {
staged: ".grok/og.tmp",
target: "public/og.jpg",
});
assert.match(parseWriteAtomicArgs([]).error, /usage:/);
assert.match(parseWriteAtomicArgs([".grok/og.tmp"]).error, /usage:/);
assert.match(parseWriteAtomicArgs(["a", "b", "c"]).error, /unexpected argument: c/);
});
test("stagingError refuses a temp inside public/ and a no-op move", () => {
const publicDir = "/workspace/public";
assert.equal(
stagingError({
staged: "/workspace/.grok/og.jpg.tmp",
target: "/workspace/public/og.jpg",
publicDir,
}),
null,
);
assert.match(
stagingError({
staged: "/workspace/public/og.jpg.tmp",
target: "/workspace/public/og.jpg",
publicDir,
}),
/vite build ships that directory verbatim/,
);
assert.match(
stagingError({
staged: "/workspace/public/og.jpg",
target: "/workspace/public/og.jpg",
publicDir,
}),
/same path/,
);
});
test("handOver replaces the target and clears the staged file", () => {
const root = makeWorkspace();
const staged = join(root, ".grok/og.jpg.tmp");
const target = join(root, "public/og.jpg");
writeFileSync(target, "old card");
writeFileSync(staged, "new card");
handOver(staged, target);
assert.equal(readFileSync(target, "utf8"), "new card");
assert.equal(existsSync(staged), false);
});
test("handOver creates a missing target directory", () => {
const root = makeWorkspace();
const staged = join(root, ".grok/site.json.tmp");
writeFileSync(staged, '{"title":"Sky Strike"}');
handOver(staged, join(root, "src/lib/og/site.json"));
assert.equal(readFileSync(join(root, "src/lib/og/site.json"), "utf8"), '{"title":"Sky Strike"}');
});
test("an interrupted pass leaves the target on its old bytes, temp-free", () => {
const root = makeWorkspace();
const target = join(root, "public/og.jpg");
writeFileSync(target, "old card");
// The staged file a killed ffmpeg leaves behind: never handed over.
writeFileSync(join(root, ".grok/og.jpg.tmp"), "half a JPEG");
assert.equal(readFileSync(target, "utf8"), "old card");
assert.throws(() => handOver(join(root, ".grok/absent.tmp"), target), { code: "ENOENT" });
assert.equal(readFileSync(target, "utf8"), "old card");
assert.equal(existsSync(`${target}.tmp-${process.pid}`), false);
});
test("a failed hand-over creates no directory for the target it never wrote", () => {
const root = makeWorkspace();
const missing = join(root, ".grok/absent.tmp");
assert.throws(() => handOver(missing, join(root, "src/lib/og/site.json")), { code: "ENOENT" });
assert.equal(existsSync(join(root, "src")), false);
});
test("a staged file on another filesystem is refused, not copied", () => {
const root = makeWorkspace();
const staged = join(root, ".grok/og.jpg.tmp");
const target = join(root, "public/og.jpg");
writeFileSync(staged, "new card");
writeFileSync(target, "old card");
const originalError = Object.assign(new Error("EXDEV"), { code: "EXDEV" });
const crossDevice = () => { throw originalError; };
assert.throws(() => handOver(staged, target, { rename: crossDevice }), {
message: /stage under \/workspace\/\.grok\//,
cause: originalError,
});
// Copying would have had to stage its own temp inside public/, which is the
// one place stagingError refuses.
assert.deepEqual(readdirSync(join(root, "public")), ["og.jpg"]);
assert.equal(readFileSync(target, "utf8"), "old card");
});
test("cli: hands the file over, and refuses a temp staged in public/", () => {
const root = makeWorkspace();
writeFileSync(join(root, ".grok/og.jpg.tmp"), "new card");
const ok = spawnSync(
process.execPath,
[SCRIPT, join(root, ".grok/og.jpg.tmp"), join(root, "public/og.jpg")],
{ encoding: "utf8" },
);
assert.equal(ok.status, 0, ok.stdout + ok.stderr);
assert.equal(readFileSync(join(root, "public/og.jpg"), "utf8"), "new card");
// publicDir comes from the script's own root, so refusal is checked there.
const templateRoot = join(dirname(SCRIPT), "..");
const staged = join(templateRoot, "public/og.jpg.tmp");
const refused = spawnSync(
process.execPath,
[SCRIPT, staged, join(templateRoot, "public/og.jpg")],
{ encoding: "utf8" },
);
assert.equal(refused.status, 1);
assert.match(refused.stderr, /stage outside/);
assert.equal(existsSync(staged), false);
});
test("cli: relative paths follow the script's root, not the caller's cwd", () => {
// Same relative pair the skill documents, run from a workspace that has its
// own public/: resolving against cwd would take the staged temp out of the
// directory the refusal is defined against and move it.
const root = makeWorkspace();
writeFileSync(join(root, "public/og.jpg.tmp"), "half a JPEG");
const run = spawnSync(process.execPath, [SCRIPT, "public/og.jpg.tmp", "public/og.jpg"], {
cwd: root,
encoding: "utf8",
});
assert.equal(run.status, 1, run.stdout + run.stderr);
assert.match(run.stderr, /stage outside/);
assert.equal(readFileSync(join(root, "public/og.jpg.tmp"), "utf8"), "half a JPEG");
assert.equal(existsSync(join(root, "public/og.jpg")), false);
});
test("every hand-over the og skill prints is one this script accepts", { skip: SCAFFOLD_QUARANTINE.ogSkillDocs }, () => {
// The card and banner recipes live in the skill's references/, not SKILL.md.
const skillDir = join(TEMPLATE_ROOT, ".grok/skills/og");
const docs = [
join(skillDir, "SKILL.md"),
...readdirSync(join(skillDir, "references")).map((f) => join(skillDir, "references", f)),
];
const invocations = docs.flatMap(
(path) => readFileSync(path, "utf8").match(/node scripts\/write-atomic\.mjs[^\n`]*/g) ?? [],
);
assert.ok(invocations.length >= 3, "og.jpg, x-banner.jpg and site.json each hand over");
for (const line of invocations) {
const argv = line.replace("node scripts/write-atomic.mjs", "").trim().split(/\s+/);
const args = parseWriteAtomicArgs(argv);
assert.equal(args.error, undefined, line);
assert.equal(
stagingError({ staged: args.staged, target: args.target, publicDir: "/workspace/public" }),
null,
line,
);
}
});
test("cli: a missing staged file fails without touching the target", () => {
const root = makeWorkspace();
writeFileSync(join(root, "public/og.jpg"), "old card");
const run = spawnSync(
process.execPath,
[SCRIPT, join(root, ".grok/absent.tmp"), join(root, "public/og.jpg")],
{ encoding: "utf8" },
);
assert.equal(run.status, 1);
assert.match(run.stderr, /\[write-atomic\]/);
assert.equal(readFileSync(join(root, "public/og.jpg"), "utf8"), "old card");
});
|