| ... | @@ -68,8 +68,7 @@ use_latest_commit: bool, | ... | @@ -68,8 +68,7 @@ use_latest_commit: bool, |
| 68 | // Above this are fields provided as inputs to `run`. | 68 | // Above this are fields provided as inputs to `run`. |
| 69 | // Below this are fields populated by `run`. | 69 | // Below this are fields populated by `run`. |
| 70 | | 70 | |
| 71 | /// This will either be relative to `global_cache`, or to the build root of | 71 | /// Relative to the build root of the root package. |
| 72 | /// the root package. | | |
| 73 | package_root: Cache.Path, | 72 | package_root: Cache.Path, |
| 74 | error_bundle: ErrorBundle.Wip, | 73 | error_bundle: ErrorBundle.Wip, |
| 75 | manifest: ?Manifest, | 74 | manifest: ?Manifest, |
| ... | @@ -115,6 +114,9 @@ pub const JobQueue = struct { | ... | @@ -115,6 +114,9 @@ pub const JobQueue = struct { |
| 115 | http_client: *std.http.Client, | 114 | http_client: *std.http.Client, |
| 116 | group: Io.Group = .init, | 115 | group: Io.Group = .init, |
| 117 | global_cache: Cache.Directory, | 116 | global_cache: Cache.Directory, |
| | 117 | local_cache: Cache.Path, |
| | 118 | /// Path to "zig-pkg" inside the package in which the user ran `zig build`. |
| | 119 | root_pkg_path: Cache.Path, |
| 118 | /// If true then, no fetching occurs, and: | 120 | /// If true then, no fetching occurs, and: |
| 119 | /// * The `global_cache` directory is assumed to be the direct parent | 121 | /// * The `global_cache` directory is assumed to be the direct parent |
| 120 | /// directory of on-disk packages rather than having the "p/" directory | 122 | /// directory of on-disk packages rather than having the "p/" directory |
| ... | @@ -325,11 +327,12 @@ pub const RunError = error{ | ... | @@ -325,11 +327,12 @@ pub const RunError = error{ |
| 325 | }; | 327 | }; |
| 326 | | 328 | |
| 327 | pub fn run(f: *Fetch) RunError!void { | 329 | pub fn run(f: *Fetch) RunError!void { |
| 328 | const io = f.job_queue.io; | 330 | const job_queue = f.job_queue; |
| | 331 | const io = job_queue.io; |
| 329 | const eb = &f.error_bundle; | 332 | const eb = &f.error_bundle; |
| 330 | const arena = f.arena.allocator(); | 333 | const arena = f.arena.allocator(); |
| 331 | const gpa = f.arena.child_allocator; | 334 | const gpa = f.arena.child_allocator; |
| 332 | const cache_root = f.job_queue.global_cache; | 335 | const local_cache_root = job_queue.local_cache; |
| 333 | | 336 | |
| 334 | try eb.init(gpa); | 337 | try eb.init(gpa); |
| 335 | | 338 | |
| ... | @@ -350,13 +353,13 @@ pub fn run(f: *Fetch) RunError!void { | ... | @@ -350,13 +353,13 @@ pub fn run(f: *Fetch) RunError!void { |
| 350 | ); | 353 | ); |
| 351 | // Packages fetched by URL may not use relative paths to escape outside the | 354 | // Packages fetched by URL may not use relative paths to escape outside the |
| 352 | // fetched package directory from within the package cache. | 355 | // fetched package directory from within the package cache. |
| 353 | if (pkg_root.root_dir.eql(cache_root)) { | 356 | if (pkg_root.root_dir.eql(local_cache_root.root_dir)) { |
| 354 | // `parent_package_root.sub_path` contains a path like this: | 357 | // `parent_package_root.sub_path` contains a path like this: |
| 355 | // "p/$hash", or | 358 | // "p/$hash", or |
| 356 | // "p/$hash/foo", with possibly more directories after "foo". | 359 | // "p/$hash/foo", with possibly more directories after "foo". |
| 357 | // We want to fail unless the resolved relative path has a | 360 | // We want to fail unless the resolved relative path has a |
| 358 | // prefix of "p/$hash/". | 361 | // prefix of "p/$hash/". |
| 359 | const prefix_len: usize = if (f.job_queue.read_only) 0 else "p/".len; | 362 | const prefix_len: usize = if (job_queue.read_only) 0 else "p/".len; |
| 360 | const parent_sub_path = f.parent_package_root.sub_path; | 363 | const parent_sub_path = f.parent_package_root.sub_path; |
| 361 | const end = find_end: { | 364 | const end = find_end: { |
| 362 | if (parent_sub_path.len > prefix_len) { | 365 | if (parent_sub_path.len > prefix_len) { |
| ... | @@ -379,7 +382,7 @@ pub fn run(f: *Fetch) RunError!void { | ... | @@ -379,7 +382,7 @@ pub fn run(f: *Fetch) RunError!void { |
| 379 | f.package_root = pkg_root; | 382 | f.package_root = pkg_root; |
| 380 | try loadManifest(f, pkg_root); | 383 | try loadManifest(f, pkg_root); |
| 381 | if (!f.has_build_zig) try checkBuildFileExistence(f); | 384 | if (!f.has_build_zig) try checkBuildFileExistence(f); |
| 382 | if (!f.job_queue.recursive) return; | 385 | if (!job_queue.recursive) return; |
| 383 | return queueJobsForDeps(f); | 386 | return queueJobsForDeps(f); |
| 384 | }, | 387 | }, |
| 385 | .remote => |remote| remote, | 388 | .remote => |remote| remote, |
| ... | @@ -411,51 +414,39 @@ pub fn run(f: *Fetch) RunError!void { | ... | @@ -411,51 +414,39 @@ pub fn run(f: *Fetch) RunError!void { |
| 411 | }; | 414 | }; |
| 412 | | 415 | |
| 413 | if (remote.hash) |expected_hash| { | 416 | if (remote.hash) |expected_hash| { |
| 414 | var prefixed_pkg_sub_path_buffer: [Package.Hash.max_len + 2]u8 = undefined; | 417 | const package_root = try job_queue.root_pkg_path.join(arena, expected_hash.toSlice()); |
| 415 | prefixed_pkg_sub_path_buffer[0] = 'p'; | 418 | if (package_root.root_dir.handle.access(io, package_root.sub_path, .{})) |_| { |
| 416 | prefixed_pkg_sub_path_buffer[1] = fs.path.sep; | | |
| 417 | const hash_slice = expected_hash.toSlice(); | | |
| 418 | @memcpy(prefixed_pkg_sub_path_buffer[2..][0..hash_slice.len], hash_slice); | | |
| 419 | const prefixed_pkg_sub_path = prefixed_pkg_sub_path_buffer[0 .. 2 + hash_slice.len]; | | |
| 420 | const prefix_len: usize = if (f.job_queue.read_only) "p/".len else 0; | | |
| 421 | const pkg_sub_path = prefixed_pkg_sub_path[prefix_len..]; | | |
| 422 | if (cache_root.handle.access(io, pkg_sub_path, .{})) |_| { | | |
| 423 | assert(f.lazy_status != .unavailable); | 419 | assert(f.lazy_status != .unavailable); |
| 424 | f.package_root = .{ | 420 | f.package_root = package_root; |
| 425 | .root_dir = cache_root, | | |
| 426 | .sub_path = try arena.dupe(u8, pkg_sub_path), | | |
| 427 | }; | | |
| 428 | try loadManifest(f, f.package_root); | 421 | try loadManifest(f, f.package_root); |
| 429 | try checkBuildFileExistence(f); | 422 | try checkBuildFileExistence(f); |
| 430 | if (!f.job_queue.recursive) return; | 423 | if (!job_queue.recursive) return; |
| 431 | return queueJobsForDeps(f); | 424 | return queueJobsForDeps(f); |
| 432 | } else |err| switch (err) { | 425 | } else |err| switch (err) { |
| 433 | error.FileNotFound => { | 426 | error.FileNotFound => { |
| 434 | switch (f.lazy_status) { | 427 | switch (f.lazy_status) { |
| 435 | .eager => {}, | 428 | .eager => {}, |
| 436 | .available => if (!f.job_queue.unlazy_set.contains(expected_hash)) { | 429 | .available => if (!job_queue.unlazy_set.contains(expected_hash)) { |
| 437 | f.lazy_status = .unavailable; | 430 | f.lazy_status = .unavailable; |
| 438 | return; | 431 | return; |
| 439 | }, | 432 | }, |
| 440 | .unavailable => unreachable, | 433 | .unavailable => unreachable, |
| 441 | } | 434 | } |
| 442 | if (f.job_queue.read_only) return f.fail( | 435 | if (job_queue.read_only) return f.fail( |
| 443 | f.name_tok, | 436 | f.name_tok, |
| 444 | try eb.printString("package not found at '{f}{s}'", .{ | 437 | try eb.printString("package not found at '{f}'", .{package_root}), |
| 445 | cache_root, pkg_sub_path, | | |
| 446 | }), | | |
| 447 | ); | 438 | ); |
| 448 | }, | 439 | }, |
| 449 | else => |e| { | 440 | else => |e| { |
| 450 | try eb.addRootErrorMessage(.{ | 441 | try eb.addRootErrorMessage(.{ |
| 451 | .msg = try eb.printString("unable to open global package cache directory '{f}{s}': {s}", .{ | 442 | .msg = try eb.printString("unable to open package cache directory {f}: {t}", .{ |
| 452 | cache_root, pkg_sub_path, @errorName(e), | 443 | package_root, e, |
| 453 | }), | 444 | }), |
| 454 | }); | 445 | }); |
| 455 | return error.FetchFailed; | 446 | return error.FetchFailed; |
| 456 | }, | 447 | }, |
| 457 | } | 448 | } |
| 458 | } else if (f.job_queue.read_only) { | 449 | } else if (job_queue.read_only) { |
| 459 | try eb.addRootErrorMessage(.{ | 450 | try eb.addRootErrorMessage(.{ |
| 460 | .msg = try eb.addString("dependency is missing hash field"), | 451 | .msg = try eb.addString("dependency is missing hash field"), |
| 461 | .src_loc = try f.srcLoc(f.location_tok), | 452 | .src_loc = try f.srcLoc(f.location_tok), |
| ... | @@ -467,7 +458,7 @@ pub fn run(f: *Fetch) RunError!void { | ... | @@ -467,7 +458,7 @@ pub fn run(f: *Fetch) RunError!void { |
| 467 | | 458 | |
| 468 | const uri = std.Uri.parse(remote.url) catch |err| return f.fail( | 459 | const uri = std.Uri.parse(remote.url) catch |err| return f.fail( |
| 469 | f.location_tok, | 460 | f.location_tok, |
| 470 | try eb.printString("invalid URI: {s}", .{@errorName(err)}), | 461 | try eb.printString("invalid URI: {t}", .{err}), |
| 471 | ); | 462 | ); |
| 472 | var buffer: [init_resource_buffer_size]u8 = undefined; | 463 | var buffer: [init_resource_buffer_size]u8 = undefined; |
| 473 | var resource: Resource = undefined; | 464 | var resource: Resource = undefined; |
| ... | @@ -487,29 +478,30 @@ fn runResource( | ... | @@ -487,29 +478,30 @@ fn runResource( |
| 487 | resource: *Resource, | 478 | resource: *Resource, |
| 488 | remote_hash: ?Package.Hash, | 479 | remote_hash: ?Package.Hash, |
| 489 | ) RunError!void { | 480 | ) RunError!void { |
| 490 | const io = f.job_queue.io; | 481 | const job_queue = f.job_queue; |
| | 482 | const io = job_queue.io; |
| 491 | defer resource.deinit(io); | 483 | defer resource.deinit(io); |
| 492 | const arena = f.arena.allocator(); | 484 | const arena = f.arena.allocator(); |
| 493 | const eb = &f.error_bundle; | 485 | const eb = &f.error_bundle; |
| 494 | const s = fs.path.sep_str; | 486 | const s = fs.path.sep_str; |
| 495 | const cache_root = f.job_queue.global_cache; | 487 | const local_cache_root = job_queue.local_cache; |
| 496 | const rand_int = r: { | 488 | const rand_int = r: { |
| 497 | var x: u64 = undefined; | 489 | var x: u64 = undefined; |
| 498 | io.random(@ptrCast(&x)); | 490 | io.random(@ptrCast(&x)); |
| 499 | break :r x; | 491 | break :r x; |
| 500 | }; | 492 | }; |
| 501 | const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(rand_int); | 493 | const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(rand_int); |
| | 494 | const tmp_directory_path = try local_cache_root.join(arena, tmp_dir_sub_path); |
| 502 | | 495 | |
| 503 | const package_sub_path = blk: { | 496 | const package_sub_path = blk: { |
| 504 | const tmp_directory_path = try cache_root.join(arena, &.{tmp_dir_sub_path}); | | |
| 505 | var tmp_directory: Cache.Directory = .{ | 497 | var tmp_directory: Cache.Directory = .{ |
| 506 | .path = tmp_directory_path, | 498 | .path = tmp_directory_path.sub_path, |
| 507 | .handle = handle: { | 499 | .handle = handle: { |
| 508 | const dir = cache_root.handle.createDirPathOpen(io, tmp_dir_sub_path, .{ | 500 | const dir = tmp_directory_path.root_dir.handle.createDirPathOpen(io, tmp_directory_path.sub_path, .{ |
| 509 | .open_options = .{ .iterate = true }, | 501 | .open_options = .{ .iterate = true }, |
| 510 | }) catch |err| { | 502 | }) catch |err| { |
| 511 | try eb.addRootErrorMessage(.{ | 503 | try eb.addRootErrorMessage(.{ |
| 512 | .msg = try eb.printString("unable to create temporary directory '{s}': {t}", .{ | 504 | .msg = try eb.printString("unable to create temporary directory '{f}': {t}", .{ |
| 513 | tmp_directory_path, err, | 505 | tmp_directory_path, err, |
| 514 | }), | 506 | }), |
| 515 | }); | 507 | }); |
| ... | @@ -545,36 +537,33 @@ fn runResource( | ... | @@ -545,36 +537,33 @@ fn runResource( |
| 545 | // directory. | 537 | // directory. |
| 546 | f.computed_hash = try computeHash(f, pkg_path, filter); | 538 | f.computed_hash = try computeHash(f, pkg_path, filter); |
| 547 | | 539 | |
| 548 | break :blk if (unpack_result.root_dir.len > 0) | 540 | if (unpack_result.root_dir.len > 0) |
| 549 | try fs.path.join(arena, &.{ tmp_dir_sub_path, unpack_result.root_dir }) | 541 | break :blk try tmp_directory_path.join(arena, unpack_result.root_dir); |
| 550 | else | 542 | |
| 551 | tmp_dir_sub_path; | 543 | break :blk tmp_directory_path; |
| 552 | }; | 544 | }; |
| 553 | | 545 | |
| 554 | const computed_package_hash = computedPackageHash(f); | 546 | const computed_package_hash = computedPackageHash(f); |
| 555 | | 547 | |
| 556 | // Rename the temporary directory into the global zig package cache | 548 | // Rename the temporary directory into the local zig package directory. If |
| 557 | // directory. If the hash already exists, delete the temporary directory | 549 | // the hash already exists, delete the temporary directory and leave the |
| 558 | // and leave the zig package cache directory untouched as it may be in use | 550 | // zig package directory untouched as it may be in use. This is done even |
| 559 | // by the system. This is done even if the hash is invalid, in case the | 551 | // if the hash is invalid, in case the package with the different hash is |
| 560 | // package with the different hash is used in the future. | 552 | // used in the future. |
| 561 | | 553 | f.package_root = try job_queue.root_pkg_path.join(arena, computed_package_hash.toSlice()); |
| 562 | f.package_root = .{ | 554 | renameTmpIntoCache(io, package_sub_path, f.package_root) catch |err| { |
| 563 | .root_dir = cache_root, | | |
| 564 | .sub_path = try std.fmt.allocPrint(arena, "p" ++ s ++ "{s}", .{computed_package_hash.toSlice()}), | | |
| 565 | }; | | |
| 566 | renameTmpIntoCache(io, cache_root.handle, package_sub_path, f.package_root.sub_path) catch |err| { | | |
| 567 | const src = try cache_root.join(arena, &.{tmp_dir_sub_path}); | | |
| 568 | const dest = try cache_root.join(arena, &.{f.package_root.sub_path}); | | |
| 569 | try eb.addRootErrorMessage(.{ .msg = try eb.printString( | 555 | try eb.addRootErrorMessage(.{ .msg = try eb.printString( |
| 570 | "unable to rename temporary directory '{s}' into package cache directory '{s}': {s}", | 556 | "unable to rename temporary directory {f} into package cache directory {f}: {t}", |
| 571 | .{ src, dest, @errorName(err) }, | 557 | .{ package_sub_path, f.package_root, err }, |
| 572 | ) }); | 558 | ) }); |
| 573 | return error.FetchFailed; | 559 | return error.FetchFailed; |
| 574 | }; | 560 | }; |
| 575 | // Remove temporary directory root if not already renamed to global cache. | 561 | // Remove temporary directory root if not already renamed to global cache. |
| 576 | if (!std.mem.eql(u8, package_sub_path, tmp_dir_sub_path)) { | 562 | if (!package_sub_path.eql(tmp_directory_path)) { |
| 577 | cache_root.handle.deleteDir(io, tmp_dir_sub_path) catch {}; | 563 | tmp_directory_path.root_dir.handle.deleteDir(io, tmp_directory_path.sub_path) catch |err| switch (err) { |
| | 564 | error.Canceled => |e| return e, |
| | 565 | else => |e| std.log.warn("failed to delete temporary directory {f}: {t}", .{ tmp_directory_path, e }), |
| | 566 | }; |
| 578 | } | 567 | } |
| 579 | | 568 | |
| 580 | // Validate the computed hash against the expected hash. If invalid, this | 569 | // Validate the computed hash against the expected hash. If invalid, this |
| ... | @@ -614,7 +603,7 @@ fn runResource( | ... | @@ -614,7 +603,7 @@ fn runResource( |
| 614 | | 603 | |
| 615 | // Spawn a new fetch job for each dependency in the manifest file. Use | 604 | // Spawn a new fetch job for each dependency in the manifest file. Use |
| 616 | // a mutex and a hash map so that redundant jobs do not get queued up. | 605 | // a mutex and a hash map so that redundant jobs do not get queued up. |
| 617 | if (!f.job_queue.recursive) return; | 606 | if (!job_queue.recursive) return; |
| 618 | return queueJobsForDeps(f); | 607 | return queueJobsForDeps(f); |
| 619 | } | 608 | } |
| 620 | | 609 | |
| ... | @@ -641,8 +630,8 @@ fn checkBuildFileExistence(f: *Fetch) RunError!void { | ... | @@ -641,8 +630,8 @@ fn checkBuildFileExistence(f: *Fetch) RunError!void { |
| 641 | error.FileNotFound => {}, | 630 | error.FileNotFound => {}, |
| 642 | else => |e| { | 631 | else => |e| { |
| 643 | try eb.addRootErrorMessage(.{ | 632 | try eb.addRootErrorMessage(.{ |
| 644 | .msg = try eb.printString("unable to access '{f}{s}': {s}", .{ | 633 | .msg = try eb.printString("unable to access '{f}{s}': {t}", .{ |
| 645 | f.package_root, Package.build_zig_basename, @errorName(e), | 634 | f.package_root, Package.build_zig_basename, e, |
| 646 | }), | 635 | }), |
| 647 | }); | 636 | }); |
| 648 | return error.FetchFailed; | 637 | return error.FetchFailed; |
| ... | @@ -667,9 +656,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void { | ... | @@ -667,9 +656,7 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void { |
| 667 | else => |e| { | 656 | else => |e| { |
| 668 | const file_path = try pkg_root.join(arena, Manifest.basename); | 657 | const file_path = try pkg_root.join(arena, Manifest.basename); |
| 669 | try eb.addRootErrorMessage(.{ | 658 | try eb.addRootErrorMessage(.{ |
| 670 | .msg = try eb.printString("unable to load package manifest '{f}': {s}", .{ | 659 | .msg = try eb.printString("unable to load package manifest '{f}': {t}", .{ file_path, e }), |
| 671 | file_path, @errorName(e), | | |
| 672 | }), | | |
| 673 | }); | 660 | }); |
| 674 | return error.FetchFailed; | 661 | return error.FetchFailed; |
| 675 | }, | 662 | }, |
| ... | @@ -1453,14 +1440,20 @@ fn recursiveDirectoryCopy(f: *Fetch, dir: Io.Dir, tmp_dir: Io.Dir) anyerror!void | ... | @@ -1453,14 +1440,20 @@ fn recursiveDirectoryCopy(f: *Fetch, dir: Io.Dir, tmp_dir: Io.Dir) anyerror!void |
| 1453 | } | 1440 | } |
| 1454 | } | 1441 | } |
| 1455 | | 1442 | |
| 1456 | pub fn renameTmpIntoCache(io: Io, cache_dir: Io.Dir, tmp_dir_sub_path: []const u8, dest_dir_sub_path: []const u8) !void { | 1443 | pub fn renameTmpIntoCache(io: Io, tmp_path: Cache.Path, dest_path: Cache.Path) !void { |
| 1457 | assert(dest_dir_sub_path[1] == fs.path.sep); | | |
| 1458 | var handled_missing_dir = false; | 1444 | var handled_missing_dir = false; |
| 1459 | while (true) { | 1445 | while (true) { |
| 1460 | cache_dir.rename(tmp_dir_sub_path, cache_dir, dest_dir_sub_path, io) catch |err| switch (err) { | 1446 | Io.Dir.rename( |
| | 1447 | tmp_path.root_dir.handle, |
| | 1448 | tmp_path.sub_path, |
| | 1449 | dest_path.root_dir.handle, |
| | 1450 | dest_path.sub_path, |
| | 1451 | io, |
| | 1452 | ) catch |err| switch (err) { |
| 1461 | error.FileNotFound => { | 1453 | error.FileNotFound => { |
| 1462 | if (handled_missing_dir) return err; | 1454 | if (handled_missing_dir) return err; |
| 1463 | cache_dir.createDir(io, dest_dir_sub_path[0..1], .default_dir) catch |mkd_err| switch (mkd_err) { | 1455 | const parent_sub_path = Io.Dir.path.dirname(dest_path.sub_path).?; |
| | 1456 | dest_path.root_dir.handle.createDir(io, parent_sub_path, .default_dir) catch |er| switch (er) { |
| 1464 | error.PathAlreadyExists => handled_missing_dir = true, | 1457 | error.PathAlreadyExists => handled_missing_dir = true, |
| 1465 | else => |e| return e, | 1458 | else => |e| return e, |
| 1466 | }; | 1459 | }; |
| ... | @@ -1468,9 +1461,11 @@ pub fn renameTmpIntoCache(io: Io, cache_dir: Io.Dir, tmp_dir_sub_path: []const u | ... | @@ -1468,9 +1461,11 @@ pub fn renameTmpIntoCache(io: Io, cache_dir: Io.Dir, tmp_dir_sub_path: []const u |
| 1468 | }, | 1461 | }, |
| 1469 | error.DirNotEmpty, error.AccessDenied => { | 1462 | error.DirNotEmpty, error.AccessDenied => { |
| 1470 | // Package has been already downloaded and may already be in use on the system. | 1463 | // Package has been already downloaded and may already be in use on the system. |
| 1471 | cache_dir.deleteTree(io, tmp_dir_sub_path) catch { | 1464 | tmp_path.root_dir.handle.deleteTree(io, tmp_path.sub_path) catch |er| switch (er) { |
| | 1465 | error.Canceled => |e| return e, |
| 1472 | // Garbage files leftover in zig-cache/tmp/ is, as they say | 1466 | // Garbage files leftover in zig-cache/tmp/ is, as they say |
| 1473 | // on Star Trek, "operating within normal parameters". | 1467 | // on Star Trek, "operating within normal parameters". |
| | 1468 | else => |e| std.log.warn("failed to delete temporary directory {f}: {t}", .{ tmp_path, e }), |
| 1474 | }; | 1469 | }; |
| 1475 | }, | 1470 | }, |
| 1476 | else => |e| return e, | 1471 | else => |e| return e, |
| ... | @@ -2244,6 +2239,7 @@ fn saveEmbedFile(io: Io, comptime tarball_name: []const u8, dir: Io.Dir) !void { | ... | @@ -2244,6 +2239,7 @@ fn saveEmbedFile(io: Io, comptime tarball_name: []const u8, dir: Io.Dir) !void { |
| 2244 | const TestFetchBuilder = struct { | 2239 | const TestFetchBuilder = struct { |
| 2245 | http_client: std.http.Client, | 2240 | http_client: std.http.Client, |
| 2246 | global_cache_directory: Cache.Directory, | 2241 | global_cache_directory: Cache.Directory, |
| | 2242 | local_cache_path: Cache.Path, |
| 2247 | job_queue: Fetch.JobQueue, | 2243 | job_queue: Fetch.JobQueue, |
| 2248 | fetch: Fetch, | 2244 | fetch: Fetch, |
| 2249 | | 2245 | |
| ... | @@ -2254,15 +2250,25 @@ const TestFetchBuilder = struct { | ... | @@ -2254,15 +2250,25 @@ const TestFetchBuilder = struct { |
| 2254 | cache_parent_dir: std.Io.Dir, | 2250 | cache_parent_dir: std.Io.Dir, |
| 2255 | path_or_url: []const u8, | 2251 | path_or_url: []const u8, |
| 2256 | ) !*Fetch { | 2252 | ) !*Fetch { |
| 2257 | const cache_dir = try cache_parent_dir.createDirPathOpen(io, "zig-global-cache", .{}); | 2253 | const global_cache_dir = try cache_parent_dir.createDirPathOpen(io, "zig-global-cache", .{}); |
| | 2254 | const package_root_dir = try cache_parent_dir.createDirPathOpen(io, "local-project-root", .{}); |
| 2258 | | 2255 | |
| 2259 | self.http_client = .{ .allocator = allocator, .io = io }; | 2256 | self.http_client = .{ .allocator = allocator, .io = io }; |
| 2260 | self.global_cache_directory = .{ .handle = cache_dir, .path = null }; | 2257 | self.global_cache_directory = .{ .handle = global_cache_dir, .path = "zig-global-cache" }; |
| | 2258 | self.local_cache_path = .{ |
| | 2259 | .root_dir = .{ .handle = package_root_dir, .path = "local-project-root" }, |
| | 2260 | .sub_path = ".zig-cache", |
| | 2261 | }; |
| 2261 | | 2262 | |
| 2262 | self.job_queue = .{ | 2263 | self.job_queue = .{ |
| 2263 | .io = io, | 2264 | .io = io, |
| 2264 | .http_client = &self.http_client, | 2265 | .http_client = &self.http_client, |
| 2265 | .global_cache = self.global_cache_directory, | 2266 | .global_cache = self.global_cache_directory, |
| | 2267 | .local_cache = self.local_cache_path, |
| | 2268 | .root_pkg_path = .{ |
| | 2269 | .root_dir = .{ .handle = package_root_dir, .path = "local-project-root" }, |
| | 2270 | .sub_path = "zig-pkg", |
| | 2271 | }, |
| 2266 | .recursive = false, | 2272 | .recursive = false, |
| 2267 | .read_only = false, | 2273 | .read_only = false, |
| 2268 | .debug_hash = false, | 2274 | .debug_hash = false, |
| ... | @@ -2276,7 +2282,7 @@ const TestFetchBuilder = struct { | ... | @@ -2276,7 +2282,7 @@ const TestFetchBuilder = struct { |
| 2276 | .hash_tok = .none, | 2282 | .hash_tok = .none, |
| 2277 | .name_tok = 0, | 2283 | .name_tok = 0, |
| 2278 | .lazy_status = .eager, | 2284 | .lazy_status = .eager, |
| 2279 | .parent_package_root = Cache.Path{ .root_dir = Cache.Directory{ .handle = cache_dir, .path = null } }, | 2285 | .parent_package_root = .{ .root_dir = .{ .handle = package_root_dir, .path = null } }, |
| 2280 | .parent_manifest_ast = null, | 2286 | .parent_manifest_ast = null, |
| 2281 | .prog_node = std.Progress.Node.none, | 2287 | .prog_node = std.Progress.Node.none, |
| 2282 | .job_queue = &self.job_queue, | 2288 | .job_queue = &self.job_queue, |