authorgravatar for igor.anic@gmail.comIgor Anić <igor.anic@gmail.com> 2024-03-30 22:43:27+01:00
committergravatar for igor.anic@gmail.comIgor Anić <igor.anic@gmail.com> 2024-04-09 15:00:21+02:00
log5a38924a7d41fee0ac5544d9ddb85ce82bc92030
tree63ad1a3f562e0ab1c2dd802aa466b853a79cf89e
parentad60b6c1edfc9ee30cf137fb1d56269e0af0941c

fetch.git: collect file create diagnostic errors

On case insensitive file systems, don't overwrite files with same name in different casing. Add diagnostic error so caller could decide what to do.

2 files changed, 18 insertions(+), 2 deletions(-)

src/Package/Fetch.zig+1
......@@ -1249,6 +1249,7 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource) anyerror!Unpac
12491249 try res.rootErrorMessage("unable to unpack packfile");
12501250 for (diagnostics.errors.items) |item| {
12511251 switch (item) {
1252 .unable_to_create_file => |i| try res.unableToCreateFile(i.file_name, i.code),
12521253 .unable_to_create_sym_link => |i| try res.unableToCreateSymLink(i.file_name, i.link_name, i.code),
12531254 }
12541255 }
src/Package/Fetch/git.zig+17-2
......@@ -46,6 +46,10 @@ pub const Diagnostics = struct {
4646 file_name: []const u8,
4747 link_name: []const u8,
4848 },
49 unable_to_create_file: struct {
50 code: anyerror,
51 file_name: []const u8,
52 },
4953 };
5054
5155 pub fn deinit(d: *Diagnostics) void {
......@@ -55,6 +59,9 @@ pub const Diagnostics = struct {
5559 d.allocator.free(info.file_name);
5660 d.allocator.free(info.link_name);
5761 },
62 .unable_to_create_file => |info| {
63 d.allocator.free(info.file_name);
64 },
5865 }
5966 }
6067 d.errors.deinit(d.allocator);
......@@ -119,11 +126,19 @@ pub const Repository = struct {
119126 try repository.checkoutTree(subdir, entry.oid, sub_path, diagnostics);
120127 },
121128 .file => {
122 var file = try dir.createFile(entry.name, .{});
123 defer file.close();
124129 try repository.odb.seekOid(entry.oid);
125130 const file_object = try repository.odb.readObject();
126131 if (file_object.type != .blob) return error.InvalidFile;
132 var file = dir.createFile(entry.name, .{ .exclusive = true }) catch |e| {
133 const file_name = try std.fs.path.join(diagnostics.allocator, &.{ current_path, entry.name });
134 errdefer diagnostics.allocator.free(file_name);
135 try diagnostics.errors.append(diagnostics.allocator, .{ .unable_to_create_file = .{
136 .code = e,
137 .file_name = file_name,
138 } });
139 continue;
140 };
141 defer file.close();
127142 try file.writeAll(file_object.data);
128143 try file.sync();
129144 },