ww: put selected toolchain first in test PATH

This commit is contained in:
2026-08-21 05:30:10 +09:00
parent 1b71250ad5
commit 9b6b1100f4
7 changed files with 586 additions and 96 deletions

View File

@@ -268,17 +268,27 @@ fn pkgfreestrs(values: []str) void = {
};
};
// Go's AppendPWD appends, then os/exec keeps the last duplicate value. WW's
// executor preserves duplicates, so discard earlier exact PWD entries here.
fn runenv(tmpdir: str, pwd: str, out: *[]str, tmpowned: *str,
pwdowned: *str) bool = {
// Go's AppendPATH and AppendPWD append, then os/exec keeps the last duplicate
// values. WW's executor preserves duplicates, so discard earlier exact entries
// and materialize the selected driver's sibling directory first in PATH.
fn runenv(tmpdir: str, pwd: str, builder: str, out: *[]str, tmpowned: *str,
pathowned: *str, pwdowned: *str) bool = {
let toolbin: str;
let oom: bool = false;
if (!pkgcanonicaldir(pkgdirname(builder), &toolbin, &oom)) {
if (!oom) {
pkgputln(os.STDERR_FILENO,
"wwtest package: cannot determine toolchain directory");
};
return false;
};
let inherited: []str = os.getenvs();
if (inherited.len > PKG_COUNT_MAX - 3) {
if (inherited.len > PKG_COUNT_MAX - 4) {
pkgputln(os.STDERR_FILENO,
"wwtest package: package graph is too large");
return false;
};
let allocation: ([]str | nomem) = pkgallocstrs(inherited.len + 3);
let allocation: ([]str | nomem) = pkgallocstrs(inherited.len + 4);
let env: []str;
match (allocation) {
case let value: []str => env = value;
@@ -291,6 +301,7 @@ fn runenv(tmpdir: str, pwd: str, out: *[]str, tmpowned: *str,
for (i < inherited.len) {
if (!strings.hasprefix(inherited[i], "TMPDIR=")
&& !strings.hasprefix(inherited[i], "LC_ALL=")
&& !strings.hasprefix(inherited[i], "PATH=")
&& !strings.hasprefix(inherited[i], "PWD=")) {
append(env, inherited[i]);
};
@@ -302,22 +313,44 @@ fn runenv(tmpdir: str, pwd: str, out: *[]str, tmpowned: *str,
pkgfreestrs(env);
return false;
};
let pwdenv: str;
if (!pkgstring(&pwdenv, "PWD=", pwd)) {
let pathenv: str;
let pathok: bool = false;
match (os.getenv("PATH")) {
case let inheritedpath: str => {
if (inheritedpath.len == 0) {
pathok = pkgstring(&pathenv, "PATH=", toolbin);
} else {
pathok = pkgstring(&pathenv, "PATH=", toolbin, ":",
inheritedpath);
};
};
case void => pathok = pkgstring(&pathenv, "PATH=", toolbin);
};
if (!pathok) {
pkgfreeownedstr(tmpenv);
pkgfreestrs(env);
return false;
};
let pwdenv: str;
if (!pkgstring(&pwdenv, "PWD=", pwd)) {
pkgfreeownedstr(tmpenv);
pkgfreeownedstr(pathenv);
pkgfreestrs(env);
return false;
};
append(env, tmpenv);
append(env, pathenv);
append(env, pwdenv);
*out = env;
*tmpowned = tmpenv;
*pathowned = pathenv;
*pwdowned = pwdenv;
return true;
};
fn freerunenv(env: []str, tmpowned: str, pwdowned: str) void = {
fn freerunenv(env: []str, tmpowned: str, pathowned: str, pwdowned: str) void = {
pkgfreeownedstr(tmpowned);
pkgfreeownedstr(pathowned);
pkgfreeownedstr(pwdowned);
pkgfreestrs(env);
};
@@ -1240,8 +1273,8 @@ fn pkgmakedir(path: str) bool = {
};
// Resolve a directory to the kernel's symlink-free absolute spelling. The
// coordinator is single-threaded while planning, so the temporary cwd change
// cannot race a child process launch.
// coordinator is single-threaded; each temporary cwd change is restored before
// it plans further paths or launches another child.
fn pkgcanonicaldir(path: str, out: *str, oom: *bool) bool = {
*oom = false;
let beforeallocation: ([]u8 | nomem) = pkgallocbytes(os.PATH_MAX);
@@ -1553,7 +1586,7 @@ fn pkgstartbuild(p: *pkgplan, groups: []pkggroup, builder: str, includes: []str,
};
fn pkgstartrun(g: *pkggroup, filters: []str, timeoutarg: str,
list: bool, h: *exec.process) bool = {
list: bool, builder: str, h: *exec.process) bool = {
if (filters.len > PKG_COUNT_MAX - 4) {
pkgputln(os.STDERR_FILENO,
"wwtest package: package graph is too large");
@@ -1581,8 +1614,10 @@ fn pkgstartrun(g: *pkggroup, filters: []str, timeoutarg: str,
for (i < filters.len) { append(ra, filters[i]); i += 1; };
let env: []str;
let tmpowned: str;
let pathowned: str;
let pwdowned: str;
if (!runenv(g.root, g.dir, &env, &tmpowned, &pwdowned)) {
if (!runenv(g.root, g.dir, builder, &env, &tmpowned,
&pathowned, &pwdowned)) {
pkgfreeownedstr(packagearg);
pkgfreestrs(ra);
return false;
@@ -1598,7 +1633,7 @@ fn pkgstartrun(g: *pkggroup, filters: []str, timeoutarg: str,
rcmd.deadline.nsec = 0i64;
rcmd.grace = 0i64: time.duration;
exec.start(h, &rcmd);
freerunenv(env, tmpowned, pwdowned);
freerunenv(env, tmpowned, pathowned, pwdowned);
pkgfreeownedstr(packagearg);
pkgfreestrs(ra);
return true;
@@ -2561,7 +2596,7 @@ export fn packagecommand(args: []str) int = {
productcompleted += 1;
} else {
if (!pkgstartrun(g, filters, timeoutarg, list,
&runhandles[gi])) {
builder, &runhandles[gi])) {
g.runstartfailed = true;
g.state = PKGDONE;
productcompleted += 1;