revision.h: store hidden refs in a `strvec`

In subsequent commits, it will be convenient to have a 'const char **' of hidden refs (matching `transfer.hiderefs`, `uploadpack.hideRefs`, etc.), instead of a `string_list`. Convert spots throughout the tree that store the list of hidden refs from a `string_list` to a `strvec`. Note that in `parse_hide_refs_config()` there is an ugly const-cast used to avoid an extra copy of each value before trimming any trailing slash characters. This could instead be written as: ref = xstrdup(value); len = strlen(ref); while (len && ref[len - 1] == '/') ref[--len] = '\0'; strvec_push(hide_refs, ref); free(ref); but the double-copy (once when calling `xstrdup()`, and another via `strvec_push()`) is wasteful. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed Jul 10, 2023 at 17:12 UTC c45841fff8f444cc61cecd42e5d2032844ecbe24
7 files changed +22 -20
builtin/receive-pack.c
+2 -2
@@ -90,7 +90,7 @@ static struct object_id push_cert_oid;
90 static struct signature_check sigcheck;
91 static const char *push_cert_nonce;
92 static const char *cert_nonce_seed;
93 -static struct string_list hidden_refs = STRING_LIST_INIT_DUP;
93 +static struct strvec hidden_refs = STRVEC_INIT;
94
95 static const char *NONCE_UNSOLICITED = "UNSOLICITED";
96 static const char *NONCE_BAD = "BAD";
@@ -2619,7 +2619,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
2619 packet_flush(1);
2620 oid_array_clear(&shallow);
2621 oid_array_clear(&ref);
2622 - string_list_clear(&hidden_refs, 0);
2622 + strvec_clear(&hidden_refs);
2623 free((void *)push_cert_nonce);
2624 return 0;
2625 }
ls-refs.c
+3 -3
@@ -72,7 +72,7 @@ struct ls_refs_data {
72 unsigned symrefs;
73 struct strvec prefixes;
74 struct strbuf buf;
75 - struct string_list hidden_refs;
75 + struct strvec hidden_refs;
76 unsigned unborn : 1;
77 };
78
@@ -155,7 +155,7 @@ int ls_refs(struct repository *r, struct packet_reader *request)
155 memset(&data, 0, sizeof(data));
156 strvec_init(&data.prefixes);
157 strbuf_init(&data.buf, 0);
158 - string_list_init_dup(&data.hidden_refs);
158 + strvec_init(&data.hidden_refs);
159
160 git_config(ls_refs_config, &data);
161
@@ -197,7 +197,7 @@ int ls_refs(struct repository *r, struct packet_reader *request)
197 packet_fflush(stdout);
198 strvec_clear(&data.prefixes);
199 strbuf_release(&data.buf);
200 - string_list_clear(&data.hidden_refs, 0);
200 + strvec_clear(&data.hidden_refs);
201 return 0;
202 }
203
refs.c
+6 -5
@@ -1427,7 +1427,7 @@ char *shorten_unambiguous_ref(const char *refname, int strict)
1427 }
1428
1429 int parse_hide_refs_config(const char *var, const char *value, const char *section,
1430 - struct string_list *hide_refs)
1430 + struct strvec *hide_refs)
1431 {
1432 const char *key;
1433 if (!strcmp("transfer.hiderefs", var) ||
@@ -1438,22 +1438,23 @@ int parse_hide_refs_config(const char *var, const char *value, const char *secti
1438
1439 if (!value)
1440 return config_error_nonbool(var);
1441 - ref = xstrdup(value);
1441 +
1442 + /* drop const to remove trailing '/' characters */
1443 + ref = (char *)strvec_push(hide_refs, value);
1444 len = strlen(ref);
1445 while (len && ref[len - 1] == '/')
1446 ref[--len] = '\0';
1445 - string_list_append_nodup(hide_refs, ref);
1447 }
1448 return 0;
1449 }
1450
1451 int ref_is_hidden(const char *refname, const char *refname_full,
1451 - const struct string_list *hide_refs)
1452 + const struct strvec *hide_refs)
1453 {
1454 int i;
1455
1456 for (i = hide_refs->nr - 1; i >= 0; i--) {
1456 - const char *match = hide_refs->items[i].string;
1457 + const char *match = hide_refs->v[i];
1458 const char *subject;
1459 int neg = 0;
1460 const char *p;
refs.h
+2 -2
@@ -814,7 +814,7 @@ int update_ref(const char *msg, const char *refname,
814 unsigned int flags, enum action_on_err onerr);
815
816 int parse_hide_refs_config(const char *var, const char *value, const char *,
817 - struct string_list *);
817 + struct strvec *);
818
819 /*
820 * Check whether a ref is hidden. If no namespace is set, both the first and
@@ -824,7 +824,7 @@ int parse_hide_refs_config(const char *var, const char *value, const char *,
824 * the ref is outside that namespace, the first parameter is NULL. The second
825 * parameter always points to the full ref name.
826 */
827 -int ref_is_hidden(const char *, const char *, const struct string_list *);
827 +int ref_is_hidden(const char *, const char *, const struct strvec *);
828
829 /* Is this a per-worktree ref living in the refs/ namespace? */
830 int is_per_worktree_ref(const char *refname);
revision.c
+1 -1
@@ -1558,7 +1558,7 @@ void init_ref_exclusions(struct ref_exclusions *exclusions)
1558 void clear_ref_exclusions(struct ref_exclusions *exclusions)
1559 {
1560 string_list_clear(&exclusions->excluded_refs, 0);
1561 - string_list_clear(&exclusions->hidden_refs, 0);
1561 + strvec_clear(&exclusions->hidden_refs);
1562 exclusions->hidden_refs_configured = 0;
1563 }
1564
revision.h
+3 -2
@@ -10,6 +10,7 @@
10 #include "decorate.h"
11 #include "ident.h"
12 #include "list-objects-filter-options.h"
13 +#include "strvec.h"
14
15 /**
16 * The revision walking API offers functions to build a list of revisions
@@ -95,7 +96,7 @@ struct ref_exclusions {
96 * Hidden refs is a list of patterns that is to be hidden via
97 * `ref_is_hidden()`.
98 */
98 - struct string_list hidden_refs;
99 + struct strvec hidden_refs;
100
101 /*
102 * Indicates whether hidden refs have been configured. This is to
@@ -110,7 +111,7 @@ struct ref_exclusions {
111 */
112 #define REF_EXCLUSIONS_INIT { \
113 .excluded_refs = STRING_LIST_INIT_DUP, \
113 - .hidden_refs = STRING_LIST_INIT_DUP, \
114 + .hidden_refs = STRVEC_INIT, \
115 }
116
117 struct oidset;
upload-pack.c
+5 -5
@@ -69,7 +69,7 @@ struct upload_pack_data {
69 struct object_array have_obj;
70 struct oid_array haves; /* v2 only */
71 struct string_list wanted_refs; /* v2 only */
72 - struct string_list hidden_refs;
72 + struct strvec hidden_refs;
73
74 struct object_array shallows;
75 struct string_list deepen_not;
@@ -127,7 +127,7 @@ static void upload_pack_data_init(struct upload_pack_data *data)
127 {
128 struct string_list symref = STRING_LIST_INIT_DUP;
129 struct string_list wanted_refs = STRING_LIST_INIT_DUP;
130 - struct string_list hidden_refs = STRING_LIST_INIT_DUP;
130 + struct strvec hidden_refs = STRVEC_INIT;
131 struct object_array want_obj = OBJECT_ARRAY_INIT;
132 struct object_array have_obj = OBJECT_ARRAY_INIT;
133 struct oid_array haves = OID_ARRAY_INIT;
@@ -162,7 +162,7 @@ static void upload_pack_data_clear(struct upload_pack_data *data)
162 {
163 string_list_clear(&data->symref, 1);
164 string_list_clear(&data->wanted_refs, 1);
165 - string_list_clear(&data->hidden_refs, 0);
165 + strvec_clear(&data->hidden_refs);
166 object_array_clear(&data->want_obj);
167 object_array_clear(&data->have_obj);
168 oid_array_clear(&data->haves);
@@ -1170,7 +1170,7 @@ static void receive_needs(struct upload_pack_data *data,
1170
1171 /* return non-zero if the ref is hidden, otherwise 0 */
1172 static int mark_our_ref(const char *refname, const char *refname_full,
1173 - const struct object_id *oid, const struct string_list *hidden_refs)
1173 + const struct object_id *oid, const struct strvec *hidden_refs)
1174 {
1175 struct object *o = lookup_unknown_object(the_repository, oid);
1176
@@ -1465,7 +1465,7 @@ static int parse_want(struct packet_writer *writer, const char *line,
1465
1466 static int parse_want_ref(struct packet_writer *writer, const char *line,
1467 struct string_list *wanted_refs,
1468 - struct string_list *hidden_refs,
1468 + struct strvec *hidden_refs,
1469 struct object_array *want_obj)
1470 {
1471 const char *refname_nons;