Skip to content

Commit 12cb71b

Browse files
committed
package: filter unpack errors for excluded files
Before this any unpack error will be raised after the unpack step. Now this is postponed until we get manifest, and if then use included folders from manifest to filter errors which are not for the files from included folders. I made a folder which has symlinks and file names with same names in different casing. ``` sample ├── build.zig ├── build.zig.zon ├── dir1 │   └── dir2 │   └── dir3 │   ├── file1 │   ├── file2 │   └── file3 ├── dir4 │   └── dir5 │   └── dir6 │   ├── file1 -> ../../../dir1/dir2/dir3/file1 │   └── file2_symlink -> ../../../dir1/dir2/dir3/file2 ├── dir7 │   └── dir8 │   └── dir9 │   ├── file4 │   └── File4 └── src ├── main.zig └── root.zig ``` Then pack this into sample.tar and another one sample_src.tar where build.zig.zon has only src in paths (excluded all problematic folders): ```Zig .paths = .{ "src", }, ``` On Linux both tars get unpacked. On Windows and macOS both fail before this changes and second succeds after this change. Windows (with disabled symlinks): ``` C:\Users\ianic\code\zig-bin\zig.exe build --global-cache-dir zig-global-cache-release C:\Users\ianic\code\issues\fetch\build.zig.zon:78:20: error: unable to unpack tarball .url = "http://10.211.55.26:8000/sample.tar", ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ note: unable to create file 'dir7/dir8/dir9/file4': PathAlreadyExists note: unable to create symlink from 'dir4/dir5/dir6/file1' to '../../../dir1/dir2/dir3/file1': AccessDenied note: unable to create symlink from 'dir4/dir5/dir6/file2_symlink' to '../../../dir1/dir2/dir3/file2': AccessDenied C:\Users\ianic\code\issues\fetch\build.zig.zon:85:20: error: unable to unpack tarball .url = "http://10.211.55.26:8000/sample_src.tar", ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ note: unable to create file 'dir7/dir8/dir9/file4': PathAlreadyExists note: unable to create symlink from 'dir4/dir5/dir6/file1' to '../../../dir1/dir2/dir3/file1': AccessDenied note: unable to create symlink from 'dir4/dir5/dir6/file2_symlink' to '../../../dir1/dir2/dir3/file2': AccessDenied PS C:\Users\ianic\code\issues\fetch> C:\Users\ianic\code\zig-bin\bin\zig.exe build --global-cache-dir zig-global-cache-release C:\Users\ianic\code\zig-io\build\stage3\bin\zig.exe build --global-cache-dir zig-global-cache-master C:\Users\ianic\code\issues\fetch\build.zig.zon:78:20: error: unable to unpack .url = "http://10.211.55.26:8000/sample.tar", ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ note: unable to create file 'dir7/dir8/dir9/file4': PathAlreadyExists note: unable to create symlink from 'dir4/dir5/dir6/file1' to '../../../dir1/dir2/dir3/file1': AccessDenied note: unable to create symlink from 'dir4/dir5/dir6/file2_symlink' to '../../../dir1/dir2/dir3/file2': AccessDenied ``` macOS ``` Fetch Packages [45/40] /Users/ianic/code/zig/issues/fetch/build.zig.zon:75:20: error: unable to unpack tarball .url = "file:///Users/ianic/code/zig/issues/fetch/sample.tar", ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ note: unable to create file 'dir7/dir8/dir9/file4': PathAlreadyExists /Users/ianic/code/zig/issues/fetch/build.zig.zon:80:20: error: unable to unpack tarball .url = "file:///Users/ianic/code/zig/issues/fetch/sample_src.tar", ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Fetch Packages [41/40] /Users/ianic/code/zig/issues/fetch/build.zig.zon:75:20: error: unable to unpack .url = "file:///Users/ianic/code/zig/issues/fetch/sample.tar", ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ note: unable to create file 'dir7/dir8/dir9/file4': PathAlreadyExists ```
1 parent d9f5100 commit 12cb71b

File tree

1 file changed

+24
-23
lines changed

1 file changed

+24
-23
lines changed

src/Package/Fetch.zig

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,8 @@ fn runResource(
461461
};
462462
defer tmp_directory.handle.close();
463463

464-
try unpackResource(f, resource, uri_path, tmp_directory);
464+
var errors = try unpackResource(f, resource, uri_path, tmp_directory);
465+
defer errors.deinit();
465466

466467
// Load, parse, and validate the unpacked build.zig.zon file. It is allowed
467468
// for the file to be missing, in which case this fetched package is
@@ -479,6 +480,9 @@ fn runResource(
479480
.include_paths = if (f.manifest) |m| m.paths else .{},
480481
};
481482

483+
try errors.remove(filter);
484+
try f.emitUnpackErrors(&errors);
485+
482486
// Compute the package hash based on the remaining files in the temporary
483487
// directory.
484488

@@ -1032,7 +1036,7 @@ fn unpackResource(
10321036
resource: *Resource,
10331037
uri_path: []const u8,
10341038
tmp_directory: Cache.Directory,
1035-
) RunError!void {
1039+
) RunError!Unpack.Errors {
10361040
const eb = &f.error_bundle;
10371041
const file_type = switch (resource.*) {
10381042
.file => FileType.fromPath(uri_path) orelse
@@ -1096,15 +1100,15 @@ fn unpackResource(
10961100
.dir => |dir| return try f.recursiveDirectoryCopy(dir, tmp_directory.handle, uri_path),
10971101
};
10981102

1099-
switch (file_type) {
1103+
return switch (file_type) {
11001104
.tar => try unpackTarball(f, tmp_directory.handle, resource.reader()),
1101-
.@"tar.gz" => {
1105+
.@"tar.gz" => brk: {
11021106
const reader = resource.reader();
11031107
var br = std.io.bufferedReaderSize(std.crypto.tls.max_ciphertext_record_len, reader);
11041108
var dcp = std.compress.gzip.decompressor(br.reader());
1105-
try unpackTarball(f, tmp_directory.handle, dcp.reader());
1109+
break :brk try unpackTarball(f, tmp_directory.handle, dcp.reader());
11061110
},
1107-
.@"tar.xz" => {
1111+
.@"tar.xz" => brk: {
11081112
const gpa = f.arena.child_allocator;
11091113
const reader = resource.reader();
11101114
var br = std.io.bufferedReaderSize(std.crypto.tls.max_ciphertext_record_len, reader);
@@ -1115,38 +1119,36 @@ fn unpackResource(
11151119
));
11161120
};
11171121
defer dcp.deinit();
1118-
try unpackTarball(f, tmp_directory.handle, dcp.reader());
1122+
break :brk try unpackTarball(f, tmp_directory.handle, dcp.reader());
11191123
},
1120-
.@"tar.zst" => {
1124+
.@"tar.zst" => brk: {
11211125
const window_size = std.compress.zstd.DecompressorOptions.default_window_buffer_len;
11221126
const window_buffer = try f.arena.allocator().create([window_size]u8);
11231127
const reader = resource.reader();
11241128
var br = std.io.bufferedReaderSize(std.crypto.tls.max_ciphertext_record_len, reader);
11251129
var dcp = std.compress.zstd.decompressor(br.reader(), .{
11261130
.window_buffer = window_buffer,
11271131
});
1128-
return unpackTarball(f, tmp_directory.handle, dcp.reader());
1132+
break :brk try unpackTarball(f, tmp_directory.handle, dcp.reader());
11291133
},
11301134
.git_pack => try unpackGitPack(f, tmp_directory.handle, resource),
1131-
}
1135+
};
11321136
}
11331137

11341138
const Unpack = @import("Unpack.zig");
11351139

1136-
fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!void {
1140+
fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!Unpack.Errors {
11371141
var unpack = Unpack.init(f.arena.child_allocator, out_dir);
1138-
defer unpack.deinit();
11391142
unpack.tarball(reader) catch |err| return f.failMsg(
11401143
err,
11411144
"unable to unpack tarball to temporary directory: {s}",
11421145
.{@errorName(err)},
11431146
);
1144-
try f.checkUnpackErrors(&unpack);
1147+
return unpack.errors;
11451148
}
11461149

1147-
fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource) RunError!void {
1150+
fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource) RunError!Unpack.Errors {
11481151
var unpack = Unpack.init(f.arena.child_allocator, out_dir);
1149-
defer unpack.deinit();
11501152

11511153
const want_oid = resource.git.want_oid;
11521154
const reader = resource.git.fetch_stream.reader();
@@ -1155,18 +1157,17 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource) RunError!void
11551157
"unable to unpack git files: {s}",
11561158
.{@errorName(err)},
11571159
);
1158-
try f.checkUnpackErrors(&unpack);
1160+
return unpack.errors;
11591161
}
11601162

1161-
fn recursiveDirectoryCopy(f: *Fetch, dir: fs.Dir, out_dir: fs.Dir, uri_path: []const u8) RunError!void {
1163+
fn recursiveDirectoryCopy(f: *Fetch, dir: fs.Dir, out_dir: fs.Dir, uri_path: []const u8) RunError!Unpack.Errors {
11621164
var unpack = Unpack.init(f.arena.child_allocator, out_dir);
1163-
defer unpack.deinit();
11641165
unpack.directory(dir) catch |err| return f.failMsg(
11651166
err,
11661167
"unable to copy directory '{s}': {s}",
11671168
.{ uri_path, @errorName(err) },
11681169
);
1169-
try f.checkUnpackErrors(&unpack);
1170+
return unpack.errors;
11701171
}
11711172

11721173
fn failMsg(f: *Fetch, err: anyerror, comptime fmt: []const u8, args: anytype) RunError {
@@ -1177,18 +1178,18 @@ fn failMsg(f: *Fetch, err: anyerror, comptime fmt: []const u8, args: anytype) Ru
11771178
}
11781179
}
11791180

1180-
fn checkUnpackErrors(f: *Fetch, unpack: *Unpack) RunError!void {
1181-
if (!unpack.hasErrors()) return;
1181+
fn emitUnpackErrors(f: *Fetch, errors: *Unpack.Errors) RunError!void {
1182+
if (errors.count() == 0) return;
11821183

11831184
const eb = &f.error_bundle;
1184-
const notes_len: u32 = @intCast(unpack.errors.items.len);
1185+
const notes_len: u32 = @intCast(errors.count());
11851186
try eb.addRootErrorMessage(.{
11861187
.msg = try eb.addString("unable to unpack"),
11871188
.src_loc = try f.srcLoc(f.location_tok),
11881189
.notes_len = notes_len,
11891190
});
11901191
const notes_start = try eb.reserveNotes(notes_len);
1191-
for (unpack.errors.items, notes_start..) |item, note_i| {
1192+
for (errors.list.items, notes_start..) |item, note_i| {
11921193
switch (item) {
11931194
.unable_to_create_sym_link => |info| {
11941195
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{

0 commit comments

Comments
 (0)