promisor-remote: keep advertised filter in memory

Currently, advertised filters are only kept in memory temporarily
during parsing, or persisted to disk if `promisor.storeFields`
contains 'partialCloneFilter'.

In a following commit though, we will add a `--filter=auto` option.
This option will enable the client to use the filters that the server
is suggesting for the promisor remotes the client accepts.

To use them even if `promisor.storeFields` is not configured, these
filters should be stored somewhere for the current session.

Let's add an `advertised_filter` field to `struct promisor_remote`
for that purpose.

To ensure that the filters are available in all cases,
filter_promisor_remote() captures them into a temporary list and
applies them to the `promisor_remote` structs after the potential
configuration reload.

Then the accepted remotes are marked as `accepted` in the repository
state. This ensures that subsequent calls to look up accepted remotes
(like in the filter construction below) actually find them.

In a following commit, we will add a `--filter=auto` option that will
enable a client to use the filters suggested by the server for the
promisor remotes the client accepted.

To enable the client to construct a filter spec based on these filters,
let's add a `promisor_remote_construct_filter(repo)` function.

This function:

- iterates over all accepted promisor remotes in the repository,
- collects the filters advertised for them (using `advertised_filter`
  which a previous commit added to `struct promisor_remote`), and
- generates a single filter spec for them (using the
  `list_objects_filter_combine()` function added by a previous commit).

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Christian Couder 2025-12-23 12:11:12 +01:00 committed by Junio C Hamano
parent c8c941181a
commit d92ba46d5a
2 changed files with 54 additions and 0 deletions

View File

@ -193,6 +193,7 @@ void promisor_remote_clear(struct promisor_remote_config *config)
while (config->promisors) {
struct promisor_remote *r = config->promisors;
free(r->partial_clone_filter);
free(r->advertised_filter);
config->promisors = config->promisors->next;
free(r);
}
@ -837,6 +838,7 @@ static void filter_promisor_remote(struct repository *repo,
struct store_info *store_info = NULL;
struct string_list_item *item;
bool reload_config = false;
struct string_list captured_filters = STRING_LIST_INIT_DUP;
if (!repo_config_get_string_tmp(the_repository, "promisor.acceptfromserver", &accept_str)) {
if (!*accept_str || !strcasecmp("None", accept_str))
@ -879,6 +881,13 @@ static void filter_promisor_remote(struct repository *repo,
reload_config = true;
strvec_push(accepted, advertised->name);
/* Capture advertised filters for accepted remotes */
if (advertised->filter) {
struct string_list_item *i;
i = string_list_append(&captured_filters, advertised->name);
i->util = xstrdup(advertised->filter);
}
}
promisor_info_free(advertised);
@ -890,6 +899,25 @@ static void filter_promisor_remote(struct repository *repo,
if (reload_config)
repo_promisor_remote_reinit(repo);
/* Apply captured filters to the stable repo state */
for_each_string_list_item(item, &captured_filters) {
struct promisor_remote *r = repo_promisor_remote_find(repo, item->string);
if (r) {
free(r->advertised_filter);
r->advertised_filter = item->util;
item->util = NULL;
}
}
string_list_clear(&captured_filters, 1);
/* Mark the remotes as accepted in the repository state */
for (size_t i = 0; i < accepted->nr; i++) {
struct promisor_remote *r = repo_promisor_remote_find(repo, accepted->v[i]);
if (r)
r->accepted = 1;
}
}
char *promisor_remote_reply(const char *info)
@ -935,3 +963,23 @@ void mark_promisor_remotes_as_accepted(struct repository *r, const char *remotes
string_list_clear(&accepted_remotes, 0);
}
char *promisor_remote_construct_filter(struct repository *repo)
{
struct string_list advertised_filters = STRING_LIST_INIT_NODUP;
struct promisor_remote *r;
char *result;
promisor_remote_init(repo);
for (r = repo->promisor_remote_config->promisors; r; r = r->next) {
if (r->accepted && r->advertised_filter)
string_list_append(&advertised_filters, r->advertised_filter);
}
result = list_objects_filter_combine(&advertised_filters);
string_list_clear(&advertised_filters, 0);
return result;
}

View File

@ -15,6 +15,7 @@ struct object_id;
struct promisor_remote {
struct promisor_remote *next;
char *partial_clone_filter;
char *advertised_filter;
unsigned int accepted : 1;
const char name[FLEX_ARRAY];
};
@ -67,4 +68,9 @@ void mark_promisor_remotes_as_accepted(struct repository *repo, const char *remo
*/
int repo_has_accepted_promisor_remote(struct repository *r);
/*
* Use the filters from the accepted remotes to create a filter.
*/
char *promisor_remote_construct_filter(struct repository *repo);
#endif /* PROMISOR_REMOTE_H */