cmd: bind package workdirs to driver identity
This commit is contained in:
@@ -32,6 +32,7 @@ static const char *usage =
|
||||
" . build the cwd's <basename>.ww\n";
|
||||
|
||||
static char *self_dir;
|
||||
static const char *self_path;
|
||||
|
||||
static const char *
|
||||
envpath(const char *name)
|
||||
@@ -1533,8 +1534,8 @@ archive_o(const char *objpath, const char *apath)
|
||||
* 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
|
||||
@@ -1629,10 +1630,10 @@ static void
|
||||
workdir_stamp_text(char *buf, size_t bufsz, int is_test, int emit_asm)
|
||||
{
|
||||
snprintf(buf, bufsz, "ww workdir fmt %d mode %s asm %d\n",
|
||||
is_test ? 5 : 4, is_test ? "test" : "build", emit_asm);
|
||||
is_test ? 6 : 5, is_test ? "test" : "build", emit_asm);
|
||||
}
|
||||
|
||||
/* A stale global tool identity invalidates every committed unit voucher in
|
||||
/* A stale global builder identity invalidates every committed unit voucher in
|
||||
* this driver-owned workdir before compilation starts. Artifacts may remain,
|
||||
* but without their unit they cannot be reused. That makes it safe to record
|
||||
* the new identity after a partial multi-root pass: successful actions have
|
||||
@@ -1753,9 +1754,16 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
if (scratchout) snprintf(scratchout, scratchoutsz, "%s", scratch);
|
||||
}
|
||||
int stale_all = 0, stampok = 0;
|
||||
char toolc[1200] = {0}, toola[1200] = {0}, stampf[1200] = {0};
|
||||
char toolw[1200] = {0}, toolc[1200] = {0}, toola[1200] = {0};
|
||||
char stampf[1200] = {0};
|
||||
char stampwant[128];
|
||||
if (warm) {
|
||||
if (self_path == NULL || !file_is_reg(self_path)) {
|
||||
fprintf(stderr, "ww: cannot read driver identity %s\n",
|
||||
self_path ? self_path : "(unknown)");
|
||||
return 1;
|
||||
}
|
||||
snprintf(toolw, sizeof toolw, "%s/.wwtool.ww", scratch);
|
||||
snprintf(toolc, sizeof toolc, "%s/.wwtool.w6c", scratch);
|
||||
snprintf(toola, sizeof toola, "%s/.wwtool.w6a", scratch);
|
||||
snprintf(stampf, sizeof stampf, "%s/.wwtool.stamp", scratch);
|
||||
@@ -1768,7 +1776,8 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
fclose(sf);
|
||||
}
|
||||
stampok = strcmp(stampwant, got) == 0;
|
||||
if (!stampok || !file_equal(toolc, c6)
|
||||
if (!stampok || !file_equal(toolw, self_path)
|
||||
|| !file_equal(toolc, c6)
|
||||
|| (!emit_asm && !file_equal(toola, a6)))
|
||||
stale_all = 1;
|
||||
if (stale_all && invalidate_workdir_units(scratch) != 0)
|
||||
@@ -2069,6 +2078,11 @@ build_one_sep_impl(const char *src, int entry_is_dir,
|
||||
* root failed; a killed pass leaves the old identity and forces another
|
||||
* invalidating pass, never false reuse. */
|
||||
if (warm) {
|
||||
if (!file_equal(toolw, self_path)
|
||||
&& copy_file_atomic(self_path, toolw) != 0) {
|
||||
fprintf(stderr, "ww: cannot record %s\n", toolw);
|
||||
free(order); return 1;
|
||||
}
|
||||
if (!file_equal(toolc, c6)
|
||||
&& copy_file_atomic(c6, toolc) != 0) {
|
||||
fprintf(stderr, "ww: cannot record %s\n", toolc);
|
||||
@@ -2973,6 +2987,7 @@ int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
if (argc >= 1) {
|
||||
self_path = argv[0];
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof buf, "%s", argv[0]);
|
||||
self_dir = strdup(dirname(buf));
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user