]> git.ipfire.org Git - thirdparty/git.git/commitdiff
fetch: stop protecting additions to ref-prefix list
authorJeff King <peff@peff.net>
Sun, 9 Mar 2025 03:10:39 +0000 (22:10 -0500)
committerJunio C Hamano <gitster@pobox.com>
Mon, 10 Mar 2025 20:13:45 +0000 (13:13 -0700)
When using the ref-prefix feature of protocol v2, a client which sends
no prefixes at all will get the full advertisement. And so the code in
git-fetch was historically loose about setting up that list based on our
refspecs. There were cases where we needed to know about some refs, so
we just didn't add anything to the ref-prefix list.

And hence further code, like that for tag-following and updating
origin/HEAD, had to be careful about adding to an empty list. E.g., see
the bug fixed by bd52d9a058 (fetch: fix following tags when fetching
specific OID, 2025-03-07).

But the previous commit removed the last such case, and now we know an
empty ref-prefix list (at least inside git-fetch's do_fetch() function)
means that we really don't need to see any refs. So we can drop those
extra conditionals.

This simplifies the code a little. But it also means that some cases can
now use ref prefixes when they would not otherwise. As the test shows,
fetching an exact oid into a local ref can now avoid enumerating all of
the refs. The refspec itself doesn't need to know about any remote refs,
and the tag auto-following can just ask about refs/tags/.

The same is true for asking about HEAD to update the local origin/HEAD.
I didn't add a test for that yet, though, as we can optimize it even
further.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/fetch.c
t/t5702-protocol-v2.sh

index f14275644166d8033b36733622c388c9352b2319..6ab101fa6dfb45366e1c190104beb465b5b6229d 100644 (file)
@@ -1778,16 +1778,14 @@ static int do_fetch(struct transport *transport,
 
        if (tags == TAGS_SET || tags == TAGS_DEFAULT) {
                must_list_refs = 1;
-               if (transport_ls_refs_options.ref_prefixes.nr)
-                       strvec_push(&transport_ls_refs_options.ref_prefixes,
-                                   "refs/tags/");
+               strvec_push(&transport_ls_refs_options.ref_prefixes,
+                           "refs/tags/");
        }
 
        if (uses_remote_tracking(transport, rs)) {
                must_list_refs = 1;
-               if (transport_ls_refs_options.ref_prefixes.nr)
-                       strvec_push(&transport_ls_refs_options.ref_prefixes,
-                                   "HEAD");
+               strvec_push(&transport_ls_refs_options.ref_prefixes,
+                           "HEAD");
        }
 
        if (must_list_refs) {
index 2f0a52a72d1636049b4734c0d1a5248dcb6a5cba..626deb05f046ca3fa07c0d08c35170decfe1d1d3 100755 (executable)
@@ -682,6 +682,7 @@ test_expect_success 'default refspec is used to filter ref when fetching' '
 test_expect_success 'set up parent for prefix tests' '
        git init prefix-parent &&
        git -C prefix-parent commit --allow-empty -m foo &&
+       git -C prefix-parent tag my-tag &&
        git -C prefix-parent branch unrelated-branch
 '
 
@@ -694,6 +695,19 @@ test_expect_success 'empty refspec filters refs when fetching' '
        test_grep ! unrelated-branch log
 '
 
+test_expect_success 'exact oid fetch with tag following' '
+       git init exact-oid-tags &&
+
+       commit=$(git -C prefix-parent rev-parse --verify HEAD) &&
+
+       test_when_finished "rm -f log" &&
+       GIT_TRACE_PACKET="$(pwd)/log" \
+               git -C exact-oid-tags fetch ../prefix-parent \
+                       $commit:refs/heads/exact &&
+       test_grep ! unrelated-branch log &&
+       git -C exact-oid-tags rev-parse --verify my-tag
+'
+
 test_expect_success 'fetch supports various ways of have lines' '
        rm -rf server client trace &&
        git init server &&