From fffc02f2914e5a70b37651e353eb3eabad5f434a Mon Sep 17 00:00:00 2001 From: Timothy Bess Date: Sun, 9 Mar 2025 18:05:11 -0400 Subject: [PATCH] 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 | 46 ++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index 0b23d5d5bdad..55f37d4dac4d 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -707,27 +707,33 @@ 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); - 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); + 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(). @@ -735,10 +741,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 }; @@ -746,7 +754,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,