diff --git a/connect.c b/connect.c index afc79a6236e8d5..8153a41100c2ac 100644 --- a/connect.c +++ b/connect.c @@ -483,6 +483,8 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader, const char *hash_name; struct strvec *ref_prefixes = transport_options ? &transport_options->ref_prefixes : NULL; + struct strvec *ref_suffixes = transport_options ? + &transport_options->ref_suffixes : NULL; const char **unborn_head_target = transport_options ? &transport_options->unborn_head_target : NULL; *list = NULL; @@ -520,6 +522,10 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader, packet_write_fmt(fd_out, "ref-prefix %s\n", ref_prefixes->v[i]); } + for (i = 0; ref_suffixes && i < ref_suffixes->nr; i++) { + packet_write_fmt(fd_out, "ref-suffix %s\n", + ref_suffixes->v[i]); + } packet_flush(fd_out); /* Process response from server */ diff --git a/ls-refs.c b/ls-refs.c index 98e69373c8404e..2074038aeb0ee8 100644 --- a/ls-refs.c +++ b/ls-refs.c @@ -42,10 +42,12 @@ static void ensure_config_read(void) } /* - * If we see this many or more "ref-prefix" lines from the client, we consider - * it "too many" and will avoid using the prefix feature entirely. + * If we see this many or more "ref-prefix" or "ref-suffix" lines from the + * client, we consider it "too many" and will avoid using the prefix or + * suffix feature entirely. */ #define TOO_MANY_PREFIXES 65536 +#define TOO_MANY_SUFFIXES 65536 /* * Check if one of the prefixes is a prefix of the ref. @@ -72,6 +74,7 @@ struct ls_refs_data { unsigned peel; unsigned symrefs; struct strvec prefixes; + struct strvec suffixes; struct strbuf buf; unsigned unborn : 1; }; @@ -152,6 +155,7 @@ int ls_refs(struct repository *r, struct packet_reader *request) memset(&data, 0, sizeof(data)); strvec_init(&data.prefixes); + strvec_init(&data.suffixes); strbuf_init(&data.buf, 0); ensure_config_read(); @@ -168,6 +172,9 @@ int ls_refs(struct repository *r, struct packet_reader *request) else if (skip_prefix(arg, "ref-prefix ", &out)) { if (data.prefixes.nr < TOO_MANY_PREFIXES) strvec_push(&data.prefixes, out); + }else if (skip_prefix(arg, "ref-suffix ", &out)) { + if (data.prefixes.nr < TOO_MANY_SUFFIXES) + strvec_push(&data.suffixes, out); } else if (!strcmp("unborn", arg)) data.unborn = allow_unborn; @@ -186,13 +193,19 @@ int ls_refs(struct repository *r, struct packet_reader *request) if (data.prefixes.nr >= TOO_MANY_PREFIXES) strvec_clear(&data.prefixes); + if (data.suffixes.nr >= TOO_MANY_SUFFIXES) + strvec_clear(&data.suffixes); + send_possibly_unborn_head(&data); if (!data.prefixes.nr) strvec_push(&data.prefixes, ""); + if (!data.suffixes.nr) + strvec_push(&data.suffixes, ""); for_each_fullref_in_prefixes(get_git_namespace(), data.prefixes.v, send_ref, &data); packet_fflush(stdout); strvec_clear(&data.prefixes); + strvec_clear(&data.suffixes); strbuf_release(&data.buf); return 0; } diff --git a/refs.h b/refs.h index 23479c7ee09b9c..f45a6368cde408 100644 --- a/refs.h +++ b/refs.h @@ -63,6 +63,16 @@ struct worktree; #define RESOLVE_REF_NO_RECURSE 0x02 #define RESOLVE_REF_ALLOW_BAD_NAME 0x04 +struct ref_patterns { + char **ref_prefixes; + char **ref_suffixes; +}; + +#define REF_PATTERNS_INIT { \ + .ref_prefixes = empty_strvec, \ + .ref_suffixes = empty_strvec, \ +} + const char *refs_resolve_ref_unsafe(struct ref_store *refs, const char *refname, int resolve_flags, diff --git a/transport.h b/transport.h index a0bc6a1e9eba8f..3a9fc7dec8b2db 100644 --- a/transport.h +++ b/transport.h @@ -254,6 +254,14 @@ struct transport_ls_refs_options { */ struct strvec ref_prefixes; + /* + * Similar with 'ref_prefixes', list of ref suffixes can be sent to + * the server (when communicating using protocol v2) to limit the + * ref advetisement too. This also will speed up some tail-matching + * operations like `git ls-remote`. + */ + struct strvec ref_suffixes; + /* * If unborn_head_target is not NULL, and the remote reports HEAD as * pointing to an unborn branch, transport_get_remote_refs() stores the