transport: do not list refs if possible
When all refs to be fetched are exact OIDs, it is possible to perform a fetch without requiring the remote to list refs if protocol v2 is used. Teach Git to do this. This currently has an effect only for lazy fetches done from partial clones. The change necessary to likewise optimize "git fetch <remote> <sha-1>" will be done in a subsequent patch. Signed-off-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jonathan Tan committed
Sep 27, 2018 at 12:24 UTC
01775651481ecd9c7288a85cfb7999f7f38ab37c
3 files changed
+16
-3
fetch-pack.c
+1
-1
@@ -1598,7 +1598,7 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
1598
if (nr_sought)
1599
nr_sought = remove_duplicates_in_refs(sought, nr_sought);
1600
1601
- if (!ref) {
1601
+ if (version != protocol_v2 && !ref) {
1602
packet_flush(fd[1]);
1603
die(_("no matching remote head"));
1604
}
t/t5702-protocol-v2.sh
+4
@@ -286,6 +286,10 @@ test_expect_success 'dynamically fetch missing object' '
286
grep "version 2" trace
287
'
288
289
+test_expect_success 'when dynamically fetching missing object, do not list refs' '
290
+ ! grep "git> command=ls-refs" trace
291
+'
292
+
293
test_expect_success 'partial fetch' '
294
rm -rf client "$(pwd)/trace" &&
295
git init client &&
transport.c
+11
-2
@@ -341,8 +341,17 @@ static int fetch_refs_via_pack(struct transport *transport,
341
args.server_options = transport->server_options;
342
args.negotiation_tips = data->options.negotiation_tips;
343
344
- if (!data->got_remote_heads)
345
- refs_tmp = get_refs_via_connect(transport, 0, NULL);
344
+ if (!data->got_remote_heads) {
345
+ int i;
346
+ int must_list_refs = 0;
347
+ for (i = 0; i < nr_heads; i++) {
348
+ if (!to_fetch[i]->exact_oid) {
349
+ must_list_refs = 1;
350
+ break;
351
+ }
352
+ }
353
+ refs_tmp = handshake(transport, 0, NULL, must_list_refs);
354
+ }
355
356
switch (data->version) {
357
case protocol_v2: