| author | |
| committer | |
| log | 21181181bf1060d5e55738651c109d7c47647633 |
| tree | ee868ceb21ddb959808b7619e0597b3f546ca1ae |
| parent | ef9966c9855dd855afda767f212abec6e5a36307 |
* Package: use std.tar diagnostics to give detailed error messages
* std.tar: add diagnostic for unsupported file type4 files changed, 148 insertions(+), 55 deletions(-)
lib/std/tar.zig+24-12| ... | ... | @@ -29,6 +29,10 @@ pub const Options = struct { |
| 29 | 29 | file_name: []const u8, |
| 30 | 30 | link_name: []const u8, |
| 31 | 31 | }, |
| 32 | unsupported_file_type: struct { | |
| 33 | file_name: []const u8, | |
| 34 | file_type: Header.FileType, | |
| 35 | }, | |
| 32 | 36 | }; |
| 33 | 37 | |
| 34 | 38 | pub fn deinit(d: *Diagnostics) void { |
| ... | ... | @@ -38,6 +42,9 @@ pub const Options = struct { |
| 38 | 42 | d.allocator.free(info.file_name); |
| 39 | 43 | d.allocator.free(info.link_name); |
| 40 | 44 | }, |
| 45 | .unsupported_file_type => |info| { | |
| 46 | d.allocator.free(info.file_name); | |
| 47 | }, | |
| 41 | 48 | } |
| 42 | 49 | } |
| 43 | 50 | d.errors.deinit(d.allocator); |
| ... | ... | @@ -50,6 +57,7 @@ pub const Header = struct { |
| 50 | 57 | bytes: *const [512]u8, |
| 51 | 58 | |
| 52 | 59 | pub const FileType = enum(u8) { |
| 60 | normal_alias = 0, | |
| 53 | 61 | normal = '0', |
| 54 | 62 | hard_link = '1', |
| 55 | 63 | symbolic_link = '2', |
| ... | ... | @@ -105,8 +113,9 @@ pub const Header = struct { |
| 105 | 113 | } |
| 106 | 114 | |
| 107 | 115 | pub fn fileType(header: Header) FileType { |
| 108 | const result = @as(FileType, @enumFromInt(header.bytes[156])); | |
| 109 | return if (result == @as(FileType, @enumFromInt(0))) .normal else result; | |
| 116 | const result: FileType = @enumFromInt(header.bytes[156]); | |
| 117 | if (result == .normal_alias) return .normal; | |
| 118 | return result; | |
| 110 | 119 | } |
| 111 | 120 | |
| 112 | 121 | fn str(header: Header, start: usize, end: usize) []const u8 { |
| ... | ... | @@ -268,18 +277,21 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !voi |
| 268 | 277 | const link_name = header.linkName(); |
| 269 | 278 | |
| 270 | 279 | dir.symLink(link_name, file_name, .{}) catch |err| { |
| 271 | if (options.diagnostics) |d| { | |
| 272 | try d.errors.append(d.allocator, .{ .unable_to_create_sym_link = .{ | |
| 273 | .code = err, | |
| 274 | .file_name = try d.allocator.dupe(u8, file_name), | |
| 275 | .link_name = try d.allocator.dupe(u8, link_name), | |
| 276 | } }); | |
| 277 | } else { | |
| 278 | return error.UnableToCreateSymLink; | |
| 279 | } | |
| 280 | const d = options.diagnostics orelse return error.UnableToCreateSymLink; | |
| 281 | try d.errors.append(d.allocator, .{ .unable_to_create_sym_link = .{ | |
| 282 | .code = err, | |
| 283 | .file_name = try d.allocator.dupe(u8, file_name), | |
| 284 | .link_name = try d.allocator.dupe(u8, link_name), | |
| 285 | } }); | |
| 280 | 286 | }; |
| 281 | 287 | }, |
| 282 | else => return error.TarUnsupportedFileType, | |
| 288 | else => |file_type| { | |
| 289 | const d = options.diagnostics orelse return error.TarUnsupportedFileType; | |
| 290 | try d.errors.append(d.allocator, .{ .unsupported_file_type = .{ | |
| 291 | .file_name = try d.allocator.dupe(u8, unstripped_file_name), | |
| 292 | .file_type = file_type, | |
| 293 | } }); | |
| 294 | }, | |
| 283 | 295 | } |
| 284 | 296 | } |
| 285 | 297 | } |
lib/std/zig/ErrorBundle.zig+12-12| ... | ... | @@ -202,7 +202,7 @@ fn renderErrorMessageToWriter( |
| 202 | 202 | try counting_stderr.writeAll(": "); |
| 203 | 203 | // This is the length of the part before the error message: |
| 204 | 204 | // e.g. "file.zig:4:5: error: " |
| 205 | const prefix_len = @as(usize, @intCast(counting_stderr.context.bytes_written)); | |
| 205 | const prefix_len: usize = @intCast(counting_stderr.context.bytes_written); | |
| 206 | 206 | try ttyconf.setColor(stderr, .reset); |
| 207 | 207 | try ttyconf.setColor(stderr, .bold); |
| 208 | 208 | if (err_msg.count == 1) { |
| ... | ... | @@ -356,7 +356,7 @@ pub const Wip = struct { |
| 356 | 356 | } |
| 357 | 357 | |
| 358 | 358 | const compile_log_str_index = if (compile_log_text.len == 0) 0 else str: { |
| 359 | const str = @as(u32, @intCast(wip.string_bytes.items.len)); | |
| 359 | const str: u32 = @intCast(wip.string_bytes.items.len); | |
| 360 | 360 | try wip.string_bytes.ensureUnusedCapacity(gpa, compile_log_text.len + 1); |
| 361 | 361 | wip.string_bytes.appendSliceAssumeCapacity(compile_log_text); |
| 362 | 362 | wip.string_bytes.appendAssumeCapacity(0); |
| ... | ... | @@ -364,8 +364,8 @@ pub const Wip = struct { |
| 364 | 364 | }; |
| 365 | 365 | |
| 366 | 366 | wip.setExtra(0, ErrorMessageList{ |
| 367 | .len = @as(u32, @intCast(wip.root_list.items.len)), | |
| 368 | .start = @as(u32, @intCast(wip.extra.items.len)), | |
| 367 | .len = @intCast(wip.root_list.items.len), | |
| 368 | .start = @intCast(wip.extra.items.len), | |
| 369 | 369 | .compile_log_text = compile_log_str_index, |
| 370 | 370 | }); |
| 371 | 371 | try wip.extra.appendSlice(gpa, @as([]const u32, @ptrCast(wip.root_list.items))); |
| ... | ... | @@ -385,7 +385,7 @@ pub const Wip = struct { |
| 385 | 385 | |
| 386 | 386 | pub fn addString(wip: *Wip, s: []const u8) !u32 { |
| 387 | 387 | const gpa = wip.gpa; |
| 388 | const index = @as(u32, @intCast(wip.string_bytes.items.len)); | |
| 388 | const index: u32 = @intCast(wip.string_bytes.items.len); | |
| 389 | 389 | try wip.string_bytes.ensureUnusedCapacity(gpa, s.len + 1); |
| 390 | 390 | wip.string_bytes.appendSliceAssumeCapacity(s); |
| 391 | 391 | wip.string_bytes.appendAssumeCapacity(0); |
| ... | ... | @@ -394,7 +394,7 @@ pub const Wip = struct { |
| 394 | 394 | |
| 395 | 395 | pub fn printString(wip: *Wip, comptime fmt: []const u8, args: anytype) !u32 { |
| 396 | 396 | const gpa = wip.gpa; |
| 397 | const index = @as(u32, @intCast(wip.string_bytes.items.len)); | |
| 397 | const index: u32 = @intCast(wip.string_bytes.items.len); | |
| 398 | 398 | try wip.string_bytes.writer(gpa).print(fmt, args); |
| 399 | 399 | try wip.string_bytes.append(gpa, 0); |
| 400 | 400 | return index; |
| ... | ... | @@ -406,15 +406,15 @@ pub const Wip = struct { |
| 406 | 406 | } |
| 407 | 407 | |
| 408 | 408 | pub fn addErrorMessage(wip: *Wip, em: ErrorMessage) !MessageIndex { |
| 409 | return @as(MessageIndex, @enumFromInt(try addExtra(wip, em))); | |
| 409 | return @enumFromInt(try addExtra(wip, em)); | |
| 410 | 410 | } |
| 411 | 411 | |
| 412 | 412 | pub fn addErrorMessageAssumeCapacity(wip: *Wip, em: ErrorMessage) MessageIndex { |
| 413 | return @as(MessageIndex, @enumFromInt(addExtraAssumeCapacity(wip, em))); | |
| 413 | return @enumFromInt(addExtraAssumeCapacity(wip, em)); | |
| 414 | 414 | } |
| 415 | 415 | |
| 416 | 416 | pub fn addSourceLocation(wip: *Wip, sl: SourceLocation) !SourceLocationIndex { |
| 417 | return @as(SourceLocationIndex, @enumFromInt(try addExtra(wip, sl))); | |
| 417 | return @enumFromInt(try addExtra(wip, sl)); | |
| 418 | 418 | } |
| 419 | 419 | |
| 420 | 420 | pub fn addReferenceTrace(wip: *Wip, rt: ReferenceTrace) !void { |
| ... | ... | @@ -430,7 +430,7 @@ pub const Wip = struct { |
| 430 | 430 | const other_list = other.getMessages(); |
| 431 | 431 | |
| 432 | 432 | // The ensureUnusedCapacity call above guarantees this. |
| 433 | const notes_start = wip.reserveNotes(@as(u32, @intCast(other_list.len))) catch unreachable; | |
| 433 | const notes_start = wip.reserveNotes(@intCast(other_list.len)) catch unreachable; | |
| 434 | 434 | for (notes_start.., other_list) |note, message| { |
| 435 | 435 | wip.extra.items[note] = @intFromEnum(wip.addOtherMessage(other, message) catch unreachable); |
| 436 | 436 | } |
| ... | ... | @@ -455,7 +455,7 @@ pub const Wip = struct { |
| 455 | 455 | try wip.extra.ensureUnusedCapacity(wip.gpa, notes_len + |
| 456 | 456 | notes_len * @typeInfo(ErrorBundle.ErrorMessage).Struct.fields.len); |
| 457 | 457 | wip.extra.items.len += notes_len; |
| 458 | return @as(u32, @intCast(wip.extra.items.len - notes_len)); | |
| 458 | return @intCast(wip.extra.items.len - notes_len); | |
| 459 | 459 | } |
| 460 | 460 | |
| 461 | 461 | fn addOtherMessage(wip: *Wip, other: ErrorBundle, msg_index: MessageIndex) !MessageIndex { |
| ... | ... | @@ -510,7 +510,7 @@ pub const Wip = struct { |
| 510 | 510 | |
| 511 | 511 | fn addExtraAssumeCapacity(wip: *Wip, extra: anytype) u32 { |
| 512 | 512 | const fields = @typeInfo(@TypeOf(extra)).Struct.fields; |
| 513 | const result = @as(u32, @intCast(wip.extra.items.len)); | |
| 513 | const result: u32 = @intCast(wip.extra.items.len); | |
| 514 | 514 | wip.extra.items.len += fields.len; |
| 515 | 515 | setExtra(wip, result, extra); |
| 516 | 516 | return result; |
src/Package.zig+92-27| ... | ... | @@ -285,7 +285,8 @@ pub fn fetchAndAddDependencies( |
| 285 | 285 | if (manifest.errors.len > 0) { |
| 286 | 286 | const file_path = try directory.join(arena, &.{Manifest.basename}); |
| 287 | 287 | for (manifest.errors) |msg| { |
| 288 | try Report.addErrorMessage(ast, file_path, error_bundle, 0, msg); | |
| 288 | const str = try error_bundle.addString(msg.msg); | |
| 289 | try Report.addErrorMessage(&ast, file_path, error_bundle, 0, str, msg.tok, msg.off); | |
| 289 | 290 | } |
| 290 | 291 | return error.PackageFetchFailed; |
| 291 | 292 | } |
| ... | ... | @@ -465,20 +466,31 @@ pub const Report = struct { |
| 465 | 466 | comptime fmt_string: []const u8, |
| 466 | 467 | fmt_args: anytype, |
| 467 | 468 | ) error{ PackageFetchFailed, OutOfMemory } { |
| 468 | const ast = report.ast orelse main.fatal(fmt_string, fmt_args); | |
| 469 | const msg = try report.error_bundle.printString(fmt_string, fmt_args); | |
| 470 | return failMsg(report, tok, msg); | |
| 471 | } | |
| 472 | ||
| 473 | fn failMsg( | |
| 474 | report: Report, | |
| 475 | tok: std.zig.Ast.TokenIndex, | |
| 476 | msg: u32, | |
| 477 | ) error{ PackageFetchFailed, OutOfMemory } { | |
| 469 | 478 | const gpa = report.error_bundle.gpa; |
| 470 | 479 | |
| 471 | 480 | const file_path = try report.directory.join(gpa, &.{Manifest.basename}); |
| 472 | 481 | defer gpa.free(file_path); |
| 473 | 482 | |
| 474 | const msg = try std.fmt.allocPrint(gpa, fmt_string, fmt_args); | |
| 475 | defer gpa.free(msg); | |
| 483 | const eb = report.error_bundle; | |
| 476 | 484 | |
| 477 | try addErrorMessage(ast.*, file_path, report.error_bundle, 0, .{ | |
| 478 | .tok = tok, | |
| 479 | .off = 0, | |
| 480 | .msg = msg, | |
| 481 | }); | |
| 485 | if (report.ast) |ast| { | |
| 486 | try addErrorMessage(ast, file_path, eb, 0, msg, tok, 0); | |
| 487 | } else { | |
| 488 | try eb.addRootErrorMessage(.{ | |
| 489 | .msg = msg, | |
| 490 | .src_loc = .none, | |
| 491 | .notes_len = 0, | |
| 492 | }); | |
| 493 | } | |
| 482 | 494 | |
| 483 | 495 | return error.PackageFetchFailed; |
| 484 | 496 | } |
| ... | ... | @@ -488,31 +500,42 @@ pub const Report = struct { |
| 488 | 500 | notes_len: u32, |
| 489 | 501 | msg: Manifest.ErrorMessage, |
| 490 | 502 | ) error{OutOfMemory}!void { |
| 491 | const ast = report.ast orelse main.fatal("{s}", .{msg.msg}); | |
| 492 | const gpa = report.error_bundle.gpa; | |
| 493 | const file_path = try report.directory.join(gpa, &.{Manifest.basename}); | |
| 494 | defer gpa.free(file_path); | |
| 495 | return addErrorMessage(ast.*, file_path, report.error_bundle, notes_len, msg); | |
| 503 | const eb = report.error_bundle; | |
| 504 | const msg_str = try eb.addString(msg.msg); | |
| 505 | if (report.ast) |ast| { | |
| 506 | const gpa = eb.gpa; | |
| 507 | const file_path = try report.directory.join(gpa, &.{Manifest.basename}); | |
| 508 | defer gpa.free(file_path); | |
| 509 | return addErrorMessage(ast, file_path, eb, notes_len, msg_str, msg.tok, msg.off); | |
| 510 | } else { | |
| 511 | return eb.addRootErrorMessage(.{ | |
| 512 | .msg = msg_str, | |
| 513 | .src_loc = .none, | |
| 514 | .notes_len = notes_len, | |
| 515 | }); | |
| 516 | } | |
| 496 | 517 | } |
| 497 | 518 | |
| 498 | 519 | fn addErrorMessage( |
| 499 | ast: std.zig.Ast, | |
| 520 | ast: *const std.zig.Ast, | |
| 500 | 521 | file_path: []const u8, |
| 501 | 522 | eb: *std.zig.ErrorBundle.Wip, |
| 502 | 523 | notes_len: u32, |
| 503 | msg: Manifest.ErrorMessage, | |
| 524 | msg_str: u32, | |
| 525 | msg_tok: std.zig.Ast.TokenIndex, | |
| 526 | msg_off: u32, | |
| 504 | 527 | ) error{OutOfMemory}!void { |
| 505 | 528 | const token_starts = ast.tokens.items(.start); |
| 506 | const start_loc = ast.tokenLocation(0, msg.tok); | |
| 529 | const start_loc = ast.tokenLocation(0, msg_tok); | |
| 507 | 530 | |
| 508 | 531 | try eb.addRootErrorMessage(.{ |
| 509 | .msg = try eb.addString(msg.msg), | |
| 532 | .msg = msg_str, | |
| 510 | 533 | .src_loc = try eb.addSourceLocation(.{ |
| 511 | 534 | .src_path = try eb.addString(file_path), |
| 512 | .span_start = token_starts[msg.tok], | |
| 513 | .span_end = @as(u32, @intCast(token_starts[msg.tok] + ast.tokenSlice(msg.tok).len)), | |
| 514 | .span_main = token_starts[msg.tok] + msg.off, | |
| 515 | .line = @as(u32, @intCast(start_loc.line)), | |
| 535 | .span_start = token_starts[msg_tok], | |
| 536 | .span_end = @as(u32, @intCast(token_starts[msg_tok] + ast.tokenSlice(msg_tok).len)), | |
| 537 | .span_main = token_starts[msg_tok] + msg_off, | |
| 538 | .line = @intCast(start_loc.line), | |
| 516 | 539 | .column = @as(u32, @intCast(start_loc.column)), |
| 517 | 540 | .source_line = try eb.addString(ast.source[start_loc.line_start..start_loc.line_end]), |
| 518 | 541 | }), |
| ... | ... | @@ -752,9 +775,9 @@ pub const ReadableResource = struct { |
| 752 | 775 | }; |
| 753 | 776 | |
| 754 | 777 | switch (try rr.getFileType(dep_location_tok, report)) { |
| 755 | .tar => try unpackTarball(prog_reader.reader(), tmp_directory.handle), | |
| 756 | .@"tar.gz" => try unpackTarballCompressed(allocator, prog_reader, tmp_directory.handle, std.compress.gzip), | |
| 757 | .@"tar.xz" => try unpackTarballCompressed(allocator, prog_reader, tmp_directory.handle, std.compress.xz), | |
| 778 | .tar => try unpackTarball(allocator, prog_reader.reader(), tmp_directory.handle, dep_location_tok, report), | |
| 779 | .@"tar.gz" => try unpackTarballCompressed(allocator, prog_reader, tmp_directory.handle, dep_location_tok, report, std.compress.gzip), | |
| 780 | .@"tar.xz" => try unpackTarballCompressed(allocator, prog_reader, tmp_directory.handle, dep_location_tok, report, std.compress.xz), | |
| 758 | 781 | .git_pack => try unpackGitPack(allocator, &prog_reader, git.parseOid(rr.path) catch unreachable, tmp_directory.handle), |
| 759 | 782 | } |
| 760 | 783 | } else { |
| ... | ... | @@ -1128,6 +1151,8 @@ fn unpackTarballCompressed( |
| 1128 | 1151 | gpa: Allocator, |
| 1129 | 1152 | reader: anytype, |
| 1130 | 1153 | out_dir: fs.Dir, |
| 1154 | dep_location_tok: std.zig.Ast.TokenIndex, | |
| 1155 | report: Report, | |
| 1131 | 1156 | comptime Compression: type, |
| 1132 | 1157 | ) !void { |
| 1133 | 1158 | var br = std.io.bufferedReaderSize(std.crypto.tls.max_ciphertext_record_len, reader); |
| ... | ... | @@ -1135,11 +1160,21 @@ fn unpackTarballCompressed( |
| 1135 | 1160 | var decompress = try Compression.decompress(gpa, br.reader()); |
| 1136 | 1161 | defer decompress.deinit(); |
| 1137 | 1162 | |
| 1138 | return unpackTarball(decompress.reader(), out_dir); | |
| 1163 | return unpackTarball(gpa, decompress.reader(), out_dir, dep_location_tok, report); | |
| 1139 | 1164 | } |
| 1140 | 1165 | |
| 1141 | fn unpackTarball(reader: anytype, out_dir: fs.Dir) !void { | |
| 1166 | fn unpackTarball( | |
| 1167 | gpa: Allocator, | |
| 1168 | reader: anytype, | |
| 1169 | out_dir: fs.Dir, | |
| 1170 | dep_location_tok: std.zig.Ast.TokenIndex, | |
| 1171 | report: Report, | |
| 1172 | ) !void { | |
| 1173 | var diagnostics: std.tar.Options.Diagnostics = .{ .allocator = gpa }; | |
| 1174 | defer diagnostics.deinit(); | |
| 1175 | ||
| 1142 | 1176 | try std.tar.pipeToFileSystem(out_dir, reader, .{ |
| 1177 | .diagnostics = &diagnostics, | |
| 1143 | 1178 | .strip_components = 1, |
| 1144 | 1179 | // TODO: we would like to set this to executable_bit_only, but two |
| 1145 | 1180 | // things need to happen before that: |
| ... | ... | @@ -1148,6 +1183,36 @@ fn unpackTarball(reader: anytype, out_dir: fs.Dir) !void { |
| 1148 | 1183 | // bit on Windows from the ACLs (see the isExecutable function). |
| 1149 | 1184 | .mode_mode = .ignore, |
| 1150 | 1185 | }); |
| 1186 | ||
| 1187 | if (diagnostics.errors.items.len > 0) { | |
| 1188 | const notes_len: u32 = @intCast(diagnostics.errors.items.len); | |
| 1189 | try report.addErrorWithNotes(notes_len, .{ | |
| 1190 | .tok = dep_location_tok, | |
| 1191 | .off = 0, | |
| 1192 | .msg = "unable to unpack tarball", | |
| 1193 | }); | |
| 1194 | const eb = report.error_bundle; | |
| 1195 | const notes_start = try eb.reserveNotes(notes_len); | |
| 1196 | for (diagnostics.errors.items, notes_start..) |item, note_i| { | |
| 1197 | switch (item) { | |
| 1198 | .unable_to_create_sym_link => |info| { | |
| 1199 | eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{ | |
| 1200 | .msg = try eb.printString("unable to create symlink from '{s}' to '{s}': {s}", .{ | |
| 1201 | info.file_name, info.link_name, @errorName(info.code), | |
| 1202 | }), | |
| 1203 | })); | |
| 1204 | }, | |
| 1205 | .unsupported_file_type => |info| { | |
| 1206 | eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{ | |
| 1207 | .msg = try eb.printString("file '{s}' has unsupported type '{c}'", .{ | |
| 1208 | info.file_name, @intFromEnum(info.file_type), | |
| 1209 | }), | |
| 1210 | })); | |
| 1211 | }, | |
| 1212 | } | |
| 1213 | } | |
| 1214 | return error.InvalidTarball; | |
| 1215 | } | |
| 1151 | 1216 | } |
| 1152 | 1217 | |
| 1153 | 1218 | fn unpackGitPack( |
src/main.zig+20-4| ... | ... | @@ -6610,6 +6610,7 @@ fn cmdFetch( |
| 6610 | 6610 | arena: Allocator, |
| 6611 | 6611 | args: []const []const u8, |
| 6612 | 6612 | ) !void { |
| 6613 | const color: Color = .auto; | |
| 6613 | 6614 | var opt_url: ?[]const u8 = null; |
| 6614 | 6615 | var override_global_cache_dir: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_GLOBAL_CACHE_DIR"); |
| 6615 | 6616 | |
| ... | ... | @@ -6651,10 +6652,17 @@ fn cmdFetch( |
| 6651 | 6652 | const root_prog_node = progress.start("Fetch", 0); |
| 6652 | 6653 | defer root_prog_node.end(); |
| 6653 | 6654 | |
| 6655 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; | |
| 6656 | try wip_errors.init(gpa); | |
| 6657 | defer wip_errors.deinit(); | |
| 6658 | ||
| 6654 | 6659 | var report: Package.Report = .{ |
| 6655 | 6660 | .ast = null, |
| 6656 | .directory = undefined, | |
| 6657 | .error_bundle = undefined, | |
| 6661 | .directory = .{ | |
| 6662 | .handle = fs.cwd(), | |
| 6663 | .path = null, | |
| 6664 | }, | |
| 6665 | .error_bundle = &wip_errors, | |
| 6658 | 6666 | }; |
| 6659 | 6667 | |
| 6660 | 6668 | var global_cache_directory: Compilation.Directory = l: { |
| ... | ... | @@ -6697,14 +6705,22 @@ fn cmdFetch( |
| 6697 | 6705 | }; |
| 6698 | 6706 | defer readable_resource.deinit(gpa); |
| 6699 | 6707 | |
| 6700 | var package_location = try readable_resource.unpack( | |
| 6708 | var package_location = readable_resource.unpack( | |
| 6701 | 6709 | gpa, |
| 6702 | 6710 | &thread_pool, |
| 6703 | 6711 | global_cache_directory, |
| 6704 | 6712 | 0, |
| 6705 | 6713 | report, |
| 6706 | 6714 | root_prog_node, |
| 6707 | ); | |
| 6715 | ) catch |err| { | |
| 6716 | if (wip_errors.root_list.items.len > 0) { | |
| 6717 | var errors = try wip_errors.toOwnedBundle(""); | |
| 6718 | defer errors.deinit(gpa); | |
| 6719 | errors.renderToStdErr(renderOptions(color)); | |
| 6720 | process.exit(1); | |
| 6721 | } | |
| 6722 | fatal("unable to unpack '{s}': {s}", .{ url, @errorName(err) }); | |
| 6723 | }; | |
| 6708 | 6724 | defer package_location.deinit(gpa); |
| 6709 | 6725 | |
| 6710 | 6726 | const hex_digest = Package.Manifest.hexDigest(package_location.hash); |