From cbe3dd12c4885adb1323742b53df1079e8efb97f Mon Sep 17 00:00:00 2001 From: Timothy Bess Date: Sun, 9 Mar 2025 18:05:11 -0400 Subject: [PATCH] Fix zig build lazy -> eager dependency promotion Before, this had a subtle ordering bug where duplicate deps that are specified as both lazy and eager in different parts of the dependency tree end up not getting fetched depending on the ordering. I modified it to resubmit lazy deps that were promoted to eager for fetching so that it will be around for the builds that expect it to be eager downstream of this. --- src/Package/Fetch.zig | 48 ++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index d729a61876..9b1d1f18cf 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -734,28 +734,34 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { // calling run(); no need to add it again. // // If we add a dep as lazy and then later try to add the same dep as eager, - // eagerness takes precedence and the existing entry is updated. + // eagerness takes precedence and the existing entry is updated and re-scheduled + // for fetching. for (dep_names, deps) |dep_name, dep| { + var promoted_existing_to_eager = false; const new_fetch = &new_fetches[new_fetch_index]; const location: Location = switch (dep.location) { - .url => |url| .{ .remote = .{ - .url = url, - .hash = h: { - const h = dep.hash orelse break :h null; - const pkg_hash: Package.Hash = .fromSlice(h); - if (h.len == 0) break :h pkg_hash; - const gop = f.job_queue.table.getOrPutAssumeCapacity(pkg_hash); - if (gop.found_existing) { - if (!dep.lazy) { - gop.value_ptr.*.lazy_status = .eager; + .url => |url| .{ + .remote = .{ + .url = url, + .hash = h: { + const h = dep.hash orelse break :h null; + const pkg_hash: Package.Hash = .fromSlice(h); + if (h.len == 0) break :h pkg_hash; + const gop = f.job_queue.table.getOrPutAssumeCapacity(pkg_hash); + if (gop.found_existing) { + if (!dep.lazy and gop.value_ptr.*.lazy_status != .eager) { + gop.value_ptr.*.lazy_status = .eager; + promoted_existing_to_eager = true; + } else { + continue; + } } - continue; - } - gop.value_ptr.* = new_fetch; - break :h pkg_hash; + gop.value_ptr.* = new_fetch; + break :h pkg_hash; + }, }, - } }, + }, .path => |rel_path| l: { // This might produce an invalid path, which is checked for // at the beginning of run(). @@ -763,10 +769,12 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { const pkg_hash = relativePathDigest(new_root, cache_root); const gop = f.job_queue.table.getOrPutAssumeCapacity(pkg_hash); if (gop.found_existing) { - if (!dep.lazy) { + if (!dep.lazy and gop.value_ptr.*.lazy_status != .eager) { gop.value_ptr.*.lazy_status = .eager; + promoted_existing_to_eager = true; + } else { + continue; } - continue; } gop.value_ptr.* = new_fetch; break :l .{ .relative_path = new_root }; @@ -774,7 +782,9 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { }; prog_names[new_fetch_index] = dep_name; new_fetch_index += 1; - f.job_queue.all_fetches.appendAssumeCapacity(new_fetch); + if (!promoted_existing_to_eager) { + f.job_queue.all_fetches.appendAssumeCapacity(new_fetch); + } new_fetch.* = .{ .arena = std.heap.ArenaAllocator.init(gpa), .location = location,