promisor-remote: support per-repository config

Instead of using global variables to store promisor remote information, store this config in struct repository instead, and add repository-agnostic non-static functions corresponding to the existing non-static functions that only work on the_repository. The actual lazy-fetching of missing objects currently does not work on repositories other than the_repository, and will still not work after this commit, so add a BUG message explaining this. A subsequent commit will remove this limitation. Signed-off-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> Reviewed-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jonathan Tan committed Jun 17, 2021 at 10:13 UTC ef7dc2e9ccb832c1dc29d5102c09f6c4a51d4dca
4 files changed +82 -46
promisor-remote.c
+55 -43
@@ -5,6 +5,11 @@
5 #include "transport.h"
6 #include "strvec.h"
7
8 +struct promisor_remote_config {
9 + struct promisor_remote *promisors;
10 + struct promisor_remote **promisors_tail;
11 +};
12 +
13 static int fetch_objects(const char *remote_name,
14 const struct object_id *oids,
15 int oid_nr)
@@ -35,10 +40,8 @@ static int fetch_objects(const char *remote_name,
40 return finish_command(&child) ? -1 : 0;
41 }
42
38 -static struct promisor_remote *promisors;
39 -static struct promisor_remote **promisors_tail = &promisors;
40 -
41 -static struct promisor_remote *promisor_remote_new(const char *remote_name)
43 +static struct promisor_remote *promisor_remote_new(struct promisor_remote_config *config,
44 + const char *remote_name)
45 {
46 struct promisor_remote *r;
47
@@ -50,18 +53,19 @@ static struct promisor_remote *promisor_remote_new(const char *remote_name)
53
54 FLEX_ALLOC_STR(r, name, remote_name);
55
53 - *promisors_tail = r;
54 - promisors_tail = &r->next;
56 + *config->promisors_tail = r;
57 + config->promisors_tail = &r->next;
58
59 return r;
60 }
61
59 -static struct promisor_remote *promisor_remote_lookup(const char *remote_name,
62 +static struct promisor_remote *promisor_remote_lookup(struct promisor_remote_config *config,
63 + const char *remote_name,
64 struct promisor_remote **previous)
65 {
66 struct promisor_remote *r, *p;
67
64 - for (p = NULL, r = promisors; r; p = r, r = r->next)
68 + for (p = NULL, r = config->promisors; r; p = r, r = r->next)
69 if (!strcmp(r->name, remote_name)) {
70 if (previous)
71 *previous = p;
@@ -71,7 +75,8 @@ static struct promisor_remote *promisor_remote_lookup(const char *remote_name,
75 return NULL;
76 }
77
74 -static void promisor_remote_move_to_tail(struct promisor_remote *r,
78 +static void promisor_remote_move_to_tail(struct promisor_remote_config *config,
79 + struct promisor_remote *r,
80 struct promisor_remote *previous)
81 {
82 if (r->next == NULL)
@@ -80,14 +85,15 @@ static void promisor_remote_move_to_tail(struct promisor_remote *r,
85 if (previous)
86 previous->next = r->next;
87 else
83 - promisors = r->next ? r->next : r;
88 + config->promisors = r->next ? r->next : r;
89 r->next = NULL;
85 - *promisors_tail = r;
86 - promisors_tail = &r->next;
90 + *config->promisors_tail = r;
91 + config->promisors_tail = &r->next;
92 }
93
94 static int promisor_remote_config(const char *var, const char *value, void *data)
95 {
96 + struct promisor_remote_config *config = data;
97 const char *name;
98 size_t namelen;
99 const char *subkey;
@@ -103,8 +109,8 @@ static int promisor_remote_config(const char *var, const char *value, void *data
109
110 remote_name = xmemdupz(name, namelen);
111
106 - if (!promisor_remote_lookup(remote_name, NULL))
107 - promisor_remote_new(remote_name);
112 + if (!promisor_remote_lookup(config, remote_name, NULL))
113 + promisor_remote_new(config, remote_name);
114
115 free(remote_name);
116 return 0;
@@ -113,9 +119,9 @@ static int promisor_remote_config(const char *var, const char *value, void *data
119 struct promisor_remote *r;
120 char *remote_name = xmemdupz(name, namelen);
121
116 - r = promisor_remote_lookup(remote_name, NULL);
122 + r = promisor_remote_lookup(config, remote_name, NULL);
123 if (!r)
118 - r = promisor_remote_new(remote_name);
124 + r = promisor_remote_new(config, remote_name);
125
126 free(remote_name);
127
@@ -128,59 +134,63 @@ static int promisor_remote_config(const char *var, const char *value, void *data
134 return 0;
135 }
136
131 -static int initialized;
132 -
133 -static void promisor_remote_init(void)
137 +static void promisor_remote_init(struct repository *r)
138 {
135 - if (initialized)
139 + struct promisor_remote_config *config;
140 +
141 + if (r->promisor_remote_config)
142 return;
137 - initialized = 1;
143 + config = r->promisor_remote_config =
144 + xcalloc(sizeof(*r->promisor_remote_config), 1);
145 + config->promisors_tail = &config->promisors;
146
139 - git_config(promisor_remote_config, NULL);
147 + repo_config(r, promisor_remote_config, config);
148
141 - if (the_repository->repository_format_partial_clone) {
149 + if (r->repository_format_partial_clone) {
150 struct promisor_remote *o, *previous;
151
144 - o = promisor_remote_lookup(the_repository->repository_format_partial_clone,
152 + o = promisor_remote_lookup(config,
153 + r->repository_format_partial_clone,
154 &previous);
155 if (o)
147 - promisor_remote_move_to_tail(o, previous);
156 + promisor_remote_move_to_tail(config, o, previous);
157 else
149 - promisor_remote_new(the_repository->repository_format_partial_clone);
158 + promisor_remote_new(config, r->repository_format_partial_clone);
159 }
160 }
161
153 -static void promisor_remote_clear(void)
162 +void promisor_remote_clear(struct promisor_remote_config *config)
163 {
155 - while (promisors) {
156 - struct promisor_remote *r = promisors;
157 - promisors = promisors->next;
164 + while (config->promisors) {
165 + struct promisor_remote *r = config->promisors;
166 + config->promisors = config->promisors->next;
167 free(r);
168 }
169
161 - promisors_tail = &promisors;
170 + config->promisors_tail = &config->promisors;
171 }
172
164 -void promisor_remote_reinit(void)
173 +void repo_promisor_remote_reinit(struct repository *r)
174 {
166 - initialized = 0;
167 - promisor_remote_clear();
168 - promisor_remote_init();
175 + promisor_remote_clear(r->promisor_remote_config);
176 + FREE_AND_NULL(r->promisor_remote_config);
177 + promisor_remote_init(r);
178 }
179
171 -struct promisor_remote *promisor_remote_find(const char *remote_name)
180 +struct promisor_remote *repo_promisor_remote_find(struct repository *r,
181 + const char *remote_name)
182 {
173 - promisor_remote_init();
183 + promisor_remote_init(r);
184
185 if (!remote_name)
176 - return promisors;
186 + return r->promisor_remote_config->promisors;
187
178 - return promisor_remote_lookup(remote_name, NULL);
188 + return promisor_remote_lookup(r->promisor_remote_config, remote_name, NULL);
189 }
190
181 -int has_promisor_remote(void)
191 +int repo_has_promisor_remote(struct repository *r)
192 {
183 - return !!promisor_remote_find(NULL);
193 + return !!repo_promisor_remote_find(r, NULL);
194 }
195
196 static int remove_fetched_oids(struct repository *repo,
@@ -228,9 +238,11 @@ int promisor_remote_get_direct(struct repository *repo,
238 if (oid_nr == 0)
239 return 0;
240
231 - promisor_remote_init();
241 + promisor_remote_init(repo);
242
233 - for (r = promisors; r; r = r->next) {
243 + if (repo != the_repository)
244 + BUG("only the_repository is supported for now");
245 + for (r = repo->promisor_remote_config->promisors; r; r = r->next) {
246 if (fetch_objects(r->name, remaining_oids, remaining_nr) < 0) {
247 if (remaining_nr == 1)
248 continue;
promisor-remote.h
+19 -3
@@ -17,9 +17,25 @@ struct promisor_remote {
17 const char name[FLEX_ARRAY];
18 };
19
20 -void promisor_remote_reinit(void);
21 -struct promisor_remote *promisor_remote_find(const char *remote_name);
22 -int has_promisor_remote(void);
20 +void repo_promisor_remote_reinit(struct repository *r);
21 +static inline void promisor_remote_reinit(void)
22 +{
23 + repo_promisor_remote_reinit(the_repository);
24 +}
25 +
26 +void promisor_remote_clear(struct promisor_remote_config *config);
27 +
28 +struct promisor_remote *repo_promisor_remote_find(struct repository *r, const char *remote_name);
29 +static inline struct promisor_remote *promisor_remote_find(const char *remote_name)
30 +{
31 + return repo_promisor_remote_find(the_repository, remote_name);
32 +}
33 +
34 +int repo_has_promisor_remote(struct repository *r);
35 +static inline int has_promisor_remote(void)
36 +{
37 + return repo_has_promisor_remote(the_repository);
38 +}
39
40 /*
41 * Fetches all requested objects from all promisor remotes, trying them one at
repository.c
+6
@@ -11,6 +11,7 @@
11 #include "lockfile.h"
12 #include "submodule-config.h"
13 #include "sparse-index.h"
14 +#include "promisor-remote.h"
15
16 /* The main repository */
17 static struct repository the_repo;
@@ -262,6 +263,11 @@ void repo_clear(struct repository *repo)
263 if (repo->index != &the_index)
264 FREE_AND_NULL(repo->index);
265 }
266 +
267 + if (repo->promisor_remote_config) {
268 + promisor_remote_clear(repo->promisor_remote_config);
269 + FREE_AND_NULL(repo->promisor_remote_config);
270 + }
271 }
272
273 int repo_read_index(struct repository *repo)
repository.h
+2
@@ -10,6 +10,7 @@ struct lock_file;
10 struct pathspec;
11 struct raw_object_store;
12 struct submodule_cache;
13 +struct promisor_remote_config;
14
15 enum untracked_cache_setting {
16 UNTRACKED_CACHE_UNSET = -1,
@@ -141,6 +142,7 @@ struct repository {
142
143 /* Configurations related to promisor remotes. */
144 char *repository_format_partial_clone;
145 + struct promisor_remote_config *promisor_remote_config;
146
147 /* Configurations */
148