Skip to content

Commit 438c199

Browse files
committed
pacakge.fetch: update unpack resource comments
1 parent 12cb71b commit 438c199

File tree

2 files changed

+59
-69
lines changed

2 files changed

+59
-69
lines changed

src/Package/Fetch.zig

Lines changed: 48 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ fn runResource(
435435
) RunError!void {
436436
defer resource.deinit();
437437
const arena = f.arena.allocator();
438+
const gpa = f.arena.child_allocator;
438439
const eb = &f.error_bundle;
439440
const s = fs.path.sep_str;
440441
const cache_root = f.job_queue.global_cache;
@@ -461,30 +462,32 @@ fn runResource(
461462
};
462463
defer tmp_directory.handle.close();
463464

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();
466469

467470
// Load, parse, and validate the unpacked build.zig.zon file. It is allowed
468471
// for the file to be missing, in which case this fetched package is
469472
// considered to be a "naked" package.
470473
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.
479475
const filter: Filter = .{
480476
.include_paths = if (f.manifest) |m| m.paths else .{},
481477
};
482478

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);
485485

486486
// Compute the package hash based on the remaining files in the temporary
487487
// 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`.
488491

489492
if (builtin.os.tag == .linux and f.job_queue.work_around_btrfs_bug) {
490493
// https://github.com/ziglang/zig/issues/17095
@@ -1034,9 +1037,9 @@ fn initResource(f: *Fetch, uri: std.Uri, server_header_buffer: []u8) RunError!Re
10341037
fn unpackResource(
10351038
f: *Fetch,
10361039
resource: *Resource,
1040+
unpack: *Unpack,
10371041
uri_path: []const u8,
1038-
tmp_directory: Cache.Directory,
1039-
) RunError!Unpack.Errors {
1042+
) RunError!void {
10401043
const eb = &f.error_bundle;
10411044
const file_type = switch (resource.*) {
10421045
.file => FileType.fromPath(uri_path) orelse
@@ -1097,18 +1100,22 @@ fn unpackResource(
10971100

10981101
.git => .git_pack,
10991102

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+
),
11011108
};
11021109

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" => {
11061113
const reader = resource.reader();
11071114
var br = std.io.bufferedReaderSize(std.crypto.tls.max_ciphertext_record_len, reader);
11081115
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);
11101117
},
1111-
.@"tar.xz" => brk: {
1118+
.@"tar.xz" => {
11121119
const gpa = f.arena.child_allocator;
11131120
const reader = resource.reader();
11141121
var br = std.io.bufferedReaderSize(std.crypto.tls.max_ciphertext_record_len, reader);
@@ -1119,55 +1126,32 @@ fn unpackResource(
11191126
));
11201127
};
11211128
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);
11231130
},
1124-
.@"tar.zst" => brk: {
1131+
.@"tar.zst" => {
11251132
const window_size = std.compress.zstd.DecompressorOptions.default_window_buffer_len;
11261133
const window_buffer = try f.arena.allocator().create([window_size]u8);
11271134
const reader = resource.reader();
11281135
var br = std.io.bufferedReaderSize(std.crypto.tls.max_ciphertext_record_len, reader);
11291136
var dcp = std.compress.zstd.decompressor(br.reader(), .{
11301137
.window_buffer = window_buffer,
11311138
});
1132-
break :brk try unpackTarball(f, tmp_directory.handle, dcp.reader());
1139+
unpack.tarball(dcp.reader()) catch |err| return f.unpackTarballError(err);
11331140
},
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+
}
11611151
}
11621152

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)});
11711155
}
11721156

11731157
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
11781162
}
11791163
}
11801164

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;
11831167

1168+
var errors = unpack.errors;
11841169
const eb = &f.error_bundle;
11851170
const notes_len: u32 = @intCast(errors.count());
1171+
11861172
try eb.addRootErrorMessage(.{
11871173
.msg = try eb.addString("unable to unpack"),
11881174
.src_loc = try f.srcLoc(f.location_tok),
@@ -1597,8 +1583,10 @@ const git = @import("Fetch/git.zig");
15971583
const Package = @import("../Package.zig");
15981584
const Manifest = Package.Manifest;
15991585
const ErrorBundle = std.zig.ErrorBundle;
1586+
const Unpack = @import("Unpack.zig");
16001587

16011588
test {
16021589
_ = Filter;
16031590
_ = FileType;
1591+
_ = Unpack;
16041592
}

src/Package/Unpack.zig

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const std = @import("std");
22
const fs = std.fs;
33
const git = @import("Fetch/git.zig");
4-
const ErrorBundle = std.zig.ErrorBundle;
4+
const Filter = @import("Fetch.zig").Filter;
55

66
allocator: std.mem.Allocator,
77
root: fs.Dir,
@@ -18,7 +18,7 @@ pub const Error = union(enum) {
1818
file_name: []const u8,
1919
},
2020

21-
pub fn filtered(self: Error, filter: Filter) bool {
21+
pub fn excluded(self: Error, filter: Filter) bool {
2222
switch (self) {
2323
.unable_to_create_file => |info| return !filter.includePath(info.file_name),
2424
.unable_to_create_sym_link => |info| return !filter.includePath(info.target_path),
@@ -69,12 +69,12 @@ pub const Errors = struct {
6969
} });
7070
}
7171

72-
pub fn remove(self: *Errors, filter: Filter) !void {
72+
pub fn filterWith(self: *Errors, filter: Filter) !void {
7373
var i = self.list.items.len;
7474
while (i > 0) {
7575
i -= 1;
7676
const item = self.list.items[i];
77-
if (item.filtered(filter)) {
77+
if (item.excluded(filter)) {
7878
_ = self.list.swapRemove(i);
7979
self.free(item);
8080
}
@@ -197,6 +197,10 @@ pub fn hasErrors(self: *Self) bool {
197197
return self.errors.count() > 0;
198198
}
199199

200+
pub fn filterErrors(self: *Self, filter: Filter) !void {
201+
try self.errors.filterWith(filter);
202+
}
203+
200204
fn copyFile(source_dir: fs.Dir, source_path: []const u8, dest_dir: fs.Dir, dest_path: []const u8) !void {
201205
source_dir.copyFile(source_path, dest_dir, dest_path, .{}) catch |err| switch (err) {
202206
error.FileNotFound => {
@@ -397,12 +401,12 @@ test "collect/filter errors" {
397401
defer filter.include_paths.deinit(gpa);
398402

399403
// no filter all paths are included
400-
try unpack.errors.remove(filter);
404+
try unpack.filterErrors(filter);
401405
try testing.expectEqual(2, unpack.errors.count());
402406

403407
// dir1 is included, dir excluded
404408
try filter.include_paths.put(gpa, "dir1", {});
405-
try unpack.errors.remove(filter);
409+
try unpack.filterErrors(filter);
406410
try testing.expectEqual(1, unpack.errors.count());
407411
try testing.expectEqualStrings("dir1/file1", unpack.errors.list.items[0].unable_to_create_file.file_name);
408412
}
@@ -412,13 +416,11 @@ test "collect/filter errors" {
412416

413417
// only src included that filters all error paths
414418
try filter.include_paths.put(gpa, "src", {});
415-
try unpack.errors.remove(filter);
419+
try unpack.filterErrors(filter);
416420
try testing.expectEqual(0, unpack.errors.count());
417421
}
418422
}
419423

420-
const Filter = @import("Fetch.zig").Filter;
421-
422424
fn createTarball(paths: []const []const u8, buf: []u8) !void {
423425
var fbs = std.io.fixedBufferStream(buf);
424426
const writer = fbs.writer();

0 commit comments

Comments
 (0)