| ... | ... | @@ -461,36 +461,26 @@ fn runResource( |
| 461 | 461 | }; |
| 462 | 462 | defer tmp_directory.handle.close(); |
| 463 | 463 | |
| 464 | | const package_dir = try unpackResource(f, resource, uri_path, tmp_directory); |
| 464 | const pkg_dir = try unpackResource(f, resource, uri_path, tmp_directory); |
| 465 | 465 | |
| 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"); |
| 488 | 478 | } |
| 489 | 479 | |
| 490 | 480 | // Load, parse, and validate the unpacked build.zig.zon file. It is allowed |
| 491 | 481 | // for the file to be missing, in which case this fetched package is |
| 492 | 482 | // considered to be a "naked" package. |
| 493 | | try loadManifest(f, .{ .root_dir = tmp_directory }); |
| 483 | try loadManifest(f, pkg_path); |
| 494 | 484 | |
| 495 | 485 | // Apply the manifest's inclusion rules to the temporary directory by |
| 496 | 486 | // deleting excluded files. If any error occurred for files that were |
| ... | ... | @@ -505,10 +495,10 @@ fn runResource( |
| 505 | 495 | |
| 506 | 496 | // Compute the package hash based on the remaining files in the temporary |
| 507 | 497 | // directory. |
| 508 | | f.actual_hash = try computeHash(f, tmp_directory, filter); |
| 498 | f.actual_hash = try computeHash(f, pkg_path, filter); |
| 509 | 499 | |
| 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 }) |
| 512 | 502 | else |
| 513 | 503 | tmp_dir_sub_path; |
| 514 | 504 | }; |
| ... | ... | @@ -1388,7 +1378,7 @@ pub fn renameTmpIntoCache( |
| 1388 | 1378 | /// function. |
| 1389 | 1379 | fn computeHash( |
| 1390 | 1380 | f: *Fetch, |
| 1391 | | tmp_directory: Cache.Directory, |
| 1381 | pkg_path: Cache.Path, |
| 1392 | 1382 | filter: Filter, |
| 1393 | 1383 | ) RunError!Manifest.Digest { |
| 1394 | 1384 | // All the path name strings need to be in memory for sorting. |
| ... | ... | @@ -1396,6 +1386,7 @@ fn computeHash( |
| 1396 | 1386 | const gpa = f.arena.child_allocator; |
| 1397 | 1387 | const eb = &f.error_bundle; |
| 1398 | 1388 | const thread_pool = f.job_queue.thread_pool; |
| 1389 | const root_dir = pkg_path.root_dir.handle; |
| 1399 | 1390 | |
| 1400 | 1391 | // Collect all files, recursively, then sort. |
| 1401 | 1392 | var all_files = std.ArrayList(*HashedFile).init(gpa); |
| ... | ... | @@ -1409,7 +1400,7 @@ fn computeHash( |
| 1409 | 1400 | var sus_dirs: std.StringArrayHashMapUnmanaged(void) = .{}; |
| 1410 | 1401 | defer sus_dirs.deinit(gpa); |
| 1411 | 1402 | |
| 1412 | | var walker = try tmp_directory.handle.walk(gpa); |
| 1403 | var walker = try root_dir.walk(gpa); |
| 1413 | 1404 | defer walker.deinit(); |
| 1414 | 1405 | |
| 1415 | 1406 | { |
| ... | ... | @@ -1423,7 +1414,7 @@ fn computeHash( |
| 1423 | 1414 | while (walker.next() catch |err| { |
| 1424 | 1415 | try eb.addRootErrorMessage(.{ .msg = try eb.printString( |
| 1425 | 1416 | "unable to walk temporary directory '{}': {s}", |
| 1426 | | .{ tmp_directory, @errorName(err) }, |
| 1417 | .{ pkg_path, @errorName(err) }, |
| 1427 | 1418 | ) }); |
| 1428 | 1419 | return error.FetchFailed; |
| 1429 | 1420 | }) |entry| { |
| ... | ... | @@ -1444,7 +1435,7 @@ fn computeHash( |
| 1444 | 1435 | }; |
| 1445 | 1436 | wait_group.start(); |
| 1446 | 1437 | try thread_pool.spawn(workerDeleteFile, .{ |
| 1447 | | tmp_directory.handle, deleted_file, &wait_group, |
| 1438 | root_dir, deleted_file, &wait_group, |
| 1448 | 1439 | }); |
| 1449 | 1440 | try deleted_files.append(deleted_file); |
| 1450 | 1441 | continue; |
| ... | ... | @@ -1467,14 +1458,14 @@ fn computeHash( |
| 1467 | 1458 | const hashed_file = try arena.create(HashedFile); |
| 1468 | 1459 | hashed_file.* = .{ |
| 1469 | 1460 | .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)), |
| 1471 | 1462 | .kind = kind, |
| 1472 | 1463 | .hash = undefined, // to be populated by the worker |
| 1473 | 1464 | .failure = undefined, // to be populated by the worker |
| 1474 | 1465 | }; |
| 1475 | 1466 | wait_group.start(); |
| 1476 | 1467 | try thread_pool.spawn(workerHashFile, .{ |
| 1477 | | tmp_directory.handle, hashed_file, &wait_group, |
| 1468 | root_dir, hashed_file, &wait_group, |
| 1478 | 1469 | }); |
| 1479 | 1470 | try all_files.append(hashed_file); |
| 1480 | 1471 | } |
| ... | ... | @@ -1493,7 +1484,7 @@ fn computeHash( |
| 1493 | 1484 | var i: usize = 0; |
| 1494 | 1485 | while (i < sus_dirs.count()) : (i += 1) { |
| 1495 | 1486 | 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) { |
| 1497 | 1488 | error.DirNotEmpty => continue, |
| 1498 | 1489 | error.FileNotFound => continue, |
| 1499 | 1490 | else => |e| { |
| ... | ... | @@ -1657,6 +1648,17 @@ const HashedFile = struct { |
| 1657 | 1648 | } |
| 1658 | 1649 | }; |
| 1659 | 1650 | |
| 1651 | /// Strips root directory name from file system path. |
| 1652 | fn 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 | |
| 1660 | 1662 | /// Make a file system path identical independently of operating system path inconsistencies. |
| 1661 | 1663 | /// This converts backslashes into forward slashes. |
| 1662 | 1664 | fn normalizePathAlloc(arena: Allocator, fs_path: []const u8) ![]const u8 { |