| author | |
| committer | |
| log | 92517c04c7ab0f87b60ed3b9a8c3e544674678fa |
| tree | 0bedfd1ce290c0be3c1d37671e428e9d7586d28b |
| parent | 58ea88f6cfbaa7a96236a53e26c86ead1ce7c9c2 |
| signature |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/319923 files changed, 157 insertions(+), 114 deletions(-)
lib/std/zig.zig+1| ... | @@ -744,6 +744,7 @@ pub fn parseTargetQueryOrReportFatalError( | ... | @@ -744,6 +744,7 @@ pub fn parseTargetQueryOrReportFatalError( |
| 744 | pub const EnvVar = enum { | 744 | pub const EnvVar = enum { |
| 745 | ZIG_GLOBAL_CACHE_DIR, | 745 | ZIG_GLOBAL_CACHE_DIR, |
| 746 | ZIG_LOCAL_CACHE_DIR, | 746 | ZIG_LOCAL_CACHE_DIR, |
| 747 | ZIG_LOCAL_PKG_DIR, | ||
| 747 | ZIG_LIB_DIR, | 748 | ZIG_LIB_DIR, |
| 748 | ZIG_LIBC, | 749 | ZIG_LIBC, |
| 749 | ZIG_BUILD_RUNNER, | 750 | ZIG_BUILD_RUNNER, |
src/Package/Fetch.zig+81-69| ... | @@ -56,6 +56,9 @@ location_tok: std.zig.Ast.TokenIndex, | ... | @@ -56,6 +56,9 @@ location_tok: std.zig.Ast.TokenIndex, |
| 56 | hash_tok: std.zig.Ast.OptionalTokenIndex, | 56 | hash_tok: std.zig.Ast.OptionalTokenIndex, |
| 57 | name_tok: std.zig.Ast.TokenIndex, | 57 | name_tok: std.zig.Ast.TokenIndex, |
| 58 | lazy_status: LazyStatus, | 58 | lazy_status: LazyStatus, |
| 59 | /// Same as `parent_packge_root` except it is unchanged when recursing into | ||
| 60 | /// relative file paths (as opposed to URL). | ||
| 61 | remote_package_root: Cache.Path, | ||
| 59 | parent_package_root: Cache.Path, | 62 | parent_package_root: Cache.Path, |
| 60 | parent_manifest_ast: ?*const std.zig.Ast, | 63 | parent_manifest_ast: ?*const std.zig.Ast, |
| 61 | prog_node: std.Progress.Node, | 64 | prog_node: std.Progress.Node, |
| ... | @@ -104,6 +107,12 @@ pub const LazyStatus = enum { | ... | @@ -104,6 +107,12 @@ pub const LazyStatus = enum { |
| 104 | unavailable, | 107 | unavailable, |
| 105 | }; | 108 | }; |
| 106 | 109 | ||
| 110 | pub 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 | |||
| 107 | /// Contains shared state among all `Fetch` tasks. | 116 | /// Contains shared state among all `Fetch` tasks. |
| 108 | pub const JobQueue = struct { | 117 | pub const JobQueue = struct { |
| 109 | io: Io, | 118 | io: Io, |
| ... | @@ -122,9 +131,8 @@ pub const JobQueue = struct { | ... | @@ -122,9 +131,8 @@ pub const JobQueue = struct { |
| 122 | /// This tracks `Fetch` tasks as well as recompression tasks. | 131 | /// This tracks `Fetch` tasks as well as recompression tasks. |
| 123 | group: Io.Group = .init, | 132 | group: Io.Group = .init, |
| 124 | global_cache: Cache.Directory, | 133 | global_cache: Cache.Directory, |
| 125 | local_cache: Cache.Path, | 134 | /// If `null`, indicates fetch globally only. |
| 126 | /// Path to "zig-pkg" inside the package in which the user ran `zig build`. | 135 | local_storage: ?*const LocalStorage, |
| 127 | root_pkg_path: Cache.Path, | ||
| 128 | /// If true then, no fetching occurs, and: | 136 | /// If true then, no fetching occurs, and: |
| 129 | /// * The `global_cache` directory is assumed to be the direct parent | 137 | /// * The `global_cache` directory is assumed to be the direct parent |
| 130 | /// directory of on-disk packages rather than having the "p/" directory | 138 | /// directory of on-disk packages rather than having the "p/" directory |
| ... | @@ -341,7 +349,7 @@ pub const JobQueue = struct { | ... | @@ -341,7 +349,7 @@ pub const JobQueue = struct { |
| 341 | ); | 349 | ); |
| 342 | } | 350 | } |
| 343 | 351 | ||
| 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 { |
| 345 | const pkg_hash_slice = package_hash.toSlice(); | 353 | const pkg_hash_slice = package_hash.toSlice(); |
| 346 | 354 | ||
| 347 | const prog_node = jq.prog_node.startFmt(0, "recompress {s}", .{pkg_hash_slice}); | 355 | const prog_node = jq.prog_node.startFmt(0, "recompress {s}", .{pkg_hash_slice}); |
| ... | @@ -359,7 +367,7 @@ pub const JobQueue = struct { | ... | @@ -359,7 +367,7 @@ pub const JobQueue = struct { |
| 359 | defer arena_instance.deinit(); | 367 | defer arena_instance.deinit(); |
| 360 | const arena = arena_instance.allocator(); | 368 | const arena = arena_instance.allocator(); |
| 361 | 369 | ||
| 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) { |
| 363 | error.Canceled => |e| return e, | 371 | error.Canceled => |e| return e, |
| 364 | error.ReadFailed => comptime unreachable, | 372 | error.ReadFailed => comptime unreachable, |
| 365 | error.WriteFailed => comptime unreachable, | 373 | error.WriteFailed => comptime unreachable, |
| ... | @@ -372,6 +380,7 @@ pub const JobQueue = struct { | ... | @@ -372,6 +380,7 @@ pub const JobQueue = struct { |
| 372 | arena: Allocator, | 380 | arena: Allocator, |
| 373 | dest_path: Cache.Path, | 381 | dest_path: Cache.Path, |
| 374 | pkg_hash_slice: []const u8, | 382 | pkg_hash_slice: []const u8, |
| 383 | package_root: Cache.Path, | ||
| 375 | prog_node: std.Progress.Node, | 384 | prog_node: std.Progress.Node, |
| 376 | ) !void { | 385 | ) !void { |
| 377 | const gpa = jq.http_client.allocator; | 386 | const gpa = jq.http_client.allocator; |
| ... | @@ -386,7 +395,7 @@ pub const JobQueue = struct { | ... | @@ -386,7 +395,7 @@ pub const JobQueue = struct { |
| 386 | var scanned_files: std.ArrayList(ScannedFile) = .empty; | 395 | var scanned_files: std.ArrayList(ScannedFile) = .empty; |
| 387 | defer scanned_files.deinit(gpa); | 396 | defer scanned_files.deinit(gpa); |
| 388 | 397 | ||
| 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 }); |
| 390 | defer pkg_dir.close(io); | 399 | defer pkg_dir.close(io); |
| 391 | 400 | ||
| 392 | { | 401 | { |
| ... | @@ -513,7 +522,6 @@ pub fn run(f: *Fetch) RunError!void { | ... | @@ -513,7 +522,6 @@ pub fn run(f: *Fetch) RunError!void { |
| 513 | const eb = &f.error_bundle; | 522 | const eb = &f.error_bundle; |
| 514 | const arena = f.arena.allocator(); | 523 | const arena = f.arena.allocator(); |
| 515 | const gpa = f.arena.child_allocator; | 524 | const gpa = f.arena.child_allocator; |
| 516 | const local_cache_root = job_queue.local_cache; | ||
| 517 | 525 | ||
| 518 | try eb.init(gpa); | 526 | try eb.init(gpa); |
| 519 | 527 | ||
| ... | @@ -534,32 +542,19 @@ pub fn run(f: *Fetch) RunError!void { | ... | @@ -534,32 +542,19 @@ pub fn run(f: *Fetch) RunError!void { |
| 534 | ); | 542 | ); |
| 535 | // Packages fetched by URL may not use relative paths to escape outside the | 543 | // Packages fetched by URL may not use relative paths to escape outside the |
| 536 | // fetched package directory from within the package cache. | 544 | // fetched package directory from within the package cache. |
| 537 | if (pkg_root.root_dir.eql(local_cache_root.root_dir)) { | 545 | |
| 538 | // `parent_package_root.sub_path` contains a path like this: | 546 | // This code path is only reachable recursively and the sub_path |
| 539 | // "p/$hash", or | 547 | // will already have been resolved to no longer have extra ".." or |
| 540 | // "p/$hash/foo", with possibly more directories after "foo". | 548 | // "." components. |
| 541 | // We want to fail unless the resolved relative path has a | 549 | assert(job_queue.local_storage != null); |
| 542 | // prefix of "p/$hash/". | 550 | log.debug("checking pkg root \"{s}\" against parent package root \"{s}\"", .{ |
| 543 | const prefix_len: usize = if (job_queue.read_only) 0 else "p/".len; | 551 | pkg_root.sub_path, f.remote_package_root.sub_path, |
| 544 | const parent_sub_path = f.parent_package_root.sub_path; | 552 | }); |
| 545 | const end = find_end: { | 553 | assert(pkg_root.root_dir.eql(f.remote_package_root.root_dir)); |
| 546 | if (parent_sub_path.len > prefix_len) { | 554 | if (!std.mem.startsWith(u8, pkg_root.sub_path, f.remote_package_root.sub_path)) return f.fail( |
| 547 | // Use `isSep` instead of `indexOfScalarPos` to account for | 555 | f.location_tok, |
| 548 | // Windows accepting both `\` and `/` as path separators. | 556 | try eb.printString("dependency path outside project: '{f}'", .{pkg_root}), |
| 549 | for (parent_sub_path[prefix_len..], prefix_len..) |c, i| { | 557 | ); |
| 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 | } | ||
| 563 | f.package_root = pkg_root; | 558 | f.package_root = pkg_root; |
| 564 | try loadManifest(f, pkg_root); | 559 | try loadManifest(f, pkg_root); |
| 565 | if (!f.has_build_zig) try checkBuildFileExistence(f); | 560 | if (!f.has_build_zig) try checkBuildFileExistence(f); |
| ... | @@ -602,6 +597,7 @@ pub fn run(f: *Fetch) RunError!void { | ... | @@ -602,6 +597,7 @@ pub fn run(f: *Fetch) RunError!void { |
| 602 | log.debug("using fork {f} for {s}", .{ fork.path, fork.manifest.name }); | 597 | log.debug("using fork {f} for {s}", .{ fork.path, fork.manifest.name }); |
| 603 | fork.uses += 1; | 598 | fork.uses += 1; |
| 604 | f.package_root = fork.path; | 599 | f.package_root = fork.path; |
| 600 | f.remote_package_root = f.package_root; | ||
| 605 | f.manifest_ast = fork.manifest_ast; | 601 | f.manifest_ast = fork.manifest_ast; |
| 606 | f.manifest = fork.manifest; | 602 | f.manifest = fork.manifest; |
| 607 | f.have_manifest = true; | 603 | f.have_manifest = true; |
| ... | @@ -610,31 +606,34 @@ pub fn run(f: *Fetch) RunError!void { | ... | @@ -610,31 +606,34 @@ pub fn run(f: *Fetch) RunError!void { |
| 610 | return queueJobsForDeps(f); | 606 | return queueJobsForDeps(f); |
| 611 | } | 607 | } |
| 612 | 608 | ||
| 613 | const package_root = try job_queue.root_pkg_path.join(arena, expected_hash.toSlice()); | 609 | if (job_queue.local_storage) |ls| { |
| 614 | if (package_root.root_dir.handle.access(io, package_root.sub_path, .{})) |_| { | 610 | const package_root = try ls.pkg_root.join(arena, expected_hash.toSlice()); |
| 615 | assert(f.lazy_status != .unavailable); | 611 | if (package_root.root_dir.handle.access(io, package_root.sub_path, .{})) |_| { |
| 616 | f.package_root = package_root; | 612 | assert(f.lazy_status != .unavailable); |
| 617 | try loadManifest(f, f.package_root); | 613 | f.package_root = package_root; |
| 618 | try checkBuildFileExistence(f); | 614 | f.remote_package_root = f.package_root; |
| 619 | if (!job_queue.recursive) return; | 615 | try loadManifest(f, f.package_root); |
| 620 | return queueJobsForDeps(f); | 616 | try checkBuildFileExistence(f); |
| 621 | } else |err| switch (err) { | 617 | if (!job_queue.recursive) return; |
| 622 | error.FileNotFound => { | 618 | return queueJobsForDeps(f); |
| 623 | log.debug("FileNotFound: {f}", .{package_root}); | 619 | } else |err| switch (err) { |
| 624 | if (job_queue.read_only and f.lazy_status == .eager) return f.fail( | 620 | error.FileNotFound => { |
| 625 | f.name_tok, | 621 | log.debug("FileNotFound: {f}", .{package_root}); |
| 626 | try eb.printString("package not found at '{f}'", .{package_root}), | 622 | if (job_queue.read_only and f.lazy_status == .eager) return f.fail( |
| 627 | ); | 623 | f.name_tok, |
| 628 | }, | 624 | try eb.printString("package not found at '{f}'", .{package_root}), |
| 629 | error.Canceled => |e| return e, | 625 | ); |
| 630 | else => |e| { | 626 | }, |
| 631 | try eb.addRootErrorMessage(.{ | 627 | error.Canceled => |e| return e, |
| 632 | .msg = try eb.printString("unable to open package cache directory {f}: {t}", .{ | 628 | else => |e| { |
| 633 | package_root, e, | 629 | try eb.addRootErrorMessage(.{ |
| 634 | }), | 630 | .msg = try eb.printString("unable to open package cache directory {f}: {t}", .{ |
| 635 | }); | 631 | package_root, e, |
| 636 | return error.FetchFailed; | 632 | }), |
| 637 | }, | 633 | }); |
| 634 | return error.FetchFailed; | ||
| 635 | }, | ||
| 636 | } | ||
| 638 | } | 637 | } |
| 639 | 638 | ||
| 640 | // Check global cache before remote fetch. | 639 | // Check global cache before remote fetch. |
| ... | @@ -713,7 +712,14 @@ fn runResource( | ... | @@ -713,7 +712,14 @@ fn runResource( |
| 713 | break :r x; | 712 | break :r x; |
| 714 | }; | 713 | }; |
| 715 | const tmp_dir_sub_path = ".tmp-" ++ std.fmt.hex(rand_int); | 714 | 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 | }; | ||
| 717 | 723 | ||
| 718 | const package_sub_path = blk: { | 724 | const package_sub_path = blk: { |
| 719 | var tmp_directory: Cache.Directory = .{ | 725 | var tmp_directory: Cache.Directory = .{ |
| ... | @@ -772,19 +778,24 @@ fn runResource( | ... | @@ -772,19 +778,24 @@ fn runResource( |
| 772 | // zig package directory untouched as it may be in use. This is done even | 778 | // zig package directory untouched as it may be in use. This is done even |
| 773 | // if the hash is invalid, in case the package with the different hash is | 779 | // if the hash is invalid, in case the package with the different hash is |
| 774 | // used in the future. | 780 | // used in the future. |
| 775 | f.package_root = try job_queue.root_pkg_path.join(arena, computed_package_hash.toSlice()); | 781 | if (job_queue.local_storage) |ls| { |
| 776 | renameTmpIntoCache(io, package_sub_path, f.package_root) catch |err| { | 782 | f.package_root = try ls.pkg_root.join(arena, computed_package_hash.toSlice()); |
| 777 | try eb.addRootErrorMessage(.{ .msg = try eb.printString( | 783 | renameTmpIntoCache(io, package_sub_path, f.package_root) catch |err| { |
| 778 | "unable to rename temporary directory {f} into package cache directory {f}: {t}", | 784 | try eb.addRootErrorMessage(.{ .msg = try eb.printString( |
| 779 | .{ package_sub_path, f.package_root, err }, | 785 | "unable to rename temporary directory {f} into package cache directory {f}: {t}", |
| 780 | ) }); | 786 | .{ package_sub_path, f.package_root, err }, |
| 781 | return error.FetchFailed; | 787 | ) }); |
| 782 | }; | 788 | return error.FetchFailed; |
| 789 | }; | ||
| 790 | } else { | ||
| 791 | f.package_root = tmp_directory_path; | ||
| 792 | } | ||
| 793 | f.remote_package_root = f.package_root; | ||
| 783 | 794 | ||
| 784 | if (!disable_recompress) { | 795 | if (!disable_recompress) { |
| 785 | // Spin off a task to recompress the tarball, with filtered files deleted, into | 796 | // Spin off a task to recompress the tarball, with filtered files deleted, into |
| 786 | // the global cache. | 797 | // 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 }); |
| 788 | } | 799 | } |
| 789 | 800 | ||
| 790 | // Remove temporary directory root if not already renamed to global cache. | 801 | // Remove temporary directory root if not already renamed to global cache. |
| ... | @@ -991,6 +1002,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { | ... | @@ -991,6 +1002,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { |
| 991 | .all => .eager, | 1002 | .all => .eager, |
| 992 | }, | 1003 | }, |
| 993 | .parent_package_root = f.package_root, | 1004 | .parent_package_root = f.package_root, |
| 1005 | .remote_package_root = f.remote_package_root, | ||
| 994 | .parent_manifest_ast = &f.manifest_ast, | 1006 | .parent_manifest_ast = &f.manifest_ast, |
| 995 | .prog_node = f.prog_node, | 1007 | .prog_node = f.prog_node, |
| 996 | .job_queue = f.job_queue, | 1008 | .job_queue = f.job_queue, |
| ... | @@ -1185,7 +1197,7 @@ fn initResource(f: *Fetch, uri: std.Uri, resource: *Resource, reader_buffer: []u | ... | @@ -1185,7 +1197,7 @@ fn initResource(f: *Fetch, uri: std.Uri, resource: *Resource, reader_buffer: []u |
| 1185 | if (ascii.eqlIgnoreCase(uri.scheme, "file")) { | 1197 | if (ascii.eqlIgnoreCase(uri.scheme, "file")) { |
| 1186 | const path = try uri.path.toRawMaybeAlloc(arena); | 1198 | const path = try uri.path.toRawMaybeAlloc(arena); |
| 1187 | const file = f.parent_package_root.openFile(io, path, .{}) catch |err| { | 1199 | 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}", .{ |
| 1189 | f.parent_package_root, path, err, | 1201 | f.parent_package_root, path, err, |
| 1190 | })); | 1202 | })); |
| 1191 | }; | 1203 | }; |
src/main.zig+75-45| ... | @@ -1360,12 +1360,7 @@ fn buildOutputType( | ... | @@ -1360,12 +1360,7 @@ fn buildOutputType( |
| 1360 | } else if (mem.eql(u8, arg, "--zig-lib-dir")) { | 1360 | } else if (mem.eql(u8, arg, "--zig-lib-dir")) { |
| 1361 | override_lib_dir = args_iter.nextOrFatal(); | 1361 | override_lib_dir = args_iter.nextOrFatal(); |
| 1362 | } else if (mem.eql(u8, arg, "--debug-log")) { | 1362 | } else if (mem.eql(u8, arg, "--debug-log")) { |
| 1363 | if (!build_options.enable_logging) { | 1363 | try addDebugLog(arena, args_iter.nextOrFatal()); |
| 1364 | warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); | ||
| 1365 | _ = args_iter.nextOrFatal(); | ||
| 1366 | } else { | ||
| 1367 | try log_scopes.append(arena, args_iter.nextOrFatal()); | ||
| 1368 | } | ||
| 1369 | } else if (mem.eql(u8, arg, "--listen")) { | 1364 | } else if (mem.eql(u8, arg, "--listen")) { |
| 1370 | const next_arg = args_iter.nextOrFatal(); | 1365 | const next_arg = args_iter.nextOrFatal(); |
| 1371 | if (mem.eql(u8, next_arg, "-")) { | 1366 | if (mem.eql(u8, next_arg, "-")) { |
| ... | @@ -4962,6 +4957,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -4962,6 +4957,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 4962 | var override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map); | 4957 | var override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map); |
| 4963 | var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); | 4958 | var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); |
| 4964 | var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map); | 4959 | var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map); |
| 4960 | var override_pkg_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_PKG_DIR.get(environ_map); | ||
| 4965 | var override_build_runner: ?[]const u8 = EnvVar.ZIG_BUILD_RUNNER.get(environ_map); | 4961 | var override_build_runner: ?[]const u8 = EnvVar.ZIG_BUILD_RUNNER.get(environ_map); |
| 4966 | var child_argv: std.ArrayList([]const u8) = .empty; | 4962 | var child_argv: std.ArrayList([]const u8) = .empty; |
| 4967 | var forks: std.ArrayList(Fork) = .empty; | 4963 | var forks: std.ArrayList(Fork) = .empty; |
| ... | @@ -5053,6 +5049,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -5053,6 +5049,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5053 | i += 1; | 5049 | i += 1; |
| 5054 | override_local_cache_dir = args[i]; | 5050 | override_local_cache_dir = args[i]; |
| 5055 | continue; | 5051 | continue; |
| 5052 | } else if (mem.eql(u8, arg, "--pkg-dir")) { | ||
| 5053 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | ||
| 5054 | i += 1; | ||
| 5055 | override_pkg_dir = args[i]; | ||
| 5056 | continue; | ||
| 5056 | } else if (mem.eql(u8, arg, "--global-cache-dir")) { | 5057 | } else if (mem.eql(u8, arg, "--global-cache-dir")) { |
| 5057 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | 5058 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| 5058 | i += 1; | 5059 | i += 1; |
| ... | @@ -5097,11 +5098,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -5097,11 +5098,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5097 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | 5098 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| 5098 | try child_argv.appendSlice(arena, args[i .. i + 2]); | 5099 | try child_argv.appendSlice(arena, args[i .. i + 2]); |
| 5099 | i += 1; | 5100 | i += 1; |
| 5100 | if (!build_options.enable_logging) { | 5101 | try addDebugLog(arena, args[i]); |
| 5101 | warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); | ||
| 5102 | } else { | ||
| 5103 | try log_scopes.append(arena, args[i]); | ||
| 5104 | } | ||
| 5105 | continue; | 5102 | continue; |
| 5106 | } else if (mem.eql(u8, arg, "--debug-compile-errors")) { | 5103 | } else if (mem.eql(u8, arg, "--debug-compile-errors")) { |
| 5107 | if (build_options.enable_debug_extensions) { | 5104 | if (build_options.enable_debug_extensions) { |
| ... | @@ -5332,9 +5329,6 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -5332,9 +5329,6 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5332 | .parent = root_mod, | 5329 | .parent = root_mod, |
| 5333 | }); | 5330 | }); |
| 5334 | 5331 | ||
| 5335 | var cleanup_build_dir: ?Io.Dir = null; | ||
| 5336 | defer if (cleanup_build_dir) |*dir| dir.close(io); | ||
| 5337 | |||
| 5338 | if (dev.env.supports(.fetch_command)) { | 5332 | if (dev.env.supports(.fetch_command)) { |
| 5339 | const fetch_prog_node = root_prog_node.start("Fetch Packages", 0); | 5333 | const fetch_prog_node = root_prog_node.start("Fetch Packages", 0); |
| 5340 | defer fetch_prog_node.end(); | 5334 | defer fetch_prog_node.end(); |
| ... | @@ -5346,33 +5340,29 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -5346,33 +5340,29 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5346 | .io = io, | 5340 | .io = io, |
| 5347 | .http_client = &http_client, | 5341 | .http_client = &http_client, |
| 5348 | .global_cache = dirs.global_cache, | 5342 | .global_cache = dirs.global_cache, |
| 5349 | .local_cache = .{ .root_dir = dirs.local_cache, .sub_path = "" }, | 5343 | .local_storage = &.{ |
| 5350 | .root_pkg_path = .{ .root_dir = build_root.directory, .sub_path = "zig-pkg" }, | 5344 | .cache_root = .{ .root_dir = dirs.local_cache, .sub_path = "" }, |
| 5351 | .read_only = false, | 5345 | .pkg_root = if (override_pkg_dir) |p| |
| 5346 | .initCwd(p) | ||
| 5347 | else if (system_pkg_dir_path) |p| | ||
| 5348 | .initCwd(p) | ||
| 5349 | else | ||
| 5350 | .{ | ||
| 5351 | .root_dir = build_root.directory, | ||
| 5352 | .sub_path = "zig-pkg", | ||
| 5353 | }, | ||
| 5354 | }, | ||
| 5352 | .recursive = true, | 5355 | .recursive = true, |
| 5353 | .debug_hash = false, | 5356 | .debug_hash = false, |
| 5354 | .unlazy_set = unlazy_set, | 5357 | .unlazy_set = unlazy_set, |
| 5355 | .fork_set = fork_set, | 5358 | .fork_set = fork_set, |
| 5356 | .mode = fetch_mode, | 5359 | .mode = fetch_mode, |
| 5357 | .prog_node = fetch_prog_node, | 5360 | .prog_node = fetch_prog_node, |
| 5361 | .read_only = system_pkg_dir_path != null, | ||
| 5358 | }; | 5362 | }; |
| 5359 | defer job_queue.deinit(); | 5363 | defer job_queue.deinit(); |
| 5360 | 5364 | ||
| 5361 | if (system_pkg_dir_path) |p| { | 5365 | if (system_pkg_dir_path == null) { |
| 5362 | const system_pkg_path: Path = .{ | ||
| 5363 | .root_dir = .{ | ||
| 5364 | .path = p, | ||
| 5365 | .handle = Io.Dir.cwd().openDir(io, p, .{}) catch |err| { | ||
| 5366 | fatal("unable to open system package directory '{s}': {t}", .{ p, err }); | ||
| 5367 | }, | ||
| 5368 | }, | ||
| 5369 | .sub_path = "", | ||
| 5370 | }; | ||
| 5371 | job_queue.global_cache = system_pkg_path.root_dir; | ||
| 5372 | job_queue.root_pkg_path = system_pkg_path; | ||
| 5373 | job_queue.read_only = true; | ||
| 5374 | cleanup_build_dir = job_queue.global_cache.handle; | ||
| 5375 | } else { | ||
| 5376 | try http_client.initDefaultProxies(arena, environ_map); | 5366 | try http_client.initDefaultProxies(arena, environ_map); |
| 5377 | } | 5367 | } |
| 5378 | 5368 | ||
| ... | @@ -5388,6 +5378,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -5388,6 +5378,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5388 | .hash_tok = .none, | 5378 | .hash_tok = .none, |
| 5389 | .name_tok = 0, | 5379 | .name_tok = 0, |
| 5390 | .lazy_status = .eager, | 5380 | .lazy_status = .eager, |
| 5381 | .remote_package_root = phantom_package_root, | ||
| 5391 | .parent_package_root = phantom_package_root, | 5382 | .parent_package_root = phantom_package_root, |
| 5392 | .parent_manifest_ast = null, | 5383 | .parent_manifest_ast = null, |
| 5393 | .prog_node = fetch_prog_node, | 5384 | .prog_node = fetch_prog_node, |
| ... | @@ -5408,6 +5399,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -5408,6 +5399,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5408 | 5399 | ||
| 5409 | .module = build_mod, | 5400 | .module = build_mod, |
| 5410 | }; | 5401 | }; |
| 5402 | |||
| 5411 | job_queue.all_fetches.appendAssumeCapacity(&fetch); | 5403 | job_queue.all_fetches.appendAssumeCapacity(&fetch); |
| 5412 | 5404 | ||
| 5413 | job_queue.table.putAssumeCapacityNoClobber( | 5405 | job_queue.table.putAssumeCapacityNoClobber( |
| ... | @@ -7040,7 +7032,10 @@ const usage_fetch = | ... | @@ -7040,7 +7032,10 @@ const usage_fetch = |
| 7040 | \\Options: | 7032 | \\Options: |
| 7041 | \\ -h, --help Print this help and exit | 7033 | \\ -h, --help Print this help and exit |
| 7042 | \\ --global-cache-dir [path] Override path to global Zig cache directory | 7034 | \\ --global-cache-dir [path] Override path to global Zig cache directory |
| 7035 | \\ --cache-dir [path] Override path to local cache directory | ||
| 7036 | \\ --pkg-dir [path] Override path to local package directory | ||
| 7043 | \\ --debug-hash Print verbose hash information to stdout | 7037 | \\ --debug-hash Print verbose hash information to stdout |
| 7038 | \\ --debug-log [scope] Enable printing debug/info log messages for scope | ||
| 7044 | \\ --save Add the fetched package to build.zig.zon | 7039 | \\ --save Add the fetched package to build.zig.zon |
| 7045 | \\ --save=[name] Add the fetched package to build.zig.zon as name | 7040 | \\ --save=[name] Add the fetched package to build.zig.zon as name |
| 7046 | \\ --save-exact Add the fetched package to build.zig.zon, storing the URL verbatim | 7041 | \\ --save-exact Add the fetched package to build.zig.zon, storing the URL verbatim |
| ... | @@ -7060,6 +7055,8 @@ fn cmdFetch( | ... | @@ -7060,6 +7055,8 @@ fn cmdFetch( |
| 7060 | const color: Color = .auto; | 7055 | const color: Color = .auto; |
| 7061 | var opt_path_or_url: ?[]const u8 = null; | 7056 | var opt_path_or_url: ?[]const u8 = null; |
| 7062 | var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); | 7057 | var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); |
| 7058 | var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map); | ||
| 7059 | var override_pkg_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_PKG_DIR.get(environ_map); | ||
| 7063 | var debug_hash: bool = false; | 7060 | var debug_hash: bool = false; |
| 7064 | var save: union(enum) { | 7061 | var save: union(enum) { |
| 7065 | no, | 7062 | no, |
| ... | @@ -7076,11 +7073,23 @@ fn cmdFetch( | ... | @@ -7076,11 +7073,23 @@ fn cmdFetch( |
| 7076 | try Io.File.stdout().writeStreamingAll(io, usage_fetch); | 7073 | try Io.File.stdout().writeStreamingAll(io, usage_fetch); |
| 7077 | return cleanExit(io); | 7074 | return cleanExit(io); |
| 7078 | } else if (mem.eql(u8, arg, "--global-cache-dir")) { | 7075 | } else if (mem.eql(u8, arg, "--global-cache-dir")) { |
| 7079 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | 7076 | if (i + 1 >= args.len) fatal("expected argument after: {s}", .{arg}); |
| 7080 | i += 1; | 7077 | i += 1; |
| 7081 | override_global_cache_dir = args[i]; | 7078 | override_global_cache_dir = args[i]; |
| 7079 | } else if (mem.eql(u8, arg, "--cache-dir")) { | ||
| 7080 | if (i + 1 >= args.len) fatal("expected argument after: {s}", .{arg}); | ||
| 7081 | i += 1; | ||
| 7082 | override_local_cache_dir = args[i]; | ||
| 7083 | } else if (mem.eql(u8, arg, "--pkg-dir")) { | ||
| 7084 | if (i + 1 >= args.len) fatal("expected argument after: {s}", .{arg}); | ||
| 7085 | i += 1; | ||
| 7086 | override_pkg_dir = args[i]; | ||
| 7082 | } else if (mem.eql(u8, arg, "--debug-hash")) { | 7087 | } else if (mem.eql(u8, arg, "--debug-hash")) { |
| 7083 | debug_hash = true; | 7088 | debug_hash = true; |
| 7089 | } else if (mem.eql(u8, arg, "--debug-log")) { | ||
| 7090 | if (i + 1 >= args.len) fatal("expected argument after: {s}", .{arg}); | ||
| 7091 | i += 1; | ||
| 7092 | try addDebugLog(arena, args[i]); | ||
| 7084 | } else if (mem.eql(u8, arg, "--save")) { | 7093 | } else if (mem.eql(u8, arg, "--save")) { |
| 7085 | save = .{ .yes = null }; | 7094 | save = .{ .yes = null }; |
| 7086 | } else if (mem.cutPrefix(u8, arg, "--save=")) |rest| { | 7095 | } else if (mem.cutPrefix(u8, arg, "--save=")) |rest| { |
| ... | @@ -7121,27 +7130,39 @@ fn cmdFetch( | ... | @@ -7121,27 +7130,39 @@ fn cmdFetch( |
| 7121 | }; | 7130 | }; |
| 7122 | defer global_cache_directory.handle.close(io); | 7131 | defer global_cache_directory.handle.close(io); |
| 7123 | 7132 | ||
| 7133 | var local_storage: Package.Fetch.LocalStorage = undefined; | ||
| 7134 | var build_root: BuildRoot = undefined; | ||
| 7135 | var build_root_initialized = false; | ||
| 7136 | defer if (build_root_initialized) build_root.deinit(io); | ||
| 7137 | |||
| 7124 | const cwd_path = try introspect.getResolvedCwd(io, arena); | 7138 | const cwd_path = try introspect.getResolvedCwd(io, arena); |
| 7125 | 7139 | ||
| 7126 | var build_root = try findBuildRoot(arena, io, .{ | 7140 | const local_storage_ptr = switch (save) { |
| 7127 | .cwd_path = cwd_path, | 7141 | .no => null, |
| 7128 | }); | 7142 | .yes, .exact => ls: { |
| 7129 | defer build_root.deinit(io); | 7143 | build_root = try findBuildRoot(arena, io, .{ .cwd_path = cwd_path }); |
| 7144 | build_root_initialized = true; | ||
| 7145 | |||
| 7146 | local_storage = .{ | ||
| 7147 | .cache_root = if (override_local_cache_dir) |p| .initCwd(p) else .{ | ||
| 7148 | .root_dir = build_root.directory, | ||
| 7149 | .sub_path = ".zig-cache", | ||
| 7150 | }, | ||
| 7151 | .pkg_root = if (override_pkg_dir) |p| .initCwd(p) else .{ | ||
| 7152 | .root_dir = build_root.directory, | ||
| 7153 | .sub_path = "zig-pkg", | ||
| 7154 | }, | ||
| 7155 | }; | ||
| 7130 | 7156 | ||
| 7131 | const local_cache_path: Path = .{ | 7157 | break :ls &local_storage; |
| 7132 | .root_dir = build_root.directory, | 7158 | }, |
| 7133 | .sub_path = ".zig-cache", | ||
| 7134 | }; | 7159 | }; |
| 7135 | 7160 | ||
| 7136 | var job_queue: Package.Fetch.JobQueue = .{ | 7161 | var job_queue: Package.Fetch.JobQueue = .{ |
| 7137 | .io = io, | 7162 | .io = io, |
| 7138 | .http_client = &http_client, | 7163 | .http_client = &http_client, |
| 7139 | .global_cache = global_cache_directory, | 7164 | .global_cache = global_cache_directory, |
| 7140 | .local_cache = local_cache_path, | 7165 | .local_storage = local_storage_ptr, |
| 7141 | .root_pkg_path = .{ | ||
| 7142 | .root_dir = build_root.directory, | ||
| 7143 | .sub_path = "zig-pkg", | ||
| 7144 | }, | ||
| 7145 | .recursive = false, | 7166 | .recursive = false, |
| 7146 | .read_only = false, | 7167 | .read_only = false, |
| 7147 | .debug_hash = debug_hash, | 7168 | .debug_hash = debug_hash, |
| ... | @@ -7157,6 +7178,7 @@ fn cmdFetch( | ... | @@ -7157,6 +7178,7 @@ fn cmdFetch( |
| 7157 | .hash_tok = .none, | 7178 | .hash_tok = .none, |
| 7158 | .name_tok = 0, | 7179 | .name_tok = 0, |
| 7159 | .lazy_status = .eager, | 7180 | .lazy_status = .eager, |
| 7181 | .remote_package_root = undefined, | ||
| 7160 | .parent_package_root = undefined, | 7182 | .parent_package_root = undefined, |
| 7161 | .parent_manifest_ast = null, | 7183 | .parent_manifest_ast = null, |
| 7162 | .prog_node = root_prog_node, | 7184 | .prog_node = root_prog_node, |
| ... | @@ -7801,3 +7823,11 @@ fn randInt(io: Io, comptime T: type) T { | ... | @@ -7801,3 +7823,11 @@ fn randInt(io: Io, comptime T: type) T { |
| 7801 | io.random(@ptrCast(&x)); | 7823 | io.random(@ptrCast(&x)); |
| 7802 | return x; | 7824 | return x; |
| 7803 | } | 7825 | } |
| 7826 | |||
| 7827 | fn addDebugLog(arena: Allocator, scope_name: []const u8) error{OutOfMemory}!void { | ||
| 7828 | if (!build_options.enable_logging) { | ||
| 7829 | warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); | ||
| 7830 | } else { | ||
| 7831 | try log_scopes.append(arena, scope_name); | ||
| 7832 | } | ||
| 7833 | } |