ww: canonicalize directory package identities

This commit is contained in:
2026-08-13 02:48:12 +09:00
parent 853090174b
commit 0aff801def
4 changed files with 781 additions and 163 deletions

View File

@@ -38,6 +38,8 @@ type pkggroup = struct {
type pkgplan = struct {
dir: str,
sourceroot: str,
identity: str,
root: str,
workdir: str,
buildout: str,
@@ -438,6 +440,24 @@ fn pkgmakedir(path: str) bool = {
return os.mkdir(path, 448i32) == 0;
};
// 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.
fn pkgcanonicaldir(path: str, out: *str) bool = {
let before: []u8 = alloc([], os.PATH_MAX: u64)!;
before.len = os.PATH_MAX;
let bn: i64 = os.getcwd(before.ptr, before.len: u64);
if (bn <= 1i64 || bn > before.len: i64) { return false; };
if (os.chdir(path) != 0) { return false; };
let after: []u8 = alloc([], os.PATH_MAX: u64)!;
after.len = os.PATH_MAX;
let an: i64 = os.getcwd(after.ptr, after.len: u64);
let restored: i32 = os.chdir(strings.frombytes(before[0:(bn - 1i64): i32]));
if (restored != 0 || an <= 1i64 || an > after.len: i64) { return false; };
*out = strings.dup(strings.frombytes(after[0:(an - 1i64): i32]));
return true;
};
// The coordinator removes only its minted temp root; validating the opened
// inode keeps a replaced path from carrying cleanup outside that ownership.
fn pkgremoveall(path: str) bool = {
@@ -519,9 +539,8 @@ fn pkgworkescape(s: str) str = {
return strings.frombytes(out);
};
fn pkgworkkey(dir: str, pkg: str) str = {
return strings.concat("d_", pkgworkescape(dir), "_p_",
pkgworkescape(pkg));
fn pkgworkkey(dir: str) str = {
return strings.concat("d_", pkgworkescape(dir));
};
fn pkgsetplanpaths(p: *pkgplan, groups: []pkggroup, root: str, index: i32,
@@ -531,10 +550,10 @@ fn pkgsetplanpaths(p: *pkgplan, groups: []pkggroup, root: str, index: i32,
if (!pkgmakedir(p.root)) { return false; };
p.workdir = "";
if (workroot.len != 0) {
// The request root and first byte-sorted product name make one stable
// escaped key for the command-scoped driver workdir.
// Canonical request-directory identity makes equivalent spellings and
// product reorderings select one command-scoped driver workdir.
p.workdir = strings.concat(workroot, "/",
pkgworkkey(p.dir, groups[p.start].pkg));
pkgworkkey(p.sourceroot));
match (os.mkdirs(p.workdir, 448)) {
case void => void;
case let e: os.oserror => return false;
@@ -601,10 +620,14 @@ fn pkgreportcommand(kind: str, g: *pkggroup, r: *exec.result) void = {
fn pkgstartbuild(p: *pkgplan, groups: []pkggroup, builder: str, includes: []str,
h: *exec.process) void = {
let ba: []str = alloc([],
(8 + (p.end - p.start) * 6 + includes.len * 2): u64)!;
(12 + (p.end - p.start) * 6 + includes.len * 2): u64)!;
append(ba, builder);
append(ba, "test");
append(ba, "-c");
if (p.identity.len != 0) {
append(ba, "--ww-root-identity");
append(ba, p.identity);
};
let i: i32 = p.start;
for (i < p.end) {
let g: *pkggroup = &groups[i];
@@ -619,6 +642,10 @@ fn pkgstartbuild(p: *pkgplan, groups: []pkggroup, builder: str, includes: []str,
append(ba, g.buildok);
i += 1;
};
// Recursive descendants derive full identities relative to the canonical
// discovery root using the driver's ordinary ordered import lookup.
append(ba, "-I");
append(ba, p.sourceroot);
let ii: i32 = 0;
for (ii < includes.len) {
append(ba, "-I");
@@ -745,6 +772,7 @@ export fn packagecommand(args: []str) int = {
let timeoutarg: str = "";
let outname: str = "";
let workroot: str = "";
let requestidentity: str = "";
let builder: str = pkgdefaultbuilder();
let i: i32 = 0;
for (i < args.len) {
@@ -819,6 +847,16 @@ export fn packagecommand(args: []str) int = {
i += 2;
continue;
};
if (strings.compare(a, "--ww-root-identity") == 0) {
if (i + 1 >= args.len || args[i + 1].len == 0
|| requestidentity.len != 0) {
pkgusage();
return 2;
};
requestidentity = args[i + 1];
i += 2;
continue;
};
if (a.len != 0 && a[0] == '-') { pkgusage(); return 2; };
append(roots, a);
i += 1;
@@ -872,6 +910,11 @@ export fn packagecommand(args: []str) int = {
pkgfailpath(discoverroot, "directory contains no WW package sources");
return 1;
};
let canonicalroot: str;
if (!pkgcanonicaldir(discoverroot, &canonicalroot)) {
pkgfailpath(discoverroot, "cannot canonicalize package directory");
return 1;
};
let srcs: []pkgsource = alloc([], ds.paths.len: u64)!;
i = 0;
@@ -985,6 +1028,8 @@ export fn packagecommand(args: []str) int = {
let plans: []pkgplan = alloc([], 1u64)!;
let plan: pkgplan;
plan.dir = discoverroot;
plan.sourceroot = canonicalroot;
plan.identity = requestidentity;
plan.start = 0;
plan.end = groups.len;
plan.state = PKGQUEUED;