Skip to content

Commit 8721e2e

Browse files
committed
Merge branch 'jt/partial-clone-submodule-1'
Prepare the internals for lazily fetching objects in submodules from their promisor remotes. * jt/partial-clone-submodule-1: promisor-remote: teach lazy-fetch in any repo run-command: refactor subprocess env preparation submodule: refrain from filtering GIT_CONFIG_COUNT promisor-remote: support per-repository config repository: move global r_f_p_c to repo struct
2 parents bd4232f + ef830cc commit 8721e2e

14 files changed

+196
-82
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,7 @@ TEST_BUILTINS_OBJS += test-oidmap.o
729729
TEST_BUILTINS_OBJS += test-online-cpus.o
730730
TEST_BUILTINS_OBJS += test-parse-options.o
731731
TEST_BUILTINS_OBJS += test-parse-pathspec-file.o
732+
TEST_BUILTINS_OBJS += test-partial-clone.o
732733
TEST_BUILTINS_OBJS += test-path-utils.o
733734
TEST_BUILTINS_OBJS += test-pcre2-config.o
734735
TEST_BUILTINS_OBJS += test-pkt-line.o

object-file.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,15 +1584,12 @@ static int do_oid_object_info_extended(struct repository *r,
15841584
}
15851585

15861586
/* Check if it is a missing object */
1587-
if (fetch_if_missing && has_promisor_remote() &&
1588-
!already_retried && r == the_repository &&
1587+
if (fetch_if_missing && repo_has_promisor_remote(r) &&
1588+
!already_retried &&
15891589
!(flags & OBJECT_INFO_SKIP_FETCH_OBJECT)) {
15901590
/*
15911591
* TODO Investigate checking promisor_remote_get_direct()
15921592
* TODO return value and stopping on error here.
1593-
* TODO Pass a repository struct through
1594-
* promisor_remote_get_direct(), such that arbitrary
1595-
* repositories work.
15961593
*/
15971594
promisor_remote_get_direct(r, real, 1);
15981595
already_retried = 1;

promisor-remote.c

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@
55
#include "transport.h"
66
#include "strvec.h"
77

8-
static char *repository_format_partial_clone;
9-
10-
void set_repository_format_partial_clone(char *partial_clone)
11-
{
12-
repository_format_partial_clone = xstrdup_or_null(partial_clone);
13-
}
8+
struct promisor_remote_config {
9+
struct promisor_remote *promisors;
10+
struct promisor_remote **promisors_tail;
11+
};
1412

1513
static int fetch_objects(struct repository *repo,
1614
const char *remote_name,
@@ -23,6 +21,8 @@ static int fetch_objects(struct repository *repo,
2321

2422
child.git_cmd = 1;
2523
child.in = -1;
24+
if (repo != the_repository)
25+
prepare_other_repo_env(&child.env_array, repo->gitdir);
2626
strvec_pushl(&child.args, "-c", "fetch.negotiationAlgorithm=noop",
2727
"fetch", remote_name, "--no-tags",
2828
"--no-write-fetch-head", "--recurse-submodules=no",
@@ -45,10 +45,8 @@ static int fetch_objects(struct repository *repo,
4545
return finish_command(&child) ? -1 : 0;
4646
}
4747

48-
static struct promisor_remote *promisors;
49-
static struct promisor_remote **promisors_tail = &promisors;
50-
51-
static struct promisor_remote *promisor_remote_new(const char *remote_name)
48+
static struct promisor_remote *promisor_remote_new(struct promisor_remote_config *config,
49+
const char *remote_name)
5250
{
5351
struct promisor_remote *r;
5452

@@ -60,18 +58,19 @@ static struct promisor_remote *promisor_remote_new(const char *remote_name)
6058

6159
FLEX_ALLOC_STR(r, name, remote_name);
6260

63-
*promisors_tail = r;
64-
promisors_tail = &r->next;
61+
*config->promisors_tail = r;
62+
config->promisors_tail = &r->next;
6563

6664
return r;
6765
}
6866

69-
static struct promisor_remote *promisor_remote_lookup(const char *remote_name,
67+
static struct promisor_remote *promisor_remote_lookup(struct promisor_remote_config *config,
68+
const char *remote_name,
7069
struct promisor_remote **previous)
7170
{
7271
struct promisor_remote *r, *p;
7372

74-
for (p = NULL, r = promisors; r; p = r, r = r->next)
73+
for (p = NULL, r = config->promisors; r; p = r, r = r->next)
7574
if (!strcmp(r->name, remote_name)) {
7675
if (previous)
7776
*previous = p;
@@ -81,7 +80,8 @@ static struct promisor_remote *promisor_remote_lookup(const char *remote_name,
8180
return NULL;
8281
}
8382

84-
static void promisor_remote_move_to_tail(struct promisor_remote *r,
83+
static void promisor_remote_move_to_tail(struct promisor_remote_config *config,
84+
struct promisor_remote *r,
8585
struct promisor_remote *previous)
8686
{
8787
if (r->next == NULL)
@@ -90,14 +90,15 @@ static void promisor_remote_move_to_tail(struct promisor_remote *r,
9090
if (previous)
9191
previous->next = r->next;
9292
else
93-
promisors = r->next ? r->next : r;
93+
config->promisors = r->next ? r->next : r;
9494
r->next = NULL;
95-
*promisors_tail = r;
96-
promisors_tail = &r->next;
95+
*config->promisors_tail = r;
96+
config->promisors_tail = &r->next;
9797
}
9898

9999
static int promisor_remote_config(const char *var, const char *value, void *data)
100100
{
101+
struct promisor_remote_config *config = data;
101102
const char *name;
102103
size_t namelen;
103104
const char *subkey;
@@ -113,8 +114,8 @@ static int promisor_remote_config(const char *var, const char *value, void *data
113114

114115
remote_name = xmemdupz(name, namelen);
115116

116-
if (!promisor_remote_lookup(remote_name, NULL))
117-
promisor_remote_new(remote_name);
117+
if (!promisor_remote_lookup(config, remote_name, NULL))
118+
promisor_remote_new(config, remote_name);
118119

119120
free(remote_name);
120121
return 0;
@@ -123,9 +124,9 @@ static int promisor_remote_config(const char *var, const char *value, void *data
123124
struct promisor_remote *r;
124125
char *remote_name = xmemdupz(name, namelen);
125126

126-
r = promisor_remote_lookup(remote_name, NULL);
127+
r = promisor_remote_lookup(config, remote_name, NULL);
127128
if (!r)
128-
r = promisor_remote_new(remote_name);
129+
r = promisor_remote_new(config, remote_name);
129130

130131
free(remote_name);
131132

@@ -138,59 +139,63 @@ static int promisor_remote_config(const char *var, const char *value, void *data
138139
return 0;
139140
}
140141

141-
static int initialized;
142-
143-
static void promisor_remote_init(void)
142+
static void promisor_remote_init(struct repository *r)
144143
{
145-
if (initialized)
144+
struct promisor_remote_config *config;
145+
146+
if (r->promisor_remote_config)
146147
return;
147-
initialized = 1;
148+
config = r->promisor_remote_config =
149+
xcalloc(sizeof(*r->promisor_remote_config), 1);
150+
config->promisors_tail = &config->promisors;
148151

149-
git_config(promisor_remote_config, NULL);
152+
repo_config(r, promisor_remote_config, config);
150153

151-
if (repository_format_partial_clone) {
154+
if (r->repository_format_partial_clone) {
152155
struct promisor_remote *o, *previous;
153156

154-
o = promisor_remote_lookup(repository_format_partial_clone,
157+
o = promisor_remote_lookup(config,
158+
r->repository_format_partial_clone,
155159
&previous);
156160
if (o)
157-
promisor_remote_move_to_tail(o, previous);
161+
promisor_remote_move_to_tail(config, o, previous);
158162
else
159-
promisor_remote_new(repository_format_partial_clone);
163+
promisor_remote_new(config, r->repository_format_partial_clone);
160164
}
161165
}
162166

163-
static void promisor_remote_clear(void)
167+
void promisor_remote_clear(struct promisor_remote_config *config)
164168
{
165-
while (promisors) {
166-
struct promisor_remote *r = promisors;
167-
promisors = promisors->next;
169+
while (config->promisors) {
170+
struct promisor_remote *r = config->promisors;
171+
config->promisors = config->promisors->next;
168172
free(r);
169173
}
170174

171-
promisors_tail = &promisors;
175+
config->promisors_tail = &config->promisors;
172176
}
173177

174-
void promisor_remote_reinit(void)
178+
void repo_promisor_remote_reinit(struct repository *r)
175179
{
176-
initialized = 0;
177-
promisor_remote_clear();
178-
promisor_remote_init();
180+
promisor_remote_clear(r->promisor_remote_config);
181+
FREE_AND_NULL(r->promisor_remote_config);
182+
promisor_remote_init(r);
179183
}
180184

181-
struct promisor_remote *promisor_remote_find(const char *remote_name)
185+
struct promisor_remote *repo_promisor_remote_find(struct repository *r,
186+
const char *remote_name)
182187
{
183-
promisor_remote_init();
188+
promisor_remote_init(r);
184189

185190
if (!remote_name)
186-
return promisors;
191+
return r->promisor_remote_config->promisors;
187192

188-
return promisor_remote_lookup(remote_name, NULL);
193+
return promisor_remote_lookup(r->promisor_remote_config, remote_name, NULL);
189194
}
190195

191-
int has_promisor_remote(void)
196+
int repo_has_promisor_remote(struct repository *r)
192197
{
193-
return !!promisor_remote_find(NULL);
198+
return !!repo_promisor_remote_find(r, NULL);
194199
}
195200

196201
static int remove_fetched_oids(struct repository *repo,
@@ -238,9 +243,9 @@ int promisor_remote_get_direct(struct repository *repo,
238243
if (oid_nr == 0)
239244
return 0;
240245

241-
promisor_remote_init();
246+
promisor_remote_init(repo);
242247

243-
for (r = promisors; r; r = r->next) {
248+
for (r = repo->promisor_remote_config->promisors; r; r = r->next) {
244249
if (fetch_objects(repo, r->name, remaining_oids, remaining_nr) < 0) {
245250
if (remaining_nr == 1)
246251
continue;

promisor-remote.h

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,25 @@ struct promisor_remote {
1717
const char name[FLEX_ARRAY];
1818
};
1919

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+
}
2339

2440
/*
2541
* Fetches all requested objects from all promisor remotes, trying them one at
@@ -32,10 +48,4 @@ int promisor_remote_get_direct(struct repository *repo,
3248
const struct object_id *oids,
3349
int oid_nr);
3450

35-
/*
36-
* This should be used only once from setup.c to set the value we got
37-
* from the extensions.partialclone config option.
38-
*/
39-
void set_repository_format_partial_clone(char *partial_clone);
40-
4151
#endif /* PROMISOR_REMOTE_H */

repository.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "lockfile.h"
1212
#include "submodule-config.h"
1313
#include "sparse-index.h"
14+
#include "promisor-remote.h"
1415

1516
/* The main repository */
1617
static struct repository the_repo;
@@ -172,6 +173,10 @@ int repo_init(struct repository *repo,
172173

173174
repo_set_hash_algo(repo, format.hash_algo);
174175

176+
/* take ownership of format.partial_clone */
177+
repo->repository_format_partial_clone = format.partial_clone;
178+
format.partial_clone = NULL;
179+
175180
if (worktree)
176181
repo_set_worktree(repo, worktree);
177182

@@ -258,6 +263,11 @@ void repo_clear(struct repository *repo)
258263
if (repo->index != &the_index)
259264
FREE_AND_NULL(repo->index);
260265
}
266+
267+
if (repo->promisor_remote_config) {
268+
promisor_remote_clear(repo->promisor_remote_config);
269+
FREE_AND_NULL(repo->promisor_remote_config);
270+
}
261271
}
262272

263273
int repo_read_index(struct repository *repo)

repository.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ struct lock_file;
1010
struct pathspec;
1111
struct raw_object_store;
1212
struct submodule_cache;
13+
struct promisor_remote_config;
1314

1415
enum untracked_cache_setting {
1516
UNTRACKED_CACHE_UNSET = -1,
@@ -139,6 +140,10 @@ struct repository {
139140
/* True if commit-graph has been disabled within this process. */
140141
int commit_graph_disabled;
141142

143+
/* Configurations related to promisor remotes. */
144+
char *repository_format_partial_clone;
145+
struct promisor_remote_config *promisor_remote_config;
146+
142147
/* Configurations */
143148

144149
/* Indicate if a repository has a different 'commondir' from 'gitdir' */

run-command.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1891,3 +1891,15 @@ int run_auto_maintenance(int quiet)
18911891

18921892
return run_command(&maint);
18931893
}
1894+
1895+
void prepare_other_repo_env(struct strvec *env_array, const char *new_git_dir)
1896+
{
1897+
const char * const *var;
1898+
1899+
for (var = local_repo_env; *var; var++) {
1900+
if (strcmp(*var, CONFIG_DATA_ENVIRONMENT) &&
1901+
strcmp(*var, CONFIG_COUNT_ENVIRONMENT))
1902+
strvec_push(env_array, *var);
1903+
}
1904+
strvec_pushf(env_array, "%s=%s", GIT_DIR_ENVIRONMENT, new_git_dir);
1905+
}

run-command.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,4 +486,14 @@ int run_processes_parallel_tr2(int n, get_next_task_fn, start_failure_fn,
486486
task_finished_fn, void *pp_cb,
487487
const char *tr2_category, const char *tr2_label);
488488

489+
/**
490+
* Convenience function which prepares env_array for a command to be run in a
491+
* new repo. This adds all GIT_* environment variables to env_array with the
492+
* exception of GIT_CONFIG_PARAMETERS and GIT_CONFIG_COUNT (which cause the
493+
* corresponding environment variables to be unset in the subprocess) and adds
494+
* an environment variable pointing to new_git_dir. See local_repo_env in
495+
* cache.h for more information.
496+
*/
497+
void prepare_other_repo_env(struct strvec *env_array, const char *new_git_dir);
498+
489499
#endif

0 commit comments

Comments
 (0)