tar: store diagnostic errors into UnpackResult

Test that UnpackResult prints same error output as diagnostic.
This commit is contained in:
Igor Anić 2024-04-07 01:04:38 +02:00
parent 9e47857ae9
commit b3339f3cd5

View File

@ -1189,38 +1189,17 @@ fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!?[]const
));
if (diagnostics.errors.items.len > 0) {
const notes_len: u32 = @intCast(diagnostics.errors.items.len);
try eb.addRootErrorMessage(.{
.msg = try eb.addString("unable to unpack tarball"),
.src_loc = try f.srcLoc(f.location_tok),
.notes_len = notes_len,
});
const notes_start = try eb.reserveNotes(notes_len);
for (diagnostics.errors.items, notes_start..) |item, note_i| {
var res = UnpackResult.init(gpa);
defer res.deinit();
for (diagnostics.errors.items) |item| {
switch (item) {
.unable_to_create_sym_link => |info| {
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
.msg = try eb.printString("unable to create symlink from '{s}' to '{s}': {s}", .{
info.file_name, info.link_name, @errorName(info.code),
}),
}));
},
.unable_to_create_file => |info| {
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
.msg = try eb.printString("unable to create file '{s}': {s}", .{
info.file_name, @errorName(info.code),
}),
}));
},
.unsupported_file_type => |info| {
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
.msg = try eb.printString("file '{s}' has unsupported type '{c}'", .{
info.file_name, @intFromEnum(info.file_type),
}),
}));
},
.unable_to_create_file => |i| try res.createFile(i.file_name, i.code),
.unable_to_create_sym_link => |i| try res.symLink(i.file_name, i.link_name, i.code),
.unsupported_file_type => |i| try res.unsupportedFileType(i.file_name, @intFromEnum(i.file_type)),
}
}
try res.bundleErrors(eb, "unable to unpack tarball", try f.srcLoc(f.location_tok));
return error.FetchFailed;
}
@ -1270,24 +1249,16 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource) anyerror!void
try repository.checkout(out_dir, want_oid, &diagnostics);
if (diagnostics.errors.items.len > 0) {
const notes_len: u32 = @intCast(diagnostics.errors.items.len);
try eb.addRootErrorMessage(.{
.msg = try eb.addString("unable to unpack packfile"),
.src_loc = try f.srcLoc(f.location_tok),
.notes_len = notes_len,
});
const notes_start = try eb.reserveNotes(notes_len);
for (diagnostics.errors.items, notes_start..) |item, note_i| {
var res = UnpackResult.init(gpa);
defer res.deinit();
for (diagnostics.errors.items) |item| {
switch (item) {
.unable_to_create_sym_link => |info| {
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
.msg = try eb.printString("unable to create symlink from '{s}' to '{s}': {s}", .{
info.file_name, info.link_name, @errorName(info.code),
}),
}));
},
.unable_to_create_sym_link => |i| try res.symLink(i.file_name, i.link_name, i.code),
}
}
try res.bundleErrors(eb, "unable to unpack packfile", try f.srcLoc(f.location_tok));
return error.InvalidGitPack;
}
}
@ -1779,6 +1750,140 @@ test FileHeader {
try std.testing.expect(h.isExecutable());
}
const UnpackResult = struct {
allocator: std.mem.Allocator,
errors: std.ArrayListUnmanaged(Error) = .{},
const Error = union(enum) {
unable_to_create_sym_link: struct {
code: anyerror,
file_name: []const u8,
link_name: []const u8,
},
unable_to_create_file: struct {
code: anyerror,
file_name: []const u8,
},
unsupported_file_type: struct {
file_name: []const u8,
file_type: u8,
},
fn excluded(self: Error, filter: Filter) bool {
switch (self) {
.unable_to_create_file => |info| return !filter.includePath(info.file_name),
.unable_to_create_sym_link => |info| return !filter.includePath(info.file_name),
.unsupported_file_type => |info| return !filter.includePath(info.file_name),
}
}
fn free(self: Error, allocator: std.mem.Allocator) void {
switch (self) {
.unable_to_create_sym_link => |info| {
allocator.free(info.file_name);
allocator.free(info.link_name);
},
.unable_to_create_file => |info| {
allocator.free(info.file_name);
},
.unsupported_file_type => |info| {
allocator.free(info.file_name);
},
}
}
};
fn init(allocator: std.mem.Allocator) UnpackResult {
return .{ .allocator = allocator };
}
fn deinit(self: *UnpackResult) void {
for (self.errors.items) |item| {
item.free(self.allocator);
}
self.errors.deinit(self.allocator);
self.* = undefined;
}
fn hasErrors(self: *UnpackResult) bool {
return self.errors.items.len > 0;
}
fn createFile(self: *UnpackResult, file_name: []const u8, err: anyerror) !void {
try self.errors.append(self.allocator, .{ .unable_to_create_file = .{
.code = err,
.file_name = try self.allocator.dupe(u8, file_name),
} });
}
fn symLink(self: *UnpackResult, file_name: []const u8, link_name: []const u8, err: anyerror) !void {
try self.errors.append(self.allocator, .{ .unable_to_create_sym_link = .{
.code = err,
.file_name = try self.allocator.dupe(u8, file_name),
.link_name = try self.allocator.dupe(u8, link_name),
} });
}
fn unsupportedFileType(self: *UnpackResult, file_name: []const u8, file_type: u8) !void {
try self.errors.append(self.allocator, .{ .unsupported_file_type = .{
.file_name = try self.allocator.dupe(u8, file_name),
.file_type = file_type,
} });
}
fn filterErrors(self: *UnpackResult, filter: Filter) !void {
var i = self.errors.items.len;
while (i > 0) {
i -= 1;
const item = self.errors.items[i];
if (item.excluded(filter)) {
_ = self.errors.swapRemove(i);
item.free(self.allocator);
}
}
}
fn bundleErrors(
self: *UnpackResult,
eb: *ErrorBundle.Wip,
msg: []const u8,
src_loc: ErrorBundle.SourceLocationIndex,
) !void {
const notes_len: u32 = @intCast(self.errors.items.len);
try eb.addRootErrorMessage(.{
.msg = try eb.addString(msg),
.src_loc = src_loc,
.notes_len = notes_len,
});
const notes_start = try eb.reserveNotes(notes_len);
for (self.errors.items, notes_start..) |item, note_i| {
switch (item) {
.unable_to_create_sym_link => |info| {
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
.msg = try eb.printString("unable to create symlink from '{s}' to '{s}': {s}", .{
info.file_name, info.link_name, @errorName(info.code),
}),
}));
},
.unable_to_create_file => |info| {
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
.msg = try eb.printString("unable to create file '{s}': {s}", .{
info.file_name, @errorName(info.code),
}),
}));
},
.unsupported_file_type => |info| {
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
.msg = try eb.printString("file '{s}' has unsupported type '{c}'", .{
info.file_name, info.file_type,
}),
}));
},
}
}
}
};
// Removing dependencies
const Package = struct {
const build_zig_basename = "build.zig";