batched upload resave: --resave-batch CLI + one staging pass per bulk upload (tasks-runner 0004)
kicad_tools --resave-batch <outdir> <file>...: N resaves in one process (one WASM init — marginal resave is ~50ms vs ~0.3s/process). Outputs in <outdir>/<index>/, per-file "RESAVE-BATCH <index> <exit-code>" stderr verdicts with the single-file 0/4/5 contract; exit 0 = loop completed, so an invalid file mid-batch can't mask its neighbors. loadSchematicHeadless now binds each schematic to ITS project via SETTINGS_MANAGER::GetProject, never Prj(): with aSetActive=false projects accumulate across batch entries and Prj() keeps returning the first one — the writer then stamped a wrong/empty project name into saved symbol-instance data. (UnloadProject is no fix: unloading the active project immediately reloads a null "" project.) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AH2iPekUGsEAYnMUD5BmAi
This commit is contained in:
parent
864ddb00a4
commit
90bc4e0222
3 changed files with 108 additions and 3 deletions
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
* Run: cd tests && npm run tools:contract
|
||||
*/
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { execFileSync, spawnSync } from "node:child_process";
|
||||
import {
|
||||
existsSync,
|
||||
mkdtempSync,
|
||||
|
|
@ -127,6 +127,43 @@ try {
|
|||
console.log("skip footprint fixtures (kicad submodule not initialized)");
|
||||
}
|
||||
|
||||
// --- resave-batch: N files, one process ----------------------------------
|
||||
// The bulk-upload normalization mode: outputs under <outdir>/<index>/,
|
||||
// per-file verdicts as "RESAVE-BATCH <index> <exit-code>" stderr lines with
|
||||
// the single-file code contract, process exit 0 when the loop completed —
|
||||
// an invalid file mid-batch must not mask its neighbors.
|
||||
{
|
||||
const badMid = out("mid-garbage.kicad_sch");
|
||||
writeFileSync(badMid, "not a schematic (");
|
||||
const r = spawnSync("node", [cli, "--resave-batch", out("batch"), demoPcb, badMid, demoSch], {
|
||||
stdio: ["ignore", "ignore", "pipe"],
|
||||
});
|
||||
const stderr = r.stderr?.toString() ?? "";
|
||||
const codes = new Map<number, number>();
|
||||
for (const m of stderr.matchAll(/^RESAVE-BATCH (\d+) (-?\d+)$/gm)) {
|
||||
codes.set(Number(m[1]), Number(m[2]));
|
||||
}
|
||||
check("batch exits 0 despite an invalid entry", r.status === 0, `exit ${r.status}`);
|
||||
check("batch reports one verdict line per entry", codes.size === 3, `${codes.size}`);
|
||||
check("batch board entry verdicts 0", codes.get(0) === 0, `${codes.get(0)}`);
|
||||
check("batch invalid entry verdicts 4", codes.get(1) === 4, `${codes.get(1)}`);
|
||||
check("batch schematic entry verdicts 0", codes.get(2) === 0, `${codes.get(2)}`);
|
||||
const producedPcb = path.join(out("batch"), "0", "demo.kicad_pcb");
|
||||
check(
|
||||
"batch board output lands in its index dir and bumps the version",
|
||||
existsSync(producedPcb) && version(producedPcb) > version(demoPcb),
|
||||
);
|
||||
const producedSch = path.join(out("batch"), "2", "demo.kicad_sch");
|
||||
check("batch schematic output lands in its index dir", existsSync(producedSch));
|
||||
check(
|
||||
"batch invalid entry produced no output dir",
|
||||
!existsSync(path.join(out("batch"), "1", path.basename(badMid))),
|
||||
);
|
||||
check("batch outputs lint clean", run(["--lint", producedPcb, producedSch]).code === 0);
|
||||
|
||||
check("batch usage (no files) exits 2", run(["--resave-batch", out("bu")]).code === 2);
|
||||
}
|
||||
|
||||
// --- exit-code contract ---------------------------------------------------
|
||||
{
|
||||
check("usage (no args) exits 2", run(["--resave"]).code === 2);
|
||||
|
|
|
|||
Loading…
Reference in a new issue