| ... | ... | @@ -447,7 +447,7 @@ fn runResource( |
| 447 | 447 | const rand_int = std.crypto.random.int(u64); |
| 448 | 448 | const tmp_dir_sub_path = "tmp" ++ s ++ Manifest.hex64(rand_int); |
| 449 | 449 | |
| 450 | | const package_sub_path = blk: { |
| 450 | const package_sub_path, const size = blk: { |
| 451 | 451 | const tmp_directory_path = try cache_root.join(arena, &.{tmp_dir_sub_path}); |
| 452 | 452 | var tmp_directory: Cache.Directory = .{ |
| 453 | 453 | .path = tmp_directory_path, |
| ... | ... | @@ -499,12 +499,14 @@ fn runResource( |
| 499 | 499 | // Empty directories have already been omitted by `unpackResource`. |
| 500 | 500 | // Compute the package hash based on the remaining files in the temporary |
| 501 | 501 | // directory. |
| 502 | | f.actual_hash = try computeHash(f, pkg_path, filter); |
| 502 | f.actual_hash, const size = try computeHash(f, pkg_path, filter); |
| 503 | 503 | |
| 504 | | break :blk if (unpack_result.root_dir.len > 0) |
| 504 | const pkg_sub_path = if (unpack_result.root_dir.len > 0) |
| 505 | 505 | try fs.path.join(arena, &.{ tmp_dir_sub_path, unpack_result.root_dir }) |
| 506 | 506 | else |
| 507 | 507 | tmp_dir_sub_path; |
| 508 | |
| 509 | break :blk .{ pkg_sub_path, size }; |
| 508 | 510 | }; |
| 509 | 511 | |
| 510 | 512 | // Rename the temporary directory into the global zig package cache |
| ... | ... | @@ -513,6 +515,14 @@ fn runResource( |
| 513 | 515 | // by the system. This is done even if the hash is invalid, in case the |
| 514 | 516 | // package with the different hash is used in the future. |
| 515 | 517 | |
| 518 | const name = f.manifest.?.name; |
| 519 | const semver = f.manifest.?.version; |
| 520 | const new_hash = Package.Manifest.NewHashDecoded.init(name, semver, @intCast(size), f.actual_hash); |
| 521 | const encoded = new_hash.encode(); |
| 522 | std.debug.print("new hash: {s}\n", .{encoded.toSlice()}); |
| 523 | |
| 524 | if (true) std.process.exit(0); |
| 525 | |
| 516 | 526 | f.package_root = .{ |
| 517 | 527 | .root_dir = cache_root, |
| 518 | 528 | .sub_path = try arena.dupe(u8, "p" ++ s ++ Manifest.hexDigest(f.actual_hash)), |
| ... | ... | @@ -1420,7 +1430,7 @@ fn computeHash( |
| 1420 | 1430 | f: *Fetch, |
| 1421 | 1431 | pkg_path: Cache.Path, |
| 1422 | 1432 | filter: Filter, |
| 1423 | | ) RunError!Manifest.Digest { |
| 1433 | ) RunError!struct { Manifest.Digest, u64 } { |
| 1424 | 1434 | // All the path name strings need to be in memory for sorting. |
| 1425 | 1435 | const arena = f.arena.allocator(); |
| 1426 | 1436 | const gpa = f.arena.child_allocator; |
| ... | ... | @@ -1499,6 +1509,7 @@ fn computeHash( |
| 1499 | 1509 | .normalized_path = try normalizePathAlloc(arena, entry_pkg_path), |
| 1500 | 1510 | .kind = kind, |
| 1501 | 1511 | .hash = undefined, // to be populated by the worker |
| 1512 | .size = undefined, // to be populated by the worker |
| 1502 | 1513 | .failure = undefined, // to be populated by the worker |
| 1503 | 1514 | }; |
| 1504 | 1515 | thread_pool.spawnWg(&wait_group, workerHashFile, .{ root_dir, hashed_file }); |
| ... | ... | @@ -1540,6 +1551,7 @@ fn computeHash( |
| 1540 | 1551 | |
| 1541 | 1552 | var hasher = Manifest.Hash.init(.{}); |
| 1542 | 1553 | var any_failures = false; |
| 1554 | var total_size: u64 = 0; |
| 1543 | 1555 | for (all_files.items) |hashed_file| { |
| 1544 | 1556 | hashed_file.failure catch |err| { |
| 1545 | 1557 | any_failures = true; |
| ... | ... | @@ -1550,6 +1562,7 @@ fn computeHash( |
| 1550 | 1562 | }); |
| 1551 | 1563 | }; |
| 1552 | 1564 | hasher.update(&hashed_file.hash); |
| 1565 | total_size += hashed_file.size; |
| 1553 | 1566 | } |
| 1554 | 1567 | for (deleted_files.items) |deleted_file| { |
| 1555 | 1568 | deleted_file.failure catch |err| { |
| ... | ... | @@ -1574,7 +1587,7 @@ fn computeHash( |
| 1574 | 1587 | }; |
| 1575 | 1588 | } |
| 1576 | 1589 | |
| 1577 | | return hasher.finalResult(); |
| 1590 | return .{ hasher.finalResult(), total_size }; |
| 1578 | 1591 | } |
| 1579 | 1592 | |
| 1580 | 1593 | fn dumpHashInfo(all_files: []const *const HashedFile) !void { |
| ... | ... | @@ -1604,20 +1617,20 @@ fn workerDeleteFile(dir: fs.Dir, deleted_file: *DeletedFile) void { |
| 1604 | 1617 | fn hashFileFallible(dir: fs.Dir, hashed_file: *HashedFile) HashedFile.Error!void { |
| 1605 | 1618 | var buf: [8000]u8 = undefined; |
| 1606 | 1619 | var hasher = Manifest.Hash.init(.{}); |
| 1620 | var size: u64 = 0; |
| 1607 | 1621 | hasher.update(hashed_file.normalized_path); |
| 1608 | 1622 | |
| 1609 | 1623 | switch (hashed_file.kind) { |
| 1610 | 1624 | .file => { |
| 1611 | 1625 | var file = try dir.openFile(hashed_file.fs_path, .{}); |
| 1612 | 1626 | defer file.close(); |
| 1613 | | // Hard-coded false executable bit: https://github.com/ziglang/zig/issues/17463 |
| 1614 | | hasher.update(&.{ 0, 0 }); |
| 1615 | 1627 | var file_header: FileHeader = .{}; |
| 1616 | 1628 | while (true) { |
| 1617 | 1629 | const bytes_read = try file.read(&buf); |
| 1618 | 1630 | if (bytes_read == 0) break; |
| 1619 | 1631 | hasher.update(buf[0..bytes_read]); |
| 1620 | 1632 | file_header.update(buf[0..bytes_read]); |
| 1633 | size += bytes_read; |
| 1621 | 1634 | } |
| 1622 | 1635 | if (file_header.isExecutable()) { |
| 1623 | 1636 | try setExecutable(file); |
| ... | ... | @@ -1635,6 +1648,7 @@ fn hashFileFallible(dir: fs.Dir, hashed_file: *HashedFile) HashedFile.Error!void |
| 1635 | 1648 | }, |
| 1636 | 1649 | } |
| 1637 | 1650 | hasher.final(&hashed_file.hash); |
| 1651 | hashed_file.size = size; |
| 1638 | 1652 | } |
| 1639 | 1653 | |
| 1640 | 1654 | fn deleteFileFallible(dir: fs.Dir, deleted_file: *DeletedFile) DeletedFile.Error!void { |
| ... | ... | @@ -1662,6 +1676,7 @@ const HashedFile = struct { |
| 1662 | 1676 | fs_path: []const u8, |
| 1663 | 1677 | normalized_path: []const u8, |
| 1664 | 1678 | hash: Manifest.Digest, |
| 1679 | size: u64, |
| 1665 | 1680 | failure: Error!void, |
| 1666 | 1681 | kind: Kind, |
| 1667 | 1682 | |