summaryrefslogtreecommitdiff
path: root/ls-refs.c
diff options
context:
space:
mode:
authorTaylor Blau <me@ttaylorr.com>2021-01-20 16:04:30 (GMT)
committerJunio C Hamano <gitster@pobox.com>2021-01-23 02:57:27 (GMT)
commitb3970c702cb0acc0551d88a5f34ad4ad2e2a6d39 (patch)
treef542287db174eb086f05257946f2e65643a2dc17 /ls-refs.c
parent83befd37249726f6a94e55f5aad1113fd18102a0 (diff)
downloadgit-b3970c702cb0acc0551d88a5f34ad4ad2e2a6d39.zip
git-b3970c702cb0acc0551d88a5f34ad4ad2e2a6d39.tar.gz
git-b3970c702cb0acc0551d88a5f34ad4ad2e2a6d39.tar.bz2
ls-refs.c: traverse prefixes of disjoint "ref-prefix" sets
ls-refs performs a single revision walk over the whole ref namespace, and sends ones that match with one of the given ref prefixes down to the user. This can be expensive if there are many refs overall, but the portion of them covered by the given prefixes is small by comparison. To attempt to reduce the difference between the number of refs traversed, and the number of refs sent, only traverse references which are in the longest common prefix of the given prefixes. This is very reminiscent of the approach taken in b31e2680c4 (ref-filter.c: find disjoint pattern prefixes, 2019-06-26) which does an analogous thing for multi-patterned 'git for-each-ref' invocations. The callback 'send_ref' is resilient to ignore extra patterns by discarding any arguments which do not begin with at least one of the specified prefixes. Similarly, the code introduced in b31e2680c4 is resilient to stop early at metacharacters, but we only pass strict prefixes here. At worst we would return too many results, but the double checking done by send_ref will throw away anything that doesn't start with something in the prefix list. Finally, if no prefixes were provided, then implicitly add the empty string (which will match all references) since this matches the existing behavior (see the "no restrictions" comment in "ls-refs.c:ref_match()"). Original-patch-by: Jacob Vosmaer <jacob@gitlab.com> Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'ls-refs.c')
-rw-r--r--ls-refs.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/ls-refs.c b/ls-refs.c
index 367597d..eaaa36d 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -110,7 +110,10 @@ int ls_refs(struct repository *r, struct strvec *keys,
die(_("expected flush after ls-refs arguments"));
head_ref_namespaced(send_ref, &data);
- for_each_namespaced_ref(send_ref, &data);
+ if (!data.prefixes.nr)
+ strvec_push(&data.prefixes, "");
+ for_each_fullref_in_prefixes(get_git_namespace(), data.prefixes.v,
+ send_ref, &data, 0);
packet_flush(1);
strvec_clear(&data.prefixes);
return 0;