Skip to content

Commit f79a515

Browse files
chriscoolgitster
authored andcommitted
promisor-remote: refactor to get rid of 'struct strvec'
In a following commit, we will use the new 'promisor-remote' protocol capability introduced by d460267 (Add 'promisor-remote' capability to protocol v2, 2025-02-18) to pass and process more information about promisor remotes than just their name and url. For that purpose, we will need to store information about other fields, especially information that might or might not be available for different promisor remotes. Unfortunately using 'struct strvec', as we currently do, to store information about the promisor remotes with one 'struct strvec' for each field like "name" or "url" does not scale easily in that case. We would need one 'struct strvec' for each new field, and then we would have to pass all these 'struct strvec' around. Let's refactor this and introduce a new 'struct promisor_info'. It will only store promisor remote information in its members. For now it has only a 'name' member for the promisor remote name and an 'url' member for its URL. We will use a 'struct string_list' to store the instances of 'struct promisor_info'. For each 'item' in the string_list, 'item->string' will point to the promisor remote name and 'item->util' will point to the corresponding 'struct promisor_info' instance. Explicit members are used within 'struct promisor_info' for type safety and clarity regarding the specific information being handled, rather than a generic key-value store. We want to specify and document each field and its content, so adding new members to the struct as more fields are supported is fine. Signed-off-by: Christian Couder <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f65182a commit f79a515

File tree

1 file changed

+66
-41
lines changed

1 file changed

+66
-41
lines changed

promisor-remote.c

Lines changed: 66 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -314,9 +314,35 @@ static int allow_unsanitized(char ch)
314314
return ch > 32 && ch < 127;
315315
}
316316

317-
static void promisor_info_vecs(struct repository *repo,
318-
struct strvec *names,
319-
struct strvec *urls)
317+
/*
318+
* Struct for promisor remotes involved in the "promisor-remote"
319+
* protocol capability.
320+
*
321+
* Except for "name", each <member> in this struct and its <value>
322+
* should correspond (either on the client side or on the server side)
323+
* to a "remote.<name>.<member>" config variable set to <value> where
324+
* "<name>" is a promisor remote name.
325+
*/
326+
struct promisor_info {
327+
const char *name;
328+
const char *url;
329+
};
330+
331+
static void promisor_info_list_clear(struct string_list *list)
332+
{
333+
for (size_t i = 0; i < list->nr; i++) {
334+
struct promisor_info *p = list->items[i].util;
335+
free((char *)p->name);
336+
free((char *)p->url);
337+
}
338+
string_list_clear(list, 1);
339+
}
340+
341+
/*
342+
* Populate 'list' with promisor remote information from the config.
343+
* The 'util' pointer of each list item will hold a 'struct promisor_info'.
344+
*/
345+
static void promisor_config_info_list(struct repository *repo, struct string_list *list)
320346
{
321347
struct promisor_remote *r;
322348

@@ -328,8 +354,14 @@ static void promisor_info_vecs(struct repository *repo,
328354

329355
/* Only add remotes with a non empty URL */
330356
if (!git_config_get_string_tmp(url_key, &url) && *url) {
331-
strvec_push(names, r->name);
332-
strvec_push(urls, url);
357+
struct promisor_info *new_info = xcalloc(1, sizeof(*new_info));
358+
struct string_list_item *item;
359+
360+
new_info->name = xstrdup(r->name);
361+
new_info->url = xstrdup(url);
362+
363+
item = string_list_append(list, new_info->name);
364+
item->util = new_info;
333365
}
334366

335367
free(url_key);
@@ -340,47 +372,36 @@ char *promisor_remote_info(struct repository *repo)
340372
{
341373
struct strbuf sb = STRBUF_INIT;
342374
int advertise_promisors = 0;
343-
struct strvec names = STRVEC_INIT;
344-
struct strvec urls = STRVEC_INIT;
375+
struct string_list config_info = STRING_LIST_INIT_NODUP;
376+
struct string_list_item *item;
345377

346378
git_config_get_bool("promisor.advertise", &advertise_promisors);
347379

348380
if (!advertise_promisors)
349381
return NULL;
350382

351-
promisor_info_vecs(repo, &names, &urls);
383+
promisor_config_info_list(repo, &config_info);
352384

353-
if (!names.nr)
385+
if (!config_info.nr)
354386
return NULL;
355387

356-
for (size_t i = 0; i < names.nr; i++) {
357-
if (i)
388+
for_each_string_list_item(item, &config_info) {
389+
struct promisor_info *p = item->util;
390+
391+
if (item != config_info.items)
358392
strbuf_addch(&sb, ';');
393+
359394
strbuf_addstr(&sb, "name=");
360-
strbuf_addstr_urlencode(&sb, names.v[i], allow_unsanitized);
395+
strbuf_addstr_urlencode(&sb, p->name, allow_unsanitized);
361396
strbuf_addstr(&sb, ",url=");
362-
strbuf_addstr_urlencode(&sb, urls.v[i], allow_unsanitized);
397+
strbuf_addstr_urlencode(&sb, p->url, allow_unsanitized);
363398
}
364399

365-
strvec_clear(&names);
366-
strvec_clear(&urls);
400+
promisor_info_list_clear(&config_info);
367401

368402
return strbuf_detach(&sb, NULL);
369403
}
370404

371-
/*
372-
* Find first index of 'nicks' where there is 'nick'. 'nick' is
373-
* compared case sensitively to the strings in 'nicks'. If not found
374-
* 'nicks->nr' is returned.
375-
*/
376-
static size_t remote_nick_find(struct strvec *nicks, const char *nick)
377-
{
378-
for (size_t i = 0; i < nicks->nr; i++)
379-
if (!strcmp(nicks->v[i], nick))
380-
return i;
381-
return nicks->nr;
382-
}
383-
384405
enum accept_promisor {
385406
ACCEPT_NONE = 0,
386407
ACCEPT_KNOWN_URL,
@@ -390,19 +411,23 @@ enum accept_promisor {
390411

391412
static int should_accept_remote(enum accept_promisor accept,
392413
const char *remote_name, const char *remote_url,
393-
struct strvec *names, struct strvec *urls)
414+
struct string_list *config_info)
394415
{
395-
size_t i;
416+
struct promisor_info *p;
417+
struct string_list_item *item;
396418

397419
if (accept == ACCEPT_ALL)
398420
return 1;
399421

400-
i = remote_nick_find(names, remote_name);
422+
/* Get config info for that promisor remote */
423+
item = string_list_lookup(config_info, remote_name);
401424

402-
if (i >= names->nr)
425+
if (!item)
403426
/* We don't know about that remote */
404427
return 0;
405428

429+
p = item->util;
430+
406431
if (accept == ACCEPT_KNOWN_NAME)
407432
return 1;
408433

@@ -414,11 +439,11 @@ static int should_accept_remote(enum accept_promisor accept,
414439
return 0;
415440
}
416441

417-
if (!strcmp(urls->v[i], remote_url))
442+
if (!strcmp(p->url, remote_url))
418443
return 1;
419444

420445
warning(_("known remote named '%s' but with URL '%s' instead of '%s'"),
421-
remote_name, urls->v[i], remote_url);
446+
remote_name, p->url, remote_url);
422447

423448
return 0;
424449
}
@@ -430,8 +455,7 @@ static void filter_promisor_remote(struct repository *repo,
430455
struct strbuf **remotes;
431456
const char *accept_str;
432457
enum accept_promisor accept = ACCEPT_NONE;
433-
struct strvec names = STRVEC_INIT;
434-
struct strvec urls = STRVEC_INIT;
458+
struct string_list config_info = STRING_LIST_INIT_NODUP;
435459

436460
if (!git_config_get_string_tmp("promisor.acceptfromserver", &accept_str)) {
437461
if (!*accept_str || !strcasecmp("None", accept_str))
@@ -450,8 +474,10 @@ static void filter_promisor_remote(struct repository *repo,
450474
if (accept == ACCEPT_NONE)
451475
return;
452476

453-
if (accept != ACCEPT_ALL)
454-
promisor_info_vecs(repo, &names, &urls);
477+
if (accept != ACCEPT_ALL) {
478+
promisor_config_info_list(repo, &config_info);
479+
string_list_sort(&config_info);
480+
}
455481

456482
/* Parse remote info received */
457483

@@ -482,16 +508,15 @@ static void filter_promisor_remote(struct repository *repo,
482508
if (remote_url)
483509
decoded_url = url_percent_decode(remote_url);
484510

485-
if (decoded_name && should_accept_remote(accept, decoded_name, decoded_url, &names, &urls))
511+
if (decoded_name && should_accept_remote(accept, decoded_name, decoded_url, &config_info))
486512
strvec_push(accepted, decoded_name);
487513

488514
strbuf_list_free(elems);
489515
free(decoded_name);
490516
free(decoded_url);
491517
}
492518

493-
strvec_clear(&names);
494-
strvec_clear(&urls);
519+
promisor_info_list_clear(&config_info);
495520
strbuf_list_free(remotes);
496521
}
497522

0 commit comments

Comments
 (0)