diff options
| -rw-r--r-- | promisor-remote.c | 86 |
1 files changed, 57 insertions, 29 deletions
diff --git a/promisor-remote.c b/promisor-remote.c index 3913e32c11..c22128d09e 100644 --- a/promisor-remote.c +++ b/promisor-remote.c @@ -405,16 +405,20 @@ struct promisor_info { const char *token; }; +static void promisor_info_free(struct promisor_info *p) +{ + free((char *)p->name); + free((char *)p->url); + free((char *)p->filter); + free((char *)p->token); + free(p); +} + static void promisor_info_list_clear(struct string_list *list) { - for (size_t i = 0; i < list->nr; i++) { - struct promisor_info *p = list->items[i].util; - free((char *)p->name); - free((char *)p->url); - free((char *)p->filter); - free((char *)p->token); - } - string_list_clear(list, 1); + for (size_t i = 0; i < list->nr; i++) + promisor_info_free(list->items[i].util); + string_list_clear(list, 0); } static void set_one_field(struct promisor_info *p, @@ -531,11 +535,13 @@ enum accept_promisor { }; static int should_accept_remote(enum accept_promisor accept, - const char *remote_name, const char *remote_url, + struct promisor_info *advertised, struct string_list *config_info) { struct promisor_info *p; struct string_list_item *item; + const char *remote_name = advertised->name; + const char *remote_url = advertised->url; if (accept == ACCEPT_ALL) return 1; @@ -578,6 +584,41 @@ static int skip_field_name_prefix(const char *elem, const char *field_name, cons return 1; } +static struct promisor_info *parse_one_advertised_remote(const char *remote_info) +{ + struct promisor_info *info = xcalloc(1, sizeof(*info)); + struct string_list elem_list = STRING_LIST_INIT_DUP; + struct string_list_item *item; + + string_list_split(&elem_list, remote_info, ",", -1); + + for_each_string_list_item(item, &elem_list) { + const char *elem = item->string; + const char *p = strchr(elem, '='); + + if (!p) { + warning(_("invalid element '%s' from remote info"), elem); + continue; + } + + if (skip_field_name_prefix(elem, promisor_field_name, &p)) + info->name = url_percent_decode(p); + else if (skip_field_name_prefix(elem, promisor_field_url, &p)) + info->url = url_percent_decode(p); + } + + string_list_clear(&elem_list, 0); + + if (!info->name || !info->url) { + warning(_("server advertised a promisor remote without a name or URL: %s"), + remote_info); + promisor_info_free(info); + return NULL; + } + + return info; +} + static void filter_promisor_remote(struct repository *repo, struct strvec *accepted, const char *info) @@ -614,32 +655,19 @@ static void filter_promisor_remote(struct repository *repo, remotes = strbuf_split_str(info, ';', 0); for (size_t i = 0; remotes[i]; i++) { - struct strbuf **elems; - const char *remote_name = NULL; - const char *remote_url = NULL; - char *decoded_name = NULL; - char *decoded_url = NULL; + struct promisor_info *advertised; strbuf_strip_suffix(remotes[i], ";"); - elems = strbuf_split(remotes[i], ','); - for (size_t j = 0; elems[j]; j++) { - strbuf_strip_suffix(elems[j], ","); - if (!skip_field_name_prefix(elems[j]->buf, promisor_field_name, &remote_name)) - skip_field_name_prefix(elems[j]->buf, promisor_field_url, &remote_url); - } + advertised = parse_one_advertised_remote(remotes[i]->buf); - if (remote_name) - decoded_name = url_percent_decode(remote_name); - if (remote_url) - decoded_url = url_percent_decode(remote_url); + if (!advertised) + continue; - if (decoded_name && should_accept_remote(accept, decoded_name, decoded_url, &config_info)) - strvec_push(accepted, decoded_name); + if (should_accept_remote(accept, advertised, &config_info)) + strvec_push(accepted, advertised->name); - strbuf_list_free(elems); - free(decoded_name); - free(decoded_url); + promisor_info_free(advertised); } promisor_info_list_clear(&config_info); |
