ww: protect public install outputs

This commit is contained in:
2026-08-21 04:11:01 +09:00
parent ce91f6662c
commit 1b71250ad5
7 changed files with 1064 additions and 90 deletions

View File

@@ -39,9 +39,13 @@ type pkggroup = struct {
bin: str,
buildok: str,
runoutput: str,
installoutput: str,
state: i32,
runstartfailed: bool,
runres: exec.result,
publicbin: bool,
installattempted: bool,
installres: exec.result,
};
type pkgplan = struct {
@@ -64,6 +68,7 @@ type pkgplan = struct {
outputcollisionbase: str,
outputcollisiondir: str,
suppressbuildreports: bool,
deferpublish: bool,
};
def PKG_COUNT_MAX: i32 = 2147483647;
@@ -1373,16 +1378,23 @@ fn pkgsetplanpaths(p: *pkgplan, groups: []pkggroup, root: str, index: i32,
pkgfailpath(g.root, "cannot create product temporary path");
return false;
};
g.publicbin = false;
g.installattempted = false;
if (buildonly) {
if (outputdir && strings.compare(g.pkg, "main") == 0
&& !p.outputpatherror && !p.emitasm) {
if (!pkgjoinpath(outname, g.basename, &g.bin)) { return false; };
} else if (outname.len != 0 && !outputdir) { g.bin = outname; }
g.publicbin = true;
} else if (outname.len != 0 && !outputdir) {
g.bin = outname;
g.publicbin = true;
}
else if (!pkgstring(&g.bin, g.root, "/package.build")) { return false; };
} else {
if (!pkgstring(&g.bin, g.root, "/package.test")) { return false; };
};
if (!pkgstring(&g.runoutput, g.root, "/test.output")
|| !pkgstring(&g.installoutput, g.root, "/install.output")
|| !pkgstring(&g.buildok, g.root, "/build.ok")) { return false; };
i += 1;
};
@@ -1484,7 +1496,8 @@ fn pkgstartbuild(p: *pkgplan, groups: []pkggroup, builder: str, includes: []str,
for (i < p.end) {
let g: *pkggroup = &groups[i];
append(ba, "--ww-package-test");
if (p.buildonly) { append(ba, "build"); }
if (p.buildonly && g.publicbin) { append(ba, "build-public"); }
else if (p.buildonly) { append(ba, "build"); }
else { append(ba, "test"); };
append(ba, g.pkg);
if (g.prodpkg.len != 0) { append(ba, g.prodpkg); }
@@ -1495,7 +1508,7 @@ fn pkgstartbuild(p: *pkgplan, groups: []pkggroup, builder: str, includes: []str,
else { append(ba, "-"); };
append(ba, g.dir);
append(ba, g.bin);
if (g.publish.len != 0) { append(ba, g.publish); }
if (g.publish.len != 0 && !p.deferpublish) { append(ba, g.publish); }
else { append(ba, "-"); };
append(ba, g.buildok);
i += 1;
@@ -1591,6 +1604,31 @@ fn pkgstartrun(g: *pkggroup, filters: []str, timeoutarg: str,
return true;
};
// Pinned builderTest orders a retained running test as build -> run ->
// BuildInstallFunc. Re-enter the selected stage driver for the final action so
// build and test share one overwrite predicate instead of copying object magic
// into the coordinator.
fn pkginstalloutput(g: *pkggroup, builder: str) void = {
let ia: []str = [builder, "test", "--ww-install-test-output",
g.bin, g.publish];
let env: []str = os.getenvs();
let icmd: exec.command;
icmd.path = builder;
icmd.argv = ia;
icmd.env = env;
icmd.dir = "";
icmd.stdoutpath = g.installoutput;
icmd.stderrpath = g.installoutput;
icmd.deadline.sec = 0i64;
icmd.deadline.nsec = 0i64;
icmd.grace = 0i64: time.duration;
let h: exec.process;
g.installattempted = true;
exec.start(&h, &icmd);
for (!exec.poll(&h)) { time.sleep(pkgpoll, time.clock.monotonic); };
g.installres = h.result;
};
fn pkgproductbuilt(g: *pkggroup, buildonly: bool) bool = {
if (buildonly || g.notests) { return pkgisreg(g.buildok); };
return pkgisreg(g.buildok) && pkgisreg(g.bin);
@@ -1602,6 +1640,35 @@ fn pkgrunok(g: *pkggroup) bool = {
&& g.runres.code == 0;
};
fn pkginstallok(g: *pkggroup) bool = {
return g.installres.errno == 0 && g.installres.cleanuperrno == 0
&& g.installres.termination == exec.termination.EXIT
&& g.installres.code == 0;
};
fn pkgemitinstall(g: *pkggroup) bool = {
if (!g.installattempted) { return true; };
let output: str;
if (!pkgread(g.installoutput, &output)) {
pkgfailpath(g.root, "cannot read install capture");
return false;
};
if (output.len != 0) {
pkgput(os.STDERR_FILENO, output);
if (output[output.len - 1] != '\n') {
pkgput(os.STDERR_FILENO, "\n");
};
};
if (!pkginstallok(g)) {
if (output.len == 0) {
pkgreportcommand(os.STDERR_FILENO, "install", g,
&g.installres);
};
return false;
};
return true;
};
fn pkgemitgroup(g: *pkggroup, compileonly: bool) bool = {
if (g.notests) {
pkgput(os.STDOUT_FILENO, "? ");
@@ -1653,8 +1720,9 @@ fn pkgemitplan(p: *pkgplan, groups: []pkggroup,
failed += 1;
} else if (buildonly) {
void;
} else if (!pkgemitgroup(&groups[i], compileonly)) {
failed += 1;
} else {
if (!pkgemitgroup(&groups[i], compileonly)) { failed += 1; };
if (!compileonly && !pkgemitinstall(&groups[i])) { failed += 1; };
};
i += 1;
};
@@ -2385,11 +2453,12 @@ export fn packagecommand(args: []str) int = {
plan.outputcollisiondir = outputcollisiondir;
plan.suppressbuildreports = buildonly
&& (outputdir || defaultoutputdir.len != 0);
plan.deferpublish = !buildonly && !compileonly && testretain && !testnull;
append(plans, plan);
let createdir: str = "";
if (buildonly && outputdir) {
createdir = outname;
} else if (!buildonly && testretain && !testnull) {
} else if (!buildonly && compileonly && testretain && !testnull) {
i = 0;
for (i < groups.len) {
if (groups[i].publish.len != 0) {
@@ -2550,6 +2619,22 @@ export fn packagecommand(args: []str) int = {
if (active > 0) { time.sleep(pkgpoll, time.clock.monotonic); };
};
// A failed, signalled, timed-out, or unstartable run propagates to its Go
// install action, so it preserves any prior retained binary. Successful
// products install independently after their private execution.
if (!compileonly) {
i = 0;
for (i < groups.len) {
let g: *pkggroup = &groups[i];
if (g.publish.len != 0 && !g.notests
&& pkgproductbuilt(g, buildonly) && !g.runstartfailed
&& pkgrunok(g)) {
pkginstalloutput(g, builder);
};
i += 1;
};
};
i = 0;
for (i < plans.len) {
failed += pkgemitplan(&plans[i], groups, compileonly, buildonly);