authorgravatar for igor.anic@gmail.comIgor Anić <igor.anic@gmail.com> 2024-04-03 21:01:29+02:00
committergravatar for igor.anic@gmail.comIgor Anić <igor.anic@gmail.com> 2024-04-03 21:01:29+02:00
log1431e34cb9e3af8d4437ca2e5f91b6da53be5a47
tree601886cfe7f071e96c7e737ab466deae5b2bbb8e
parentb1e70edd907da91bc0863b541d04a15f2093f9a0

fetch: remove one openDir in runResource

Based on comment: https://github.com/ziglang/zig/pull/19111#discussion_r1548640939 computeHash finds all files in temporary directory. There is no difference on what path are they. When calculating hash normalized_path must be set relative to package root. That's the place where we strip root if needed.

1 files changed, 36 insertions(+), 34 deletions(-)

src/Package/Fetch.zig+36-34
......@@ -461,36 +461,26 @@ fn runResource(
461461 };
462462 defer tmp_directory.handle.close();
463463
464 const package_dir = try unpackResource(f, resource, uri_path, tmp_directory);
464 const pkg_dir = try unpackResource(f, resource, uri_path, tmp_directory);
465465
466 if (package_dir) |dir_name| {
467 // Position tmp_directory to dir_name inside tmp_dir_sub_path.
468 const path = try cache_root.join(arena, &.{ tmp_dir_sub_path, dir_name });
469 const handle = tmp_directory.handle.openDir(dir_name, .{ .iterate = true }) catch |err| {
470 try eb.addRootErrorMessage(.{
471 .msg = try eb.printString("unable to open temporary directory '{s}': {s}", .{
472 path, @errorName(err),
473 }),
474 });
475 return error.FetchFailed;
476 };
477 tmp_directory.handle.close();
478 tmp_directory = .{ .path = path, .handle = handle };
479 } else {
480 // btrfs workaround; reopen tmp_directory
481 if (native_os == .linux and f.job_queue.work_around_btrfs_bug) {
482 // https://github.com/ziglang/zig/issues/17095
483 tmp_directory.handle.close();
484 tmp_directory.handle = cache_root.handle.makeOpenPath(tmp_dir_sub_path, .{
485 .iterate = true,
486 }) catch @panic("btrfs workaround failed");
487 }
466 var pkg_path: Cache.Path = if (pkg_dir) |pkg_dir_name|
467 .{ .root_dir = tmp_directory, .sub_path = pkg_dir_name }
468 else
469 .{ .root_dir = tmp_directory };
470
471 // btrfs workaround; reopen tmp_directory
472 if (native_os == .linux and f.job_queue.work_around_btrfs_bug) {
473 // https://github.com/ziglang/zig/issues/17095
474 pkg_path.root_dir.handle.close();
475 pkg_path.root_dir.handle = cache_root.handle.makeOpenPath(tmp_dir_sub_path, .{
476 .iterate = true,
477 }) catch @panic("btrfs workaround failed");
488478 }
489479
490480 // Load, parse, and validate the unpacked build.zig.zon file. It is allowed
491481 // for the file to be missing, in which case this fetched package is
492482 // considered to be a "naked" package.
493 try loadManifest(f, .{ .root_dir = tmp_directory });
483 try loadManifest(f, pkg_path);
494484
495485 // Apply the manifest's inclusion rules to the temporary directory by
496486 // deleting excluded files. If any error occurred for files that were
......@@ -505,10 +495,10 @@ fn runResource(
505495
506496 // Compute the package hash based on the remaining files in the temporary
507497 // directory.
508 f.actual_hash = try computeHash(f, tmp_directory, filter);
498 f.actual_hash = try computeHash(f, pkg_path, filter);
509499
510 break :blk if (package_dir) |dir_name|
511 try fs.path.join(arena, &.{ tmp_dir_sub_path, dir_name })
500 break :blk if (pkg_dir) |pkg_dir_name|
501 try fs.path.join(arena, &.{ tmp_dir_sub_path, pkg_dir_name })
512502 else
513503 tmp_dir_sub_path;
514504 };
......@@ -1388,7 +1378,7 @@ pub fn renameTmpIntoCache(
13881378/// function.
13891379fn computeHash(
13901380 f: *Fetch,
1391 tmp_directory: Cache.Directory,
1381 pkg_path: Cache.Path,
13921382 filter: Filter,
13931383) RunError!Manifest.Digest {
13941384 // All the path name strings need to be in memory for sorting.
......@@ -1396,6 +1386,7 @@ fn computeHash(
13961386 const gpa = f.arena.child_allocator;
13971387 const eb = &f.error_bundle;
13981388 const thread_pool = f.job_queue.thread_pool;
1389 const root_dir = pkg_path.root_dir.handle;
13991390
14001391 // Collect all files, recursively, then sort.
14011392 var all_files = std.ArrayList(*HashedFile).init(gpa);
......@@ -1409,7 +1400,7 @@ fn computeHash(
14091400 var sus_dirs: std.StringArrayHashMapUnmanaged(void) = .{};
14101401 defer sus_dirs.deinit(gpa);
14111402
1412 var walker = try tmp_directory.handle.walk(gpa);
1403 var walker = try root_dir.walk(gpa);
14131404 defer walker.deinit();
14141405
14151406 {
......@@ -1423,7 +1414,7 @@ fn computeHash(
14231414 while (walker.next() catch |err| {
14241415 try eb.addRootErrorMessage(.{ .msg = try eb.printString(
14251416 "unable to walk temporary directory '{}': {s}",
1426 .{ tmp_directory, @errorName(err) },
1417 .{ pkg_path, @errorName(err) },
14271418 ) });
14281419 return error.FetchFailed;
14291420 }) |entry| {
......@@ -1444,7 +1435,7 @@ fn computeHash(
14441435 };
14451436 wait_group.start();
14461437 try thread_pool.spawn(workerDeleteFile, .{
1447 tmp_directory.handle, deleted_file, &wait_group,
1438 root_dir, deleted_file, &wait_group,
14481439 });
14491440 try deleted_files.append(deleted_file);
14501441 continue;
......@@ -1467,14 +1458,14 @@ fn computeHash(
14671458 const hashed_file = try arena.create(HashedFile);
14681459 hashed_file.* = .{
14691460 .fs_path = fs_path,
1470 .normalized_path = try normalizePathAlloc(arena, fs_path),
1461 .normalized_path = try normalizePathAlloc(arena, stripRoot(fs_path, pkg_path.sub_path)),
14711462 .kind = kind,
14721463 .hash = undefined, // to be populated by the worker
14731464 .failure = undefined, // to be populated by the worker
14741465 };
14751466 wait_group.start();
14761467 try thread_pool.spawn(workerHashFile, .{
1477 tmp_directory.handle, hashed_file, &wait_group,
1468 root_dir, hashed_file, &wait_group,
14781469 });
14791470 try all_files.append(hashed_file);
14801471 }
......@@ -1493,7 +1484,7 @@ fn computeHash(
14931484 var i: usize = 0;
14941485 while (i < sus_dirs.count()) : (i += 1) {
14951486 const sus_dir = sus_dirs.keys()[i];
1496 tmp_directory.handle.deleteDir(sus_dir) catch |err| switch (err) {
1487 root_dir.deleteDir(sus_dir) catch |err| switch (err) {
14971488 error.DirNotEmpty => continue,
14981489 error.FileNotFound => continue,
14991490 else => |e| {
......@@ -1657,6 +1648,17 @@ const HashedFile = struct {
16571648 }
16581649};
16591650
1651/// Strips root directory name from file system path.
1652fn stripRoot(fs_path: []const u8, root_dir: []const u8) []const u8 {
1653 if (root_dir.len == 0 or fs_path.len <= root_dir.len) return fs_path;
1654
1655 if (std.mem.eql(u8, fs_path[0..root_dir.len], root_dir) and fs_path[root_dir.len] == fs.path.sep) {
1656 return fs_path[root_dir.len + 1 ..];
1657 }
1658
1659 return fs_path;
1660}
1661
16601662/// Make a file system path identical independently of operating system path inconsistencies.
16611663/// This converts backslashes into forward slashes.
16621664fn normalizePathAlloc(arena: Allocator, fs_path: []const u8) ![]const u8 {