zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit ba656e5c9f58e0440278918e5c6cdf0ac2fe673c (tree)
parent f1a9344ffeaa9b449eb111a112df33c845a1210c
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Mon, 16 Oct 2023 18:15:47 -0700

zig fetch: add `--debug-hash` argument

This argument causes zig to print verbose hashing information to stdout,
which can be used to diff two different fetches and find out why the
hashes do not equal each other.

Diffstat:
Msrc/Package/Fetch.zig | 37++++++++++++++++++++++++++++++++++---
Msrc/main.zig | 7+++++++
2 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig @@ -81,6 +81,10 @@ pub const JobQueue = struct { wait_group: WaitGroup = .{}, global_cache: Cache.Directory, recursive: bool, + /// Dumps hash information to stdout which can be used to troubleshoot why + /// two hashes of the same package do not match. + /// If this is true, `recursive` must be false. + debug_hash: bool, work_around_btrfs_bug: bool, pub const Table = std.AutoArrayHashMapUnmanaged(Manifest.MultiHashHexDigest, *Fetch); @@ -1315,7 +1319,7 @@ fn computeHash( const kind: HashedFile.Kind = switch (entry.kind) { .directory => unreachable, .file => .file, - .sym_link => .sym_link, + .sym_link => .link, else => return f.fail(f.location_tok, try eb.printString( "package contains '{s}' which has illegal file type '{s}'", .{ entry.path, @tagName(entry.kind) }, @@ -1399,9 +1403,36 @@ fn computeHash( } if (any_failures) return error.FetchFailed; + + if (f.job_queue.debug_hash) { + assert(!f.job_queue.recursive); + // Print something to stdout that can be text diffed to figure out why + // the package hash is different. + dumpHashInfo(all_files.items) catch |err| { + std.debug.print("unable to write to stdout: {s}\n", .{@errorName(err)}); + std.process.exit(1); + }; + } + return hasher.finalResult(); } +fn dumpHashInfo(all_files: []const *const HashedFile) !void { + const stdout = std.io.getStdOut(); + var bw = std.io.bufferedWriter(stdout.writer()); + const w = bw.writer(); + + for (all_files) |hashed_file| { + try w.print("{s}: {s}: {s}\n", .{ + @tagName(hashed_file.kind), + std.fmt.fmtSliceHexLower(&hashed_file.hash), + hashed_file.normalized_path, + }); + } + + try bw.flush(); +} + fn workerHashFile(dir: fs.Dir, hashed_file: *HashedFile, wg: *WaitGroup) void { defer wg.finish(); hashed_file.failure = hashFileFallible(dir, hashed_file); @@ -1427,7 +1458,7 @@ fn hashFileFallible(dir: fs.Dir, hashed_file: *HashedFile) HashedFile.Error!void hasher.update(buf[0..bytes_read]); } }, - .sym_link => { + .link => { const link_name = try dir.readLink(hashed_file.fs_path, &buf); if (fs.path.sep != canonical_sep) { // Package hashes are intended to be consistent across @@ -1480,7 +1511,7 @@ const HashedFile = struct { fs.File.StatError || fs.Dir.ReadLinkError; - const Kind = enum { file, sym_link }; + const Kind = enum { file, link }; fn lessThan(context: void, lhs: *const HashedFile, rhs: *const HashedFile) bool { _ = context; diff --git a/src/main.zig b/src/main.zig @@ -5143,6 +5143,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi .thread_pool = &thread_pool, .global_cache = global_cache_directory, .recursive = true, + .debug_hash = false, .work_around_btrfs_bug = work_around_btrfs_bug, }; defer job_queue.deinit(); @@ -6991,6 +6992,7 @@ pub const usage_fetch = \\Options: \\ -h, --help Print this help and exit \\ --global-cache-dir [path] Override path to global Zig cache directory + \\ --debug-hash Print verbose hash information to stdout \\ ; @@ -7004,6 +7006,7 @@ fn cmdFetch( std.process.hasEnvVarConstant("ZIG_BTRFS_WORKAROUND"); var opt_path_or_url: ?[]const u8 = null; var override_global_cache_dir: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_GLOBAL_CACHE_DIR"); + var debug_hash: bool = false; { var i: usize = 0; @@ -7019,6 +7022,9 @@ fn cmdFetch( i += 1; override_global_cache_dir = args[i]; continue; + } else if (mem.eql(u8, arg, "--debug-hash")) { + debug_hash = true; + continue; } else { fatal("unrecognized parameter: '{s}'", .{arg}); } @@ -7057,6 +7063,7 @@ fn cmdFetch( .thread_pool = &thread_pool, .global_cache = global_cache_directory, .recursive = false, + .debug_hash = debug_hash, .work_around_btrfs_bug = work_around_btrfs_bug, }; defer job_queue.deinit();