authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-06 19:39:39-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-07 10:04:52-07:00
log4567241d8d238c47c0e0844af15764ccc851c8fc
treef3d75ff145b92cc76980ea6bb40008a4eacdbebf
parent6b411f147c49ce0a0004f314b9c40e78ed804c5b

fetch: avoid copying Resource


2 files changed, 25 insertions(+), 27 deletions(-)

src/Package/Fetch.zig+22-24
...@@ -400,7 +400,8 @@ pub fn run(f: *Fetch) RunError!void {...@@ -400,7 +400,8 @@ pub fn run(f: *Fetch) RunError!void {
400 .{ path_or_url, file_err, uri_err },400 .{ path_or_url, file_err, uri_err },
401 ));401 ));
402 };402 };
403 var resource = try f.initResource(uri, &server_header_buffer);403 var resource: Resource = undefined;
404 try f.initResource(uri, &resource, &server_header_buffer);
404 return f.runResource(try uri.path.toRawMaybeAlloc(arena), &resource, null);405 return f.runResource(try uri.path.toRawMaybeAlloc(arena), &resource, null);
405 }406 }
406 },407 },
...@@ -466,7 +467,8 @@ pub fn run(f: *Fetch) RunError!void {...@@ -466,7 +467,8 @@ pub fn run(f: *Fetch) RunError!void {
466 try eb.printString("invalid URI: {s}", .{@errorName(err)}),467 try eb.printString("invalid URI: {s}", .{@errorName(err)}),
467 );468 );
468 var buffer: [init_resource_buffer_size]u8 = undefined;469 var buffer: [init_resource_buffer_size]u8 = undefined;
469 var resource = try f.initResource(uri, &buffer);470 var resource: Resource = undefined;
471 try f.initResource(uri, &resource, &buffer);
470 return f.runResource(try uri.path.toRawMaybeAlloc(arena), &resource, remote.hash);472 return f.runResource(try uri.path.toRawMaybeAlloc(arena), &resource, remote.hash);
471}473}
472474
...@@ -880,7 +882,7 @@ const Resource = union(enum) {...@@ -880,7 +882,7 @@ const Resource = union(enum) {
880882
881 const HttpRequest = struct {883 const HttpRequest = struct {
882 request: std.http.Client.Request,884 request: std.http.Client.Request,
883 head: std.http.Client.Response.Head,885 response: std.http.Client.Response,
884 buffer: []u8,886 buffer: []u8,
885 };887 };
886888
...@@ -900,13 +902,7 @@ const Resource = union(enum) {...@@ -900,13 +902,7 @@ const Resource = union(enum) {
900 fn reader(resource: *Resource) *std.Io.Reader {902 fn reader(resource: *Resource) *std.Io.Reader {
901 return switch (resource.*) {903 return switch (resource.*) {
902 .file => |*file_reader| return &file_reader.interface,904 .file => |*file_reader| return &file_reader.interface,
903 .http_request => |*http_request| {905 .http_request => |*http_request| return http_request.response.reader(http_request.buffer),
904 const response: std.http.Client.Response = .{
905 .request = &http_request.request,
906 .head = http_request.head,
907 };
908 return response.reader(http_request.buffer);
909 },
910 .git => |*g| return &g.fetch_stream.reader,906 .git => |*g| return &g.fetch_stream.reader,
911 .dir => unreachable,907 .dir => unreachable,
912 };908 };
...@@ -974,7 +970,7 @@ const FileType = enum {...@@ -974,7 +970,7 @@ const FileType = enum {
974970
975const init_resource_buffer_size = git.Packet.max_data_length;971const init_resource_buffer_size = git.Packet.max_data_length;
976972
977fn initResource(f: *Fetch, uri: std.Uri, reader_buffer: []u8) RunError!Resource {973fn initResource(f: *Fetch, uri: std.Uri, resource: *Resource, reader_buffer: []u8) RunError!void {
978 const gpa = f.arena.child_allocator;974 const gpa = f.arena.child_allocator;
979 const arena = f.arena.allocator();975 const arena = f.arena.allocator();
980 const eb = &f.error_bundle;976 const eb = &f.error_bundle;
...@@ -986,7 +982,8 @@ fn initResource(f: *Fetch, uri: std.Uri, reader_buffer: []u8) RunError!Resource...@@ -986,7 +982,8 @@ fn initResource(f: *Fetch, uri: std.Uri, reader_buffer: []u8) RunError!Resource
986 f.parent_package_root, path, err,982 f.parent_package_root, path, err,
987 }));983 }));
988 };984 };
989 return .{ .file = file.reader(reader_buffer) };985 resource.* = .{ .file = file.reader(reader_buffer) };
986 return;
990 }987 }
991988
992 const http_client = f.job_queue.http_client;989 const http_client = f.job_queue.http_client;
...@@ -994,15 +991,21 @@ fn initResource(f: *Fetch, uri: std.Uri, reader_buffer: []u8) RunError!Resource...@@ -994,15 +991,21 @@ fn initResource(f: *Fetch, uri: std.Uri, reader_buffer: []u8) RunError!Resource
994 if (ascii.eqlIgnoreCase(uri.scheme, "http") or991 if (ascii.eqlIgnoreCase(uri.scheme, "http") or
995 ascii.eqlIgnoreCase(uri.scheme, "https"))992 ascii.eqlIgnoreCase(uri.scheme, "https"))
996 {993 {
997 var request = http_client.request(.GET, uri, .{}) catch |err|994 resource.* = .{ .http_request = .{
998 return f.fail(f.location_tok, try eb.printString("unable to connect to server: {t}", .{err}));995 .request = http_client.request(.GET, uri, .{}) catch |err|
996 return f.fail(f.location_tok, try eb.printString("unable to connect to server: {t}", .{err})),
997 .response = undefined,
998 .buffer = reader_buffer,
999 } };
1000 const request = &resource.http_request.request;
999 defer request.deinit();1001 defer request.deinit();
10001002
1001 request.sendBodiless() catch |err|1003 request.sendBodiless() catch |err|
1002 return f.fail(f.location_tok, try eb.printString("HTTP request failed: {t}", .{err}));1004 return f.fail(f.location_tok, try eb.printString("HTTP request failed: {t}", .{err}));
10031005
1004 var redirect_buffer: [1024]u8 = undefined;1006 var redirect_buffer: [1024]u8 = undefined;
1005 const response = request.receiveHead(&redirect_buffer) catch |err|1007 const response = &resource.http_request.response;
1008 response.* = request.receiveHead(&redirect_buffer) catch |err|
1006 return f.fail(f.location_tok, try eb.printString("invalid HTTP response: {t}", .{err}));1009 return f.fail(f.location_tok, try eb.printString("invalid HTTP response: {t}", .{err}));
10071010
1008 if (response.head.status != .ok) return f.fail(f.location_tok, try eb.printString(1011 if (response.head.status != .ok) return f.fail(f.location_tok, try eb.printString(
...@@ -1010,11 +1013,7 @@ fn initResource(f: *Fetch, uri: std.Uri, reader_buffer: []u8) RunError!Resource...@@ -1010,11 +1013,7 @@ fn initResource(f: *Fetch, uri: std.Uri, reader_buffer: []u8) RunError!Resource
1010 .{ response.head.status, response.head.status.phrase() orelse "" },1013 .{ response.head.status, response.head.status.phrase() orelse "" },
1011 ));1014 ));
10121015
1013 return .{ .http_request = .{1016 return;
1014 .request = request,
1015 .head = response.head,
1016 .buffer = reader_buffer,
1017 } };
1018 }1017 }
10191018
1020 if (ascii.eqlIgnoreCase(uri.scheme, "git+http") or1019 if (ascii.eqlIgnoreCase(uri.scheme, "git+http") or
...@@ -1087,13 +1086,12 @@ fn initResource(f: *Fetch, uri: std.Uri, reader_buffer: []u8) RunError!Resource...@@ -1087,13 +1086,12 @@ fn initResource(f: *Fetch, uri: std.Uri, reader_buffer: []u8) RunError!Resource
1087 };1086 };
1088 errdefer fetch_stream.deinit();1087 errdefer fetch_stream.deinit();
10891088
1090 if (true) @panic("TODO this moves fetch_stream, invalidating its reader");1089 resource.* = .{ .git = .{
1091
1092 return .{ .git = .{
1093 .session = session,1090 .session = session,
1094 .fetch_stream = fetch_stream,1091 .fetch_stream = fetch_stream,
1095 .want_oid = want_oid,1092 .want_oid = want_oid,
1096 } };1093 } };
1094 return;
1097 }1095 }
10981096
1099 return f.fail(f.location_tok, try eb.printString("unsupported URL scheme: {s}", .{uri.scheme}));1097 return f.fail(f.location_tok, try eb.printString("unsupported URL scheme: {s}", .{uri.scheme}));
...@@ -1111,7 +1109,7 @@ fn unpackResource(...@@ -1111,7 +1109,7 @@ fn unpackResource(
1111 return f.fail(f.location_tok, try eb.printString("unknown file type: '{s}'", .{uri_path})),1109 return f.fail(f.location_tok, try eb.printString("unknown file type: '{s}'", .{uri_path})),
11121110
1113 .http_request => |*http_request| ft: {1111 .http_request => |*http_request| ft: {
1114 const head = &http_request.head;1112 const head = &http_request.response.head;
11151113
1116 // Content-Type takes first precedence.1114 // Content-Type takes first precedence.
1117 const content_type = head.content_type orelse1115 const content_type = head.content_type orelse
src/Package/Fetch/git.zig+3-3
...@@ -773,7 +773,7 @@ pub const Session = struct {...@@ -773,7 +773,7 @@ pub const Session = struct {
773 try request.sendBodiless();773 try request.sendBodiless();
774774
775 var redirect_buffer: [1024]u8 = undefined;775 var redirect_buffer: [1024]u8 = undefined;
776 const response = try request.receiveHead(&redirect_buffer);776 var response = try request.receiveHead(&redirect_buffer);
777 if (response.head.status != .ok) return error.ProtocolError;777 if (response.head.status != .ok) return error.ProtocolError;
778 const any_redirects_occurred = request.redirect_behavior.remaining() < max_redirects;778 const any_redirects_occurred = request.redirect_behavior.remaining() < max_redirects;
779 if (any_redirects_occurred) {779 if (any_redirects_occurred) {
...@@ -918,7 +918,7 @@ pub const Session = struct {...@@ -918,7 +918,7 @@ pub const Session = struct {
918 errdefer request.deinit();918 errdefer request.deinit();
919 try request.sendBodyComplete(body.buffered());919 try request.sendBodyComplete(body.buffered());
920920
921 const response = try request.receiveHead(options.buffer);921 var response = try request.receiveHead(options.buffer);
922 if (response.head.status != .ok) return error.ProtocolError;922 if (response.head.status != .ok) return error.ProtocolError;
923 it.reader = response.reader(options.buffer);923 it.reader = response.reader(options.buffer);
924 }924 }
...@@ -1037,7 +1037,7 @@ pub const Session = struct {...@@ -1037,7 +1037,7 @@ pub const Session = struct {
10371037
1038 try request.sendBodyComplete(body.buffered());1038 try request.sendBodyComplete(body.buffered());
10391039
1040 const response = try request.receiveHead(&.{});1040 var response = try request.receiveHead(&.{});
1041 if (response.head.status != .ok) return error.ProtocolError;1041 if (response.head.status != .ok) return error.ProtocolError;
10421042
1043 const reader = response.reader(response_buffer);1043 const reader = response.reader(response_buffer);