Skip to content

Commit 9b1ca98

Browse files
committed
support xz compressed tarballs in the package manager
This includes a breaking change: std.compress.gzip.GzipStream renamed to std.compress.gzip.Decompress This follows the same naming convention as std.compress.xz so that the stream type can be passed as a comptime parameter.
1 parent 6a7ee1f commit 9b1ca98

File tree

2 files changed

+26
-16
lines changed

2 files changed

+26
-16
lines changed

lib/std/compress/gzip.zig

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// Decompressor for GZIP data streams (RFC1952)
33

4-
const std = @import("std");
4+
const std = @import("../std.zig");
55
const io = std.io;
66
const fs = std.fs;
77
const testing = std.testing;
@@ -17,10 +17,7 @@ const FCOMMENT = 1 << 4;
1717

1818
const max_string_len = 1024;
1919

20-
/// TODO: the fully qualified namespace to this declaration is
21-
/// std.compress.gzip.GzipStream which has a redundant "gzip" in the name.
22-
/// Instead, it should be `std.compress.gzip.Stream`.
23-
pub fn GzipStream(comptime ReaderType: type) type {
20+
pub fn Decompress(comptime ReaderType: type) type {
2421
return struct {
2522
const Self = @This();
2623

@@ -154,14 +151,14 @@ pub fn GzipStream(comptime ReaderType: type) type {
154151
};
155152
}
156153

157-
pub fn gzipStream(allocator: mem.Allocator, reader: anytype) !GzipStream(@TypeOf(reader)) {
158-
return GzipStream(@TypeOf(reader)).init(allocator, reader);
154+
pub fn decompress(allocator: mem.Allocator, reader: anytype) !Decompress(@TypeOf(reader)) {
155+
return Decompress(@TypeOf(reader)).init(allocator, reader);
159156
}
160157

161158
fn testReader(data: []const u8, comptime expected: []const u8) !void {
162159
var in_stream = io.fixedBufferStream(data);
163160

164-
var gzip_stream = try gzipStream(testing.allocator, in_stream.reader());
161+
var gzip_stream = try decompress(testing.allocator, in_stream.reader());
165162
defer gzip_stream.deinit();
166163

167164
// Read and decompress the whole file

src/Package.zig

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -370,14 +370,11 @@ fn fetchAndUnpack(
370370
if (mem.endsWith(u8, uri.path, ".tar.gz")) {
371371
// I observed the gzip stream to read 1 byte at a time, so I am using a
372372
// buffered reader on the front of it.
373-
var br = std.io.bufferedReaderSize(std.crypto.tls.max_ciphertext_record_len, req.reader());
374-
375-
var gzip_stream = try std.compress.gzip.gzipStream(gpa, br.reader());
376-
defer gzip_stream.deinit();
377-
378-
try std.tar.pipeToFileSystem(tmp_directory.handle, gzip_stream.reader(), .{
379-
.strip_components = 1,
380-
});
373+
try unpackTarball(gpa, &req, tmp_directory.handle, std.compress.gzip);
374+
} else if (mem.endsWith(u8, uri.path, ".tar.xz")) {
375+
// I have not checked what buffer sizes the xz decompression implementation uses
376+
// by default, so the same logic applies for buffering the reader as for gzip.
377+
try unpackTarball(gpa, &req, tmp_directory.handle, std.compress.xz);
381378
} else {
382379
return reportError(
383380
ini,
@@ -430,6 +427,22 @@ fn fetchAndUnpack(
430427
return createWithDir(gpa, fqn, global_cache_directory, pkg_dir_sub_path, build_zig_basename);
431428
}
432429

430+
fn unpackTarball(
431+
gpa: Allocator,
432+
req: *std.http.Client.Request,
433+
out_dir: fs.Dir,
434+
comptime compression: type,
435+
) !void {
436+
var br = std.io.bufferedReaderSize(std.crypto.tls.max_ciphertext_record_len, req.reader());
437+
438+
var decompress = try compression.decompress(gpa, br.reader());
439+
defer decompress.deinit();
440+
441+
try std.tar.pipeToFileSystem(out_dir, decompress.reader(), .{
442+
.strip_components = 1,
443+
});
444+
}
445+
433446
fn reportError(
434447
ini: std.Ini,
435448
comp_directory: Compilation.Directory,

0 commit comments

Comments
 (0)