Skip to content

Commit af2ac24

Browse files
committed
Fetch: handle compressed git+http
1 parent 5ce8e93 commit af2ac24

File tree

4 files changed

+87
-90
lines changed

4 files changed

+87
-90
lines changed

lib/std/http.zig

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,14 @@ pub const ContentEncoding = enum {
292292
});
293293
return map.get(s);
294294
}
295+
296+
pub fn minBufferCapacity(ce: ContentEncoding) usize {
297+
return switch (ce) {
298+
.zstd => std.compress.zstd.default_window_len,
299+
.gzip, .deflate => std.compress.flate.max_window_len,
300+
.compress, .identity => 0,
301+
};
302+
}
295303
};
296304

297305
pub const Connection = enum {
@@ -464,8 +472,8 @@ pub const Reader = struct {
464472
transfer_encoding: TransferEncoding,
465473
content_length: ?u64,
466474
content_encoding: ContentEncoding,
467-
decompressor: *Decompressor,
468-
decompression_buffer: []u8,
475+
decompress: *Decompress,
476+
decompress_buffer: []u8,
469477
) *std.Io.Reader {
470478
if (transfer_encoding == .none and content_length == null) {
471479
assert(reader.state == .received_head);
@@ -475,22 +483,22 @@ pub const Reader = struct {
475483
return reader.in;
476484
},
477485
.deflate => {
478-
decompressor.* = .{ .flate = .init(reader.in, .zlib, decompression_buffer) };
479-
return &decompressor.flate.reader;
486+
decompress.* = .{ .flate = .init(reader.in, .zlib, decompress_buffer) };
487+
return &decompress.flate.reader;
480488
},
481489
.gzip => {
482-
decompressor.* = .{ .flate = .init(reader.in, .gzip, decompression_buffer) };
483-
return &decompressor.flate.reader;
490+
decompress.* = .{ .flate = .init(reader.in, .gzip, decompress_buffer) };
491+
return &decompress.flate.reader;
484492
},
485493
.zstd => {
486-
decompressor.* = .{ .zstd = .init(reader.in, decompression_buffer, .{ .verify_checksum = false }) };
487-
return &decompressor.zstd.reader;
494+
decompress.* = .{ .zstd = .init(reader.in, decompress_buffer, .{ .verify_checksum = false }) };
495+
return &decompress.zstd.reader;
488496
},
489497
.compress => unreachable,
490498
}
491499
}
492500
const transfer_reader = bodyReader(reader, transfer_buffer, transfer_encoding, content_length);
493-
return decompressor.init(transfer_reader, decompression_buffer, content_encoding);
501+
return decompress.init(transfer_reader, decompress_buffer, content_encoding);
494502
}
495503

496504
fn contentLengthStream(
@@ -692,33 +700,33 @@ pub const Reader = struct {
692700
}
693701
};
694702

695-
pub const Decompressor = union(enum) {
703+
pub const Decompress = union(enum) {
696704
flate: std.compress.flate.Decompress,
697705
zstd: std.compress.zstd.Decompress,
698706
none: *std.Io.Reader,
699707

700708
pub fn init(
701-
decompressor: *Decompressor,
709+
decompress: *Decompress,
702710
transfer_reader: *std.Io.Reader,
703711
buffer: []u8,
704712
content_encoding: ContentEncoding,
705713
) *std.Io.Reader {
706714
switch (content_encoding) {
707715
.identity => {
708-
decompressor.* = .{ .none = transfer_reader };
716+
decompress.* = .{ .none = transfer_reader };
709717
return transfer_reader;
710718
},
711719
.deflate => {
712-
decompressor.* = .{ .flate = .init(transfer_reader, .zlib, buffer) };
713-
return &decompressor.flate.reader;
720+
decompress.* = .{ .flate = .init(transfer_reader, .zlib, buffer) };
721+
return &decompress.flate.reader;
714722
},
715723
.gzip => {
716-
decompressor.* = .{ .flate = .init(transfer_reader, .gzip, buffer) };
717-
return &decompressor.flate.reader;
724+
decompress.* = .{ .flate = .init(transfer_reader, .gzip, buffer) };
725+
return &decompress.flate.reader;
718726
},
719727
.zstd => {
720-
decompressor.* = .{ .zstd = .init(transfer_reader, buffer, .{ .verify_checksum = false }) };
721-
return &decompressor.zstd.reader;
728+
decompress.* = .{ .zstd = .init(transfer_reader, buffer, .{ .verify_checksum = false }) };
729+
return &decompress.zstd.reader;
722730
},
723731
.compress => unreachable,
724732
}

lib/std/http/Client.zig

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -724,8 +724,8 @@ pub const Response = struct {
724724
pub fn readerDecompressing(
725725
response: *Response,
726726
transfer_buffer: []u8,
727-
decompressor: *http.Decompressor,
728-
decompression_buffer: []u8,
727+
decompress: *http.Decompress,
728+
decompress_buffer: []u8,
729729
) *Reader {
730730
response.head.invalidateStrings();
731731
const head = &response.head;
@@ -734,8 +734,8 @@ pub const Response = struct {
734734
head.transfer_encoding,
735735
head.content_length,
736736
head.content_encoding,
737-
decompressor,
738-
decompression_buffer,
737+
decompress,
738+
decompress_buffer,
739739
);
740740
}
741741

@@ -1797,8 +1797,8 @@ pub fn fetch(client: *Client, options: FetchOptions) FetchError!FetchResult {
17971797
defer if (options.decompress_buffer == null) client.allocator.free(decompress_buffer);
17981798

17991799
var transfer_buffer: [64]u8 = undefined;
1800-
var decompressor: http.Decompressor = undefined;
1801-
const reader = response.readerDecompressing(&transfer_buffer, &decompressor, decompress_buffer);
1800+
var decompress: http.Decompress = undefined;
1801+
const reader = response.readerDecompressing(&transfer_buffer, &decompress, decompress_buffer);
18021802

18031803
_ = reader.streamRemaining(response_writer) catch |err| switch (err) {
18041804
error.ReadFailed => return response.bodyErr().?,

src/Package/Fetch.zig

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,9 @@ const Resource = union(enum) {
883883
const HttpRequest = struct {
884884
request: std.http.Client.Request,
885885
response: std.http.Client.Response,
886-
buffer: []u8,
886+
transfer_buffer: []u8,
887+
decompress: std.http.Decompress,
888+
decompress_buffer: []u8,
887889
};
888890

889891
fn deinit(resource: *Resource) void {
@@ -892,7 +894,6 @@ const Resource = union(enum) {
892894
.http_request => |*http_request| http_request.request.deinit(),
893895
.git => |*git_resource| {
894896
git_resource.fetch_stream.deinit();
895-
git_resource.session.deinit();
896897
},
897898
.dir => |*dir| dir.close(),
898899
}
@@ -902,7 +903,11 @@ const Resource = union(enum) {
902903
fn reader(resource: *Resource) *std.Io.Reader {
903904
return switch (resource.*) {
904905
.file => |*file_reader| return &file_reader.interface,
905-
.http_request => |*http_request| return http_request.response.reader(http_request.buffer),
906+
.http_request => |*http_request| return http_request.response.readerDecompressing(
907+
http_request.transfer_buffer,
908+
&http_request.decompress,
909+
http_request.decompress_buffer,
910+
),
906911
.git => |*g| return &g.fetch_stream.reader,
907912
.dir => unreachable,
908913
};
@@ -971,7 +976,6 @@ const FileType = enum {
971976
const init_resource_buffer_size = git.Packet.max_data_length;
972977

973978
fn initResource(f: *Fetch, uri: std.Uri, resource: *Resource, reader_buffer: []u8) RunError!void {
974-
const gpa = f.arena.child_allocator;
975979
const arena = f.arena.allocator();
976980
const eb = &f.error_bundle;
977981

@@ -995,7 +999,9 @@ fn initResource(f: *Fetch, uri: std.Uri, resource: *Resource, reader_buffer: []u
995999
.request = http_client.request(.GET, uri, .{}) catch |err|
9961000
return f.fail(f.location_tok, try eb.printString("unable to connect to server: {t}", .{err})),
9971001
.response = undefined,
998-
.buffer = reader_buffer,
1002+
.transfer_buffer = reader_buffer,
1003+
.decompress_buffer = &.{},
1004+
.decompress = undefined,
9991005
} };
10001006
const request = &resource.http_request.request;
10011007
errdefer request.deinit();
@@ -1019,6 +1025,7 @@ fn initResource(f: *Fetch, uri: std.Uri, resource: *Resource, reader_buffer: []u
10191025
.{ response.head.status, response.head.status.phrase() orelse "" },
10201026
));
10211027

1028+
resource.http_request.decompress_buffer = try arena.alloc(u8, response.head.content_encoding.minBufferCapacity());
10221029
return;
10231030
}
10241031

@@ -1027,13 +1034,12 @@ fn initResource(f: *Fetch, uri: std.Uri, resource: *Resource, reader_buffer: []u
10271034
{
10281035
var transport_uri = uri;
10291036
transport_uri.scheme = uri.scheme["git+".len..];
1030-
var session = git.Session.init(gpa, http_client, transport_uri, reader_buffer) catch |err| {
1031-
return f.fail(f.location_tok, try eb.printString(
1032-
"unable to discover remote git server capabilities: {s}",
1033-
.{@errorName(err)},
1034-
));
1037+
var session = git.Session.init(arena, http_client, transport_uri, reader_buffer) catch |err| {
1038+
return f.fail(
1039+
f.location_tok,
1040+
try eb.printString("unable to discover remote git server capabilities: {t}", .{err}),
1041+
);
10351042
};
1036-
errdefer session.deinit();
10371043

10381044
const want_oid = want_oid: {
10391045
const want_ref =

0 commit comments

Comments
 (0)