| ... | ... | @@ -499,13 +499,13 @@ const Report = struct { |
| 499 | 499 | }; |
| 500 | 500 | |
| 501 | 501 | const FetchLocation = union(enum) { |
| 502 | | /// The absolute path to a file or directory. |
| 502 | /// The relative path to a file or directory. |
| 503 | 503 | /// This may be a file that requires unpacking (such as a .tar.gz), |
| 504 | 504 | /// or the path to the root directory of a package. |
| 505 | 505 | file: []const u8, |
| 506 | 506 | http_request: std.Uri, |
| 507 | 507 | |
| 508 | | pub fn init(gpa: Allocator, directory: Compilation.Directory, dep: Manifest.Dependency, report: Report) !FetchLocation { |
| 508 | pub fn init(gpa: Allocator, dep: Manifest.Dependency, report: Report) !FetchLocation { |
| 509 | 509 | switch (dep.location) { |
| 510 | 510 | .url => |url| { |
| 511 | 511 | const uri = std.Uri.parse(url) catch |err| switch (err) { |
| ... | ... | @@ -518,18 +518,11 @@ const FetchLocation = union(enum) { |
| 518 | 518 | return .{ .http_request = uri }; |
| 519 | 519 | }, |
| 520 | 520 | .path => |path| { |
| 521 | | const unescaped = try std.Uri.unescapeString(gpa, path); |
| 522 | | defer gpa.free(unescaped); |
| 523 | | const unnormalized_path = try unnormalizePath(gpa, unescaped); |
| 524 | | defer gpa.free(unnormalized_path); |
| 525 | | |
| 526 | | if (fs.path.isAbsolute(unnormalized_path)) { |
| 521 | if (fs.path.isAbsolute(path)) { |
| 527 | 522 | return report.fail(dep.location_tok, "Absolute paths are not allowed. Use a relative path instead", .{}); |
| 528 | 523 | } |
| 529 | 524 | |
| 530 | | const new_path = try fs.path.resolve(gpa, &.{ directory.path.?, unnormalized_path }); |
| 531 | | |
| 532 | | return .{ .file = new_path }; |
| 525 | return .{ .file = try gpa.dupe(u8, path) }; |
| 533 | 526 | }, |
| 534 | 527 | } |
| 535 | 528 | } |
| ... | ... | @@ -563,9 +556,9 @@ const FetchLocation = union(enum) { |
| 563 | 556 | return .{ |
| 564 | 557 | .path = owned_path, |
| 565 | 558 | .resource = if (is_dir) |
| 566 | | .{ .directory = try fs.openIterableDirAbsolute(file, .{}) } |
| 559 | .{ .directory = try root_dir.handle.openIterableDir(file, .{}) } |
| 567 | 560 | else |
| 568 | | .{ .file = try fs.openFileAbsolute(file, .{}) }, |
| 561 | .{ .file = try root_dir.handle.openFile(file, .{}) }, |
| 569 | 562 | }; |
| 570 | 563 | }, |
| 571 | 564 | .http_request => |uri| { |
| ... | ... | @@ -609,6 +602,7 @@ const ReadableResource = struct { |
| 609 | 602 | rr: *ReadableResource, |
| 610 | 603 | allocator: Allocator, |
| 611 | 604 | thread_pool: *ThreadPool, |
| 605 | root_dir: Compilation.Directory, |
| 612 | 606 | global_cache_directory: Compilation.Directory, |
| 613 | 607 | dep: Manifest.Dependency, |
| 614 | 608 | report: Report, |
| ... | ... | @@ -618,7 +612,8 @@ const ReadableResource = struct { |
| 618 | 612 | .directory => { |
| 619 | 613 | return .{ |
| 620 | 614 | .hash = computePathHash(rr.path), |
| 621 | | .dir_path = try allocator.dupe(u8, rr.path), |
| 615 | .root_src_dir_path = try allocator.dupe(u8, rr.path), |
| 616 | .root_dir = root_dir, |
| 622 | 617 | }; |
| 623 | 618 | }, |
| 624 | 619 | inline .file, .http_request => |*r| { |
| ... | ... | @@ -684,15 +679,16 @@ const ReadableResource = struct { |
| 684 | 679 | |
| 685 | 680 | const pkg_dir_sub_path = "p" ++ s ++ Manifest.hexDigest(actual_hash); |
| 686 | 681 | const unpacked_path = try global_cache_directory.join(allocator, &.{pkg_dir_sub_path}); |
| 687 | | errdefer allocator.free(unpacked_path); |
| 682 | defer allocator.free(unpacked_path); |
| 688 | 683 | |
| 689 | 684 | const relative_unpacked_path = try fs.path.relative(allocator, global_cache_directory.path.?, unpacked_path); |
| 690 | | defer allocator.free(relative_unpacked_path); |
| 685 | errdefer allocator.free(relative_unpacked_path); |
| 691 | 686 | try renameTmpIntoCache(global_cache_directory.handle, tmp_dir_sub_path, relative_unpacked_path); |
| 692 | 687 | |
| 693 | 688 | return .{ |
| 694 | 689 | .hash = actual_hash, |
| 695 | | .dir_path = unpacked_path, |
| 690 | .root_src_dir_path = relative_unpacked_path, |
| 691 | .root_dir = global_cache_directory, |
| 696 | 692 | }; |
| 697 | 693 | }, |
| 698 | 694 | } |
| ... | ... | @@ -785,10 +781,11 @@ pub const PackageLocation = struct { |
| 785 | 781 | /// For packages that require unpacking, this is the hash of the package contents. |
| 786 | 782 | /// For directories, this is the hash of the absolute file path. |
| 787 | 783 | hash: [Manifest.Hash.digest_length]u8, |
| 788 | | dir_path: []const u8, |
| 784 | root_src_dir_path: []const u8, |
| 785 | root_dir: Compilation.Directory, |
| 789 | 786 | |
| 790 | 787 | pub fn deinit(pl: *PackageLocation, allocator: Allocator) void { |
| 791 | | allocator.free(pl.dir_path); |
| 788 | allocator.free(pl.root_src_dir_path); |
| 792 | 789 | pl.* = undefined; |
| 793 | 790 | } |
| 794 | 791 | }; |
| ... | ... | @@ -934,13 +931,13 @@ fn fetchAndUnpack( |
| 934 | 931 | pkg_prog_node.activate(); |
| 935 | 932 | pkg_prog_node.context.refresh(); |
| 936 | 933 | |
| 937 | | var fetch_location = try FetchLocation.init(gpa, directory, dep.*, report); |
| 934 | var fetch_location = try FetchLocation.init(gpa, dep.*, report); |
| 938 | 935 | defer fetch_location.deinit(gpa); |
| 939 | 936 | |
| 940 | 937 | var readable_resource = try fetch_location.fetch(gpa, directory, http_client, dep.*, report); |
| 941 | 938 | defer readable_resource.deinit(gpa); |
| 942 | 939 | |
| 943 | | var package_location = try readable_resource.unpack(gpa, thread_pool, global_cache_directory, dep.*, report, &pkg_prog_node); |
| 940 | var package_location = try readable_resource.unpack(gpa, thread_pool, directory, global_cache_directory, dep.*, report, &pkg_prog_node); |
| 944 | 941 | defer package_location.deinit(gpa); |
| 945 | 942 | |
| 946 | 943 | const actual_hex = Manifest.hexDigest(package_location.hash); |
| ... | ... | @@ -973,24 +970,23 @@ fn fetchAndUnpack( |
| 973 | 970 | return report.fail(dep.hash_tok, "hash not allowed for directory package", .{}); |
| 974 | 971 | } |
| 975 | 972 | // Since directory dependencies don't provide a hash in build.zig.zon, |
| 976 | | // set the hash here to be the hash of the absolute path to the dependency. |
| 973 | // set the hash here to be the hash of the path to the dependency. |
| 977 | 974 | dep.hash = try gpa.dupe(u8, &actual_hex); |
| 978 | 975 | } |
| 979 | 976 | |
| 980 | | const build_zig_path = try std.fs.path.join(gpa, &.{ package_location.dir_path, build_zig_basename }); |
| 977 | const build_zig_path = try std.fs.path.join(gpa, &.{ package_location.root_src_dir_path, build_zig_basename }); |
| 981 | 978 | defer gpa.free(build_zig_path); |
| 982 | | assert(fs.path.isAbsolute(build_zig_path)); |
| 983 | 979 | |
| 984 | | global_cache_directory.handle.access(build_zig_path, .{}) catch |err| switch (err) { |
| 980 | package_location.root_dir.handle.access(build_zig_path, .{}) catch |err| switch (err) { |
| 985 | 981 | error.FileNotFound => { |
| 986 | | const module = try create(gpa, package_location.dir_path, ""); |
| 982 | const module = try createWithDir(gpa, package_location.root_dir, package_location.root_src_dir_path, ""); |
| 987 | 983 | try all_modules.put(gpa, actual_hex, .{ .non_zig_pkg = module }); |
| 988 | 984 | return .{ .non_zig_pkg = module }; |
| 989 | 985 | }, |
| 990 | 986 | else => return err, |
| 991 | 987 | }; |
| 992 | 988 | |
| 993 | | const module = try create(gpa, package_location.dir_path, build_zig_basename); |
| 989 | const module = try createWithDir(gpa, package_location.root_dir, package_location.root_src_dir_path, build_zig_basename); |
| 994 | 990 | try all_modules.put(gpa, actual_hex, .{ .zig_pkg = module }); |
| 995 | 991 | return .{ .zig_pkg = module }; |
| 996 | 992 | } |
| ... | ... | @@ -1126,25 +1122,6 @@ fn normalizePath(arena: Allocator, fs_path: []const u8) ![]const u8 { |
| 1126 | 1122 | return normalized; |
| 1127 | 1123 | } |
| 1128 | 1124 | |
| 1129 | | /// Make a OS-specific file system path |
| 1130 | | /// This performs the inverse operation of normalizePath, |
| 1131 | | /// converting forward slashes into backslashes on Windows |
| 1132 | | fn unnormalizePath(arena: Allocator, fs_path: []const u8) ![]const u8 { |
| 1133 | | const canonical_sep = '/'; |
| 1134 | | |
| 1135 | | const unnormalized = try arena.dupe(u8, fs_path); |
| 1136 | | if (fs.path.sep == canonical_sep) |
| 1137 | | return unnormalized; |
| 1138 | | |
| 1139 | | for (unnormalized) |*byte| { |
| 1140 | | switch (byte.*) { |
| 1141 | | canonical_sep => byte.* = fs.path.sep, |
| 1142 | | else => continue, |
| 1143 | | } |
| 1144 | | } |
| 1145 | | return unnormalized; |
| 1146 | | } |
| 1147 | | |
| 1148 | 1125 | fn workerHashFile(dir: fs.Dir, hashed_file: *HashedFile, wg: *WaitGroup) void { |
| 1149 | 1126 | defer wg.finish(); |
| 1150 | 1127 | hashed_file.failure = hashFileFallible(dir, hashed_file); |