Skip to content

Commit 8e59b61

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. 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 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 8e59b61

File tree

1 file changed

+70
-41
lines changed

1 file changed

+70
-41
lines changed

promisor-remote.c

Lines changed: 70 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,15 @@ static int should_accept_remote(enum accept_promisor accept,
414439
return 0;
415440
}
416441

417-
if (!strcmp(urls->v[i], remote_url))
442+
if (!p->url)
443+
BUG("bad config_info (invalid URL) for remote '%s'",
444+
remote_name);
445+
446+
if (!strcmp(p->url, remote_url))
418447
return 1;
419448

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

423452
return 0;
424453
}
@@ -430,8 +459,7 @@ static void filter_promisor_remote(struct repository *repo,
430459
struct strbuf **remotes;
431460
const char *accept_str;
432461
enum accept_promisor accept = ACCEPT_NONE;
433-
struct strvec names = STRVEC_INIT;
434-
struct strvec urls = STRVEC_INIT;
462+
struct string_list config_info = STRING_LIST_INIT_NODUP;
435463

436464
if (!git_config_get_string_tmp("promisor.acceptfromserver", &accept_str)) {
437465
if (!*accept_str || !strcasecmp("None", accept_str))
@@ -450,8 +478,10 @@ static void filter_promisor_remote(struct repository *repo,
450478
if (accept == ACCEPT_NONE)
451479
return;
452480

453-
if (accept != ACCEPT_ALL)
454-
promisor_info_vecs(repo, &names, &urls);
481+
if (accept != ACCEPT_ALL) {
482+
promisor_config_info_list(repo, &config_info);
483+
string_list_sort(&config_info);
484+
}
455485

456486
/* Parse remote info received */
457487

@@ -482,16 +512,15 @@ static void filter_promisor_remote(struct repository *repo,
482512
if (remote_url)
483513
decoded_url = url_percent_decode(remote_url);
484514

485-
if (decoded_name && should_accept_remote(accept, decoded_name, decoded_url, &names, &urls))
515+
if (decoded_name && should_accept_remote(accept, decoded_name, decoded_url, &config_info))
486516
strvec_push(accepted, decoded_name);
487517

488518
strbuf_list_free(elems);
489519
free(decoded_name);
490520
free(decoded_url);
491521
}
492522

493-
strvec_clear(&names);
494-
strvec_clear(&urls);
523+
promisor_info_list_clear(&config_info);
495524
strbuf_list_free(remotes);
496525
}
497526

0 commit comments

Comments
 (0)