| author | |
| committer | |
| log | 05ce1f99a60df0bcede00af1c98a1e5fdce35051 |
| tree | b9dfb4f32f94125bda0a1ad925fec8a66179f9ed |
| parent | 2569f4ff8514f47730c1abd42691f8fc1cdd22d5 |
7 files changed, 122 insertions(+), 107 deletions(-)
lib/std/Io/Reader.zig+9| ... | ... | @@ -1709,6 +1709,15 @@ fn failingDiscard(r: *Reader, limit: Limit) Error!usize { |
| 1709 | 1709 | return error.ReadFailed; |
| 1710 | 1710 | } |
| 1711 | 1711 | |
| 1712 | pub fn adaptToOldInterface(r: *Reader) std.Io.AnyReader { | |
| 1713 | return .{ .context = r, .readFn = derpRead }; | |
| 1714 | } | |
| 1715 | ||
| 1716 | fn derpRead(context: *const anyopaque, buffer: []u8) anyerror!usize { | |
| 1717 | const r: *Reader = @constCast(@alignCast(@ptrCast(context))); | |
| 1718 | return r.readSliceShort(buffer); | |
| 1719 | } | |
| 1720 | ||
| 1712 | 1721 | test "readAlloc when the backing reader provides one byte at a time" { |
| 1713 | 1722 | const str = "This is a test"; |
| 1714 | 1723 | var tiny_buffer: [1]u8 = undefined; |
lib/std/compress/flate/Decompress.zig+5-5| ... | ... | @@ -23,7 +23,7 @@ dst_dec: DistanceDecoder, |
| 23 | 23 | final_block: bool, |
| 24 | 24 | state: State, |
| 25 | 25 | |
| 26 | read_err: ?Error, | |
| 26 | err: ?Error, | |
| 27 | 27 | |
| 28 | 28 | const BlockType = enum(u2) { |
| 29 | 29 | stored = 0, |
| ... | ... | @@ -74,7 +74,7 @@ pub fn init(input: *Reader, container: Container, buffer: []u8) Decompress { |
| 74 | 74 | .dst_dec = .{}, |
| 75 | 75 | .final_block = false, |
| 76 | 76 | .state = .protocol_header, |
| 77 | .read_err = null, | |
| 77 | .err = null, | |
| 78 | 78 | }; |
| 79 | 79 | } |
| 80 | 80 | |
| ... | ... | @@ -153,7 +153,7 @@ pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!us |
| 153 | 153 | if (d.state == .end) { |
| 154 | 154 | return error.EndOfStream; |
| 155 | 155 | } else { |
| 156 | d.read_err = error.EndOfStream; | |
| 156 | d.err = error.EndOfStream; | |
| 157 | 157 | return error.ReadFailed; |
| 158 | 158 | } |
| 159 | 159 | }, |
| ... | ... | @@ -161,7 +161,7 @@ pub fn stream(r: *Reader, w: *Writer, limit: std.Io.Limit) Reader.StreamError!us |
| 161 | 161 | else => |e| { |
| 162 | 162 | // In the event of an error, state is unmodified so that it can be |
| 163 | 163 | // better used to diagnose the failure. |
| 164 | d.read_err = e; | |
| 164 | d.err = e; | |
| 165 | 165 | return error.ReadFailed; |
| 166 | 166 | }, |
| 167 | 167 | }; |
| ... | ... | @@ -1179,7 +1179,7 @@ fn testFailure(container: Container, in: []const u8, expected_err: anyerror) !vo |
| 1179 | 1179 | |
| 1180 | 1180 | var decompress: Decompress = .init(&reader, container, &.{}); |
| 1181 | 1181 | try testing.expectError(error.ReadFailed, decompress.reader.streamRemaining(&aw.writer)); |
| 1182 | try testing.expectEqual(expected_err, decompress.read_err orelse return error.TestFailed); | |
| 1182 | try testing.expectEqual(expected_err, decompress.err orelse return error.TestFailed); | |
| 1183 | 1183 | } |
| 1184 | 1184 | |
| 1185 | 1185 | fn testDecompress(container: Container, compressed: []const u8, expected_plain: []const u8) !void { |
lib/std/http/Client.zig+9-10| ... | ... | @@ -405,8 +405,8 @@ pub const RequestTransfer = union(enum) { |
| 405 | 405 | |
| 406 | 406 | /// The decompressor for response messages. |
| 407 | 407 | pub const Compression = union(enum) { |
| 408 | deflate: std.compress.flate.Decompress, | |
| 409 | gzip: std.compress.flate.Decompress, | |
| 408 | //deflate: std.compress.flate.Decompress, | |
| 409 | //gzip: std.compress.flate.Decompress, | |
| 410 | 410 | // https://github.com/ziglang/zig/issues/18937 |
| 411 | 411 | //zstd: ZstdDecompressor, |
| 412 | 412 | none: void, |
| ... | ... | @@ -1074,12 +1074,10 @@ pub const Request = struct { |
| 1074 | 1074 | switch (req.response.transfer_compression) { |
| 1075 | 1075 | .identity => req.response.compression = .none, |
| 1076 | 1076 | .compress, .@"x-compress" => return error.CompressionUnsupported, |
| 1077 | .deflate => req.response.compression = .{ | |
| 1078 | .deflate = std.compress.zlib.decompressor(req.transferReader()), | |
| 1079 | }, | |
| 1080 | .gzip, .@"x-gzip" => req.response.compression = .{ | |
| 1081 | .gzip = std.compress.gzip.decompressor(req.transferReader()), | |
| 1082 | }, | |
| 1077 | // I'm about to upstream my http.Client rewrite | |
| 1078 | .deflate => return error.CompressionUnsupported, | |
| 1079 | // I'm about to upstream my http.Client rewrite | |
| 1080 | .gzip, .@"x-gzip" => return error.CompressionUnsupported, | |
| 1083 | 1081 | // https://github.com/ziglang/zig/issues/18937 |
| 1084 | 1082 | //.zstd => req.response.compression = .{ |
| 1085 | 1083 | // .zstd = std.compress.zstd.decompressStream(req.client.allocator, req.transferReader()), |
| ... | ... | @@ -1105,8 +1103,9 @@ pub const Request = struct { |
| 1105 | 1103 | /// Reads data from the response body. Must be called after `wait`. |
| 1106 | 1104 | pub fn read(req: *Request, buffer: []u8) ReadError!usize { |
| 1107 | 1105 | const out_index = switch (req.response.compression) { |
| 1108 | .deflate => |*deflate| deflate.read(buffer) catch return error.DecompressionFailure, | |
| 1109 | .gzip => |*gzip| gzip.read(buffer) catch return error.DecompressionFailure, | |
| 1106 | // I'm about to upstream my http client rewrite | |
| 1107 | //.deflate => |*deflate| deflate.readSlice(buffer) catch return error.DecompressionFailure, | |
| 1108 | //.gzip => |*gzip| gzip.read(buffer) catch return error.DecompressionFailure, | |
| 1110 | 1109 | // https://github.com/ziglang/zig/issues/18937 |
| 1111 | 1110 | //.zstd => |*zstd| zstd.read(buffer) catch return error.DecompressionFailure, |
| 1112 | 1111 | else => try req.transferRead(buffer), |
lib/std/zip.zig+45-39| ... | ... | @@ -7,8 +7,9 @@ const builtin = @import("builtin"); |
| 7 | 7 | const std = @import("std"); |
| 8 | 8 | const File = std.fs.File; |
| 9 | 9 | const is_le = builtin.target.cpu.arch.endian() == .little; |
| 10 | const Writer = std.io.Writer; | |
| 11 | const Reader = std.io.Reader; | |
| 10 | const Writer = std.Io.Writer; | |
| 11 | const Reader = std.Io.Reader; | |
| 12 | const flate = std.compress.flate; | |
| 12 | 13 | |
| 13 | 14 | pub const CompressionMethod = enum(u16) { |
| 14 | 15 | store = 0, |
| ... | ... | @@ -117,6 +118,7 @@ pub const EndRecord = extern struct { |
| 117 | 118 | pub const FindFileError = File.GetEndPosError || File.SeekError || File.ReadError || error{ |
| 118 | 119 | ZipNoEndRecord, |
| 119 | 120 | EndOfStream, |
| 121 | ReadFailed, | |
| 120 | 122 | }; |
| 121 | 123 | |
| 122 | 124 | pub fn findFile(fr: *File.Reader) FindFileError!EndRecord { |
| ... | ... | @@ -137,8 +139,7 @@ pub const EndRecord = extern struct { |
| 137 | 139 | |
| 138 | 140 | try fr.seekTo(end_pos - @as(u64, new_loaded_len)); |
| 139 | 141 | const read_buf: []u8 = buf[buf.len - new_loaded_len ..][0..read_len]; |
| 140 | var br = fr.interface().unbuffered(); | |
| 141 | br.readSlice(read_buf) catch |err| switch (err) { | |
| 142 | fr.interface.readSliceAll(read_buf) catch |err| switch (err) { | |
| 142 | 143 | error.ReadFailed => return fr.err.?, |
| 143 | 144 | error.EndOfStream => return error.EndOfStream, |
| 144 | 145 | }; |
| ... | ... | @@ -164,7 +165,7 @@ pub const EndRecord = extern struct { |
| 164 | 165 | pub const Decompress = struct { |
| 165 | 166 | interface: Reader, |
| 166 | 167 | state: union { |
| 167 | inflate: std.compress.flate.Decompress, | |
| 168 | inflate: flate.Decompress, | |
| 168 | 169 | store: *Reader, |
| 169 | 170 | }, |
| 170 | 171 | |
| ... | ... | @@ -201,7 +202,7 @@ pub const Decompress = struct { |
| 201 | 202 | |
| 202 | 203 | fn streamDeflate(r: *Reader, w: *Writer, limit: std.io.Limit) Reader.StreamError!usize { |
| 203 | 204 | const d: *Decompress = @fieldParentPtr("interface", r); |
| 204 | return std.compress.flate.Decompress.read(&d.inflate, w, limit); | |
| 205 | return flate.Decompress.read(&d.inflate, w, limit); | |
| 205 | 206 | } |
| 206 | 207 | }; |
| 207 | 208 | |
| ... | ... | @@ -305,7 +306,7 @@ pub const Iterator = struct { |
| 305 | 306 | if (locator_end_offset > stream_len) |
| 306 | 307 | return error.ZipTruncated; |
| 307 | 308 | try input.seekTo(stream_len - locator_end_offset); |
| 308 | const locator = input.interface.takeStructEndian(EndLocator64, .little) catch |err| switch (err) { | |
| 309 | const locator = input.interface.takeStruct(EndLocator64, .little) catch |err| switch (err) { | |
| 309 | 310 | error.ReadFailed => return input.err.?, |
| 310 | 311 | error.EndOfStream => return error.EndOfStream, |
| 311 | 312 | }; |
| ... | ... | @@ -318,7 +319,7 @@ pub const Iterator = struct { |
| 318 | 319 | |
| 319 | 320 | try input.seekTo(locator.record_file_offset); |
| 320 | 321 | |
| 321 | const record64 = input.interface.takeStructEndian(EndRecord64, .little) catch |err| switch (err) { | |
| 322 | const record64 = input.interface.takeStruct(EndRecord64, .little) catch |err| switch (err) { | |
| 322 | 323 | error.ReadFailed => return input.err.?, |
| 323 | 324 | error.EndOfStream => return error.EndOfStream, |
| 324 | 325 | }; |
| ... | ... | @@ -374,7 +375,7 @@ pub const Iterator = struct { |
| 374 | 375 | const header_zip_offset = self.cd_zip_offset + self.cd_record_offset; |
| 375 | 376 | const input = self.input; |
| 376 | 377 | try input.seekTo(header_zip_offset); |
| 377 | const header = input.interface.takeStructEndian(CentralDirectoryFileHeader, .little) catch |err| switch (err) { | |
| 378 | const header = input.interface.takeStruct(CentralDirectoryFileHeader, .little) catch |err| switch (err) { | |
| 378 | 379 | error.ReadFailed => return input.err.?, |
| 379 | 380 | error.EndOfStream => return error.EndOfStream, |
| 380 | 381 | }; |
| ... | ... | @@ -405,7 +406,7 @@ pub const Iterator = struct { |
| 405 | 406 | const extra = extra_buf[0..header.extra_len]; |
| 406 | 407 | |
| 407 | 408 | try input.seekTo(header_zip_offset + @sizeOf(CentralDirectoryFileHeader) + header.filename_len); |
| 408 | input.interface.readSlice(extra) catch |err| switch (err) { | |
| 409 | input.interface.readSliceAll(extra) catch |err| switch (err) { | |
| 409 | 410 | error.ReadFailed => return input.err.?, |
| 410 | 411 | error.EndOfStream => return error.EndOfStream, |
| 411 | 412 | }; |
| ... | ... | @@ -460,7 +461,7 @@ pub const Iterator = struct { |
| 460 | 461 | options: ExtractOptions, |
| 461 | 462 | filename_buf: []u8, |
| 462 | 463 | dest: std.fs.Dir, |
| 463 | ) !u32 { | |
| 464 | ) !void { | |
| 464 | 465 | if (filename_buf.len < self.filename_len) |
| 465 | 466 | return error.ZipInsufficientBuffer; |
| 466 | 467 | switch (self.compression_method) { |
| ... | ... | @@ -470,13 +471,13 @@ pub const Iterator = struct { |
| 470 | 471 | const filename = filename_buf[0..self.filename_len]; |
| 471 | 472 | { |
| 472 | 473 | try stream.seekTo(self.header_zip_offset + @sizeOf(CentralDirectoryFileHeader)); |
| 473 | try stream.interface.readSlice(filename); | |
| 474 | try stream.interface.readSliceAll(filename); | |
| 474 | 475 | } |
| 475 | 476 | |
| 476 | 477 | const local_data_header_offset: u64 = local_data_header_offset: { |
| 477 | 478 | const local_header = blk: { |
| 478 | 479 | try stream.seekTo(self.file_offset); |
| 479 | break :blk try stream.interface.takeStructEndian(LocalFileHeader, .little); | |
| 480 | break :blk try stream.interface.takeStruct(LocalFileHeader, .little); | |
| 480 | 481 | }; |
| 481 | 482 | if (!std.mem.eql(u8, &local_header.signature, &local_file_header_sig)) |
| 482 | 483 | return error.ZipBadFileOffset; |
| ... | ... | @@ -502,7 +503,7 @@ pub const Iterator = struct { |
| 502 | 503 | |
| 503 | 504 | { |
| 504 | 505 | try stream.seekTo(self.file_offset + @sizeOf(LocalFileHeader) + local_header.filename_len); |
| 505 | try stream.interface.readSlice(extra); | |
| 506 | try stream.interface.readSliceAll(extra); | |
| 506 | 507 | } |
| 507 | 508 | |
| 508 | 509 | var extra_offset: usize = 0; |
| ... | ... | @@ -550,7 +551,7 @@ pub const Iterator = struct { |
| 550 | 551 | if (self.uncompressed_size != 0) |
| 551 | 552 | return error.ZipBadDirectorySize; |
| 552 | 553 | try dest.makePath(filename[0 .. filename.len - 1]); |
| 553 | return std.hash.Crc32.hash(&.{}); | |
| 554 | return; | |
| 554 | 555 | } |
| 555 | 556 | |
| 556 | 557 | const out_file = blk: { |
| ... | ... | @@ -564,31 +565,36 @@ pub const Iterator = struct { |
| 564 | 565 | break :blk try dest.createFile(filename, .{ .exclusive = true }); |
| 565 | 566 | }; |
| 566 | 567 | defer out_file.close(); |
| 567 | var file_writer = out_file.writer(); | |
| 568 | var file_bw = file_writer.writer(&.{}); | |
| 568 | var out_file_buffer: [1024]u8 = undefined; | |
| 569 | var file_writer = out_file.writer(&out_file_buffer); | |
| 569 | 570 | const local_data_file_offset: u64 = |
| 570 | 571 | @as(u64, self.file_offset) + |
| 571 | 572 | @as(u64, @sizeOf(LocalFileHeader)) + |
| 572 | 573 | local_data_header_offset; |
| 573 | 574 | try stream.seekTo(local_data_file_offset); |
| 574 | var limited_file_reader = stream.interface.limited(.limited(self.compressed_size)); | |
| 575 | var file_read_buffer: [1000]u8 = undefined; | |
| 576 | var decompress_read_buffer: [1000]u8 = undefined; | |
| 577 | var limited_br = limited_file_reader.reader().buffered(&file_read_buffer); | |
| 578 | var decompress: Decompress = undefined; | |
| 579 | var decompress_br = decompress.readable(&limited_br, self.compression_method, &decompress_read_buffer); | |
| 580 | const start_out = file_bw.count; | |
| 581 | var hash_writer = file_bw.hashed(std.hash.Crc32.init()); | |
| 582 | var hash_bw = hash_writer.writer(&.{}); | |
| 583 | decompress_br.readAll(&hash_bw, .limited(self.uncompressed_size)) catch |err| switch (err) { | |
| 584 | error.ReadFailed => return stream.err.?, | |
| 585 | error.WriteFailed => return file_writer.err.?, | |
| 586 | error.EndOfStream => return error.ZipDecompressTruncated, | |
| 587 | }; | |
| 588 | if (limited_file_reader.remaining.nonzero()) return error.ZipDecompressTruncated; | |
| 589 | const written = file_bw.count - start_out; | |
| 590 | if (written != self.uncompressed_size) return error.ZipUncompressSizeMismatch; | |
| 591 | return hash_writer.hasher.final(); | |
| 575 | ||
| 576 | // TODO limit based on self.compressed_size | |
| 577 | ||
| 578 | switch (self.compression_method) { | |
| 579 | .store => { | |
| 580 | stream.interface.streamExact(&file_writer.interface, self.uncompressed_size) catch |err| switch (err) { | |
| 581 | error.ReadFailed => return stream.err.?, | |
| 582 | error.WriteFailed => return file_writer.err.?, | |
| 583 | error.EndOfStream => return error.ZipDecompressTruncated, | |
| 584 | }; | |
| 585 | }, | |
| 586 | .deflate => { | |
| 587 | var flate_buffer: [flate.max_window_len]u8 = undefined; | |
| 588 | var decompress: flate.Decompress = .init(&stream.interface, .raw, &flate_buffer); | |
| 589 | decompress.reader.streamExact(&file_writer.interface, self.uncompressed_size) catch |err| switch (err) { | |
| 590 | error.ReadFailed => return stream.err.?, | |
| 591 | error.WriteFailed => return file_writer.err orelse decompress.err.?, | |
| 592 | error.EndOfStream => return error.ZipDecompressTruncated, | |
| 593 | }; | |
| 594 | }, | |
| 595 | else => return error.UnsupportedCompressionMethod, | |
| 596 | } | |
| 597 | try file_writer.end(); | |
| 592 | 598 | } |
| 593 | 599 | }; |
| 594 | 600 | }; |
| ... | ... | @@ -636,19 +642,19 @@ pub const ExtractOptions = struct { |
| 636 | 642 | /// Allow filenames within the zip to use backslashes. Back slashes are normalized |
| 637 | 643 | /// to forward slashes before forwarding them to platform APIs. |
| 638 | 644 | allow_backslashes: bool = false, |
| 639 | ||
| 640 | 645 | diagnostics: ?*Diagnostics = null, |
| 646 | verify_checksums: bool = false, | |
| 641 | 647 | }; |
| 642 | 648 | |
| 643 | 649 | /// Extract the zipped files to the given `dest` directory. |
| 644 | 650 | pub fn extract(dest: std.fs.Dir, fr: *File.Reader, options: ExtractOptions) !void { |
| 651 | if (options.verify_checksums) @panic("TODO unimplemented"); | |
| 652 | ||
| 645 | 653 | var iter = try Iterator.init(fr); |
| 646 | 654 | |
| 647 | 655 | var filename_buf: [std.fs.max_path_bytes]u8 = undefined; |
| 648 | 656 | while (try iter.next()) |entry| { |
| 649 | const crc32 = try entry.extract(fr, options, &filename_buf, dest); | |
| 650 | if (crc32 != entry.crc32) | |
| 651 | return error.ZipCrcMismatch; | |
| 657 | try entry.extract(fr, options, &filename_buf, dest); | |
| 652 | 658 | if (options.diagnostics) |d| { |
| 653 | 659 | try d.nextFilename(filename_buf[0..entry.filename_len]); |
| 654 | 660 | } |
src/Package/Fetch.zig+15-10| ... | ... | @@ -1203,12 +1203,11 @@ fn unpackResource( |
| 1203 | 1203 | return unpackTarball(f, tmp_directory.handle, &adapter.new_interface); |
| 1204 | 1204 | }, |
| 1205 | 1205 | .@"tar.gz" => { |
| 1206 | const reader = resource.reader(); | |
| 1207 | var br = std.io.bufferedReaderSize(std.crypto.tls.max_ciphertext_record_len, reader); | |
| 1208 | var dcp = std.compress.gzip.decompressor(br.reader()); | |
| 1209 | var adapter_buffer: [1024]u8 = undefined; | |
| 1210 | var adapter = dcp.reader().adaptToNewApi(&adapter_buffer); | |
| 1211 | return try unpackTarball(f, tmp_directory.handle, &adapter.new_interface); | |
| 1206 | var adapter_buffer: [std.crypto.tls.max_ciphertext_record_len]u8 = undefined; | |
| 1207 | var adapter = resource.reader().adaptToNewApi(&adapter_buffer); | |
| 1208 | var flate_buffer: [std.compress.flate.max_window_len]u8 = undefined; | |
| 1209 | var decompress: std.compress.flate.Decompress = .init(&adapter.new_interface, .gzip, &flate_buffer); | |
| 1210 | return try unpackTarball(f, tmp_directory.handle, &decompress.reader); | |
| 1212 | 1211 | }, |
| 1213 | 1212 | .@"tar.xz" => { |
| 1214 | 1213 | const gpa = f.arena.child_allocator; |
| ... | ... | @@ -1352,7 +1351,10 @@ fn unzip(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackResult { |
| 1352 | 1351 | )); |
| 1353 | 1352 | defer zip_file.close(); |
| 1354 | 1353 | |
| 1355 | std.zip.extract(out_dir, zip_file.seekableStream(), .{ | |
| 1354 | var zip_file_buffer: [1024]u8 = undefined; | |
| 1355 | var zip_file_reader = zip_file.reader(&zip_file_buffer); | |
| 1356 | ||
| 1357 | std.zip.extract(out_dir, &zip_file_reader, .{ | |
| 1356 | 1358 | .allow_backslashes = true, |
| 1357 | 1359 | .diagnostics = &diagnostics, |
| 1358 | 1360 | }) catch |err| return f.fail(f.location_tok, try eb.printString( |
| ... | ... | @@ -1384,23 +1386,26 @@ fn unpackGitPack(f: *Fetch, out_dir: fs.Dir, resource: *Resource.Git) anyerror!U |
| 1384 | 1386 | defer pack_dir.close(); |
| 1385 | 1387 | var pack_file = try pack_dir.createFile("pkg.pack", .{ .read = true }); |
| 1386 | 1388 | defer pack_file.close(); |
| 1387 | var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init(); | |
| 1389 | var pack_file_buffer: [4096]u8 = undefined; | |
| 1390 | var fifo = std.fifo.LinearFifo(u8, .{ .Slice = {} }).init(&pack_file_buffer); | |
| 1388 | 1391 | try fifo.pump(resource.fetch_stream.reader(), pack_file.deprecatedWriter()); |
| 1389 | 1392 | |
| 1393 | var pack_file_reader = pack_file.reader(&pack_file_buffer); | |
| 1394 | ||
| 1390 | 1395 | var index_file = try pack_dir.createFile("pkg.idx", .{ .read = true }); |
| 1391 | 1396 | defer index_file.close(); |
| 1392 | 1397 | { |
| 1393 | 1398 | const index_prog_node = f.prog_node.start("Index pack", 0); |
| 1394 | 1399 | defer index_prog_node.end(); |
| 1395 | 1400 | var index_buffered_writer = std.io.bufferedWriter(index_file.deprecatedWriter()); |
| 1396 | try git.indexPack(gpa, object_format, pack_file, index_buffered_writer.writer()); | |
| 1401 | try git.indexPack(gpa, object_format, &pack_file_reader, index_buffered_writer.writer()); | |
| 1397 | 1402 | try index_buffered_writer.flush(); |
| 1398 | 1403 | } |
| 1399 | 1404 | |
| 1400 | 1405 | { |
| 1401 | 1406 | const checkout_prog_node = f.prog_node.start("Checkout", 0); |
| 1402 | 1407 | defer checkout_prog_node.end(); |
| 1403 | var repository = try git.Repository.init(gpa, object_format, pack_file, index_file); | |
| 1408 | var repository = try git.Repository.init(gpa, object_format, &pack_file_reader, index_file); | |
| 1404 | 1409 | defer repository.deinit(); |
| 1405 | 1410 | var diagnostics: git.Diagnostics = .{ .allocator = arena }; |
| 1406 | 1411 | try repository.checkout(out_dir, resource.want_oid, &diagnostics); |
src/Package/Fetch/git.zig+32-35| ... | ... | @@ -73,7 +73,7 @@ pub const Oid = union(Format) { |
| 73 | 73 | }; |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | pub fn readBytes(oid_format: Format, reader: anytype) @TypeOf(reader).NoEofError!Oid { | |
| 76 | pub fn readBytes(oid_format: Format, reader: anytype) !Oid { | |
| 77 | 77 | return switch (oid_format) { |
| 78 | 78 | inline else => |tag| @unionInit(Oid, @tagName(tag), try reader.readBytesNoEof(tag.byteLength())), |
| 79 | 79 | }; |
| ... | ... | @@ -166,7 +166,7 @@ pub const Diagnostics = struct { |
| 166 | 166 | pub const Repository = struct { |
| 167 | 167 | odb: Odb, |
| 168 | 168 | |
| 169 | pub fn init(allocator: Allocator, format: Oid.Format, pack_file: std.fs.File, index_file: std.fs.File) !Repository { | |
| 169 | pub fn init(allocator: Allocator, format: Oid.Format, pack_file: *std.fs.File.Reader, index_file: std.fs.File) !Repository { | |
| 170 | 170 | return .{ .odb = try Odb.init(allocator, format, pack_file, index_file) }; |
| 171 | 171 | } |
| 172 | 172 | |
| ... | ... | @@ -335,14 +335,14 @@ pub const Repository = struct { |
| 335 | 335 | /// [pack-format](https://git-scm.com/docs/pack-format). |
| 336 | 336 | const Odb = struct { |
| 337 | 337 | format: Oid.Format, |
| 338 | pack_file: std.fs.File, | |
| 338 | pack_file: *std.fs.File.Reader, | |
| 339 | 339 | index_header: IndexHeader, |
| 340 | 340 | index_file: std.fs.File, |
| 341 | 341 | cache: ObjectCache = .{}, |
| 342 | 342 | allocator: Allocator, |
| 343 | 343 | |
| 344 | 344 | /// Initializes the database from open pack and index files. |
| 345 | fn init(allocator: Allocator, format: Oid.Format, pack_file: std.fs.File, index_file: std.fs.File) !Odb { | |
| 345 | fn init(allocator: Allocator, format: Oid.Format, pack_file: *std.fs.File.Reader, index_file: std.fs.File) !Odb { | |
| 346 | 346 | try pack_file.seekTo(0); |
| 347 | 347 | try index_file.seekTo(0); |
| 348 | 348 | const index_header = try IndexHeader.read(index_file.deprecatedReader()); |
| ... | ... | @@ -362,14 +362,14 @@ const Odb = struct { |
| 362 | 362 | |
| 363 | 363 | /// Reads the object at the current position in the database. |
| 364 | 364 | fn readObject(odb: *Odb) !Object { |
| 365 | var base_offset = try odb.pack_file.getPos(); | |
| 365 | var base_offset = odb.pack_file.logicalPos(); | |
| 366 | 366 | var base_header: EntryHeader = undefined; |
| 367 | 367 | var delta_offsets: std.ArrayListUnmanaged(u64) = .empty; |
| 368 | 368 | defer delta_offsets.deinit(odb.allocator); |
| 369 | 369 | const base_object = while (true) { |
| 370 | 370 | if (odb.cache.get(base_offset)) |base_object| break base_object; |
| 371 | 371 | |
| 372 | base_header = try EntryHeader.read(odb.format, odb.pack_file.deprecatedReader()); | |
| 372 | base_header = try EntryHeader.read(odb.format, odb.pack_file.interface.adaptToOldInterface()); | |
| 373 | 373 | switch (base_header) { |
| 374 | 374 | .ofs_delta => |ofs_delta| { |
| 375 | 375 | try delta_offsets.append(odb.allocator, base_offset); |
| ... | ... | @@ -379,10 +379,10 @@ const Odb = struct { |
| 379 | 379 | .ref_delta => |ref_delta| { |
| 380 | 380 | try delta_offsets.append(odb.allocator, base_offset); |
| 381 | 381 | try odb.seekOid(ref_delta.base_object); |
| 382 | base_offset = try odb.pack_file.getPos(); | |
| 382 | base_offset = odb.pack_file.logicalPos(); | |
| 383 | 383 | }, |
| 384 | 384 | else => { |
| 385 | const base_data = try readObjectRaw(odb.allocator, odb.pack_file.deprecatedReader(), base_header.uncompressedLength()); | |
| 385 | const base_data = try readObjectRaw(odb.allocator, &odb.pack_file.interface, base_header.uncompressedLength()); | |
| 386 | 386 | errdefer odb.allocator.free(base_data); |
| 387 | 387 | const base_object: Object = .{ .type = base_header.objectType(), .data = base_data }; |
| 388 | 388 | try odb.cache.put(odb.allocator, base_offset, base_object); |
| ... | ... | @@ -1227,7 +1227,7 @@ const IndexEntry = struct { |
| 1227 | 1227 | |
| 1228 | 1228 | /// Writes out a version 2 index for the given packfile, as documented in |
| 1229 | 1229 | /// [pack-format](https://git-scm.com/docs/pack-format). |
| 1230 | pub fn indexPack(allocator: Allocator, format: Oid.Format, pack: std.fs.File, index_writer: anytype) !void { | |
| 1230 | pub fn indexPack(allocator: Allocator, format: Oid.Format, pack: *std.fs.File.Reader, index_writer: anytype) !void { | |
| 1231 | 1231 | try pack.seekTo(0); |
| 1232 | 1232 | |
| 1233 | 1233 | var index_entries: std.AutoHashMapUnmanaged(Oid, IndexEntry) = .empty; |
| ... | ... | @@ -1324,12 +1324,11 @@ pub fn indexPack(allocator: Allocator, format: Oid.Format, pack: std.fs.File, in |
| 1324 | 1324 | fn indexPackFirstPass( |
| 1325 | 1325 | allocator: Allocator, |
| 1326 | 1326 | format: Oid.Format, |
| 1327 | pack: std.fs.File, | |
| 1327 | pack: *std.fs.File.Reader, | |
| 1328 | 1328 | index_entries: *std.AutoHashMapUnmanaged(Oid, IndexEntry), |
| 1329 | 1329 | pending_deltas: *std.ArrayListUnmanaged(IndexEntry), |
| 1330 | 1330 | ) !Oid { |
| 1331 | var pack_buffered_reader = std.io.bufferedReader(pack.deprecatedReader()); | |
| 1332 | var pack_counting_reader = std.io.countingReader(pack_buffered_reader.reader()); | |
| 1331 | var pack_counting_reader = std.io.countingReader(pack.interface.adaptToOldInterface()); | |
| 1333 | 1332 | var pack_hashed_reader = hashedReader(pack_counting_reader.reader(), Oid.Hasher.init(format)); |
| 1334 | 1333 | const pack_reader = pack_hashed_reader.reader(); |
| 1335 | 1334 | |
| ... | ... | @@ -1340,15 +1339,19 @@ fn indexPackFirstPass( |
| 1340 | 1339 | const entry_offset = pack_counting_reader.bytes_read; |
| 1341 | 1340 | var entry_crc32_reader = hashedReader(pack_reader, std.hash.Crc32.init()); |
| 1342 | 1341 | const entry_header = try EntryHeader.read(format, entry_crc32_reader.reader()); |
| 1342 | var adapter_buffer: [1024]u8 = undefined; | |
| 1343 | var adapter = entry_crc32_reader.reader().adaptToNewApi(&adapter_buffer); | |
| 1344 | var flate_buffer: [std.compress.flate.max_window_len]u8 = undefined; | |
| 1345 | var entry_decompress_stream: std.compress.flate.Decompress = .init(&adapter.new_interface, .zlib, &flate_buffer); | |
| 1346 | const old = entry_decompress_stream.reader.adaptToOldInterface(); | |
| 1347 | var entry_counting_reader = std.io.countingReader(old); | |
| 1343 | 1348 | switch (entry_header) { |
| 1344 | 1349 | .commit, .tree, .blob, .tag => |object| { |
| 1345 | var entry_decompress_stream = std.compress.zlib.decompressor(entry_crc32_reader.reader()); | |
| 1346 | var entry_counting_reader = std.io.countingReader(entry_decompress_stream.reader()); | |
| 1347 | 1350 | var entry_hashed_writer = hashedWriter(std.io.null_writer, Oid.Hasher.init(format)); |
| 1348 | 1351 | const entry_writer = entry_hashed_writer.writer(); |
| 1349 | 1352 | // The object header is not included in the pack data but is |
| 1350 | 1353 | // part of the object's ID |
| 1351 | try entry_writer.print("{s} {}\x00", .{ @tagName(entry_header), object.uncompressed_length }); | |
| 1354 | try entry_writer.print("{s} {d}\x00", .{ @tagName(entry_header), object.uncompressed_length }); | |
| 1352 | 1355 | var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init(); |
| 1353 | 1356 | try fifo.pump(entry_counting_reader.reader(), entry_writer); |
| 1354 | 1357 | if (entry_counting_reader.bytes_read != object.uncompressed_length) { |
| ... | ... | @@ -1361,8 +1364,6 @@ fn indexPackFirstPass( |
| 1361 | 1364 | }); |
| 1362 | 1365 | }, |
| 1363 | 1366 | inline .ofs_delta, .ref_delta => |delta| { |
| 1364 | var entry_decompress_stream = std.compress.zlib.decompressor(entry_crc32_reader.reader()); | |
| 1365 | var entry_counting_reader = std.io.countingReader(entry_decompress_stream.reader()); | |
| 1366 | 1367 | var fifo = std.fifo.LinearFifo(u8, .{ .Static = 4096 }).init(); |
| 1367 | 1368 | try fifo.pump(entry_counting_reader.reader(), std.io.null_writer); |
| 1368 | 1369 | if (entry_counting_reader.bytes_read != delta.uncompressed_length) { |
| ... | ... | @@ -1377,7 +1378,7 @@ fn indexPackFirstPass( |
| 1377 | 1378 | } |
| 1378 | 1379 | |
| 1379 | 1380 | const pack_checksum = pack_hashed_reader.hasher.finalResult(); |
| 1380 | const recorded_checksum = try Oid.readBytes(format, pack_buffered_reader.reader()); | |
| 1381 | const recorded_checksum = try Oid.readBytes(format, pack.interface.adaptToOldInterface()); | |
| 1381 | 1382 | if (!mem.eql(u8, pack_checksum.slice(), recorded_checksum.slice())) { |
| 1382 | 1383 | return error.CorruptedPack; |
| 1383 | 1384 | } |
| ... | ... | @@ -1394,7 +1395,7 @@ fn indexPackFirstPass( |
| 1394 | 1395 | fn indexPackHashDelta( |
| 1395 | 1396 | allocator: Allocator, |
| 1396 | 1397 | format: Oid.Format, |
| 1397 | pack: std.fs.File, | |
| 1398 | pack: *std.fs.File.Reader, | |
| 1398 | 1399 | delta: IndexEntry, |
| 1399 | 1400 | index_entries: std.AutoHashMapUnmanaged(Oid, IndexEntry), |
| 1400 | 1401 | cache: *ObjectCache, |
| ... | ... | @@ -1408,7 +1409,7 @@ fn indexPackHashDelta( |
| 1408 | 1409 | if (cache.get(base_offset)) |base_object| break base_object; |
| 1409 | 1410 | |
| 1410 | 1411 | try pack.seekTo(base_offset); |
| 1411 | base_header = try EntryHeader.read(format, pack.deprecatedReader()); | |
| 1412 | base_header = try EntryHeader.read(format, pack.interface.adaptToOldInterface()); | |
| 1412 | 1413 | switch (base_header) { |
| 1413 | 1414 | .ofs_delta => |ofs_delta| { |
| 1414 | 1415 | try delta_offsets.append(allocator, base_offset); |
| ... | ... | @@ -1419,7 +1420,7 @@ fn indexPackHashDelta( |
| 1419 | 1420 | base_offset = (index_entries.get(ref_delta.base_object) orelse return null).offset; |
| 1420 | 1421 | }, |
| 1421 | 1422 | else => { |
| 1422 | const base_data = try readObjectRaw(allocator, pack.deprecatedReader(), base_header.uncompressedLength()); | |
| 1423 | const base_data = try readObjectRaw(allocator, &pack.interface, base_header.uncompressedLength()); | |
| 1423 | 1424 | errdefer allocator.free(base_data); |
| 1424 | 1425 | const base_object: Object = .{ .type = base_header.objectType(), .data = base_data }; |
| 1425 | 1426 | try cache.put(allocator, base_offset, base_object); |
| ... | ... | @@ -1444,7 +1445,7 @@ fn indexPackHashDelta( |
| 1444 | 1445 | fn resolveDeltaChain( |
| 1445 | 1446 | allocator: Allocator, |
| 1446 | 1447 | format: Oid.Format, |
| 1447 | pack: std.fs.File, | |
| 1448 | pack: *std.fs.File.Reader, | |
| 1448 | 1449 | base_object: Object, |
| 1449 | 1450 | delta_offsets: []const u64, |
| 1450 | 1451 | cache: *ObjectCache, |
| ... | ... | @@ -1456,8 +1457,8 @@ fn resolveDeltaChain( |
| 1456 | 1457 | |
| 1457 | 1458 | const delta_offset = delta_offsets[i]; |
| 1458 | 1459 | try pack.seekTo(delta_offset); |
| 1459 | const delta_header = try EntryHeader.read(format, pack.deprecatedReader()); | |
| 1460 | const delta_data = try readObjectRaw(allocator, pack.deprecatedReader(), delta_header.uncompressedLength()); | |
| 1460 | const delta_header = try EntryHeader.read(format, pack.interface.adaptToOldInterface()); | |
| 1461 | const delta_data = try readObjectRaw(allocator, &pack.interface, delta_header.uncompressedLength()); | |
| 1461 | 1462 | defer allocator.free(delta_data); |
| 1462 | 1463 | var delta_stream = std.io.fixedBufferStream(delta_data); |
| 1463 | 1464 | const delta_reader = delta_stream.reader(); |
| ... | ... | @@ -1481,18 +1482,14 @@ fn resolveDeltaChain( |
| 1481 | 1482 | /// Reads the complete contents of an object from `reader`. This function may |
| 1482 | 1483 | /// read more bytes than required from `reader`, so the reader position after |
| 1483 | 1484 | /// returning is not reliable. |
| 1484 | fn readObjectRaw(allocator: Allocator, reader: anytype, size: u64) ![]u8 { | |
| 1485 | fn readObjectRaw(allocator: Allocator, reader: *std.Io.Reader, size: u64) ![]u8 { | |
| 1485 | 1486 | const alloc_size = std.math.cast(usize, size) orelse return error.ObjectTooLarge; |
| 1486 | var buffered_reader = std.io.bufferedReader(reader); | |
| 1487 | var decompress_stream = std.compress.zlib.decompressor(buffered_reader.reader()); | |
| 1488 | const data = try allocator.alloc(u8, alloc_size); | |
| 1489 | errdefer allocator.free(data); | |
| 1490 | try decompress_stream.reader().readNoEof(data); | |
| 1491 | _ = decompress_stream.reader().readByte() catch |e| switch (e) { | |
| 1492 | error.EndOfStream => return data, | |
| 1493 | else => |other| return other, | |
| 1494 | }; | |
| 1495 | return error.InvalidFormat; | |
| 1487 | var aw: std.Io.Writer.Allocating = .init(allocator); | |
| 1488 | try aw.ensureTotalCapacity(alloc_size); | |
| 1489 | defer aw.deinit(); | |
| 1490 | var decompress: std.compress.flate.Decompress = .init(reader, .zlib, &.{}); | |
| 1491 | try decompress.reader.streamExact(&aw.writer, alloc_size); | |
| 1492 | return aw.toOwnedSlice(); | |
| 1496 | 1493 | } |
| 1497 | 1494 | |
| 1498 | 1495 | /// Expands delta data from `delta_reader` to `writer`. `base_object` must |
src/link/Elf/Object.zig+7-8| ... | ... | @@ -1198,15 +1198,14 @@ pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index |
| 1198 | 1198 | const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*; |
| 1199 | 1199 | switch (chdr.ch_type) { |
| 1200 | 1200 | .ZLIB => { |
| 1201 | var stream = std.io.fixedBufferStream(data[@sizeOf(elf.Elf64_Chdr)..]); | |
| 1202 | var zlib_stream = std.compress.zlib.decompressor(stream.reader()); | |
| 1201 | var stream: std.Io.Reader = .fixed(data[@sizeOf(elf.Elf64_Chdr)..]); | |
| 1202 | var zlib_stream: std.compress.flate.Decompress = .init(&stream, .zlib, &.{}); | |
| 1203 | 1203 | const size = std.math.cast(usize, chdr.ch_size) orelse return error.Overflow; |
| 1204 | const decomp = try gpa.alloc(u8, size); | |
| 1205 | const nread = zlib_stream.reader().readAll(decomp) catch return error.InputOutput; | |
| 1206 | if (nread != decomp.len) { | |
| 1207 | return error.InputOutput; | |
| 1208 | } | |
| 1209 | return decomp; | |
| 1204 | var aw: std.Io.Writer.Allocating = .init(gpa); | |
| 1205 | try aw.ensureUnusedCapacity(size); | |
| 1206 | defer aw.deinit(); | |
| 1207 | _ = try zlib_stream.reader.streamRemaining(&aw.writer); | |
| 1208 | return aw.toOwnedSlice(); | |
| 1210 | 1209 | }, |
| 1211 | 1210 | else => @panic("TODO unhandled compression scheme"), |
| 1212 | 1211 | } |