summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Taylor Blau <me@ttaylorr.com>2021-01-20 11:04:30 -0500
committerLibravatar Junio C Hamano <gitster@pobox.com>2021-01-22 18:57:27 -0800
commitb3970c702cb0acc0551d88a5f34ad4ad2e2a6d39 (patch)
treef542287db174eb086f05257946f2e65643a2dc17
parentls-refs.c: initialize 'prefixes' before using it (diff)
downloadtgif-b3970c702cb0acc0551d88a5f34ad4ad2e2a6d39.tar.xz
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>
-rw-r--r--ls-refs.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/ls-refs.c b/ls-refs.c
index 367597d447..eaaa36d0df 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;