Skip to content

Commit 5a985df

Browse files
committed
package: refactor unpack errors reporting
Just refactoring to put similar code closer.
1 parent 489b102 commit 5a985df

File tree

2 files changed

+95
-83
lines changed

2 files changed

+95
-83
lines changed

src/Package/Fetch.zig

Lines changed: 70 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,12 +1093,7 @@ fn unpackResource(
10931093

10941094
.git => .git_pack,
10951095

1096-
.dir => |dir| return f.recursiveDirectoryCopy(dir, tmp_directory.handle) catch |err| {
1097-
return f.fail(f.location_tok, try eb.printString(
1098-
"unable to copy directory '{s}': {s}",
1099-
.{ uri_path, @errorName(err) },
1100-
));
1101-
},
1096+
.dir => |dir| return try f.recursiveDirectoryCopy(dir, tmp_directory.handle, uri_path),
11021097
};
11031098

11041099
switch (file_type) {
@@ -1132,64 +1127,94 @@ fn unpackResource(
11321127
});
11331128
return unpackTarball(f, tmp_directory.handle, dcp.reader());
11341129
},
1135-
.git_pack => unpackGitPack(f, tmp_directory.handle, resource) catch |err| switch (err) {
1136-
error.FetchFailed => return error.FetchFailed,
1137-
error.OutOfMemory => return error.OutOfMemory,
1138-
else => |e| return f.fail(f.location_tok, try eb.printString(
1139-
"unable to unpack git files: {s}",
1140-
.{@errorName(e)},
1141-
)),
1142-
},
1130+
.git_pack => try unpackGitPack(f, tmp_directory.handle, resource),
11431131
}
11441132
}
11451133

11461134
const Unpack = @import("Unpack.zig");
11471135

11481136
fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!void {
1149-
const eb = &f.error_bundle;
1150-
const gpa = f.arena.child_allocator;
1151-
1152-
var unpack = Unpack{ .allocator = gpa, .root = out_dir };
1137+
var unpack = Unpack.init(f.arena.child_allocator, out_dir);
11531138
defer unpack.deinit();
1154-
unpack.tarball(reader) catch |err| return f.fail(
1155-
f.location_tok,
1156-
try eb.printString(
1157-
"unable to unpack tarball to temporary directory: {s}",
1158-
.{@errorName(err)},
1159-
),
1139+
unpack.tarball(reader) catch |err| return f.failMsg(
1140+
err,
1141+
"unable to unpack tarball to temporary directory: {s}",
1142+
.{@errorName(err)},
11601143
);
1161-
if (unpack.hasErrors()) {
1162-
try unpack.bundleErrors(eb, try f.srcLoc(f.location_tok));
1163-
return error.FetchFailed;
1164-
}
1144+
try f.checkUnpackErrors(&unpack);
11651145
}
11661146

1167-
fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource) anyerror!void {
1168-
const eb = &f.error_bundle;
1169-
const gpa = f.arena.child_allocator;
1147+
fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource) RunError!void {
1148+
var unpack = Unpack.init(f.arena.child_allocator, out_dir);
1149+
defer unpack.deinit();
1150+
11701151
const want_oid = resource.git.want_oid;
11711152
const reader = resource.git.fetch_stream.reader();
1153+
unpack.gitPack(want_oid, reader) catch |err| return f.failMsg(
1154+
err,
1155+
"unable to unpack git files: {s}",
1156+
.{@errorName(err)},
1157+
);
1158+
try f.checkUnpackErrors(&unpack);
1159+
}
11721160

1173-
var unpack = Unpack{ .allocator = gpa, .root = out_dir };
1161+
fn recursiveDirectoryCopy(f: *Fetch, dir: fs.Dir, out_dir: fs.Dir, uri_path: []const u8) RunError!void {
1162+
var unpack = Unpack.init(f.arena.child_allocator, out_dir);
11741163
defer unpack.deinit();
1175-
try unpack.gitPack(want_oid, reader);
1176-
if (unpack.hasErrors()) {
1177-
try unpack.bundleErrors(eb, try f.srcLoc(f.location_tok));
1178-
return error.FetchFailed;
1179-
}
1164+
unpack.directory(dir) catch |err| return f.failMsg(
1165+
err,
1166+
"unable to copy directory '{s}': {s}",
1167+
.{ uri_path, @errorName(err) },
1168+
);
1169+
try f.checkUnpackErrors(&unpack);
11801170
}
11811171

1182-
fn recursiveDirectoryCopy(f: *Fetch, dir: fs.Dir, tmp_dir: fs.Dir) anyerror!void {
1172+
fn failMsg(f: *Fetch, err: anyerror, comptime fmt: []const u8, args: anytype) RunError {
11831173
const eb = &f.error_bundle;
1184-
const gpa = f.arena.child_allocator;
1174+
switch (err) {
1175+
error.OutOfMemory => return error.OutOfMemory,
1176+
else => return f.fail(f.location_tok, try eb.printString(fmt, args)),
1177+
}
1178+
}
11851179

1186-
var unpack = Unpack{ .allocator = gpa, .root = tmp_dir };
1187-
defer unpack.deinit();
1188-
try unpack.directory(dir);
1189-
if (unpack.hasErrors()) {
1190-
try unpack.bundleErrors(eb, try f.srcLoc(f.location_tok));
1191-
return error.FetchFailed;
1180+
fn checkUnpackErrors(f: *Fetch, unpack: *Unpack) RunError!void {
1181+
if (!unpack.hasErrors()) return;
1182+
1183+
const eb = &f.error_bundle;
1184+
const notes_len: u32 = @intCast(unpack.errors.items.len);
1185+
try eb.addRootErrorMessage(.{
1186+
.msg = try eb.addString("unable to unpack"),
1187+
.src_loc = try f.srcLoc(f.location_tok),
1188+
.notes_len = notes_len,
1189+
});
1190+
const notes_start = try eb.reserveNotes(notes_len);
1191+
for (unpack.errors.items, notes_start..) |item, note_i| {
1192+
switch (item) {
1193+
.unable_to_create_sym_link => |info| {
1194+
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
1195+
.msg = try eb.printString("unable to create symlink from '{s}' to '{s}': {s}", .{
1196+
info.sym_link_path, info.target_path, @errorName(info.code),
1197+
}),
1198+
}));
1199+
},
1200+
.unable_to_create_file => |info| {
1201+
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
1202+
.msg = try eb.printString("unable to create file '{s}': {s}", .{
1203+
info.file_name, @errorName(info.code),
1204+
}),
1205+
}));
1206+
},
1207+
.unsupported_file_type => |info| {
1208+
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
1209+
.msg = try eb.printString("file '{s}' has unsupported type '{c}'", .{
1210+
info.file_name, info.file_type,
1211+
}),
1212+
}));
1213+
},
1214+
}
11921215
}
1216+
1217+
return error.FetchFailed;
11931218
}
11941219

11951220
pub fn renameTmpIntoCache(

src/Package/Unpack.zig

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ pub const Error = union(enum) {
2424
},
2525
};
2626

27+
pub fn init(allocator: std.mem.Allocator, root: fs.Dir) Self {
28+
return .{
29+
.allocator = allocator,
30+
.root = root,
31+
};
32+
}
33+
2734
pub fn deinit(self: *Self) void {
2835
for (self.errors.items) |item| {
2936
switch (item) {
@@ -81,6 +88,21 @@ pub fn tarball(self: *Self, reader: anytype) !void {
8188
}
8289

8390
pub fn gitPack(self: *Self, commit_oid: git.Oid, reader: anytype) !void {
91+
// Same interface as std.fs.Dir.createFile, symLink
92+
const inf = struct {
93+
parent: *Self,
94+
95+
pub fn makePath(_: @This(), _: []const u8) !void {}
96+
97+
pub fn createFile(t: @This(), sub_path: []const u8, _: fs.File.CreateFlags) !fs.File {
98+
return (try t.parent.createFile(sub_path)) orelse error.Skip;
99+
}
100+
101+
pub fn symLink(t: @This(), target_path: []const u8, sym_link_path: []const u8, _: fs.Dir.SymLinkFlags) !void {
102+
try t.parent.symLink(target_path, sym_link_path);
103+
}
104+
}{ .parent = self };
105+
84106
var pack_dir = try self.root.makeOpenPath(".git", .{});
85107
defer pack_dir.close();
86108
var pack_file = try pack_dir.createFile("pkg.pack", .{ .read = true });
@@ -101,7 +123,7 @@ pub fn gitPack(self: *Self, commit_oid: git.Oid, reader: anytype) !void {
101123
{
102124
var repository = try git.Repository.init(self.allocator, pack_file, index_file);
103125
defer repository.deinit();
104-
try repository.checkout2(self, commit_oid);
126+
try repository.checkout2(inf, commit_oid);
105127
}
106128

107129
try self.root.deleteTree(".git");
@@ -130,41 +152,6 @@ pub fn hasErrors(self: *Self) bool {
130152
return self.errors.items.len > 0;
131153
}
132154

133-
pub fn bundleErrors(self: *Self, eb: *ErrorBundle.Wip, src_loc: ErrorBundle.SourceLocationIndex) !void {
134-
const notes_len: u32 = @intCast(self.errors.items.len);
135-
try eb.addRootErrorMessage(.{
136-
.msg = try eb.addString("unable to unpack"),
137-
.src_loc = src_loc,
138-
.notes_len = notes_len,
139-
});
140-
const notes_start = try eb.reserveNotes(notes_len);
141-
for (self.errors.items, notes_start..) |item, note_i| {
142-
switch (item) {
143-
.unable_to_create_sym_link => |info| {
144-
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
145-
.msg = try eb.printString("unable to create symlink from '{s}' to '{s}': {s}", .{
146-
info.sym_link_path, info.target_path, @errorName(info.code),
147-
}),
148-
}));
149-
},
150-
.unable_to_create_file => |info| {
151-
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
152-
.msg = try eb.printString("unable to create file '{s}': {s}", .{
153-
info.file_name, @errorName(info.code),
154-
}),
155-
}));
156-
},
157-
.unsupported_file_type => |info| {
158-
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
159-
.msg = try eb.printString("file '{s}' has unsupported type '{c}'", .{
160-
info.file_name, info.file_type,
161-
}),
162-
}));
163-
},
164-
}
165-
}
166-
}
167-
168155
fn copyFile(source_dir: fs.Dir, source_path: []const u8, dest_dir: fs.Dir, dest_path: []const u8) !void {
169156
source_dir.copyFile(source_path, dest_dir, dest_path, .{}) catch |err| switch (err) {
170157
error.FileNotFound => {
@@ -177,7 +164,7 @@ fn copyFile(source_dir: fs.Dir, source_path: []const u8, dest_dir: fs.Dir, dest_
177164

178165
/// Returns fs.File on success, null on failure.
179166
/// Errors are collected in errors list.
180-
pub fn createFile(self: *Self, sub_path: []const u8) !?fs.File {
167+
fn createFile(self: *Self, sub_path: []const u8) !?fs.File {
181168
return createFilePath(self.root, sub_path) catch |err| {
182169
try self.errors.append(self.allocator, .{ .unable_to_create_file = .{
183170
.code = err,
@@ -187,7 +174,7 @@ pub fn createFile(self: *Self, sub_path: []const u8) !?fs.File {
187174
};
188175
}
189176

190-
pub fn symLink(self: *Self, target_path: []const u8, sym_link_path: []const u8) !void {
177+
fn symLink(self: *Self, target_path: []const u8, sym_link_path: []const u8) !void {
191178
symLinkPath(self.root, target_path, sym_link_path) catch |err| {
192179
try self.errors.append(self.allocator, .{ .unable_to_create_sym_link = .{
193180
.code = err,

0 commit comments

Comments
 (0)