authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-06 14:03:43-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-06 14:03:43-08:00
log632d1fb948f46ae09c8e3a5e12acedafde56084a
treeba8f46f01c3e44d56ccb3afb3026272db32a33cf
parent5f453b45d395239d1b26d6cec3d3ac7f407e0fb0

fetch: fix manifest memory management


3 files changed, 29 insertions(+), 20 deletions(-)

src/Package/Fetch.zig+18-12
......@@ -76,8 +76,9 @@ use_latest_commit: bool,
7676/// Relative to the build root of the root package.
7777package_root: Cache.Path,
7878error_bundle: ErrorBundle.Wip,
79manifest: ?Manifest,
79manifest: Manifest,
8080manifest_ast: std.zig.Ast,
81have_manifest: bool,
8182computed_hash: ComputedHash,
8283/// Fetch logic notices whether a package has a build.zig file and sets this flag.
8384has_build_zig: bool,
......@@ -282,7 +283,8 @@ pub const JobQueue = struct {
282283 , .{std.zig.fmtString(hash_slice)});
283284 }
284285
285 if (fetch.manifest) |*manifest| {
286 if (fetch.have_manifest) {
287 const manifest = &fetch.manifest;
286288 try buf.appendSlice(
287289 \\ pub const deps: []const struct { []const u8, []const u8 } = &.{
288290 \\
......@@ -317,7 +319,8 @@ pub const JobQueue = struct {
317319 );
318320
319321 const root_fetch = jq.all_fetches.items[0];
320 const root_manifest = &root_fetch.manifest.?;
322 assert(root_fetch.have_manifest);
323 const root_manifest = &root_fetch.manifest;
321324
322325 for (root_manifest.dependencies.keys(), root_manifest.dependencies.values()) |name, dep| {
323326 const h = depDigest(root_fetch.package_root, jq.global_cache, dep) orelse continue;
......@@ -716,7 +719,7 @@ fn runResource(
716719 try loadManifest(f, pkg_path);
717720
718721 const filter: Filter = .{
719 .include_paths = if (f.manifest) |m| m.paths else .{},
722 .include_paths = if (f.have_manifest) f.manifest.paths else .{},
720723 };
721724
722725 // Ignore errors that were excluded by manifest, such as failure to
......@@ -809,7 +812,8 @@ fn runResource(
809812
810813pub fn computedPackageHash(f: *const Fetch) Package.Hash {
811814 const saturated_size = std.math.cast(u32, f.computed_hash.total_size) orelse std.math.maxInt(u32);
812 if (f.manifest) |man| {
815 if (f.have_manifest) {
816 const man = &f.manifest;
813817 var version_buffer: [32]u8 = undefined;
814818 const version: []const u8 = std.fmt.bufPrint(&version_buffer, "{f}", .{man.version}) catch &version_buffer;
815819 return .init(f.computed_hash.digest, man.name, version, man.id, saturated_size);
......@@ -846,15 +850,13 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {
846850 const arena = f.arena.allocator();
847851 const manifest_path = try pkg_root.join(arena, Manifest.basename);
848852
849 f.manifest = @as(Manifest, undefined);
850
851853 Manifest.load(
852854 io,
853855 arena,
854856 manifest_path,
855857 &f.manifest_ast,
856858 eb,
857 &f.manifest.?,
859 &f.manifest,
858860 f.allow_missing_paths_field,
859861 ) catch |err| switch (err) {
860862 error.FileNotFound => return,
......@@ -867,6 +869,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {
867869 return error.FetchFailed;
868870 },
869871 };
872 f.have_manifest = true;
870873}
871874
872875fn queueJobsForDeps(f: *Fetch) RunError!void {
......@@ -875,7 +878,8 @@ fn queueJobsForDeps(f: *Fetch) RunError!void {
875878 assert(f.job_queue.recursive);
876879
877880 // If the package does not have a build.zig.zon file then there are no dependencies.
878 const manifest = f.manifest orelse return;
881 if (!f.have_manifest) return;
882 const manifest = &f.manifest;
879883
880884 const new_fetches, const prog_names = nf: {
881885 const parent_arena = f.arena.allocator();
......@@ -980,8 +984,9 @@ fn queueJobsForDeps(f: *Fetch) RunError!void {
980984
981985 .package_root = undefined,
982986 .error_bundle = undefined,
983 .manifest = null,
987 .manifest = undefined,
984988 .manifest_ast = undefined,
989 .have_manifest = false,
985990 .computed_hash = undefined,
986991 .has_build_zig = false,
987992 .oom_flag = false,
......@@ -1958,7 +1963,7 @@ const Filter = struct {
19581963 include_paths: std.StringArrayHashMapUnmanaged(void) = .empty,
19591964
19601965 /// sub_path is relative to the package root.
1961 pub fn includePath(self: Filter, sub_path: []const u8) bool {
1966 pub fn includePath(self: *const Filter, sub_path: []const u8) bool {
19621967 if (self.include_paths.count() == 0) return true;
19631968 if (self.include_paths.contains("")) return true;
19641969 if (self.include_paths.contains(".")) return true;
......@@ -2349,8 +2354,9 @@ const TestFetchBuilder = struct {
23492354
23502355 .package_root = undefined,
23512356 .error_bundle = undefined,
2352 .manifest = null,
2357 .manifest = undefined,
23532358 .manifest_ast = undefined,
2359 .have_manifest = false,
23542360 .computed_hash = undefined,
23552361 .has_build_zig = false,
23562362 .oom_flag = false,
src/Package/Manifest.zig+3-3
......@@ -645,7 +645,7 @@ test "basic" {
645645
646646 var rng = std.Random.DefaultPrng.init(0);
647647
648 var manifest = try Manifest.parse(gpa, ast, rng.random(), .{});
648 var manifest = try Manifest.parse(gpa, &ast, rng.random(), .{});
649649 defer manifest.deinit(gpa);
650650
651651 try testing.expect(manifest.errors.len == 0);
......@@ -691,7 +691,7 @@ test "minimum_zig_version" {
691691
692692 var rng = std.Random.DefaultPrng.init(0);
693693
694 var manifest = try Manifest.parse(gpa, ast, rng.random(), .{});
694 var manifest = try Manifest.parse(gpa, &ast, rng.random(), .{});
695695 defer manifest.deinit(gpa);
696696
697697 try testing.expect(manifest.errors.len == 0);
......@@ -726,7 +726,7 @@ test "minimum_zig_version - invalid version" {
726726
727727 var rng = std.Random.DefaultPrng.init(0);
728728
729 var manifest = try Manifest.parse(gpa, ast, rng.random(), .{});
729 var manifest = try Manifest.parse(gpa, &ast, rng.random(), .{});
730730 defer manifest.deinit(gpa);
731731
732732 try testing.expect(manifest.errors.len == 1);
src/main.zig+8-5
......@@ -5323,8 +5323,9 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
53235323
53245324 .package_root = undefined,
53255325 .error_bundle = undefined,
5326 .manifest = null,
5326 .manifest = undefined,
53275327 .manifest_ast = undefined,
5328 .have_manifest = false,
53285329 .computed_hash = undefined,
53295330 .has_build_zig = true,
53305331 .oom_flag = false,
......@@ -5402,7 +5403,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
54025403 // dependencies' build.zig modules by name.
54035404 for (fetches) |f| {
54045405 const mod = f.module orelse continue;
5405 const man = f.manifest orelse continue;
5406 if (!f.have_manifest) continue;
5407 const man = &f.manifest;
54065408 const dep_names = man.dependencies.keys();
54075409 try mod.deps.ensureUnusedCapacity(arena, @intCast(dep_names.len));
54085410 for (dep_names, man.dependencies.values()) |name, dep| {
......@@ -7134,8 +7136,9 @@ fn cmdFetch(
71347136
71357137 .package_root = undefined,
71367138 .error_bundle = undefined,
7137 .manifest = null,
7139 .manifest = undefined,
71387140 .manifest_ast = undefined,
7141 .have_manifest = false,
71397142 .computed_hash = undefined,
71407143 .has_build_zig = false,
71417144 .oom_flag = false,
......@@ -7171,9 +7174,9 @@ fn cmdFetch(
71717174 },
71727175 .yes, .exact => |name| name: {
71737176 if (name) |n| break :name n;
7174 const fetched_manifest = fetch.manifest orelse
7177 if (!fetch.have_manifest)
71757178 fatal("unable to determine name; fetched package has no build.zig.zon file", .{});
7176 break :name fetched_manifest.name;
7179 break :name fetch.manifest.name;
71777180 },
71787181 };
71797182