@@ -435,6 +435,7 @@ fn runResource(
435
435
) RunError ! void {
436
436
defer resource .deinit ();
437
437
const arena = f .arena .allocator ();
438
+ const gpa = f .arena .child_allocator ;
438
439
const eb = & f .error_bundle ;
439
440
const s = fs .path .sep_str ;
440
441
const cache_root = f .job_queue .global_cache ;
@@ -461,30 +462,32 @@ fn runResource(
461
462
};
462
463
defer tmp_directory .handle .close ();
463
464
464
- var errors = try unpackResource (f , resource , uri_path , tmp_directory );
465
- defer errors .deinit ();
465
+ // Fetch and unpack a URL into a temporary directory.
466
+ var unpack = Unpack .init (gpa , tmp_directory .handle );
467
+ try unpackResource (f , resource , & unpack , uri_path );
468
+ defer unpack .deinit ();
466
469
467
470
// Load, parse, and validate the unpacked build.zig.zon file. It is allowed
468
471
// for the file to be missing, in which case this fetched package is
469
472
// considered to be a "naked" package.
470
473
try loadManifest (f , .{ .root_dir = tmp_directory });
471
-
472
- // Apply the manifest's inclusion rules to the temporary directory by
473
- // deleting excluded files. If any error occurred for files that were
474
- // ultimately excluded, those errors should be ignored, such as failure to
475
- // create symlinks that weren't supposed to be included anyway.
476
-
477
- // Empty directories have already been omitted by `unpackResource`.
478
-
474
+ // Manifest's inclusion rules.
479
475
const filter : Filter = .{
480
476
.include_paths = if (f .manifest ) | m | m .paths else .{},
481
477
};
482
478
483
- try errors .remove (filter );
484
- try f .emitUnpackErrors (& errors );
479
+ // Apply the manifest's inclusion rules to the errors collected during
480
+ // unpacking resource. If any error occurred for files that were
481
+ // ultimately excluded, those errors will be ignored, such as failure to
482
+ // create symlinks that weren't supposed to be included anyway.
483
+ try unpack .filterErrors (filter );
484
+ try f .bundleUnpackErrors (& unpack );
485
485
486
486
// Compute the package hash based on the remaining files in the temporary
487
487
// directory.
488
+ // It will also apply the manifest's inclusion rules to the temporary
489
+ // directory by deleting excluded files.
490
+ // Empty directories have already been omitted by `unpackResource`.
488
491
489
492
if (builtin .os .tag == .linux and f .job_queue .work_around_btrfs_bug ) {
490
493
// https://github.com/ziglang/zig/issues/17095
@@ -1034,9 +1037,9 @@ fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Re
1034
1037
fn unpackResource (
1035
1038
f : * Fetch ,
1036
1039
resource : * Resource ,
1040
+ unpack : * Unpack ,
1037
1041
uri_path : []const u8 ,
1038
- tmp_directory : Cache.Directory ,
1039
- ) RunError ! Unpack.Errors {
1042
+ ) RunError ! void {
1040
1043
const eb = & f .error_bundle ;
1041
1044
const file_type = switch (resource .* ) {
1042
1045
.file = > FileType .fromPath (uri_path ) orelse
@@ -1097,18 +1100,22 @@ fn unpackResource(
1097
1100
1098
1101
.git = > .git_pack ,
1099
1102
1100
- .dir = > | dir | return try f .recursiveDirectoryCopy (dir , tmp_directory .handle , uri_path ),
1103
+ .dir = > | dir | return unpack .directory (dir ) catch | err | return f .failMsg (
1104
+ err ,
1105
+ "unable to copy directory '{s}': {s}" ,
1106
+ .{ uri_path , @errorName (err ) },
1107
+ ),
1101
1108
};
1102
1109
1103
- return switch (file_type ) {
1104
- .tar = > try unpackTarball ( f , tmp_directory . handle , resource .reader ()),
1105
- .@"tar.gz" = > brk : {
1110
+ switch (file_type ) {
1111
+ .tar = > unpack . tarball ( resource .reader ()) catch | err | return f . unpackTarballError ( err ),
1112
+ .@"tar.gz" = > {
1106
1113
const reader = resource .reader ();
1107
1114
var br = std .io .bufferedReaderSize (std .crypto .tls .max_ciphertext_record_len , reader );
1108
1115
var dcp = std .compress .gzip .decompressor (br .reader ());
1109
- break : brk try unpackTarball ( f , tmp_directory . handle , dcp .reader ());
1116
+ unpack . tarball ( dcp .reader ()) catch | err | return f . unpackTarballError ( err );
1110
1117
},
1111
- .@"tar.xz" = > brk : {
1118
+ .@"tar.xz" = > {
1112
1119
const gpa = f .arena .child_allocator ;
1113
1120
const reader = resource .reader ();
1114
1121
var br = std .io .bufferedReaderSize (std .crypto .tls .max_ciphertext_record_len , reader );
@@ -1119,55 +1126,32 @@ fn unpackResource(
1119
1126
));
1120
1127
};
1121
1128
defer dcp .deinit ();
1122
- break : brk try unpackTarball ( f , tmp_directory . handle , dcp .reader ());
1129
+ unpack . tarball ( dcp .reader ()) catch | err | return f . unpackTarballError ( err );
1123
1130
},
1124
- .@"tar.zst" = > brk : {
1131
+ .@"tar.zst" = > {
1125
1132
const window_size = std .compress .zstd .DecompressorOptions .default_window_buffer_len ;
1126
1133
const window_buffer = try f .arena .allocator ().create ([window_size ]u8 );
1127
1134
const reader = resource .reader ();
1128
1135
var br = std .io .bufferedReaderSize (std .crypto .tls .max_ciphertext_record_len , reader );
1129
1136
var dcp = std .compress .zstd .decompressor (br .reader (), .{
1130
1137
.window_buffer = window_buffer ,
1131
1138
});
1132
- break : brk try unpackTarball ( f , tmp_directory . handle , dcp .reader ());
1139
+ unpack . tarball ( dcp .reader ()) catch | err | return f . unpackTarballError ( err );
1133
1140
},
1134
- .git_pack = > try unpackGitPack (f , tmp_directory .handle , resource ),
1135
- };
1136
- }
1137
-
1138
- const Unpack = @import ("Unpack.zig" );
1139
-
1140
- fn unpackTarball (f : * Fetch , out_dir : fs.Dir , reader : anytype ) RunError ! Unpack.Errors {
1141
- var unpack = Unpack .init (f .arena .child_allocator , out_dir );
1142
- unpack .tarball (reader ) catch | err | return f .failMsg (
1143
- err ,
1144
- "unable to unpack tarball to temporary directory: {s}" ,
1145
- .{@errorName (err )},
1146
- );
1147
- return unpack .errors ;
1148
- }
1149
-
1150
- fn unpackGitPack (f : * Fetch , out_dir : fs.Dir , resource : * Resource ) RunError ! Unpack.Errors {
1151
- var unpack = Unpack .init (f .arena .child_allocator , out_dir );
1152
-
1153
- const want_oid = resource .git .want_oid ;
1154
- const reader = resource .git .fetch_stream .reader ();
1155
- unpack .gitPack (want_oid , reader ) catch | err | return f .failMsg (
1156
- err ,
1157
- "unable to unpack git files: {s}" ,
1158
- .{@errorName (err )},
1159
- );
1160
- return unpack .errors ;
1141
+ .git_pack = > {
1142
+ const want_oid = resource .git .want_oid ;
1143
+ const reader = resource .git .fetch_stream .reader ();
1144
+ unpack .gitPack (want_oid , reader ) catch | err | return f .failMsg (
1145
+ err ,
1146
+ "unable to unpack git files: {s}" ,
1147
+ .{@errorName (err )},
1148
+ );
1149
+ },
1150
+ }
1161
1151
}
1162
1152
1163
- fn recursiveDirectoryCopy (f : * Fetch , dir : fs.Dir , out_dir : fs.Dir , uri_path : []const u8 ) RunError ! Unpack.Errors {
1164
- var unpack = Unpack .init (f .arena .child_allocator , out_dir );
1165
- unpack .directory (dir ) catch | err | return f .failMsg (
1166
- err ,
1167
- "unable to copy directory '{s}': {s}" ,
1168
- .{ uri_path , @errorName (err ) },
1169
- );
1170
- return unpack .errors ;
1153
+ fn unpackTarballError (f : * Fetch , err : anyerror ) RunError {
1154
+ return f .failMsg (err , "unable to unpack tarball to temporary directory: {s}" , .{@errorName (err )});
1171
1155
}
1172
1156
1173
1157
fn failMsg (f : * Fetch , err : anyerror , comptime fmt : []const u8 , args : anytype ) RunError {
@@ -1178,11 +1162,13 @@ fn failMsg(f: *Fetch, err: anyerror, comptime fmt: []const u8, args: anytype) Ru
1178
1162
}
1179
1163
}
1180
1164
1181
- fn emitUnpackErrors (f : * Fetch , errors : * Unpack.Errors ) RunError ! void {
1182
- if (errors . count () == 0 ) return ;
1165
+ fn bundleUnpackErrors (f : * Fetch , unpack : * Unpack ) RunError ! void {
1166
+ if (! unpack . hasErrors () ) return ;
1183
1167
1168
+ var errors = unpack .errors ;
1184
1169
const eb = & f .error_bundle ;
1185
1170
const notes_len : u32 = @intCast (errors .count ());
1171
+
1186
1172
try eb .addRootErrorMessage (.{
1187
1173
.msg = try eb .addString ("unable to unpack" ),
1188
1174
.src_loc = try f .srcLoc (f .location_tok ),
@@ -1597,8 +1583,10 @@ const git = @import("Fetch/git.zig");
1597
1583
const Package = @import ("../Package.zig" );
1598
1584
const Manifest = Package .Manifest ;
1599
1585
const ErrorBundle = std .zig .ErrorBundle ;
1586
+ const Unpack = @import ("Unpack.zig" );
1600
1587
1601
1588
test {
1602
1589
_ = Filter ;
1603
1590
_ = FileType ;
1591
+ _ = Unpack ;
1604
1592
}
0 commit comments