authorgravatar for igor.anic@gmail.comIgor Anić <igor.anic@gmail.com> 2024-03-28 21:06:26+01:00
committergravatar for igor.anic@gmail.comIgor Anić <igor.anic@gmail.com> 2024-04-09 15:00:21+02:00
loga0790914b4e0123e36432e2c0bcbf2a517fc410a
tree19abc7616d7a948ff6913f984cb946a2ad3070f4
parentb3339f3cd5b1eeb3419ee136e378dc3e348e6a83

fetch: return UnpackResult from unpackResource

Test that we are still outputing same errors.

1 files changed, 42 insertions(+), 38 deletions(-)

src/Package/Fetch.zig+42-38
......@@ -461,13 +461,16 @@ fn runResource(
461461 };
462462 defer tmp_directory.handle.close();
463463
464 // Unpack resource into tmp_directory. A non-null return value means
465 // that the package contents are inside a `pkg_dir` sub-directory.
466 const pkg_dir = try unpackResource(f, resource, uri_path, tmp_directory);
464 var unpack_result = try unpackResource(f, resource, uri_path, tmp_directory);
465 defer unpack_result.deinit();
466 if (unpack_result.hasErrors()) {
467 try unpack_result.bundleErrors(eb, try f.srcLoc(f.location_tok));
468 return error.FetchFailed;
469 }
467470
468471 var pkg_path: Cache.Path = .{
469472 .root_dir = tmp_directory,
470 .sub_path = if (pkg_dir) |pkg_dir_name| pkg_dir_name else "",
473 .sub_path = if (unpack_result.root_dir) |root_dir| root_dir else "",
471474 };
472475
473476 // Apply btrfs workaround if needed. Reopen tmp_directory.
......@@ -500,8 +503,8 @@ fn runResource(
500503 // directory.
501504 f.actual_hash = try computeHash(f, pkg_path, filter);
502505
503 break :blk if (pkg_dir) |pkg_dir_name|
504 try fs.path.join(arena, &.{ tmp_dir_sub_path, pkg_dir_name })
506 break :blk if (unpack_result.root_dir) |root_dir|
507 try fs.path.join(arena, &.{ tmp_dir_sub_path, root_dir })
505508 else
506509 tmp_dir_sub_path;
507510 };
......@@ -1053,7 +1056,7 @@ fn unpackResource(
10531056 resource: *Resource,
10541057 uri_path: []const u8,
10551058 tmp_directory: Cache.Directory,
1056) RunError!?[]const u8 {
1059) RunError!UnpackResult {
10571060 const eb = &f.error_bundle;
10581061 const file_type = switch (resource.*) {
10591062 .file => FileType.fromPath(uri_path) orelse
......@@ -1121,7 +1124,8 @@ fn unpackResource(
11211124 .{ uri_path, @errorName(err) },
11221125 ));
11231126 };
1124 return null;
1127 const gpa = f.arena.child_allocator;
1128 return UnpackResult.init(gpa);
11251129 },
11261130 };
11271131
......@@ -1156,23 +1160,19 @@ fn unpackResource(
11561160 });
11571161 return try unpackTarball(f, tmp_directory.handle, dcp.reader());
11581162 },
1159 .git_pack => {
1160 unpackGitPack(f, tmp_directory.handle, resource) catch |err| switch (err) {
1161 error.FetchFailed => return error.FetchFailed,
1162 error.OutOfMemory => return error.OutOfMemory,
1163 else => |e| return f.fail(f.location_tok, try eb.printString(
1164 "unable to unpack git files: {s}",
1165 .{@errorName(e)},
1166 )),
1167 };
1168 return null;
1163 .git_pack => return unpackGitPack(f, tmp_directory.handle, resource) catch |err| switch (err) {
1164 error.FetchFailed => return error.FetchFailed,
1165 error.OutOfMemory => return error.OutOfMemory,
1166 else => |e| return f.fail(f.location_tok, try eb.printString(
1167 "unable to unpack git files: {s}",
1168 .{@errorName(e)},
1169 )),
11691170 },
11701171 }
11711172}
11721173
1173fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!?[]const u8 {
1174fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackResult {
11741175 const eb = &f.error_bundle;
1175 const arena = f.arena.allocator();
11761176 const gpa = f.arena.child_allocator;
11771177
11781178 var diagnostics: std.tar.Diagnostics = .{ .allocator = gpa };
......@@ -1188,10 +1188,11 @@ fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!?[]const
11881188 .{@errorName(err)},
11891189 ));
11901190
1191 var res = UnpackResult.init(gpa);
1192 if (diagnostics.root_dir) |root_dir| {
1193 res.root_dir = try gpa.dupe(u8, root_dir);
1194 }
11911195 if (diagnostics.errors.items.len > 0) {
1192 var res = UnpackResult.init(gpa);
1193 defer res.deinit();
1194
11951196 for (diagnostics.errors.items) |item| {
11961197 switch (item) {
11971198 .unable_to_create_file => |i| try res.createFile(i.file_name, i.code),
......@@ -1199,21 +1200,17 @@ fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!?[]const
11991200 .unsupported_file_type => |i| try res.unsupportedFileType(i.file_name, @intFromEnum(i.file_type)),
12001201 }
12011202 }
1202 try res.bundleErrors(eb, "unable to unpack tarball", try f.srcLoc(f.location_tok));
1203 return error.FetchFailed;
1203 try res.rootErrorMessage("unable to unpack tarball");
12041204 }
1205
1206 return if (diagnostics.root_dir) |root_dir|
1207 return try arena.dupe(u8, root_dir)
1208 else
1209 null;
1205 return res;
12101206}
12111207
1212fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource) anyerror!void {
1213 const eb = &f.error_bundle;
1208fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource) anyerror!UnpackResult {
12141209 const gpa = f.arena.child_allocator;
12151210 const want_oid = resource.git.want_oid;
12161211 const reader = resource.git.fetch_stream.reader();
1212
1213 var res = UnpackResult.init(gpa);
12171214 // The .git directory is used to store the packfile and associated index, but
12181215 // we do not attempt to replicate the exact structure of a real .git
12191216 // directory, since that isn't relevant for fetching a package.
......@@ -1249,7 +1246,6 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource) anyerror!void
12491246 try repository.checkout(out_dir, want_oid, &diagnostics);
12501247
12511248 if (diagnostics.errors.items.len > 0) {
1252 var res = UnpackResult.init(gpa);
12531249 defer res.deinit();
12541250
12551251 for (diagnostics.errors.items) |item| {
......@@ -1257,14 +1253,13 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource) anyerror!void
12571253 .unable_to_create_sym_link => |i| try res.symLink(i.file_name, i.link_name, i.code),
12581254 }
12591255 }
1260 try res.bundleErrors(eb, "unable to unpack packfile", try f.srcLoc(f.location_tok));
1261
1262 return error.InvalidGitPack;
1256 try res.rootErrorMessage("unable to unpack packfile");
12631257 }
12641258 }
12651259 }
12661260
12671261 try out_dir.deleteTree(".git");
1262 return res;
12681263}
12691264
12701265fn recursiveDirectoryCopy(f: *Fetch, dir: fs.Dir, tmp_dir: fs.Dir) anyerror!void {
......@@ -1753,6 +1748,8 @@ test FileHeader {
17531748const UnpackResult = struct {
17541749 allocator: std.mem.Allocator,
17551750 errors: std.ArrayListUnmanaged(Error) = .{},
1751 root_error_message: []const u8 = "",
1752 root_dir: ?[]const u8 = null,
17561753
17571754 const Error = union(enum) {
17581755 unable_to_create_sym_link: struct {
......@@ -1802,6 +1799,10 @@ const UnpackResult = struct {
18021799 item.free(self.allocator);
18031800 }
18041801 self.errors.deinit(self.allocator);
1802 self.allocator.free(self.root_error_message);
1803 if (self.root_dir) |root_dir| {
1804 self.allocator.free(root_dir);
1805 }
18051806 self.* = undefined;
18061807 }
18071808
......@@ -1843,15 +1844,18 @@ const UnpackResult = struct {
18431844 }
18441845 }
18451846
1847 fn rootErrorMessage(self: *UnpackResult, msg: []const u8) !void {
1848 self.root_error_message = try self.allocator.dupe(u8, msg);
1849 }
1850
18461851 fn bundleErrors(
18471852 self: *UnpackResult,
18481853 eb: *ErrorBundle.Wip,
1849 msg: []const u8,
18501854 src_loc: ErrorBundle.SourceLocationIndex,
18511855 ) !void {
18521856 const notes_len: u32 = @intCast(self.errors.items.len);
18531857 try eb.addRootErrorMessage(.{
1854 .msg = try eb.addString(msg),
1858 .msg = try eb.addString(self.root_error_message),
18551859 .src_loc = src_loc,
18561860 .notes_len = notes_len,
18571861 });