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,...@@ -76,8 +76,9 @@ use_latest_commit: bool,
76/// Relative to the build root of the root package.76/// Relative to the build root of the root package.
77package_root: Cache.Path,77package_root: Cache.Path,
78error_bundle: ErrorBundle.Wip,78error_bundle: ErrorBundle.Wip,
79manifest: ?Manifest,79manifest: Manifest,
80manifest_ast: std.zig.Ast,80manifest_ast: std.zig.Ast,
81have_manifest: bool,
81computed_hash: ComputedHash,82computed_hash: ComputedHash,
82/// Fetch logic notices whether a package has a build.zig file and sets this flag.83/// Fetch logic notices whether a package has a build.zig file and sets this flag.
83has_build_zig: bool,84has_build_zig: bool,
...@@ -282,7 +283,8 @@ pub const JobQueue = struct {...@@ -282,7 +283,8 @@ pub const JobQueue = struct {
282 , .{std.zig.fmtString(hash_slice)});283 , .{std.zig.fmtString(hash_slice)});
283 }284 }
284285
285 if (fetch.manifest) |*manifest| {286 if (fetch.have_manifest) {
287 const manifest = &fetch.manifest;
286 try buf.appendSlice(288 try buf.appendSlice(
287 \\ pub const deps: []const struct { []const u8, []const u8 } = &.{289 \\ pub const deps: []const struct { []const u8, []const u8 } = &.{
288 \\290 \\
...@@ -317,7 +319,8 @@ pub const JobQueue = struct {...@@ -317,7 +319,8 @@ pub const JobQueue = struct {
317 );319 );
318320
319 const root_fetch = jq.all_fetches.items[0];321 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
322 for (root_manifest.dependencies.keys(), root_manifest.dependencies.values()) |name, dep| {325 for (root_manifest.dependencies.keys(), root_manifest.dependencies.values()) |name, dep| {
323 const h = depDigest(root_fetch.package_root, jq.global_cache, dep) orelse continue;326 const h = depDigest(root_fetch.package_root, jq.global_cache, dep) orelse continue;
...@@ -716,7 +719,7 @@ fn runResource(...@@ -716,7 +719,7 @@ fn runResource(
716 try loadManifest(f, pkg_path);719 try loadManifest(f, pkg_path);
717720
718 const filter: Filter = .{721 const filter: Filter = .{
719 .include_paths = if (f.manifest) |m| m.paths else .{},722 .include_paths = if (f.have_manifest) f.manifest.paths else .{},
720 };723 };
721724
722 // Ignore errors that were excluded by manifest, such as failure to725 // Ignore errors that were excluded by manifest, such as failure to
...@@ -809,7 +812,8 @@ fn runResource(...@@ -809,7 +812,8 @@ fn runResource(
809812
810pub fn computedPackageHash(f: *const Fetch) Package.Hash {813pub fn computedPackageHash(f: *const Fetch) Package.Hash {
811 const saturated_size = std.math.cast(u32, f.computed_hash.total_size) orelse std.math.maxInt(u32);814 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;
813 var version_buffer: [32]u8 = undefined;817 var version_buffer: [32]u8 = undefined;
814 const version: []const u8 = std.fmt.bufPrint(&version_buffer, "{f}", .{man.version}) catch &version_buffer;818 const version: []const u8 = std.fmt.bufPrint(&version_buffer, "{f}", .{man.version}) catch &version_buffer;
815 return .init(f.computed_hash.digest, man.name, version, man.id, saturated_size);819 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 {...@@ -846,15 +850,13 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {
846 const arena = f.arena.allocator();850 const arena = f.arena.allocator();
847 const manifest_path = try pkg_root.join(arena, Manifest.basename);851 const manifest_path = try pkg_root.join(arena, Manifest.basename);
848852
849 f.manifest = @as(Manifest, undefined);
850
851 Manifest.load(853 Manifest.load(
852 io,854 io,
853 arena,855 arena,
854 manifest_path,856 manifest_path,
855 &f.manifest_ast,857 &f.manifest_ast,
856 eb,858 eb,
857 &f.manifest.?,859 &f.manifest,
858 f.allow_missing_paths_field,860 f.allow_missing_paths_field,
859 ) catch |err| switch (err) {861 ) catch |err| switch (err) {
860 error.FileNotFound => return,862 error.FileNotFound => return,
...@@ -867,6 +869,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {...@@ -867,6 +869,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void {
867 return error.FetchFailed;869 return error.FetchFailed;
868 },870 },
869 };871 };
872 f.have_manifest = true;
870}873}
871874
872fn queueJobsForDeps(f: *Fetch) RunError!void {875fn queueJobsForDeps(f: *Fetch) RunError!void {
...@@ -875,7 +878,8 @@ fn queueJobsForDeps(f: *Fetch) RunError!void {...@@ -875,7 +878,8 @@ fn queueJobsForDeps(f: *Fetch) RunError!void {
875 assert(f.job_queue.recursive);878 assert(f.job_queue.recursive);
876879
877 // If the package does not have a build.zig.zon file then there are no dependencies.880 // 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
880 const new_fetches, const prog_names = nf: {884 const new_fetches, const prog_names = nf: {
881 const parent_arena = f.arena.allocator();885 const parent_arena = f.arena.allocator();
...@@ -980,8 +984,9 @@ fn queueJobsForDeps(f: *Fetch) RunError!void {...@@ -980,8 +984,9 @@ fn queueJobsForDeps(f: *Fetch) RunError!void {
980984
981 .package_root = undefined,985 .package_root = undefined,
982 .error_bundle = undefined,986 .error_bundle = undefined,
983 .manifest = null,987 .manifest = undefined,
984 .manifest_ast = undefined,988 .manifest_ast = undefined,
989 .have_manifest = false,
985 .computed_hash = undefined,990 .computed_hash = undefined,
986 .has_build_zig = false,991 .has_build_zig = false,
987 .oom_flag = false,992 .oom_flag = false,
...@@ -1958,7 +1963,7 @@ const Filter = struct {...@@ -1958,7 +1963,7 @@ const Filter = struct {
1958 include_paths: std.StringArrayHashMapUnmanaged(void) = .empty,1963 include_paths: std.StringArrayHashMapUnmanaged(void) = .empty,
19591964
1960 /// sub_path is relative to the package root.1965 /// 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 {
1962 if (self.include_paths.count() == 0) return true;1967 if (self.include_paths.count() == 0) return true;
1963 if (self.include_paths.contains("")) return true;1968 if (self.include_paths.contains("")) return true;
1964 if (self.include_paths.contains(".")) return true;1969 if (self.include_paths.contains(".")) return true;
...@@ -2349,8 +2354,9 @@ const TestFetchBuilder = struct {...@@ -2349,8 +2354,9 @@ const TestFetchBuilder = struct {
23492354
2350 .package_root = undefined,2355 .package_root = undefined,
2351 .error_bundle = undefined,2356 .error_bundle = undefined,
2352 .manifest = null,2357 .manifest = undefined,
2353 .manifest_ast = undefined,2358 .manifest_ast = undefined,
2359 .have_manifest = false,
2354 .computed_hash = undefined,2360 .computed_hash = undefined,
2355 .has_build_zig = false,2361 .has_build_zig = false,
2356 .oom_flag = false,2362 .oom_flag = false,
src/Package/Manifest.zig+3-3
...@@ -645,7 +645,7 @@ test "basic" {...@@ -645,7 +645,7 @@ test "basic" {
645645
646 var rng = std.Random.DefaultPrng.init(0);646 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(), .{});
649 defer manifest.deinit(gpa);649 defer manifest.deinit(gpa);
650650
651 try testing.expect(manifest.errors.len == 0);651 try testing.expect(manifest.errors.len == 0);
...@@ -691,7 +691,7 @@ test "minimum_zig_version" {...@@ -691,7 +691,7 @@ test "minimum_zig_version" {
691691
692 var rng = std.Random.DefaultPrng.init(0);692 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(), .{});
695 defer manifest.deinit(gpa);695 defer manifest.deinit(gpa);
696696
697 try testing.expect(manifest.errors.len == 0);697 try testing.expect(manifest.errors.len == 0);
...@@ -726,7 +726,7 @@ test "minimum_zig_version - invalid version" {...@@ -726,7 +726,7 @@ test "minimum_zig_version - invalid version" {
726726
727 var rng = std.Random.DefaultPrng.init(0);727 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(), .{});
730 defer manifest.deinit(gpa);730 defer manifest.deinit(gpa);
731731
732 try testing.expect(manifest.errors.len == 1);732 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,...@@ -5323,8 +5323,9 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
53235323
5324 .package_root = undefined,5324 .package_root = undefined,
5325 .error_bundle = undefined,5325 .error_bundle = undefined,
5326 .manifest = null,5326 .manifest = undefined,
5327 .manifest_ast = undefined,5327 .manifest_ast = undefined,
5328 .have_manifest = false,
5328 .computed_hash = undefined,5329 .computed_hash = undefined,
5329 .has_build_zig = true,5330 .has_build_zig = true,
5330 .oom_flag = false,5331 .oom_flag = false,
...@@ -5402,7 +5403,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,...@@ -5402,7 +5403,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
5402 // dependencies' build.zig modules by name.5403 // dependencies' build.zig modules by name.
5403 for (fetches) |f| {5404 for (fetches) |f| {
5404 const mod = f.module orelse continue;5405 const mod = f.module orelse continue;
5405 const man = f.manifest orelse continue;5406 if (!f.have_manifest) continue;
5407 const man = &f.manifest;
5406 const dep_names = man.dependencies.keys();5408 const dep_names = man.dependencies.keys();
5407 try mod.deps.ensureUnusedCapacity(arena, @intCast(dep_names.len));5409 try mod.deps.ensureUnusedCapacity(arena, @intCast(dep_names.len));
5408 for (dep_names, man.dependencies.values()) |name, dep| {5410 for (dep_names, man.dependencies.values()) |name, dep| {
...@@ -7134,8 +7136,9 @@ fn cmdFetch(...@@ -7134,8 +7136,9 @@ fn cmdFetch(
71347136
7135 .package_root = undefined,7137 .package_root = undefined,
7136 .error_bundle = undefined,7138 .error_bundle = undefined,
7137 .manifest = null,7139 .manifest = undefined,
7138 .manifest_ast = undefined,7140 .manifest_ast = undefined,
7141 .have_manifest = false,
7139 .computed_hash = undefined,7142 .computed_hash = undefined,
7140 .has_build_zig = false,7143 .has_build_zig = false,
7141 .oom_flag = false,7144 .oom_flag = false,
...@@ -7171,9 +7174,9 @@ fn cmdFetch(...@@ -7171,9 +7174,9 @@ fn cmdFetch(
7171 },7174 },
7172 .yes, .exact => |name| name: {7175 .yes, .exact => |name| name: {
7173 if (name) |n| break :name n;7176 if (name) |n| break :name n;
7174 const fetched_manifest = fetch.manifest orelse7177 if (!fetch.have_manifest)
7175 fatal("unable to determine name; fetched package has no build.zig.zon file", .{});7178 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;
7177 },7180 },
7178 };7181 };
71797182