remote: move static variables into per-repository struct

remote.c does not works with non-the_repository because it stores its state as static variables. To support non-the_repository, we can use a per-repository struct for the remotes subsystem. Prepare for this change by defining a struct remote_state that holds the remotes subsystem state and move the static variables of remote.c into the_repository->remote_state. This introduces no behavioral or API changes. Signed-off-by: Glen Choo <chooglen@google.com> Reviewed-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Glen Choo committed Nov 17, 2021 at 16:53 UTC fd3cb0501e175bcac042587cb7bb75e16034a5b7
4 files changed +170 -67
remote.c
+124 -67
@@ -21,33 +21,6 @@ struct counted_string {
21 size_t len;
22 const char *s;
23 };
24 -struct rewrite {
25 - const char *base;
26 - size_t baselen;
27 - struct counted_string *instead_of;
28 - int instead_of_nr;
29 - int instead_of_alloc;
30 -};
31 -struct rewrites {
32 - struct rewrite **rewrite;
33 - int rewrite_alloc;
34 - int rewrite_nr;
35 -};
36 -
37 -static struct remote **remotes;
38 -static int remotes_alloc;
39 -static int remotes_nr;
40 -static struct hashmap remotes_hash;
41 -
42 -static struct branch **branches;
43 -static int branches_alloc;
44 -static int branches_nr;
45 -
46 -static struct branch *current_branch;
47 -static const char *pushremote_name;
48 -
49 -static struct rewrites rewrites;
50 -static struct rewrites rewrites_push;
24
25 static int valid_remote(const struct remote *remote)
26 {
@@ -94,14 +67,16 @@ static void add_pushurl(struct remote *remote, const char *pushurl)
67
68 static void add_pushurl_alias(struct remote *remote, const char *url)
69 {
97 - const char *pushurl = alias_url(url, &rewrites_push);
70 + const char *pushurl =
71 + alias_url(url, &the_repository->remote_state->rewrites_push);
72 if (pushurl != url)
73 add_pushurl(remote, pushurl);
74 }
75
76 static void add_url_alias(struct remote *remote, const char *url)
77 {
104 - add_url(remote, alias_url(url, &rewrites));
78 + add_url(remote,
79 + alias_url(url, &the_repository->remote_state->rewrites));
80 add_pushurl_alias(remote, url);
81 }
82
@@ -127,12 +102,6 @@ static int remotes_hash_cmp(const void *unused_cmp_data,
102 return strcmp(a->name, b->name);
103 }
104
130 -static inline void init_remotes_hash(void)
131 -{
132 - if (!remotes_hash.cmpfn)
133 - hashmap_init(&remotes_hash, remotes_hash_cmp, NULL, 0);
134 -}
135 -
105 static struct remote *make_remote(const char *name, int len)
106 {
107 struct remote *ret;
@@ -142,12 +111,12 @@ static struct remote *make_remote(const char *name, int len)
111 if (!len)
112 len = strlen(name);
113
145 - init_remotes_hash();
114 lookup.str = name;
115 lookup.len = len;
116 hashmap_entry_init(&lookup_entry, memhash(name, len));
117
150 - e = hashmap_get(&remotes_hash, &lookup_entry, &lookup);
118 + e = hashmap_get(&the_repository->remote_state->remotes_hash,
119 + &lookup_entry, &lookup);
120 if (e)
121 return container_of(e, struct remote, ent);
122
@@ -158,15 +127,41 @@ static struct remote *make_remote(const char *name, int len)
127 refspec_init(&ret->push, REFSPEC_PUSH);
128 refspec_init(&ret->fetch, REFSPEC_FETCH);
129
161 - ALLOC_GROW(remotes, remotes_nr + 1, remotes_alloc);
162 - remotes[remotes_nr++] = ret;
130 + ALLOC_GROW(the_repository->remote_state->remotes,
131 + the_repository->remote_state->remotes_nr + 1,
132 + the_repository->remote_state->remotes_alloc);
133 + the_repository->remote_state
134 + ->remotes[the_repository->remote_state->remotes_nr++] = ret;
135
136 hashmap_entry_init(&ret->ent, lookup_entry.hash);
165 - if (hashmap_put_entry(&remotes_hash, ret, ent))
137 + if (hashmap_put_entry(&the_repository->remote_state->remotes_hash, ret,
138 + ent))
139 BUG("hashmap_put overwrote entry after hashmap_get returned NULL");
140 return ret;
141 }
142
143 +static void remote_clear(struct remote *remote)
144 +{
145 + int i;
146 +
147 + free((char *)remote->name);
148 + free((char *)remote->foreign_vcs);
149 +
150 + for (i = 0; i < remote->url_nr; i++) {
151 + free((char *)remote->url[i]);
152 + }
153 + FREE_AND_NULL(remote->pushurl);
154 +
155 + for (i = 0; i < remote->pushurl_nr; i++) {
156 + free((char *)remote->pushurl[i]);
157 + }
158 + FREE_AND_NULL(remote->pushurl);
159 + free((char *)remote->receivepack);
160 + free((char *)remote->uploadpack);
161 + FREE_AND_NULL(remote->http_proxy);
162 + FREE_AND_NULL(remote->http_proxy_authmethod);
163 +}
164 +
165 static void add_merge(struct branch *branch, const char *name)
166 {
167 ALLOC_GROW(branch->merge_name, branch->merge_nr + 1,
@@ -179,15 +174,20 @@ static struct branch *make_branch(const char *name, size_t len)
174 struct branch *ret;
175 int i;
176
182 - for (i = 0; i < branches_nr; i++) {
183 - if (!strncmp(name, branches[i]->name, len) &&
184 - !branches[i]->name[len])
185 - return branches[i];
177 + for (i = 0; i < the_repository->remote_state->branches_nr; i++) {
178 + if (!strncmp(name,
179 + the_repository->remote_state->branches[i]->name,
180 + len) &&
181 + !the_repository->remote_state->branches[i]->name[len])
182 + return the_repository->remote_state->branches[i];
183 }
184
188 - ALLOC_GROW(branches, branches_nr + 1, branches_alloc);
185 + ALLOC_GROW(the_repository->remote_state->branches,
186 + the_repository->remote_state->branches_nr + 1,
187 + the_repository->remote_state->branches_alloc);
188 CALLOC_ARRAY(ret, 1);
190 - branches[branches_nr++] = ret;
189 + the_repository->remote_state
190 + ->branches[the_repository->remote_state->branches_nr++] = ret;
191 ret->name = xstrndup(name, len);
192 ret->refname = xstrfmt("refs/heads/%s", ret->name);
193
@@ -327,12 +327,16 @@ static int handle_config(const char *key, const char *value, void *cb)
327 if (!strcmp(subkey, "insteadof")) {
328 if (!value)
329 return config_error_nonbool(key);
330 - rewrite = make_rewrite(&rewrites, name, namelen);
330 + rewrite = make_rewrite(
331 + &the_repository->remote_state->rewrites, name,
332 + namelen);
333 add_instead_of(rewrite, xstrdup(value));
334 } else if (!strcmp(subkey, "pushinsteadof")) {
335 if (!value)
336 return config_error_nonbool(key);
335 - rewrite = make_rewrite(&rewrites_push, name, namelen);
337 + rewrite = make_rewrite(
338 + &the_repository->remote_state->rewrites_push,
339 + name, namelen);
340 add_instead_of(rewrite, xstrdup(value));
341 }
342 }
@@ -342,7 +346,9 @@ static int handle_config(const char *key, const char *value, void *cb)
346
347 /* Handle remote.* variables */
348 if (!name && !strcmp(subkey, "pushdefault"))
345 - return git_config_string(&pushremote_name, key, value);
349 + return git_config_string(
350 + &the_repository->remote_state->pushremote_name, key,
351 + value);
352
353 if (!name)
354 return 0;
@@ -425,18 +431,34 @@ static int handle_config(const char *key, const char *value, void *cb)
431 static void alias_all_urls(void)
432 {
433 int i, j;
428 - for (i = 0; i < remotes_nr; i++) {
434 + for (i = 0; i < the_repository->remote_state->remotes_nr; i++) {
435 int add_pushurl_aliases;
430 - if (!remotes[i])
436 + if (!the_repository->remote_state->remotes[i])
437 continue;
432 - for (j = 0; j < remotes[i]->pushurl_nr; j++) {
433 - remotes[i]->pushurl[j] = alias_url(remotes[i]->pushurl[j], &rewrites);
438 + for (j = 0;
439 + j < the_repository->remote_state->remotes[i]->pushurl_nr;
440 + j++) {
441 + the_repository->remote_state->remotes[i]->pushurl[j] =
442 + alias_url(
443 + the_repository->remote_state->remotes[i]
444 + ->pushurl[j],
445 + &the_repository->remote_state->rewrites);
446 }
435 - add_pushurl_aliases = remotes[i]->pushurl_nr == 0;
436 - for (j = 0; j < remotes[i]->url_nr; j++) {
447 + add_pushurl_aliases =
448 + the_repository->remote_state->remotes[i]->pushurl_nr ==
449 + 0;
450 + for (j = 0;
451 + j < the_repository->remote_state->remotes[i]->url_nr;
452 + j++) {
453 if (add_pushurl_aliases)
438 - add_pushurl_alias(remotes[i], remotes[i]->url[j]);
439 - remotes[i]->url[j] = alias_url(remotes[i]->url[j], &rewrites);
454 + add_pushurl_alias(
455 + the_repository->remote_state->remotes[i],
456 + the_repository->remote_state->remotes[i]
457 + ->url[j]);
458 + the_repository->remote_state->remotes[i]
459 + ->url[j] = alias_url(
460 + the_repository->remote_state->remotes[i]->url[j],
461 + &the_repository->remote_state->rewrites);
462 }
463 }
464 }
@@ -450,12 +472,13 @@ static void read_config(void)
472 return;
473 loaded = 1;
474
453 - current_branch = NULL;
475 + the_repository->remote_state->current_branch = NULL;
476 if (startup_info->have_repository) {
477 const char *head_ref = resolve_ref_unsafe("HEAD", 0, NULL, &flag);
478 if (head_ref && (flag & REF_ISSYMREF) &&
479 skip_prefix(head_ref, "refs/heads/", &head_ref)) {
458 - current_branch = make_branch(head_ref, strlen(head_ref));
480 + the_repository->remote_state->current_branch =
481 + make_branch(head_ref, strlen(head_ref));
482 }
483 }
484 git_config(handle_config, NULL);
@@ -493,10 +516,10 @@ const char *pushremote_for_branch(struct branch *branch, int *explicit)
516 *explicit = 1;
517 return branch->pushremote_name;
518 }
496 - if (pushremote_name) {
519 + if (the_repository->remote_state->pushremote_name) {
520 if (explicit)
521 *explicit = 1;
499 - return pushremote_name;
522 + return the_repository->remote_state->pushremote_name;
523 }
524 return remote_for_branch(branch, explicit);
525 }
@@ -534,7 +557,8 @@ static struct remote *remote_get_1(const char *name,
557 if (name)
558 name_given = 1;
559 else
537 - name = get_default(current_branch, &name_given);
560 + name = get_default(the_repository->remote_state->current_branch,
561 + &name_given);
562
563 ret = make_remote(name, 0);
564 if (valid_remote_nick(name) && have_git_dir()) {
@@ -573,11 +597,13 @@ int for_each_remote(each_remote_fn fn, void *priv)
597 {
598 int i, result = 0;
599 read_config();
576 - for (i = 0; i < remotes_nr && !result; i++) {
577 - struct remote *r = remotes[i];
578 - if (!r)
600 + for (i = 0; i < the_repository->remote_state->remotes_nr && !result;
601 + i++) {
602 + struct remote *remote =
603 + the_repository->remote_state->remotes[i];
604 + if (!remote)
605 continue;
580 - result = fn(r, priv);
606 + result = fn(remote, priv);
607 }
608 return result;
609 }
@@ -1685,7 +1711,7 @@ struct branch *branch_get(const char *name)
1711
1712 read_config();
1713 if (!name || !*name || !strcmp(name, "HEAD"))
1688 - ret = current_branch;
1714 + ret = the_repository->remote_state->current_branch;
1715 else
1716 ret = make_branch(name, strlen(name));
1717 set_merge(ret);
@@ -2585,3 +2611,34 @@ void apply_push_cas(struct push_cas_option *cas,
2611 check_if_includes_upstream(ref);
2612 }
2613 }
2614 +
2615 +struct remote_state *remote_state_new(void)
2616 +{
2617 + struct remote_state *r = xmalloc(sizeof(*r));
2618 +
2619 + memset(r, 0, sizeof(*r));
2620 +
2621 + hashmap_init(&r->remotes_hash, remotes_hash_cmp, NULL, 0);
2622 + return r;
2623 +}
2624 +
2625 +void remote_state_clear(struct remote_state *remote_state)
2626 +{
2627 + int i;
2628 +
2629 + for (i = 0; i < remote_state->remotes_nr; i++) {
2630 + remote_clear(remote_state->remotes[i]);
2631 + }
2632 + FREE_AND_NULL(remote_state->remotes);
2633 + remote_state->remotes_alloc = 0;
2634 + remote_state->remotes_nr = 0;
2635 +
2636 + hashmap_clear_and_free(&remote_state->remotes_hash, struct remote, ent);
2637 +
2638 + for (i = 0; i < remote_state->branches_nr; i++) {
2639 + FREE_AND_NULL(remote_state->branches[i]);
2640 + }
2641 + FREE_AND_NULL(remote_state->branches);
2642 + remote_state->branches_alloc = 0;
2643 + remote_state->branches_nr = 0;
2644 +}
remote.h
+34
@@ -23,6 +23,40 @@ enum {
23 REMOTE_BRANCHES
24 };
25
26 +struct rewrite {
27 + const char *base;
28 + size_t baselen;
29 + struct counted_string *instead_of;
30 + int instead_of_nr;
31 + int instead_of_alloc;
32 +};
33 +
34 +struct rewrites {
35 + struct rewrite **rewrite;
36 + int rewrite_alloc;
37 + int rewrite_nr;
38 +};
39 +
40 +struct remote_state {
41 + struct remote **remotes;
42 + int remotes_alloc;
43 + int remotes_nr;
44 + struct hashmap remotes_hash;
45 +
46 + struct branch **branches;
47 + int branches_alloc;
48 + int branches_nr;
49 +
50 + struct branch *current_branch;
51 + const char *pushremote_name;
52 +
53 + struct rewrites rewrites;
54 + struct rewrites rewrites_push;
55 +};
56 +
57 +void remote_state_clear(struct remote_state *remote_state);
58 +struct remote_state *remote_state_new(void);
59 +
60 struct remote {
61 struct hashmap_entry ent;
62
repository.c
+8
@@ -9,6 +9,7 @@
9 #include "config.h"
10 #include "object.h"
11 #include "lockfile.h"
12 +#include "remote.h"
13 #include "submodule-config.h"
14 #include "sparse-index.h"
15 #include "promisor-remote.h"
@@ -24,6 +25,7 @@ void initialize_the_repository(void)
25
26 the_repo.index = &the_index;
27 the_repo.objects = raw_object_store_new();
28 + the_repo.remote_state = remote_state_new();
29 the_repo.parsed_objects = parsed_object_pool_new();
30
31 repo_set_hash_algo(&the_repo, GIT_HASH_SHA1);
@@ -164,6 +166,7 @@ int repo_init(struct repository *repo,
166
167 repo->objects = raw_object_store_new();
168 repo->parsed_objects = parsed_object_pool_new();
169 + repo->remote_state = remote_state_new();
170
171 if (repo_init_gitdir(repo, gitdir))
172 goto error;
@@ -270,6 +273,11 @@ void repo_clear(struct repository *repo)
273 promisor_remote_clear(repo->promisor_remote_config);
274 FREE_AND_NULL(repo->promisor_remote_config);
275 }
276 +
277 + if (repo->remote_state) {
278 + remote_state_clear(repo->remote_state);
279 + FREE_AND_NULL(repo->remote_state);
280 + }
281 }
282
283 int repo_read_index(struct repository *repo)
repository.h
+4
@@ -11,6 +11,7 @@ struct pathspec;
11 struct raw_object_store;
12 struct submodule_cache;
13 struct promisor_remote_config;
14 +struct remote_state;
15
16 enum untracked_cache_setting {
17 UNTRACKED_CACHE_KEEP,
@@ -127,6 +128,9 @@ struct repository {
128 */
129 struct index_state *index;
130
131 + /* Repository's remotes and associated structures. */
132 + struct remote_state *remote_state;
133 +
134 /* Repository's current hash algorithm, as serialized on disk. */
135 const struct git_hash_algo *hash_algo;
136