git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 3/3] ls-refs.c: traverse prefixes of disjoint "ref-prefix" sets

From
Taylor Blau <me@ttaylorr.com>
Date
Jan 20, 2021, 16:04 UTC
Message-ID
<b97dfb706fe7a94381a978fa9678dde0738106c2.1611158549.git.me@ttaylorr.com>
In-Reply-To
<cover.1611158549.git.me@ttaylorr.com>

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>
---
 ls-refs.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
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;
-- 
2.30.0.138.g6d7191ea01
Previous: Jacob VosmaerNext: Taylor Blau
Message 14 of 27 in “Re: [PATCH 1/1] ls-refs.c: minimize number of refs visited”
  1. Jacob VosmaerJan 19, 2021
  2. 0/2 ls-refs: only traverse through longest common ref prefixTaylor Blau, Jan 19, 2021
  3. 2/2 ls-refs.c: traverse longest common ref prefixTaylor Blau, Jan 19, 2021
  4. Jeff KingJan 19, 2021
  5. Taylor BlauJan 19, 2021
  6. Jeff KingJan 20, 2021
  7. Jacob VosmaerJan 20, 2021
  8. 1/2 refs: expose 'for_each_fullref_in_prefixes'Taylor Blau, Jan 19, 2021
  9. 0/3 ls-refs: traverse prefixes of disjoint "ref-prefix" setsTaylor Blau, Jan 20, 2021
  10. 2/3 ls-refs.c: initialize 'prefixes' before using itTaylor Blau, Jan 20, 2021
  11. Jeff KingJan 20, 2021
  12. Taylor BlauJan 20, 2021
  13. Jacob VosmaerJan 20, 2021
  14. 3/3 ls-refs.c: traverse prefixes of disjoint "ref-prefix" setsTaylor Blau, Jan 20, 2021
  15. 1/3 refs: expose 'for_each_fullref_in_prefixes'Taylor Blau, Jan 20, 2021
  16. Jeff KingJan 20, 2021
  17. Taylor BlauJan 20, 2021
  18. Junio C HamanoJan 23, 2021
  19. Taylor BlauJan 25, 2021
  20. Junio C HamanoJan 23, 2021
  21. Taylor BlauJan 19, 2021
  22. Jeff KingJan 19, 2021
  23. Jeff KingJan 19, 2021
  24. Taylor BlauJan 19, 2021
  25. Jeff KingJan 19, 2021
  26. Jeff KingJan 19, 2021
  27. Taylor BlauJan 19, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.