authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-21 18:06:13+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-04-21 18:06:13+02:00
logb5d8966e05926c31b16cdd18ee324cf3b6381d51
treed35339bac764cbf199484e8bcec23979cacbb63e
parent3252a0553175690ff8a2f0aa8a5697c8344ec59c
parent74b56501b3ac7421a7ae7bda177b7d1b737242dd

Merge pull request 'package fetching fixes and enhancements' (#31992) from fetch-enhancements into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31992

3 files changed, 157 insertions(+), 114 deletions(-)

lib/std/zig.zig+1
......@@ -744,6 +744,7 @@ pub fn parseTargetQueryOrReportFatalError(
744744pub const EnvVar = enum {
745745 ZIG_GLOBAL_CACHE_DIR,
746746 ZIG_LOCAL_CACHE_DIR,
747 ZIG_LOCAL_PKG_DIR,
747748 ZIG_LIB_DIR,
748749 ZIG_LIBC,
749750 ZIG_BUILD_RUNNER,
src/Package/Fetch.zig+81-69
......@@ -56,6 +56,9 @@ location_tok: std.zig.Ast.TokenIndex,
5656hash_tok: std.zig.Ast.OptionalTokenIndex,
5757name_tok: std.zig.Ast.TokenIndex,
5858lazy_status: LazyStatus,
59/// Same as `parent_packge_root` except it is unchanged when recursing into
60/// relative file paths (as opposed to URL).
61remote_package_root: Cache.Path,
5962parent_package_root: Cache.Path,
6063parent_manifest_ast: ?*const std.zig.Ast,
6164prog_node: std.Progress.Node,
......@@ -104,6 +107,12 @@ pub const LazyStatus = enum {
104107 unavailable,
105108};
106109
110pub const LocalStorage = struct {
111 cache_root: Cache.Path,
112 /// Path to "zig-pkg" inside the package in which the user ran `zig build`.
113 pkg_root: Cache.Path,
114};
115
107116/// Contains shared state among all `Fetch` tasks.
108117pub const JobQueue = struct {
109118 io: Io,
......@@ -122,9 +131,8 @@ pub const JobQueue = struct {
122131 /// This tracks `Fetch` tasks as well as recompression tasks.
123132 group: Io.Group = .init,
124133 global_cache: Cache.Directory,
125 local_cache: Cache.Path,
126 /// Path to "zig-pkg" inside the package in which the user ran `zig build`.
127 root_pkg_path: Cache.Path,
134 /// If `null`, indicates fetch globally only.
135 local_storage: ?*const LocalStorage,
128136 /// If true then, no fetching occurs, and:
129137 /// * The `global_cache` directory is assumed to be the direct parent
130138 /// directory of on-disk packages rather than having the "p/" directory
......@@ -341,7 +349,7 @@ pub const JobQueue = struct {
341349 );
342350 }
343351
344 fn recompress(jq: *JobQueue, package_hash: Package.Hash) Io.Cancelable!void {
352 fn recompress(jq: *JobQueue, package_hash: Package.Hash, package_root: Cache.Path) Io.Cancelable!void {
345353 const pkg_hash_slice = package_hash.toSlice();
346354
347355 const prog_node = jq.prog_node.startFmt(0, "recompress {s}", .{pkg_hash_slice});
......@@ -359,7 +367,7 @@ pub const JobQueue = struct {
359367 defer arena_instance.deinit();
360368 const arena = arena_instance.allocator();
361369
362 recompressFallible(jq, arena, dest_path, pkg_hash_slice, prog_node) catch |err| switch (err) {
370 recompressFallible(jq, arena, dest_path, pkg_hash_slice, package_root, prog_node) catch |err| switch (err) {
363371 error.Canceled => |e| return e,
364372 error.ReadFailed => comptime unreachable,
365373 error.WriteFailed => comptime unreachable,
......@@ -372,6 +380,7 @@ pub const JobQueue = struct {
372380 arena: Allocator,
373381 dest_path: Cache.Path,
374382 pkg_hash_slice: []const u8,
383 package_root: Cache.Path,
375384 prog_node: std.Progress.Node,
376385 ) !void {
377386 const gpa = jq.http_client.allocator;
......@@ -386,7 +395,7 @@ pub const JobQueue = struct {
386395 var scanned_files: std.ArrayList(ScannedFile) = .empty;
387396 defer scanned_files.deinit(gpa);
388397
389 var pkg_dir = try jq.root_pkg_path.openDir(io, pkg_hash_slice, .{ .iterate = true });
398 var pkg_dir = try package_root.root_dir.handle.openDir(io, package_root.sub_path, .{ .iterate = true });
390399 defer pkg_dir.close(io);
391400
392401 {
......@@ -513,7 +522,6 @@ pub fn run(f: *Fetch) RunError!void {
513522 const eb = &f.error_bundle;
514523 const arena = f.arena.allocator();
515524 const gpa = f.arena.child_allocator;
516 const local_cache_root = job_queue.local_cache;
517525
518526 try eb.init(gpa);
519527
......@@ -534,32 +542,19 @@ pub fn run(f: *Fetch) RunError!void {
534542 );
535543 // Packages fetched by URL may not use relative paths to escape outside the
536544 // fetched package directory from within the package cache.
537 if (pkg_root.root_dir.eql(local_cache_root.root_dir)) {
538 // `parent_package_root.sub_path` contains a path like this:
539 // "p/$hash", or
540 // "p/$hash/foo", with possibly more directories after "foo".
541 // We want to fail unless the resolved relative path has a
542 // prefix of "p/$hash/".
543 const prefix_len: usize = if (job_queue.read_only) 0 else "p/".len;
544 const parent_sub_path = f.parent_package_root.sub_path;
545 const end = find_end: {
546 if (parent_sub_path.len > prefix_len) {
547 // Use `isSep` instead of `indexOfScalarPos` to account for
548 // Windows accepting both `\` and `/` as path separators.
549 for (parent_sub_path[prefix_len..], prefix_len..) |c, i| {
550 if (std.fs.path.isSep(c)) break :find_end i;
551 }
552 }
553 break :find_end parent_sub_path.len;
554 };
555 const expected_prefix = parent_sub_path[0..end];
556 if (!std.mem.startsWith(u8, pkg_root.sub_path, expected_prefix)) {
557 return f.fail(
558 f.location_tok,
559 try eb.printString("dependency path outside project: '{f}'", .{pkg_root}),
560 );
561 }
562 }
545
546 // This code path is only reachable recursively and the sub_path
547 // will already have been resolved to no longer have extra ".." or
548 // "." components.
549 assert(job_queue.local_storage != null);
550 log.debug("checking pkg root \"{s}\" against parent package root \"{s}\"", .{
551 pkg_root.sub_path, f.remote_package_root.sub_path,
552 });
553 assert(pkg_root.root_dir.eql(f.remote_package_root.root_dir));
554 if (!std.mem.startsWith(u8, pkg_root.sub_path, f.remote_package_root.sub_path)) return f.fail(
555 f.location_tok,
556 try eb.printString("dependency path outside project: '{f}'", .{pkg_root}),
557 );
563558 f.package_root = pkg_root;
564559 try loadManifest(f, pkg_root);
565560 if (!f.has_build_zig) try checkBuildFileExistence(f);
......@@ -602,6 +597,7 @@ pub fn run(f: *Fetch) RunError!void {
602597 log.debug("using fork {f} for {s}", .{ fork.path, fork.manifest.name });
603598 fork.uses += 1;
604599 f.package_root = fork.path;
600 f.remote_package_root = f.package_root;
605601 f.manifest_ast = fork.manifest_ast;
606602 f.manifest = fork.manifest;
607603 f.have_manifest = true;
......@@ -610,31 +606,34 @@ pub fn run(f: *Fetch) RunError!void {
610606 return queueJobsForDeps(f);
611607 }
612608
613 const package_root = try job_queue.root_pkg_path.join(arena, expected_hash.toSlice());
614 if (package_root.root_dir.handle.access(io, package_root.sub_path, .{})) |_| {
615 assert(f.lazy_status != .unavailable);
616 f.package_root = package_root;
617 try loadManifest(f, f.package_root);
618 try checkBuildFileExistence(f);
619 if (!job_queue.recursive) return;
620 return queueJobsForDeps(f);
621 } else |err| switch (err) {
622 error.FileNotFound => {
623 log.debug("FileNotFound: {f}", .{package_root});
624 if (job_queue.read_only and f.lazy_status == .eager) return f.fail(
625 f.name_tok,
626 try eb.printString("package not found at '{f}'", .{package_root}),
627 );
628 },
629 error.Canceled => |e| return e,
630 else => |e| {
631 try eb.addRootErrorMessage(.{
632 .msg = try eb.printString("unable to open package cache directory {f}: {t}", .{
633 package_root, e,
634 }),
635 });
636 return error.FetchFailed;
637 },
609 if (job_queue.local_storage) |ls| {
610 const package_root = try ls.pkg_root.join(arena, expected_hash.toSlice());
611 if (package_root.root_dir.handle.access(io, package_root.sub_path, .{})) |_| {
612 assert(f.lazy_status != .unavailable);
613 f.package_root = package_root;
614 f.remote_package_root = f.package_root;
615 try loadManifest(f, f.package_root);
616 try checkBuildFileExistence(f);
617 if (!job_queue.recursive) return;
618 return queueJobsForDeps(f);
619 } else |err| switch (err) {
620 error.FileNotFound => {
621 log.debug("FileNotFound: {f}", .{package_root});
622 if (job_queue.read_only and f.lazy_status == .eager) return f.fail(
623 f.name_tok,
624 try eb.printString("package not found at '{f}'", .{package_root}),
625 );
626 },
627 error.Canceled => |e| return e,
628 else => |e| {
629 try eb.addRootErrorMessage(.{
630 .msg = try eb.printString("unable to open package cache directory {f}: {t}", .{
631 package_root, e,
632 }),
633 });
634 return error.FetchFailed;
635 },
636 }
638637 }
639638
640639 // Check global cache before remote fetch.
......@@ -713,7 +712,14 @@ fn runResource(
713712 break :r x;
714713 };
715714 const tmp_dir_sub_path = ".tmp-" ++ std.fmt.hex(rand_int);
716 const tmp_directory_path = try job_queue.root_pkg_path.join(arena, tmp_dir_sub_path);
715 const tmp_tmp_dir_sub_path = "tmp/" ++ tmp_dir_sub_path;
716 const tmp_directory_path: Cache.Path = if (job_queue.local_storage) |ls|
717 try ls.pkg_root.join(arena, tmp_dir_sub_path)
718 else
719 .{
720 .root_dir = job_queue.global_cache,
721 .sub_path = tmp_tmp_dir_sub_path,
722 };
717723
718724 const package_sub_path = blk: {
719725 var tmp_directory: Cache.Directory = .{
......@@ -772,19 +778,24 @@ fn runResource(
772778 // zig package directory untouched as it may be in use. This is done even
773779 // if the hash is invalid, in case the package with the different hash is
774780 // used in the future.
775 f.package_root = try job_queue.root_pkg_path.join(arena, computed_package_hash.toSlice());
776 renameTmpIntoCache(io, package_sub_path, f.package_root) catch |err| {
777 try eb.addRootErrorMessage(.{ .msg = try eb.printString(
778 "unable to rename temporary directory {f} into package cache directory {f}: {t}",
779 .{ package_sub_path, f.package_root, err },
780 ) });
781 return error.FetchFailed;
782 };
781 if (job_queue.local_storage) |ls| {
782 f.package_root = try ls.pkg_root.join(arena, computed_package_hash.toSlice());
783 renameTmpIntoCache(io, package_sub_path, f.package_root) catch |err| {
784 try eb.addRootErrorMessage(.{ .msg = try eb.printString(
785 "unable to rename temporary directory {f} into package cache directory {f}: {t}",
786 .{ package_sub_path, f.package_root, err },
787 ) });
788 return error.FetchFailed;
789 };
790 } else {
791 f.package_root = tmp_directory_path;
792 }
793 f.remote_package_root = f.package_root;
783794
784795 if (!disable_recompress) {
785796 // Spin off a task to recompress the tarball, with filtered files deleted, into
786797 // the global cache.
787 job_queue.group.async(io, JobQueue.recompress, .{ job_queue, computed_package_hash });
798 job_queue.group.async(io, JobQueue.recompress, .{ job_queue, computed_package_hash, f.package_root });
788799 }
789800
790801 // Remove temporary directory root if not already renamed to global cache.
......@@ -991,6 +1002,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void {
9911002 .all => .eager,
9921003 },
9931004 .parent_package_root = f.package_root,
1005 .remote_package_root = f.remote_package_root,
9941006 .parent_manifest_ast = &f.manifest_ast,
9951007 .prog_node = f.prog_node,
9961008 .job_queue = f.job_queue,
......@@ -1185,7 +1197,7 @@ fn initResource(f: *Fetch, uri: std.Uri, resource: *Resource, reader_buffer: []u
11851197 if (ascii.eqlIgnoreCase(uri.scheme, "file")) {
11861198 const path = try uri.path.toRawMaybeAlloc(arena);
11871199 const file = f.parent_package_root.openFile(io, path, .{}) catch |err| {
1188 return f.fail(f.location_tok, try eb.printString("unable to open '{f}{s}': {t}", .{
1200 return f.fail(f.location_tok, try eb.printString("unable to open {f}/{s}: {t}", .{
11891201 f.parent_package_root, path, err,
11901202 }));
11911203 };
src/main.zig+75-45
......@@ -1359,12 +1359,7 @@ fn buildOutputType(
13591359 } else if (mem.eql(u8, arg, "--zig-lib-dir")) {
13601360 override_lib_dir = args_iter.nextOrFatal();
13611361 } else if (mem.eql(u8, arg, "--debug-log")) {
1362 if (!build_options.enable_logging) {
1363 warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{});
1364 _ = args_iter.nextOrFatal();
1365 } else {
1366 try log_scopes.append(arena, args_iter.nextOrFatal());
1367 }
1362 try addDebugLog(arena, args_iter.nextOrFatal());
13681363 } else if (mem.eql(u8, arg, "--listen")) {
13691364 const next_arg = args_iter.nextOrFatal();
13701365 if (mem.eql(u8, next_arg, "-")) {
......@@ -4958,6 +4953,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
49584953 var override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map);
49594954 var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map);
49604955 var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map);
4956 var override_pkg_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_PKG_DIR.get(environ_map);
49614957 var override_build_runner: ?[]const u8 = EnvVar.ZIG_BUILD_RUNNER.get(environ_map);
49624958 var child_argv: std.ArrayList([]const u8) = .empty;
49634959 var forks: std.ArrayList(Fork) = .empty;
......@@ -5048,6 +5044,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
50485044 i += 1;
50495045 override_local_cache_dir = args[i];
50505046 continue;
5047 } else if (mem.eql(u8, arg, "--pkg-dir")) {
5048 if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg});
5049 i += 1;
5050 override_pkg_dir = args[i];
5051 continue;
50515052 } else if (mem.eql(u8, arg, "--global-cache-dir")) {
50525053 if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg});
50535054 i += 1;
......@@ -5092,11 +5093,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
50925093 if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg});
50935094 try child_argv.appendSlice(arena, args[i .. i + 2]);
50945095 i += 1;
5095 if (!build_options.enable_logging) {
5096 warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{});
5097 } else {
5098 try log_scopes.append(arena, args[i]);
5099 }
5096 try addDebugLog(arena, args[i]);
51005097 continue;
51015098 } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
51025099 if (build_options.enable_debug_extensions) {
......@@ -5325,9 +5322,6 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
53255322 .parent = root_mod,
53265323 });
53275324
5328 var cleanup_build_dir: ?Io.Dir = null;
5329 defer if (cleanup_build_dir) |*dir| dir.close(io);
5330
53315325 if (dev.env.supports(.fetch_command)) {
53325326 const fetch_prog_node = root_prog_node.start("Fetch Packages", 0);
53335327 defer fetch_prog_node.end();
......@@ -5339,33 +5333,29 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
53395333 .io = io,
53405334 .http_client = &http_client,
53415335 .global_cache = dirs.global_cache,
5342 .local_cache = .{ .root_dir = dirs.local_cache, .sub_path = "" },
5343 .root_pkg_path = .{ .root_dir = build_root.directory, .sub_path = "zig-pkg" },
5344 .read_only = false,
5336 .local_storage = &.{
5337 .cache_root = .{ .root_dir = dirs.local_cache, .sub_path = "" },
5338 .pkg_root = if (override_pkg_dir) |p|
5339 .initCwd(p)
5340 else if (system_pkg_dir_path) |p|
5341 .initCwd(p)
5342 else
5343 .{
5344 .root_dir = build_root.directory,
5345 .sub_path = "zig-pkg",
5346 },
5347 },
53455348 .recursive = true,
53465349 .debug_hash = false,
53475350 .unlazy_set = unlazy_set,
53485351 .fork_set = fork_set,
53495352 .mode = fetch_mode,
53505353 .prog_node = fetch_prog_node,
5354 .read_only = system_pkg_dir_path != null,
53515355 };
53525356 defer job_queue.deinit();
53535357
5354 if (system_pkg_dir_path) |p| {
5355 const system_pkg_path: Path = .{
5356 .root_dir = .{
5357 .path = p,
5358 .handle = Io.Dir.cwd().openDir(io, p, .{}) catch |err| {
5359 fatal("unable to open system package directory '{s}': {t}", .{ p, err });
5360 },
5361 },
5362 .sub_path = "",
5363 };
5364 job_queue.global_cache = system_pkg_path.root_dir;
5365 job_queue.root_pkg_path = system_pkg_path;
5366 job_queue.read_only = true;
5367 cleanup_build_dir = job_queue.global_cache.handle;
5368 } else {
5358 if (system_pkg_dir_path == null) {
53695359 try http_client.initDefaultProxies(arena, environ_map);
53705360 }
53715361
......@@ -5381,6 +5371,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
53815371 .hash_tok = .none,
53825372 .name_tok = 0,
53835373 .lazy_status = .eager,
5374 .remote_package_root = phantom_package_root,
53845375 .parent_package_root = phantom_package_root,
53855376 .parent_manifest_ast = null,
53865377 .prog_node = fetch_prog_node,
......@@ -5401,6 +5392,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8,
54015392
54025393 .module = build_mod,
54035394 };
5395
54045396 job_queue.all_fetches.appendAssumeCapacity(&fetch);
54055397
54065398 job_queue.table.putAssumeCapacityNoClobber(
......@@ -7032,7 +7024,10 @@ const usage_fetch =
70327024 \\Options:
70337025 \\ -h, --help Print this help and exit
70347026 \\ --global-cache-dir [path] Override path to global Zig cache directory
7027 \\ --cache-dir [path] Override path to local cache directory
7028 \\ --pkg-dir [path] Override path to local package directory
70357029 \\ --debug-hash Print verbose hash information to stdout
7030 \\ --debug-log [scope] Enable printing debug/info log messages for scope
70367031 \\ --save Add the fetched package to build.zig.zon
70377032 \\ --save=[name] Add the fetched package to build.zig.zon as name
70387033 \\ --save-exact Add the fetched package to build.zig.zon, storing the URL verbatim
......@@ -7052,6 +7047,8 @@ fn cmdFetch(
70527047 const color: Color = .auto;
70537048 var opt_path_or_url: ?[]const u8 = null;
70547049 var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map);
7050 var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map);
7051 var override_pkg_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_PKG_DIR.get(environ_map);
70557052 var debug_hash: bool = false;
70567053 var save: union(enum) {
70577054 no,
......@@ -7068,11 +7065,23 @@ fn cmdFetch(
70687065 try Io.File.stdout().writeStreamingAll(io, usage_fetch);
70697066 return cleanExit(io);
70707067 } else if (mem.eql(u8, arg, "--global-cache-dir")) {
7071 if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg});
7068 if (i + 1 >= args.len) fatal("expected argument after: {s}", .{arg});
70727069 i += 1;
70737070 override_global_cache_dir = args[i];
7071 } else if (mem.eql(u8, arg, "--cache-dir")) {
7072 if (i + 1 >= args.len) fatal("expected argument after: {s}", .{arg});
7073 i += 1;
7074 override_local_cache_dir = args[i];
7075 } else if (mem.eql(u8, arg, "--pkg-dir")) {
7076 if (i + 1 >= args.len) fatal("expected argument after: {s}", .{arg});
7077 i += 1;
7078 override_pkg_dir = args[i];
70747079 } else if (mem.eql(u8, arg, "--debug-hash")) {
70757080 debug_hash = true;
7081 } else if (mem.eql(u8, arg, "--debug-log")) {
7082 if (i + 1 >= args.len) fatal("expected argument after: {s}", .{arg});
7083 i += 1;
7084 try addDebugLog(arena, args[i]);
70767085 } else if (mem.eql(u8, arg, "--save")) {
70777086 save = .{ .yes = null };
70787087 } else if (mem.cutPrefix(u8, arg, "--save=")) |rest| {
......@@ -7113,27 +7122,39 @@ fn cmdFetch(
71137122 };
71147123 defer global_cache_directory.handle.close(io);
71157124
7125 var local_storage: Package.Fetch.LocalStorage = undefined;
7126 var build_root: BuildRoot = undefined;
7127 var build_root_initialized = false;
7128 defer if (build_root_initialized) build_root.deinit(io);
7129
71167130 const cwd_path = try introspect.getResolvedCwd(io, arena);
71177131
7118 var build_root = try findBuildRoot(arena, io, .{
7119 .cwd_path = cwd_path,
7120 });
7121 defer build_root.deinit(io);
7132 const local_storage_ptr = switch (save) {
7133 .no => null,
7134 .yes, .exact => ls: {
7135 build_root = try findBuildRoot(arena, io, .{ .cwd_path = cwd_path });
7136 build_root_initialized = true;
7137
7138 local_storage = .{
7139 .cache_root = if (override_local_cache_dir) |p| .initCwd(p) else .{
7140 .root_dir = build_root.directory,
7141 .sub_path = ".zig-cache",
7142 },
7143 .pkg_root = if (override_pkg_dir) |p| .initCwd(p) else .{
7144 .root_dir = build_root.directory,
7145 .sub_path = "zig-pkg",
7146 },
7147 };
71227148
7123 const local_cache_path: Path = .{
7124 .root_dir = build_root.directory,
7125 .sub_path = ".zig-cache",
7149 break :ls &local_storage;
7150 },
71267151 };
71277152
71287153 var job_queue: Package.Fetch.JobQueue = .{
71297154 .io = io,
71307155 .http_client = &http_client,
71317156 .global_cache = global_cache_directory,
7132 .local_cache = local_cache_path,
7133 .root_pkg_path = .{
7134 .root_dir = build_root.directory,
7135 .sub_path = "zig-pkg",
7136 },
7157 .local_storage = local_storage_ptr,
71377158 .recursive = false,
71387159 .read_only = false,
71397160 .debug_hash = debug_hash,
......@@ -7149,6 +7170,7 @@ fn cmdFetch(
71497170 .hash_tok = .none,
71507171 .name_tok = 0,
71517172 .lazy_status = .eager,
7173 .remote_package_root = undefined,
71527174 .parent_package_root = undefined,
71537175 .parent_manifest_ast = null,
71547176 .prog_node = root_prog_node,
......@@ -7793,3 +7815,11 @@ fn randInt(io: Io, comptime T: type) T {
77937815 io.random(@ptrCast(&x));
77947816 return x;
77957817}
7818
7819fn addDebugLog(arena: Allocator, scope_name: []const u8) error{OutOfMemory}!void {
7820 if (!build_options.enable_logging) {
7821 warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{});
7822 } else {
7823 try log_scopes.append(arena, scope_name);
7824 }
7825}