cmd: bind package workdirs to driver identity

This commit is contained in:
2026-08-12 15:51:44 +09:00
parent 5c19f51a4d
commit 5eec5d3711
2 changed files with 46 additions and 13 deletions

View File

@@ -25,6 +25,8 @@ import syntax;
// the cgen #127 mod-mangle attribution bug consumer per rule-7.
def CMD_MAX: u64 = 8192u64;
let selfpath: *u8;
// Tool-local (NOT a lib wrapper): messages are built from many
// fragments and we route through os.write to avoid libc stdio.
// .len replaces the error-prone hand-counted byte literals these sites
@@ -1803,8 +1805,8 @@ fn archiveo(objpath: *u8, apath: *u8) i32 = {
// A `-w DIR` workdir is a caller-owned persistent package-artifact tree
// that replaces the fresh `.sepwork` scratch. Staleness is pure content
// identity, never mtime: a package is reused only when its freshly
// composed unit byte-equals the committed unit AND the tool copies
// recorded in the dir byte-equal the live tools — every decision is
// composed unit byte-equals the committed unit AND the driver/tool copies
// recorded in the dir byte-equal the live executables — every decision is
// reproducible by hand with cmp(1) against plain files. Artifacts commit
// via temp + rename with the unit renamed last, so a killed build can
// never leave a committed unit vouching for uncommitted artifacts. The
@@ -1914,14 +1916,14 @@ fn copyfileatomic(src: *u8, dst: *u8) i32 = {
fn workdirstamptext(istest: i32, emitasm: i32) str = {
if (istest != 0) {
if (emitasm != 0) {
return "ww workdir fmt 5 mode test asm 1\n";
return "ww workdir fmt 6 mode test asm 1\n";
};
return "ww workdir fmt 5 mode test asm 0\n";
return "ww workdir fmt 6 mode test asm 0\n";
};
if (emitasm != 0) {
return "ww workdir fmt 4 mode build asm 1\n";
return "ww workdir fmt 5 mode build asm 1\n";
};
return "ww workdir fmt 4 mode build asm 0\n";
return "ww workdir fmt 5 mode build asm 0\n";
};
fn stampmatches(path: *u8, want: str) bool = {
@@ -1976,7 +1978,7 @@ fn recordproductstatus(path: *u8) i32 = {
return os.rename(pathstr(tmpp), pathstr(path));
};
// Remove every committed unit voucher before a stale-tool pass. Remaining
// Remove every committed unit voucher before a stale-builder pass. Remaining
// artifacts cannot be reused without their matching unit, so a partial pass
// may safely record its new tool identity: successful actions have current
// units and failed/no-longer-requested actions have none.
@@ -2138,17 +2140,26 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
};
let staleall: bool = false;
let stampok: bool = false;
let toolw: *u8 = nil;
let toolc: *u8 = nil;
let toola: *u8 = nil;
let stampf: *u8 = nil;
let stampwant: str = "";
if (warm) {
if (!fileisreg(selfpath)) {
cerrpath("ww: cannot read driver identity ", selfpath, "\n");
return 1;
};
toolw = joinpathlit(scratch, ".wwtool.ww");
toolc = joinpathlit(scratch, ".wwtool.w6c");
toola = joinpathlit(scratch, ".wwtool.w6a");
stampf = joinpathlit(scratch, ".wwtool.stamp");
stampwant = workdirstamptext(istest, emitasm);
stampok = stampmatches(stampf, stampwant);
staleall = !stampok;
if (!staleall) {
if (!fileequal(toolw, selfpath)) { staleall = true; };
};
if (!staleall) {
if (!fileequal(toolc, c6)) { staleall = true; };
};
@@ -2589,6 +2600,12 @@ fn buildonesepimpl(selfdir: *u8, src: *u8, entryisdir: i32,
// successful units remain safe to vouch for when a sibling root fails;
// a killed pass retains the old identity and invalidates again next time.
if (warm) {
if (!fileequal(toolw, selfpath)) {
if (copyfileatomic(selfpath, toolw) != 0) {
cerrpath("ww: cannot record ", toolw, "\n");
return 1;
};
};
if (!fileequal(toolc, c6)) {
if (copyfileatomic(c6, toolc) != 0) {
cerrpath("ww: cannot record ", toolc, "\n");
@@ -3732,6 +3749,7 @@ export fn main(argc: i32, argv: **u8) i32 = {
writeusage(2);
return 2;
};
selfpath = argv[0];
let selfdir: []u8 = alloc([], (os.PATH_MAX: u64))!;
selfdir.len = os.PATH_MAX;