| ... | ... | @@ -56,7 +56,7 @@ package_root: Cache.Path, |
| 56 | 56 | error_bundle: ErrorBundle.Wip, |
| 57 | 57 | manifest: ?Manifest, |
| 58 | 58 | manifest_ast: std.zig.Ast, |
| 59 | | actual_hash: Manifest.Digest, |
| 59 | computed_hash: ComputedHash, |
| 60 | 60 | /// Fetch logic notices whether a package has a build.zig file and sets this flag. |
| 61 | 61 | has_build_zig: bool, |
| 62 | 62 | /// Indicates whether the task aborted due to an out-of-memory condition. |
| ... | ... | @@ -116,8 +116,8 @@ pub const JobQueue = struct { |
| 116 | 116 | /// as lazy. |
| 117 | 117 | unlazy_set: UnlazySet = .{}, |
| 118 | 118 | |
| 119 | | pub const Table = std.AutoArrayHashMapUnmanaged(Manifest.MultiHashHexDigest, *Fetch); |
| 120 | | pub const UnlazySet = std.AutoArrayHashMapUnmanaged(Manifest.MultiHashHexDigest, void); |
| 119 | pub const Table = std.AutoArrayHashMapUnmanaged(Package.Hash, *Fetch); |
| 120 | pub const UnlazySet = std.AutoArrayHashMapUnmanaged(Package.Hash, void); |
| 121 | 121 | |
| 122 | 122 | pub fn deinit(jq: *JobQueue) void { |
| 123 | 123 | if (jq.all_fetches.items.len == 0) return; |
| ... | ... | @@ -160,22 +160,24 @@ pub const JobQueue = struct { |
| 160 | 160 | |
| 161 | 161 | // Ensure the generated .zig file is deterministic. |
| 162 | 162 | jq.table.sortUnstable(@as(struct { |
| 163 | | keys: []const Manifest.MultiHashHexDigest, |
| 163 | keys: []const Package.Hash, |
| 164 | 164 | pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool { |
| 165 | | return std.mem.lessThan(u8, &ctx.keys[a_index], &ctx.keys[b_index]); |
| 165 | return std.mem.lessThan(u8, &ctx.keys[a_index].bytes, &ctx.keys[b_index].bytes); |
| 166 | 166 | } |
| 167 | 167 | }, .{ .keys = keys })); |
| 168 | 168 | |
| 169 | | for (keys, jq.table.values()) |hash, fetch| { |
| 169 | for (keys, jq.table.values()) |*hash, fetch| { |
| 170 | 170 | if (fetch == jq.all_fetches.items[0]) { |
| 171 | 171 | // The first one is a dummy package for the current project. |
| 172 | 172 | continue; |
| 173 | 173 | } |
| 174 | 174 | |
| 175 | const hash_slice = hash.toSlice(); |
| 176 | |
| 175 | 177 | try buf.writer().print( |
| 176 | 178 | \\ pub const {} = struct {{ |
| 177 | 179 | \\ |
| 178 | | , .{std.zig.fmtId(&hash)}); |
| 180 | , .{std.zig.fmtId(hash_slice)}); |
| 179 | 181 | |
| 180 | 182 | lazy: { |
| 181 | 183 | switch (fetch.lazy_status) { |
| ... | ... | @@ -207,7 +209,7 @@ pub const JobQueue = struct { |
| 207 | 209 | try buf.writer().print( |
| 208 | 210 | \\ pub const build_zig = @import("{}"); |
| 209 | 211 | \\ |
| 210 | | , .{std.zig.fmtEscapes(&hash)}); |
| 212 | , .{std.zig.fmtEscapes(hash_slice)}); |
| 211 | 213 | } |
| 212 | 214 | |
| 213 | 215 | if (fetch.manifest) |*manifest| { |
| ... | ... | @@ -219,7 +221,7 @@ pub const JobQueue = struct { |
| 219 | 221 | const h = depDigest(fetch.package_root, jq.global_cache, dep) orelse continue; |
| 220 | 222 | try buf.writer().print( |
| 221 | 223 | " .{{ \"{}\", \"{}\" }},\n", |
| 222 | | .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(&h) }, |
| 224 | .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(h.toSlice()) }, |
| 223 | 225 | ); |
| 224 | 226 | } |
| 225 | 227 | |
| ... | ... | @@ -251,7 +253,7 @@ pub const JobQueue = struct { |
| 251 | 253 | const h = depDigest(root_fetch.package_root, jq.global_cache, dep) orelse continue; |
| 252 | 254 | try buf.writer().print( |
| 253 | 255 | " .{{ \"{}\", \"{}\" }},\n", |
| 254 | | .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(&h) }, |
| 256 | .{ std.zig.fmtEscapes(name), std.zig.fmtEscapes(h.toSlice()) }, |
| 255 | 257 | ); |
| 256 | 258 | } |
| 257 | 259 | try buf.appendSlice("};\n"); |
| ... | ... | @@ -283,7 +285,7 @@ pub const Location = union(enum) { |
| 283 | 285 | url: []const u8, |
| 284 | 286 | /// If this is null it means the user omitted the hash field from a dependency. |
| 285 | 287 | /// It will be an error but the logic should still fetch and print the discovered hash. |
| 286 | | hash: ?Manifest.MultiHashHexDigest, |
| 288 | hash: ?Package.Hash, |
| 287 | 289 | }; |
| 288 | 290 | }; |
| 289 | 291 | |
| ... | ... | @@ -325,9 +327,11 @@ pub fn run(f: *Fetch) RunError!void { |
| 325 | 327 | // "p/$hash/foo", with possibly more directories after "foo". |
| 326 | 328 | // We want to fail unless the resolved relative path has a |
| 327 | 329 | // prefix of "p/$hash/". |
| 328 | | const digest_len = @typeInfo(Manifest.MultiHashHexDigest).array.len; |
| 329 | 330 | const prefix_len: usize = if (f.job_queue.read_only) 0 else "p/".len; |
| 330 | | const expected_prefix = f.parent_package_root.sub_path[0 .. prefix_len + digest_len]; |
| 331 | const parent_sub_path = f.parent_package_root.sub_path; |
| 332 | const end = std.mem.indexOfScalarPos(u8, parent_sub_path, prefix_len, fs.path.sep) orelse |
| 333 | parent_sub_path.len; |
| 334 | const expected_prefix = parent_sub_path[prefix_len..end]; |
| 331 | 335 | if (!std.mem.startsWith(u8, pkg_root.sub_path, expected_prefix)) { |
| 332 | 336 | return f.fail( |
| 333 | 337 | f.location_tok, |
| ... | ... | @@ -367,9 +371,13 @@ pub fn run(f: *Fetch) RunError!void { |
| 367 | 371 | }, |
| 368 | 372 | }; |
| 369 | 373 | |
| 370 | | const s = fs.path.sep_str; |
| 371 | 374 | if (remote.hash) |expected_hash| { |
| 372 | | const prefixed_pkg_sub_path = "p" ++ s ++ expected_hash; |
| 375 | var prefixed_pkg_sub_path_buffer: [100]u8 = undefined; |
| 376 | prefixed_pkg_sub_path_buffer[0] = 'p'; |
| 377 | prefixed_pkg_sub_path_buffer[1] = fs.path.sep; |
| 378 | const hash_slice = expected_hash.toSlice(); |
| 379 | @memcpy(prefixed_pkg_sub_path_buffer[2..][0..hash_slice.len], hash_slice); |
| 380 | const prefixed_pkg_sub_path = prefixed_pkg_sub_path_buffer[0 .. 2 + hash_slice.len]; |
| 373 | 381 | const prefix_len: usize = if (f.job_queue.read_only) "p/".len else 0; |
| 374 | 382 | const pkg_sub_path = prefixed_pkg_sub_path[prefix_len..]; |
| 375 | 383 | if (cache_root.handle.access(pkg_sub_path, .{})) |_| { |
| ... | ... | @@ -437,7 +445,7 @@ fn runResource( |
| 437 | 445 | f: *Fetch, |
| 438 | 446 | uri_path: []const u8, |
| 439 | 447 | resource: *Resource, |
| 440 | | remote_hash: ?Manifest.MultiHashHexDigest, |
| 448 | remote_hash: ?Package.Hash, |
| 441 | 449 | ) RunError!void { |
| 442 | 450 | defer resource.deinit(); |
| 443 | 451 | const arena = f.arena.allocator(); |
| ... | ... | @@ -499,7 +507,7 @@ fn runResource( |
| 499 | 507 | // Empty directories have already been omitted by `unpackResource`. |
| 500 | 508 | // Compute the package hash based on the remaining files in the temporary |
| 501 | 509 | // directory. |
| 502 | | f.actual_hash = try computeHash(f, pkg_path, filter); |
| 510 | f.computed_hash = try computeHash(f, pkg_path, filter); |
| 503 | 511 | |
| 504 | 512 | break :blk if (unpack_result.root_dir.len > 0) |
| 505 | 513 | try fs.path.join(arena, &.{ tmp_dir_sub_path, unpack_result.root_dir }) |
| ... | ... | @@ -507,6 +515,8 @@ fn runResource( |
| 507 | 515 | tmp_dir_sub_path; |
| 508 | 516 | }; |
| 509 | 517 | |
| 518 | const computed_package_hash = computedPackageHash(f); |
| 519 | |
| 510 | 520 | // Rename the temporary directory into the global zig package cache |
| 511 | 521 | // directory. If the hash already exists, delete the temporary directory |
| 512 | 522 | // and leave the zig package cache directory untouched as it may be in use |
| ... | ... | @@ -515,7 +525,7 @@ fn runResource( |
| 515 | 525 | |
| 516 | 526 | f.package_root = .{ |
| 517 | 527 | .root_dir = cache_root, |
| 518 | | .sub_path = try arena.dupe(u8, "p" ++ s ++ Manifest.hexDigest(f.actual_hash)), |
| 528 | .sub_path = try std.fmt.allocPrint(arena, "p" ++ s ++ "{s}", .{computed_package_hash.toSlice()}), |
| 519 | 529 | }; |
| 520 | 530 | renameTmpIntoCache(cache_root.handle, package_sub_path, f.package_root.sub_path) catch |err| { |
| 521 | 531 | const src = try cache_root.join(arena, &.{tmp_dir_sub_path}); |
| ... | ... | @@ -534,13 +544,22 @@ fn runResource( |
| 534 | 544 | // Validate the computed hash against the expected hash. If invalid, this |
| 535 | 545 | // job is done. |
| 536 | 546 | |
| 537 | | const actual_hex = Manifest.hexDigest(f.actual_hash); |
| 538 | 547 | if (remote_hash) |declared_hash| { |
| 539 | | if (!std.mem.eql(u8, &declared_hash, &actual_hex)) { |
| 540 | | return f.fail(f.hash_tok, try eb.printString( |
| 541 | | "hash mismatch: manifest declares {s} but the fetched package has {s}", |
| 542 | | .{ declared_hash, actual_hex }, |
| 543 | | )); |
| 548 | if (declared_hash.isOld()) { |
| 549 | const actual_hex = Package.multiHashHexDigest(f.computed_hash.digest); |
| 550 | if (!std.mem.eql(u8, declared_hash.toSlice(), &actual_hex)) { |
| 551 | return f.fail(f.hash_tok, try eb.printString( |
| 552 | "hash mismatch: manifest declares {s} but the fetched package has {s}", |
| 553 | .{ declared_hash.toSlice(), actual_hex }, |
| 554 | )); |
| 555 | } |
| 556 | } else { |
| 557 | if (!computed_package_hash.eql(&declared_hash)) { |
| 558 | return f.fail(f.hash_tok, try eb.printString( |
| 559 | "hash mismatch: manifest declares {s} but the fetched package has {s}", |
| 560 | .{ declared_hash.toSlice(), computed_package_hash.toSlice() }, |
| 561 | )); |
| 562 | } |
| 544 | 563 | } |
| 545 | 564 | } else if (!f.omit_missing_hash_error) { |
| 546 | 565 | const notes_len = 1; |
| ... | ... | @@ -551,7 +570,7 @@ fn runResource( |
| 551 | 570 | }); |
| 552 | 571 | const notes_start = try eb.reserveNotes(notes_len); |
| 553 | 572 | eb.extra.items[notes_start] = @intFromEnum(try eb.addErrorMessage(.{ |
| 554 | | .msg = try eb.printString("expected .hash = \"{s}\",", .{&actual_hex}), |
| 573 | .msg = try eb.printString("expected .hash = \"{s}\",", .{computed_package_hash.toSlice()}), |
| 555 | 574 | })); |
| 556 | 575 | return error.FetchFailed; |
| 557 | 576 | } |
| ... | ... | @@ -562,6 +581,16 @@ fn runResource( |
| 562 | 581 | return queueJobsForDeps(f); |
| 563 | 582 | } |
| 564 | 583 | |
| 584 | pub fn computedPackageHash(f: *const Fetch) Package.Hash { |
| 585 | const saturated_size = std.math.cast(u32, f.computed_hash.total_size) orelse std.math.maxInt(u32); |
| 586 | if (f.manifest) |man| { |
| 587 | var version_buffer: [32]u8 = undefined; |
| 588 | const version: []const u8 = std.fmt.bufPrint(&version_buffer, "{}", .{man.version}) catch &version_buffer; |
| 589 | return .init(f.computed_hash.digest, man.name, version, saturated_size); |
| 590 | } |
| 591 | return .initNaked(f.computed_hash.digest, saturated_size); |
| 592 | } |
| 593 | |
| 565 | 594 | /// `computeHash` gets a free check for the existence of `build.zig`, but when |
| 566 | 595 | /// not computing a hash, we need to do a syscall to check for it. |
| 567 | 596 | fn checkBuildFileExistence(f: *Fetch) RunError!void { |
| ... | ... | @@ -673,9 +702,8 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { |
| 673 | 702 | .url = url, |
| 674 | 703 | .hash = h: { |
| 675 | 704 | const h = dep.hash orelse break :h null; |
| 676 | | const digest_len = @typeInfo(Manifest.MultiHashHexDigest).array.len; |
| 677 | | const multihash_digest = h[0..digest_len].*; |
| 678 | | const gop = f.job_queue.table.getOrPutAssumeCapacity(multihash_digest); |
| 705 | const pkg_hash: Package.Hash = .fromSlice(h); |
| 706 | const gop = f.job_queue.table.getOrPutAssumeCapacity(pkg_hash); |
| 679 | 707 | if (gop.found_existing) { |
| 680 | 708 | if (!dep.lazy) { |
| 681 | 709 | gop.value_ptr.*.lazy_status = .eager; |
| ... | ... | @@ -683,15 +711,15 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { |
| 683 | 711 | continue; |
| 684 | 712 | } |
| 685 | 713 | gop.value_ptr.* = new_fetch; |
| 686 | | break :h multihash_digest; |
| 714 | break :h pkg_hash; |
| 687 | 715 | }, |
| 688 | 716 | } }, |
| 689 | 717 | .path => |rel_path| l: { |
| 690 | 718 | // This might produce an invalid path, which is checked for |
| 691 | 719 | // at the beginning of run(). |
| 692 | 720 | const new_root = try f.package_root.resolvePosix(parent_arena, rel_path); |
| 693 | | const multihash_digest = relativePathDigest(new_root, cache_root); |
| 694 | | const gop = f.job_queue.table.getOrPutAssumeCapacity(multihash_digest); |
| 721 | const pkg_hash = relativePathDigest(new_root, cache_root); |
| 722 | const gop = f.job_queue.table.getOrPutAssumeCapacity(pkg_hash); |
| 695 | 723 | if (gop.found_existing) { |
| 696 | 724 | if (!dep.lazy) { |
| 697 | 725 | gop.value_ptr.*.lazy_status = .eager; |
| ... | ... | @@ -724,7 +752,7 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { |
| 724 | 752 | .error_bundle = undefined, |
| 725 | 753 | .manifest = null, |
| 726 | 754 | .manifest_ast = undefined, |
| 727 | | .actual_hash = undefined, |
| 755 | .computed_hash = undefined, |
| 728 | 756 | .has_build_zig = false, |
| 729 | 757 | .oom_flag = false, |
| 730 | 758 | .latest_commit = null, |
| ... | ... | @@ -746,11 +774,8 @@ fn queueJobsForDeps(f: *Fetch) RunError!void { |
| 746 | 774 | } |
| 747 | 775 | } |
| 748 | 776 | |
| 749 | | pub fn relativePathDigest( |
| 750 | | pkg_root: Cache.Path, |
| 751 | | cache_root: Cache.Directory, |
| 752 | | ) Manifest.MultiHashHexDigest { |
| 753 | | var hasher = Manifest.Hash.init(.{}); |
| 777 | pub fn relativePathDigest(pkg_root: Cache.Path, cache_root: Cache.Directory) Package.Hash { |
| 778 | var hasher = Package.Hash.Algo.init(.{}); |
| 754 | 779 | // This hash is a tuple of: |
| 755 | 780 | // * whether it relative to the global cache directory or to the root package |
| 756 | 781 | // * the relative file path from there to the build root of the package |
| ... | ... | @@ -759,7 +784,7 @@ pub fn relativePathDigest( |
| 759 | 784 | else |
| 760 | 785 | &package_hash_prefix_project); |
| 761 | 786 | hasher.update(pkg_root.sub_path); |
| 762 | | return Manifest.hexDigest(hasher.finalResult()); |
| 787 | return .fromSlice(&hasher.finalResult()); |
| 763 | 788 | } |
| 764 | 789 | |
| 765 | 790 | pub fn workerRun(f: *Fetch, prog_name: []const u8) void { |
| ... | ... | @@ -1387,11 +1412,7 @@ fn recursiveDirectoryCopy(f: *Fetch, dir: fs.Dir, tmp_dir: fs.Dir) anyerror!void |
| 1387 | 1412 | } |
| 1388 | 1413 | } |
| 1389 | 1414 | |
| 1390 | | pub fn renameTmpIntoCache( |
| 1391 | | cache_dir: fs.Dir, |
| 1392 | | tmp_dir_sub_path: []const u8, |
| 1393 | | dest_dir_sub_path: []const u8, |
| 1394 | | ) !void { |
| 1415 | pub fn renameTmpIntoCache(cache_dir: fs.Dir, tmp_dir_sub_path: []const u8, dest_dir_sub_path: []const u8) !void { |
| 1395 | 1416 | assert(dest_dir_sub_path[1] == fs.path.sep); |
| 1396 | 1417 | var handled_missing_dir = false; |
| 1397 | 1418 | while (true) { |
| ... | ... | @@ -1417,16 +1438,17 @@ pub fn renameTmpIntoCache( |
| 1417 | 1438 | } |
| 1418 | 1439 | } |
| 1419 | 1440 | |
| 1441 | const ComputedHash = struct { |
| 1442 | digest: Package.Hash.Digest, |
| 1443 | total_size: u64, |
| 1444 | }; |
| 1445 | |
| 1420 | 1446 | /// Assumes that files not included in the package have already been filtered |
| 1421 | 1447 | /// prior to calling this function. This ensures that files not protected by |
| 1422 | 1448 | /// the hash are not present on the file system. Empty directories are *not |
| 1423 | 1449 | /// hashed* and must not be present on the file system when calling this |
| 1424 | 1450 | /// function. |
| 1425 | | fn computeHash( |
| 1426 | | f: *Fetch, |
| 1427 | | pkg_path: Cache.Path, |
| 1428 | | filter: Filter, |
| 1429 | | ) RunError!Manifest.Digest { |
| 1451 | fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!ComputedHash { |
| 1430 | 1452 | // All the path name strings need to be in memory for sorting. |
| 1431 | 1453 | const arena = f.arena.allocator(); |
| 1432 | 1454 | const gpa = f.arena.child_allocator; |
| ... | ... | @@ -1449,6 +1471,9 @@ fn computeHash( |
| 1449 | 1471 | var walker = try root_dir.walk(gpa); |
| 1450 | 1472 | defer walker.deinit(); |
| 1451 | 1473 | |
| 1474 | // Total number of bytes of file contents included in the package. |
| 1475 | var total_size: u64 = 0; |
| 1476 | |
| 1452 | 1477 | { |
| 1453 | 1478 | // The final hash will be a hash of each file hashed independently. This |
| 1454 | 1479 | // allows hashing in parallel. |
| ... | ... | @@ -1506,6 +1531,7 @@ fn computeHash( |
| 1506 | 1531 | .kind = kind, |
| 1507 | 1532 | .hash = undefined, // to be populated by the worker |
| 1508 | 1533 | .failure = undefined, // to be populated by the worker |
| 1534 | .size = undefined, // to be populated by the worker |
| 1509 | 1535 | }; |
| 1510 | 1536 | thread_pool.spawnWg(&wait_group, workerHashFile, .{ root_dir, hashed_file }); |
| 1511 | 1537 | try all_files.append(hashed_file); |
| ... | ... | @@ -1544,7 +1570,7 @@ fn computeHash( |
| 1544 | 1570 | |
| 1545 | 1571 | std.mem.sortUnstable(*HashedFile, all_files.items, {}, HashedFile.lessThan); |
| 1546 | 1572 | |
| 1547 | | var hasher = Manifest.Hash.init(.{}); |
| 1573 | var hasher = Package.Hash.Algo.init(.{}); |
| 1548 | 1574 | var any_failures = false; |
| 1549 | 1575 | for (all_files.items) |hashed_file| { |
| 1550 | 1576 | hashed_file.failure catch |err| { |
| ... | ... | @@ -1556,6 +1582,7 @@ fn computeHash( |
| 1556 | 1582 | }); |
| 1557 | 1583 | }; |
| 1558 | 1584 | hasher.update(&hashed_file.hash); |
| 1585 | total_size += hashed_file.size; |
| 1559 | 1586 | } |
| 1560 | 1587 | for (deleted_files.items) |deleted_file| { |
| 1561 | 1588 | deleted_file.failure catch |err| { |
| ... | ... | @@ -1580,7 +1607,10 @@ fn computeHash( |
| 1580 | 1607 | }; |
| 1581 | 1608 | } |
| 1582 | 1609 | |
| 1583 | | return hasher.finalResult(); |
| 1610 | return .{ |
| 1611 | .digest = hasher.finalResult(), |
| 1612 | .total_size = total_size, |
| 1613 | }; |
| 1584 | 1614 | } |
| 1585 | 1615 | |
| 1586 | 1616 | fn dumpHashInfo(all_files: []const *const HashedFile) !void { |
| ... | ... | @@ -1609,8 +1639,9 @@ fn workerDeleteFile(dir: fs.Dir, deleted_file: *DeletedFile) void { |
| 1609 | 1639 | |
| 1610 | 1640 | fn hashFileFallible(dir: fs.Dir, hashed_file: *HashedFile) HashedFile.Error!void { |
| 1611 | 1641 | var buf: [8000]u8 = undefined; |
| 1612 | | var hasher = Manifest.Hash.init(.{}); |
| 1642 | var hasher = Package.Hash.Algo.init(.{}); |
| 1613 | 1643 | hasher.update(hashed_file.normalized_path); |
| 1644 | var file_size: u64 = 0; |
| 1614 | 1645 | |
| 1615 | 1646 | switch (hashed_file.kind) { |
| 1616 | 1647 | .file => { |
| ... | ... | @@ -1622,6 +1653,7 @@ fn hashFileFallible(dir: fs.Dir, hashed_file: *HashedFile) HashedFile.Error!void |
| 1622 | 1653 | while (true) { |
| 1623 | 1654 | const bytes_read = try file.read(&buf); |
| 1624 | 1655 | if (bytes_read == 0) break; |
| 1656 | file_size += bytes_read; |
| 1625 | 1657 | hasher.update(buf[0..bytes_read]); |
| 1626 | 1658 | file_header.update(buf[0..bytes_read]); |
| 1627 | 1659 | } |
| ... | ... | @@ -1641,6 +1673,7 @@ fn hashFileFallible(dir: fs.Dir, hashed_file: *HashedFile) HashedFile.Error!void |
| 1641 | 1673 | }, |
| 1642 | 1674 | } |
| 1643 | 1675 | hasher.final(&hashed_file.hash); |
| 1676 | hashed_file.size = file_size; |
| 1644 | 1677 | } |
| 1645 | 1678 | |
| 1646 | 1679 | fn deleteFileFallible(dir: fs.Dir, deleted_file: *DeletedFile) DeletedFile.Error!void { |
| ... | ... | @@ -1667,9 +1700,10 @@ const DeletedFile = struct { |
| 1667 | 1700 | const HashedFile = struct { |
| 1668 | 1701 | fs_path: []const u8, |
| 1669 | 1702 | normalized_path: []const u8, |
| 1670 | | hash: Manifest.Digest, |
| 1703 | hash: Package.Hash.Digest, |
| 1671 | 1704 | failure: Error!void, |
| 1672 | 1705 | kind: Kind, |
| 1706 | size: u64, |
| 1673 | 1707 | |
| 1674 | 1708 | const Error = |
| 1675 | 1709 | fs.File.OpenError || |
| ... | ... | @@ -1744,12 +1778,8 @@ const Filter = struct { |
| 1744 | 1778 | } |
| 1745 | 1779 | }; |
| 1746 | 1780 | |
| 1747 | | pub fn depDigest( |
| 1748 | | pkg_root: Cache.Path, |
| 1749 | | cache_root: Cache.Directory, |
| 1750 | | dep: Manifest.Dependency, |
| 1751 | | ) ?Manifest.MultiHashHexDigest { |
| 1752 | | if (dep.hash) |h| return h[0..Manifest.multihash_hex_digest_len].*; |
| 1781 | pub fn depDigest(pkg_root: Cache.Path, cache_root: Cache.Directory, dep: Manifest.Dependency) ?Package.Hash { |
| 1782 | if (dep.hash) |h| return .fromSlice(h); |
| 1753 | 1783 | |
| 1754 | 1784 | switch (dep.location) { |
| 1755 | 1785 | .url => return null, |
| ... | ... | @@ -2137,7 +2167,7 @@ test "tarball with excluded duplicate paths" { |
| 2137 | 2167 | defer fb.deinit(); |
| 2138 | 2168 | try fetch.run(); |
| 2139 | 2169 | |
| 2140 | | const hex_digest = Package.Manifest.hexDigest(fetch.actual_hash); |
| 2170 | const hex_digest = Package.multiHashHexDigest(fetch.computed_hash.digest); |
| 2141 | 2171 | try std.testing.expectEqualStrings( |
| 2142 | 2172 | "12200bafe035cbb453dd717741b66e9f9d1e6c674069d06121dafa1b2e62eb6b22da", |
| 2143 | 2173 | &hex_digest, |
| ... | ... | @@ -2181,7 +2211,7 @@ test "tarball without root folder" { |
| 2181 | 2211 | defer fb.deinit(); |
| 2182 | 2212 | try fetch.run(); |
| 2183 | 2213 | |
| 2184 | | const hex_digest = Package.Manifest.hexDigest(fetch.actual_hash); |
| 2214 | const hex_digest = Package.multiHashHexDigest(fetch.computed_hash.digest); |
| 2185 | 2215 | try std.testing.expectEqualStrings( |
| 2186 | 2216 | "12209f939bfdcb8b501a61bb4a43124dfa1b2848adc60eec1e4624c560357562b793", |
| 2187 | 2217 | &hex_digest, |
| ... | ... | @@ -2222,7 +2252,7 @@ test "set executable bit based on file content" { |
| 2222 | 2252 | try fetch.run(); |
| 2223 | 2253 | try std.testing.expectEqualStrings( |
| 2224 | 2254 | "1220fecb4c06a9da8673c87fe8810e15785f1699212f01728eadce094d21effeeef3", |
| 2225 | | &Manifest.hexDigest(fetch.actual_hash), |
| 2255 | &Package.multiHashHexDigest(fetch.computed_hash.digest), |
| 2226 | 2256 | ); |
| 2227 | 2257 | |
| 2228 | 2258 | var out = try fb.packageDir(); |
| ... | ... | @@ -2304,7 +2334,7 @@ const TestFetchBuilder = struct { |
| 2304 | 2334 | .error_bundle = undefined, |
| 2305 | 2335 | .manifest = null, |
| 2306 | 2336 | .manifest_ast = undefined, |
| 2307 | | .actual_hash = undefined, |
| 2337 | .computed_hash = undefined, |
| 2308 | 2338 | .has_build_zig = false, |
| 2309 | 2339 | .oom_flag = false, |
| 2310 | 2340 | .latest_commit = null, |