Skip to content

Commit 650b2e2

Browse files
committed
Merge branch 'jk/fetch-ref-prefix-cleanup'
In protocol v2 where the refs advertisement is constrained, we try to tell the server side not to limit the advertisement when there is no specific need to, which has been the source of confusion and recent bugs. Revamp the logic to simplify. * jk/fetch-ref-prefix-cleanup: fetch: use ref prefix list to skip ls-refs fetch: avoid ls-refs only to ask for HEAD symref update fetch: stop protecting additions to ref-prefix list fetch: ask server to advertise HEAD for config-less fetch refspec_ref_prefixes(): clean up refspec_item logic t5516: beef up exact-oid ref prefixes test t5516: drop NEEDSWORK about v2 reachability behavior t5516: prefer "oid" to "sha1" in some test titles t5702: fix typo in test name
2 parents ef0d6b7 + c702dd4 commit 650b2e2

File tree

4 files changed

+85
-39
lines changed

4 files changed

+85
-39
lines changed

builtin/fetch.c

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,7 +1718,6 @@ static int do_fetch(struct transport *transport,
17181718
const struct ref *remote_refs;
17191719
struct transport_ls_refs_options transport_ls_refs_options =
17201720
TRANSPORT_LS_REFS_OPTIONS_INIT;
1721-
int must_list_refs = 1;
17221721
struct fetch_head fetch_head = { 0 };
17231722
struct strbuf err = STRBUF_INIT;
17241723

@@ -1737,21 +1736,7 @@ static int do_fetch(struct transport *transport,
17371736
}
17381737

17391738
if (rs->nr) {
1740-
int i;
1741-
17421739
refspec_ref_prefixes(rs, &transport_ls_refs_options.ref_prefixes);
1743-
1744-
/*
1745-
* We can avoid listing refs if all of them are exact
1746-
* OIDs
1747-
*/
1748-
must_list_refs = 0;
1749-
for (i = 0; i < rs->nr; i++) {
1750-
if (!rs->items[i].exact_sha1) {
1751-
must_list_refs = 1;
1752-
break;
1753-
}
1754-
}
17551740
} else {
17561741
struct branch *branch = branch_get(NULL);
17571742

@@ -1766,23 +1751,30 @@ static int do_fetch(struct transport *transport,
17661751
branch->merge[i]->src);
17671752
}
17681753
}
1769-
}
17701754

1771-
if (tags == TAGS_SET || tags == TAGS_DEFAULT) {
1772-
must_list_refs = 1;
1773-
if (transport_ls_refs_options.ref_prefixes.nr)
1774-
strvec_push(&transport_ls_refs_options.ref_prefixes,
1775-
"refs/tags/");
1776-
}
1777-
1778-
if (uses_remote_tracking(transport, rs)) {
1779-
must_list_refs = 1;
1780-
if (transport_ls_refs_options.ref_prefixes.nr)
1755+
/*
1756+
* If there are no refs specified to fetch, then we just
1757+
* fetch HEAD; mention that to narrow the advertisement.
1758+
*/
1759+
if (!transport_ls_refs_options.ref_prefixes.nr)
17811760
strvec_push(&transport_ls_refs_options.ref_prefixes,
17821761
"HEAD");
17831762
}
17841763

1785-
if (must_list_refs) {
1764+
if (tags == TAGS_SET || tags == TAGS_DEFAULT)
1765+
strvec_push(&transport_ls_refs_options.ref_prefixes,
1766+
"refs/tags/");
1767+
1768+
if (transport_ls_refs_options.ref_prefixes.nr &&
1769+
uses_remote_tracking(transport, rs))
1770+
strvec_push(&transport_ls_refs_options.ref_prefixes,
1771+
"HEAD");
1772+
1773+
/*
1774+
* Only initiate ref listing if we have at least one ref we want to
1775+
* know about.
1776+
*/
1777+
if (transport_ls_refs_options.ref_prefixes.nr) {
17861778
trace2_region_enter("fetch", "remote_refs", the_repository);
17871779
remote_refs = transport_get_remote_refs(transport,
17881780
&transport_ls_refs_options);

refspec.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,14 +246,24 @@ void refspec_ref_prefixes(const struct refspec *rs,
246246
const struct refspec_item *item = &rs->items[i];
247247
const char *prefix = NULL;
248248

249-
if (item->exact_sha1 || item->negative)
249+
if (item->negative)
250250
continue;
251-
if (rs->fetch == REFSPEC_FETCH)
252-
prefix = item->src;
253-
else if (item->dst)
254-
prefix = item->dst;
255-
else if (item->src && !item->exact_sha1)
251+
252+
if (rs->fetch == REFSPEC_FETCH) {
253+
if (item->exact_sha1)
254+
continue;
256255
prefix = item->src;
256+
} else {
257+
/*
258+
* Pushes can have an explicit destination like
259+
* "foo:bar", or can implicitly use the src for both
260+
* ("foo" is the same as "foo:foo").
261+
*/
262+
if (item->dst)
263+
prefix = item->dst;
264+
else if (item->src && !item->exact_sha1)
265+
prefix = item->src;
266+
}
257267

258268
if (!prefix)
259269
continue;

t/t5516-fetch-push.sh

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ test_expect_success 'push tag with non-existent, incomplete dest' '
495495
496496
'
497497

498-
test_expect_success 'push sha1 with non-existent, incomplete dest' '
498+
test_expect_success 'push oid with non-existent, incomplete dest' '
499499
500500
mk_test testrepo &&
501501
test_must_fail git push testrepo $(git rev-parse main):foo
@@ -1251,7 +1251,7 @@ do
12511251
'
12521252
done
12531253

1254-
test_expect_success 'fetch exact SHA1' '
1254+
test_expect_success 'fetch exact oid' '
12551255
mk_test testrepo heads/main hidden/one &&
12561256
git push testrepo main:refs/hidden/one &&
12571257
(
@@ -1297,7 +1297,7 @@ test_expect_success 'fetch exact SHA1' '
12971297
)
12981298
'
12991299

1300-
test_expect_success 'fetch exact SHA1 in protocol v2' '
1300+
test_expect_success 'fetch exact oid in protocol v2' '
13011301
mk_test testrepo heads/main hidden/one &&
13021302
git push testrepo main:refs/hidden/one &&
13031303
git -C testrepo config transfer.hiderefs refs/hidden &&
@@ -1312,8 +1312,10 @@ test_expect_success 'fetch exact SHA1 in protocol v2' '
13121312
test_must_fail git -C child cat-file -t $the_commit &&
13131313
13141314
# fetching the hidden object succeeds by default
1315-
# NEEDSWORK: should this match the v0 behavior instead?
1316-
git -C child fetch -v ../testrepo $the_commit:refs/heads/copy
1315+
GIT_TRACE_PACKET=$PWD/trace.out \
1316+
git -C child fetch -v ../testrepo $the_commit:refs/heads/copy &&
1317+
1318+
test_grep ! "ref-prefix.*$the_commit" trace.out
13171319
'
13181320

13191321
for configallowtipsha1inwant in true false

t/t5702-protocol-v2.sh

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ test_expect_success 'even with handcrafted request, filter does not work if not
665665
test-tool -C server serve-v2 --stateless-rpc <in >/dev/null
666666
'
667667

668-
test_expect_success 'default refspec is used to filter ref when fetchcing' '
668+
test_expect_success 'default refspec is used to filter ref when fetching' '
669669
test_when_finished "rm -f log" &&
670670
671671
GIT_TRACE_PACKET="$(pwd)/log" git -C file_child -c protocol.version=2 \
@@ -679,6 +679,48 @@ test_expect_success 'default refspec is used to filter ref when fetchcing' '
679679
grep "ref-prefix refs/tags/" log
680680
'
681681

682+
test_expect_success 'set up parent for prefix tests' '
683+
git init prefix-parent &&
684+
git -C prefix-parent commit --allow-empty -m foo &&
685+
git -C prefix-parent tag my-tag &&
686+
git -C prefix-parent branch unrelated-branch
687+
'
688+
689+
test_expect_success 'empty refspec filters refs when fetching' '
690+
git init configless-child &&
691+
692+
test_when_finished "rm -f log" &&
693+
GIT_TRACE_PACKET="$(pwd)/log" \
694+
git -C configless-child fetch ../prefix-parent &&
695+
test_grep ! unrelated-branch log
696+
'
697+
698+
test_expect_success 'exact oid fetch with tag following' '
699+
git init exact-oid-tags &&
700+
701+
commit=$(git -C prefix-parent rev-parse --verify HEAD) &&
702+
703+
test_when_finished "rm -f log" &&
704+
GIT_TRACE_PACKET="$(pwd)/log" \
705+
git -C exact-oid-tags fetch ../prefix-parent \
706+
$commit:refs/heads/exact &&
707+
test_grep ! unrelated-branch log &&
708+
git -C exact-oid-tags rev-parse --verify my-tag
709+
'
710+
711+
test_expect_success 'exact oid fetch avoids pointless HEAD request' '
712+
git init exact-oid-head &&
713+
git -C exact-oid-head remote add origin ../prefix-parent &&
714+
715+
commit=$(git -C prefix-parent rev-parse --verify HEAD) &&
716+
717+
test_when_finished "rm -f log" &&
718+
GIT_TRACE_PACKET="$(pwd)/log" \
719+
git -C exact-oid-head fetch --no-tags origin \
720+
$commit:refs/heads/exact &&
721+
test_grep ! command=ls-refs log
722+
'
723+
682724
test_expect_success 'fetch supports various ways of have lines' '
683725
rm -rf server client trace &&
684726
git init server &&

0 commit comments

Comments
 (0)