| ... | ... | @@ -40,6 +40,7 @@ const native_os = builtin.os.tag; |
| 40 | 40 | const std = @import("std"); |
| 41 | 41 | const Io = std.Io; |
| 42 | 42 | const fs = std.fs; |
| 43 | const log = std.log.scoped(.fetch); |
| 43 | 44 | const assert = std.debug.assert; |
| 44 | 45 | const ascii = std.ascii; |
| 45 | 46 | const Allocator = std.mem.Allocator; |
| ... | ... | @@ -324,7 +325,7 @@ pub const JobQueue = struct { |
| 324 | 325 | error.Canceled => |e| return e, |
| 325 | 326 | error.ReadFailed => comptime unreachable, |
| 326 | 327 | error.WriteFailed => comptime unreachable, |
| 327 | | else => |e| std.log.warn("failed caching recompressed tarball to {f}: {t}", .{ dest_path, e }), |
| 328 | else => |e| log.warn("failed caching recompressed tarball to {f}: {t}", .{ dest_path, e }), |
| 328 | 329 | }; |
| 329 | 330 | } |
| 330 | 331 | |
| ... | ... | @@ -508,14 +509,14 @@ pub fn run(f: *Fetch) RunError!void { |
| 508 | 509 | .path_or_url => |path_or_url| { |
| 509 | 510 | if (Io.Dir.cwd().openDir(io, path_or_url, .{ .iterate = true })) |dir| { |
| 510 | 511 | var resource: Resource = .{ .dir = dir }; |
| 511 | | return f.runResource(path_or_url, &resource, null); |
| 512 | return f.runResource(path_or_url, &resource, null, false); |
| 512 | 513 | } else |dir_err| { |
| 513 | 514 | var server_header_buffer: [init_resource_buffer_size]u8 = undefined; |
| 514 | 515 | |
| 515 | 516 | const file_err = if (dir_err == error.NotDir) e: { |
| 516 | 517 | if (Io.Dir.cwd().openFile(io, path_or_url, .{})) |file| { |
| 517 | 518 | var resource: Resource = .{ .file = file.reader(io, &server_header_buffer) }; |
| 518 | | return f.runResource(path_or_url, &resource, null); |
| 519 | return f.runResource(path_or_url, &resource, null, false); |
| 519 | 520 | } else |err| break :e err; |
| 520 | 521 | } else dir_err; |
| 521 | 522 | |
| ... | ... | @@ -527,11 +528,13 @@ pub fn run(f: *Fetch) RunError!void { |
| 527 | 528 | }; |
| 528 | 529 | var resource: Resource = undefined; |
| 529 | 530 | try f.initResource(uri, &resource, &server_header_buffer); |
| 530 | | return f.runResource(try uri.path.toRawMaybeAlloc(arena), &resource, null); |
| 531 | return f.runResource(try uri.path.toRawMaybeAlloc(arena), &resource, null, false); |
| 531 | 532 | } |
| 532 | 533 | }, |
| 533 | 534 | }; |
| 534 | 535 | |
| 536 | var resource_buffer: [init_resource_buffer_size]u8 = undefined; |
| 537 | |
| 535 | 538 | if (remote.hash) |expected_hash| { |
| 536 | 539 | const package_root = try job_queue.root_pkg_path.join(arena, expected_hash.toSlice()); |
| 537 | 540 | if (package_root.root_dir.handle.access(io, package_root.sub_path, .{})) |_| { |
| ... | ... | @@ -543,19 +546,13 @@ pub fn run(f: *Fetch) RunError!void { |
| 543 | 546 | return queueJobsForDeps(f); |
| 544 | 547 | } else |err| switch (err) { |
| 545 | 548 | error.FileNotFound => { |
| 546 | | switch (f.lazy_status) { |
| 547 | | .eager => {}, |
| 548 | | .available => if (!job_queue.unlazy_set.contains(expected_hash)) { |
| 549 | | f.lazy_status = .unavailable; |
| 550 | | return; |
| 551 | | }, |
| 552 | | .unavailable => unreachable, |
| 553 | | } |
| 549 | log.debug("FileNotFound: {f}", .{package_root}); |
| 554 | 550 | if (job_queue.read_only) return f.fail( |
| 555 | 551 | f.name_tok, |
| 556 | 552 | try eb.printString("package not found at '{f}'", .{package_root}), |
| 557 | 553 | ); |
| 558 | 554 | }, |
| 555 | error.Canceled => |e| return e, |
| 559 | 556 | else => |e| { |
| 560 | 557 | try eb.addRootErrorMessage(.{ |
| 561 | 558 | .msg = try eb.printString("unable to open package cache directory {f}: {t}", .{ |
| ... | ... | @@ -565,6 +562,38 @@ pub fn run(f: *Fetch) RunError!void { |
| 565 | 562 | return error.FetchFailed; |
| 566 | 563 | }, |
| 567 | 564 | } |
| 565 | |
| 566 | // Check global cache before remote fetch. |
| 567 | const cached_tarball_sub_path = try std.fmt.allocPrint(arena, "p/{s}.tar.gz", .{expected_hash.toSlice()}); |
| 568 | const cached_tarball_path: Cache.Path = .{ |
| 569 | .root_dir = job_queue.global_cache, |
| 570 | .sub_path = cached_tarball_sub_path, |
| 571 | }; |
| 572 | if (cached_tarball_path.root_dir.handle.openFile(io, cached_tarball_path.sub_path, .{})) |file| { |
| 573 | log.debug("found global cached tarball {f}", .{cached_tarball_path}); |
| 574 | var resource: Resource = .{ .file = file.reader(io, &resource_buffer) }; |
| 575 | return f.runResource(cached_tarball_sub_path, &resource, remote.hash, true); |
| 576 | } else |err| switch (err) { |
| 577 | error.FileNotFound => log.debug("FileNotFound: {f}", .{cached_tarball_path}), |
| 578 | error.Canceled => |e| return e, |
| 579 | else => |e| { |
| 580 | try eb.addRootErrorMessage(.{ |
| 581 | .msg = try eb.printString("unable to open globally cached package {f}: {t}", .{ |
| 582 | cached_tarball_path, e, |
| 583 | }), |
| 584 | }); |
| 585 | return error.FetchFailed; |
| 586 | }, |
| 587 | } |
| 588 | |
| 589 | switch (f.lazy_status) { |
| 590 | .eager => {}, |
| 591 | .available => if (!job_queue.unlazy_set.contains(expected_hash)) { |
| 592 | f.lazy_status = .unavailable; |
| 593 | return; |
| 594 | }, |
| 595 | .unavailable => unreachable, |
| 596 | } |
| 568 | 597 | } else if (job_queue.read_only) { |
| 569 | 598 | try eb.addRootErrorMessage(.{ |
| 570 | 599 | .msg = try eb.addString("dependency is missing hash field"), |
| ... | ... | @@ -574,15 +603,13 @@ pub fn run(f: *Fetch) RunError!void { |
| 574 | 603 | } |
| 575 | 604 | |
| 576 | 605 | // Fetch and unpack the remote into a temporary directory. |
| 577 | | |
| 578 | 606 | const uri = std.Uri.parse(remote.url) catch |err| return f.fail( |
| 579 | 607 | f.location_tok, |
| 580 | 608 | try eb.printString("invalid URI: {t}", .{err}), |
| 581 | 609 | ); |
| 582 | | var buffer: [init_resource_buffer_size]u8 = undefined; |
| 583 | 610 | var resource: Resource = undefined; |
| 584 | | try f.initResource(uri, &resource, &buffer); |
| 585 | | return f.runResource(try uri.path.toRawMaybeAlloc(arena), &resource, remote.hash); |
| 611 | try f.initResource(uri, &resource, &resource_buffer); |
| 612 | return f.runResource(try uri.path.toRawMaybeAlloc(arena), &resource, remote.hash, false); |
| 586 | 613 | } |
| 587 | 614 | |
| 588 | 615 | pub fn deinit(f: *Fetch) void { |
| ... | ... | @@ -596,6 +623,7 @@ fn runResource( |
| 596 | 623 | uri_path: []const u8, |
| 597 | 624 | resource: *Resource, |
| 598 | 625 | remote_hash: ?Package.Hash, |
| 626 | disable_recompress: bool, |
| 599 | 627 | ) RunError!void { |
| 600 | 628 | const job_queue = f.job_queue; |
| 601 | 629 | assert(!job_queue.read_only); |
| ... | ... | @@ -681,15 +709,17 @@ fn runResource( |
| 681 | 709 | return error.FetchFailed; |
| 682 | 710 | }; |
| 683 | 711 | |
| 684 | | // Spin off a task to recompress the tarball, with filtered files deleted, into |
| 685 | | // the global cache. |
| 686 | | job_queue.group.async(io, JobQueue.recompress, .{ job_queue, computed_package_hash }); |
| 712 | if (!disable_recompress) { |
| 713 | // Spin off a task to recompress the tarball, with filtered files deleted, into |
| 714 | // the global cache. |
| 715 | job_queue.group.async(io, JobQueue.recompress, .{ job_queue, computed_package_hash }); |
| 716 | } |
| 687 | 717 | |
| 688 | 718 | // Remove temporary directory root if not already renamed to global cache. |
| 689 | 719 | if (!package_sub_path.eql(tmp_directory_path)) { |
| 690 | 720 | tmp_directory_path.root_dir.handle.deleteDir(io, tmp_directory_path.sub_path) catch |err| switch (err) { |
| 691 | 721 | error.Canceled => |e| return e, |
| 692 | | else => |e| std.log.warn("failed to delete temporary directory {f}: {t}", .{ tmp_directory_path, e }), |
| 722 | else => |e| log.warn("failed to delete temporary directory {f}: {t}", .{ tmp_directory_path, e }), |
| 693 | 723 | }; |
| 694 | 724 | } |
| 695 | 725 | |
| ... | ... | @@ -1588,7 +1618,7 @@ pub fn renameTmpIntoCache(io: Io, tmp_path: Cache.Path, dest_path: Cache.Path) ! |
| 1588 | 1618 | error.Canceled => |e| return e, |
| 1589 | 1619 | // Garbage files leftover in zig-cache/tmp/ is, as they say |
| 1590 | 1620 | // on Star Trek, "operating within normal parameters". |
| 1591 | | else => |e| std.log.warn("failed to delete temporary directory {f}: {t}", .{ tmp_path, e }), |
| 1621 | else => |e| log.warn("failed to delete temporary directory {f}: {t}", .{ tmp_path, e }), |
| 1592 | 1622 | }; |
| 1593 | 1623 | }, |
| 1594 | 1624 | else => |e| return e, |