| ... | @@ -1189,38 +1189,17 @@ fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!?[]const | ... | @@ -1189,38 +1189,17 @@ fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!?[]const |
| 1189 | )); | 1189 | )); |
| 1190 | | 1190 | |
| 1191 | if (diagnostics.errors.items.len > 0) { | 1191 | if (diagnostics.errors.items.len > 0) { |
| 1192 | const notes_len: u32 = @intCast(diagnostics.errors.items.len); | 1192 | var res = UnpackResult.init(gpa); |
| 1193 | try eb.addRootErrorMessage(.{ | 1193 | defer res.deinit(); |
| 1194 | .msg = try eb.addString("unable to unpack tarball"), | 1194 | |
| 1195 | .src_loc = try f.srcLoc(f.location_tok), | 1195 | for (diagnostics.errors.items) |item| { |
| 1196 | .notes_len = notes_len, | | |
| 1197 | }); | | |
| 1198 | const notes_start = try eb.reserveNotes(notes_len); | | |
| 1199 | for (diagnostics.errors.items, notes_start..) |item, note_i| { | | |
| 1200 | switch (item) { | 1196 | switch (item) { |
| 1201 | .unable_to_create_sym_link => |info| { | 1197 | .unable_to_create_file => |i| try res.createFile(i.file_name, i.code), |
| 1202 | eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{ | 1198 | .unable_to_create_sym_link => |i| try res.symLink(i.file_name, i.link_name, i.code), |
| 1203 | .msg = try eb.printString("unable to create symlink from '{s}' to '{s}': {s}", .{ | 1199 | .unsupported_file_type => |i| try res.unsupportedFileType(i.file_name, @intFromEnum(i.file_type)), |
| 1204 | info.file_name, info.link_name, @errorName(info.code), | | |
| 1205 | }), | | |
| 1206 | })); | | |
| 1207 | }, | | |
| 1208 | .unable_to_create_file => |info| { | | |
| 1209 | eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{ | | |
| 1210 | .msg = try eb.printString("unable to create file '{s}': {s}", .{ | | |
| 1211 | info.file_name, @errorName(info.code), | | |
| 1212 | }), | | |
| 1213 | })); | | |
| 1214 | }, | | |
| 1215 | .unsupported_file_type => |info| { | | |
| 1216 | eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{ | | |
| 1217 | .msg = try eb.printString("file '{s}' has unsupported type '{c}'", .{ | | |
| 1218 | info.file_name, @intFromEnum(info.file_type), | | |
| 1219 | }), | | |
| 1220 | })); | | |
| 1221 | }, | | |
| 1222 | } | 1200 | } |
| 1223 | } | 1201 | } |
| | 1202 | try res.bundleErrors(eb, "unable to unpack tarball", try f.srcLoc(f.location_tok)); |
| 1224 | return error.FetchFailed; | 1203 | return error.FetchFailed; |
| 1225 | } | 1204 | } |
| 1226 | | 1205 | |
| ... | @@ -1270,24 +1249,16 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource) anyerror!void | ... | @@ -1270,24 +1249,16 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource) anyerror!void |
| 1270 | try repository.checkout(out_dir, want_oid, &diagnostics); | 1249 | try repository.checkout(out_dir, want_oid, &diagnostics); |
| 1271 | | 1250 | |
| 1272 | if (diagnostics.errors.items.len > 0) { | 1251 | if (diagnostics.errors.items.len > 0) { |
| 1273 | const notes_len: u32 = @intCast(diagnostics.errors.items.len); | 1252 | var res = UnpackResult.init(gpa); |
| 1274 | try eb.addRootErrorMessage(.{ | 1253 | defer res.deinit(); |
| 1275 | .msg = try eb.addString("unable to unpack packfile"), | 1254 | |
| 1276 | .src_loc = try f.srcLoc(f.location_tok), | 1255 | for (diagnostics.errors.items) |item| { |
| 1277 | .notes_len = notes_len, | | |
| 1278 | }); | | |
| 1279 | const notes_start = try eb.reserveNotes(notes_len); | | |
| 1280 | for (diagnostics.errors.items, notes_start..) |item, note_i| { | | |
| 1281 | switch (item) { | 1256 | switch (item) { |
| 1282 | .unable_to_create_sym_link => |info| { | 1257 | .unable_to_create_sym_link => |i| try res.symLink(i.file_name, i.link_name, i.code), |
| 1283 | eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{ | | |
| 1284 | .msg = try eb.printString("unable to create symlink from '{s}' to '{s}': {s}", .{ | | |
| 1285 | info.file_name, info.link_name, @errorName(info.code), | | |
| 1286 | }), | | |
| 1287 | })); | | |
| 1288 | }, | | |
| 1289 | } | 1258 | } |
| 1290 | } | 1259 | } |
| | 1260 | try res.bundleErrors(eb, "unable to unpack packfile", try f.srcLoc(f.location_tok)); |
| | 1261 | |
| 1291 | return error.InvalidGitPack; | 1262 | return error.InvalidGitPack; |
| 1292 | } | 1263 | } |
| 1293 | } | 1264 | } |
| ... | @@ -1779,6 +1750,140 @@ test FileHeader { | ... | @@ -1779,6 +1750,140 @@ test FileHeader { |
| 1779 | try std.testing.expect(h.isExecutable()); | 1750 | try std.testing.expect(h.isExecutable()); |
| 1780 | } | 1751 | } |
| 1781 | | 1752 | |
| | 1753 | const UnpackResult = struct { |
| | 1754 | allocator: std.mem.Allocator, |
| | 1755 | errors: std.ArrayListUnmanaged(Error) = .{}, |
| | 1756 | |
| | 1757 | const Error = union(enum) { |
| | 1758 | unable_to_create_sym_link: struct { |
| | 1759 | code: anyerror, |
| | 1760 | file_name: []const u8, |
| | 1761 | link_name: []const u8, |
| | 1762 | }, |
| | 1763 | unable_to_create_file: struct { |
| | 1764 | code: anyerror, |
| | 1765 | file_name: []const u8, |
| | 1766 | }, |
| | 1767 | unsupported_file_type: struct { |
| | 1768 | file_name: []const u8, |
| | 1769 | file_type: u8, |
| | 1770 | }, |
| | 1771 | |
| | 1772 | fn excluded(self: Error, filter: Filter) bool { |
| | 1773 | switch (self) { |
| | 1774 | .unable_to_create_file => |info| return !filter.includePath(info.file_name), |
| | 1775 | .unable_to_create_sym_link => |info| return !filter.includePath(info.file_name), |
| | 1776 | .unsupported_file_type => |info| return !filter.includePath(info.file_name), |
| | 1777 | } |
| | 1778 | } |
| | 1779 | |
| | 1780 | fn free(self: Error, allocator: std.mem.Allocator) void { |
| | 1781 | switch (self) { |
| | 1782 | .unable_to_create_sym_link => |info| { |
| | 1783 | allocator.free(info.file_name); |
| | 1784 | allocator.free(info.link_name); |
| | 1785 | }, |
| | 1786 | .unable_to_create_file => |info| { |
| | 1787 | allocator.free(info.file_name); |
| | 1788 | }, |
| | 1789 | .unsupported_file_type => |info| { |
| | 1790 | allocator.free(info.file_name); |
| | 1791 | }, |
| | 1792 | } |
| | 1793 | } |
| | 1794 | }; |
| | 1795 | |
| | 1796 | fn init(allocator: std.mem.Allocator) UnpackResult { |
| | 1797 | return .{ .allocator = allocator }; |
| | 1798 | } |
| | 1799 | |
| | 1800 | fn deinit(self: *UnpackResult) void { |
| | 1801 | for (self.errors.items) |item| { |
| | 1802 | item.free(self.allocator); |
| | 1803 | } |
| | 1804 | self.errors.deinit(self.allocator); |
| | 1805 | self.* = undefined; |
| | 1806 | } |
| | 1807 | |
| | 1808 | fn hasErrors(self: *UnpackResult) bool { |
| | 1809 | return self.errors.items.len > 0; |
| | 1810 | } |
| | 1811 | |
| | 1812 | fn createFile(self: *UnpackResult, file_name: []const u8, err: anyerror) !void { |
| | 1813 | try self.errors.append(self.allocator, .{ .unable_to_create_file = .{ |
| | 1814 | .code = err, |
| | 1815 | .file_name = try self.allocator.dupe(u8, file_name), |
| | 1816 | } }); |
| | 1817 | } |
| | 1818 | |
| | 1819 | fn symLink(self: *UnpackResult, file_name: []const u8, link_name: []const u8, err: anyerror) !void { |
| | 1820 | try self.errors.append(self.allocator, .{ .unable_to_create_sym_link = .{ |
| | 1821 | .code = err, |
| | 1822 | .file_name = try self.allocator.dupe(u8, file_name), |
| | 1823 | .link_name = try self.allocator.dupe(u8, link_name), |
| | 1824 | } }); |
| | 1825 | } |
| | 1826 | |
| | 1827 | fn unsupportedFileType(self: *UnpackResult, file_name: []const u8, file_type: u8) !void { |
| | 1828 | try self.errors.append(self.allocator, .{ .unsupported_file_type = .{ |
| | 1829 | .file_name = try self.allocator.dupe(u8, file_name), |
| | 1830 | .file_type = file_type, |
| | 1831 | } }); |
| | 1832 | } |
| | 1833 | |
| | 1834 | fn filterErrors(self: *UnpackResult, filter: Filter) !void { |
| | 1835 | var i = self.errors.items.len; |
| | 1836 | while (i > 0) { |
| | 1837 | i -= 1; |
| | 1838 | const item = self.errors.items[i]; |
| | 1839 | if (item.excluded(filter)) { |
| | 1840 | _ = self.errors.swapRemove(i); |
| | 1841 | item.free(self.allocator); |
| | 1842 | } |
| | 1843 | } |
| | 1844 | } |
| | 1845 | |
| | 1846 | fn bundleErrors( |
| | 1847 | self: *UnpackResult, |
| | 1848 | eb: *ErrorBundle.Wip, |
| | 1849 | msg: []const u8, |
| | 1850 | src_loc: ErrorBundle.SourceLocationIndex, |
| | 1851 | ) !void { |
| | 1852 | const notes_len: u32 = @intCast(self.errors.items.len); |
| | 1853 | try eb.addRootErrorMessage(.{ |
| | 1854 | .msg = try eb.addString(msg), |
| | 1855 | .src_loc = src_loc, |
| | 1856 | .notes_len = notes_len, |
| | 1857 | }); |
| | 1858 | const notes_start = try eb.reserveNotes(notes_len); |
| | 1859 | for (self.errors.items, notes_start..) |item, note_i| { |
| | 1860 | switch (item) { |
| | 1861 | .unable_to_create_sym_link => |info| { |
| | 1862 | eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{ |
| | 1863 | .msg = try eb.printString("unable to create symlink from '{s}' to '{s}': {s}", .{ |
| | 1864 | info.file_name, info.link_name, @errorName(info.code), |
| | 1865 | }), |
| | 1866 | })); |
| | 1867 | }, |
| | 1868 | .unable_to_create_file => |info| { |
| | 1869 | eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{ |
| | 1870 | .msg = try eb.printString("unable to create file '{s}': {s}", .{ |
| | 1871 | info.file_name, @errorName(info.code), |
| | 1872 | }), |
| | 1873 | })); |
| | 1874 | }, |
| | 1875 | .unsupported_file_type => |info| { |
| | 1876 | eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{ |
| | 1877 | .msg = try eb.printString("file '{s}' has unsupported type '{c}'", .{ |
| | 1878 | info.file_name, info.file_type, |
| | 1879 | }), |
| | 1880 | })); |
| | 1881 | }, |
| | 1882 | } |
| | 1883 | } |
| | 1884 | } |
| | 1885 | }; |
| | 1886 | |
| 1782 | // Removing dependencies | 1887 | // Removing dependencies |
| 1783 | const Package = struct { | 1888 | const Package = struct { |
| 1784 | const build_zig_basename = "build.zig"; | 1889 | const build_zig_basename = "build.zig"; |