]> git.ipfire.org Git - thirdparty/git.git/blame - promisor-remote.c
treewide: be explicit about dependence on gettext.h
[thirdparty/git.git] / promisor-remote.c
CommitLineData
48de3158 1#include "cache.h"
f394e093 2#include "gettext.h"
41771fa4 3#include "hex.h"
9e27beaa 4#include "object-store.h"
48de3158
CC
5#include "promisor-remote.h"
6#include "config.h"
db27dca5 7#include "transport.h"
7ca3c0ac 8#include "strvec.h"
301f1e3a 9#include "packfile.h"
db27dca5 10
ef7dc2e9
JT
11struct promisor_remote_config {
12 struct promisor_remote *promisors;
13 struct promisor_remote **promisors_tail;
14};
60b7a92d 15
78cfdd0c
EN
16static int fetch_objects(struct repository *repo,
17 const char *remote_name,
db27dca5
CC
18 const struct object_id *oids,
19 int oid_nr)
20{
7ca3c0ac 21 struct child_process child = CHILD_PROCESS_INIT;
db27dca5 22 int i;
7ca3c0ac
JT
23 FILE *child_in;
24
25 child.git_cmd = 1;
26 child.in = -1;
ef830cc4 27 if (repo != the_repository)
29fda24d 28 prepare_other_repo_env(&child.env, repo->gitdir);
7ca3c0ac
JT
29 strvec_pushl(&child.args, "-c", "fetch.negotiationAlgorithm=noop",
30 "fetch", remote_name, "--no-tags",
31 "--no-write-fetch-head", "--recurse-submodules=no",
32 "--filter=blob:none", "--stdin", NULL);
33 if (start_command(&child))
34 die(_("promisor-remote: unable to fork off fetch subprocess"));
35 child_in = xfdopen(child.in, "w");
db27dca5 36
78cfdd0c
EN
37 trace2_data_intmax("promisor", repo, "fetch_count", oid_nr);
38
db27dca5 39 for (i = 0; i < oid_nr; i++) {
7ca3c0ac
JT
40 if (fputs(oid_to_hex(&oids[i]), child_in) < 0)
41 die_errno(_("promisor-remote: could not write to fetch subprocess"));
42 if (fputc('\n', child_in) < 0)
43 die_errno(_("promisor-remote: could not write to fetch subprocess"));
db27dca5 44 }
7ca3c0ac
JT
45
46 if (fclose(child_in) < 0)
47 die_errno(_("promisor-remote: could not close stdin to fetch subprocess"));
48 return finish_command(&child) ? -1 : 0;
db27dca5 49}
48de3158 50
ef7dc2e9
JT
51static struct promisor_remote *promisor_remote_new(struct promisor_remote_config *config,
52 const char *remote_name)
48de3158
CC
53{
54 struct promisor_remote *r;
55
56 if (*remote_name == '/') {
57 warning(_("promisor remote name cannot begin with '/': %s"),
58 remote_name);
59 return NULL;
60 }
61
62 FLEX_ALLOC_STR(r, name, remote_name);
63
ef7dc2e9
JT
64 *config->promisors_tail = r;
65 config->promisors_tail = &r->next;
48de3158
CC
66
67 return r;
68}
69
ef7dc2e9
JT
70static struct promisor_remote *promisor_remote_lookup(struct promisor_remote_config *config,
71 const char *remote_name,
48de3158
CC
72 struct promisor_remote **previous)
73{
74 struct promisor_remote *r, *p;
75
ef7dc2e9 76 for (p = NULL, r = config->promisors; r; p = r, r = r->next)
48de3158
CC
77 if (!strcmp(r->name, remote_name)) {
78 if (previous)
79 *previous = p;
80 return r;
81 }
82
83 return NULL;
84}
85
ef7dc2e9
JT
86static void promisor_remote_move_to_tail(struct promisor_remote_config *config,
87 struct promisor_remote *r,
faf2abf4
CC
88 struct promisor_remote *previous)
89{
afe8a907 90 if (!r->next)
65904b8b
ES
91 return;
92
faf2abf4
CC
93 if (previous)
94 previous->next = r->next;
95 else
ef7dc2e9 96 config->promisors = r->next ? r->next : r;
faf2abf4 97 r->next = NULL;
ef7dc2e9
JT
98 *config->promisors_tail = r;
99 config->promisors_tail = &r->next;
faf2abf4
CC
100}
101
48de3158
CC
102static int promisor_remote_config(const char *var, const char *value, void *data)
103{
ef7dc2e9 104 struct promisor_remote_config *config = data;
48de3158 105 const char *name;
f5914f4b 106 size_t namelen;
48de3158
CC
107 const char *subkey;
108
109 if (parse_config_key(var, "remote", &name, &namelen, &subkey) < 0)
110 return 0;
111
112 if (!strcmp(subkey, "promisor")) {
113 char *remote_name;
114
115 if (!git_config_bool(var, value))
116 return 0;
117
118 remote_name = xmemdupz(name, namelen);
119
ef7dc2e9
JT
120 if (!promisor_remote_lookup(config, remote_name, NULL))
121 promisor_remote_new(config, remote_name);
48de3158
CC
122
123 free(remote_name);
124 return 0;
125 }
fa3d1b63
CC
126 if (!strcmp(subkey, "partialclonefilter")) {
127 struct promisor_remote *r;
128 char *remote_name = xmemdupz(name, namelen);
129
ef7dc2e9 130 r = promisor_remote_lookup(config, remote_name, NULL);
fa3d1b63 131 if (!r)
ef7dc2e9 132 r = promisor_remote_new(config, remote_name);
fa3d1b63
CC
133
134 free(remote_name);
135
136 if (!r)
137 return 0;
138
139 return git_config_string(&r->partial_clone_filter, var, value);
140 }
48de3158
CC
141
142 return 0;
143}
144
ef7dc2e9 145static void promisor_remote_init(struct repository *r)
48de3158 146{
ef7dc2e9
JT
147 struct promisor_remote_config *config;
148
149 if (r->promisor_remote_config)
48de3158 150 return;
ef7dc2e9 151 config = r->promisor_remote_config =
c4bbd9bb 152 xcalloc(1, sizeof(*r->promisor_remote_config));
ef7dc2e9 153 config->promisors_tail = &config->promisors;
48de3158 154
ef7dc2e9 155 repo_config(r, promisor_remote_config, config);
faf2abf4 156
ef7dc2e9 157 if (r->repository_format_partial_clone) {
faf2abf4
CC
158 struct promisor_remote *o, *previous;
159
ef7dc2e9
JT
160 o = promisor_remote_lookup(config,
161 r->repository_format_partial_clone,
faf2abf4
CC
162 &previous);
163 if (o)
ef7dc2e9 164 promisor_remote_move_to_tail(config, o, previous);
faf2abf4 165 else
ef7dc2e9 166 promisor_remote_new(config, r->repository_format_partial_clone);
faf2abf4 167 }
48de3158
CC
168}
169
ef7dc2e9 170void promisor_remote_clear(struct promisor_remote_config *config)
9cfebc1f 171{
ef7dc2e9
JT
172 while (config->promisors) {
173 struct promisor_remote *r = config->promisors;
174 config->promisors = config->promisors->next;
9cfebc1f
CC
175 free(r);
176 }
177
ef7dc2e9 178 config->promisors_tail = &config->promisors;
9cfebc1f
CC
179}
180
ef7dc2e9 181void repo_promisor_remote_reinit(struct repository *r)
9cfebc1f 182{
ef7dc2e9
JT
183 promisor_remote_clear(r->promisor_remote_config);
184 FREE_AND_NULL(r->promisor_remote_config);
185 promisor_remote_init(r);
9cfebc1f
CC
186}
187
ef7dc2e9
JT
188struct promisor_remote *repo_promisor_remote_find(struct repository *r,
189 const char *remote_name)
48de3158 190{
ef7dc2e9 191 promisor_remote_init(r);
48de3158
CC
192
193 if (!remote_name)
ef7dc2e9 194 return r->promisor_remote_config->promisors;
48de3158 195
ef7dc2e9 196 return promisor_remote_lookup(r->promisor_remote_config, remote_name, NULL);
48de3158
CC
197}
198
ef7dc2e9 199int repo_has_promisor_remote(struct repository *r)
48de3158 200{
ef7dc2e9 201 return !!repo_promisor_remote_find(r, NULL);
48de3158 202}
9e27beaa
CC
203
204static int remove_fetched_oids(struct repository *repo,
205 struct object_id **oids,
206 int oid_nr, int to_free)
207{
208 int i, remaining_nr = 0;
209 int *remaining = xcalloc(oid_nr, sizeof(*remaining));
210 struct object_id *old_oids = *oids;
211 struct object_id *new_oids;
212
213 for (i = 0; i < oid_nr; i++)
214 if (oid_object_info_extended(repo, &old_oids[i], NULL,
215 OBJECT_INFO_SKIP_FETCH_OBJECT)) {
216 remaining[i] = 1;
217 remaining_nr++;
218 }
219
220 if (remaining_nr) {
221 int j = 0;
ca56dadb 222 CALLOC_ARRAY(new_oids, remaining_nr);
9e27beaa
CC
223 for (i = 0; i < oid_nr; i++)
224 if (remaining[i])
225 oidcpy(&new_oids[j++], &old_oids[i]);
226 *oids = new_oids;
227 if (to_free)
228 free(old_oids);
229 }
230
231 free(remaining);
232
233 return remaining_nr;
234}
235
00057bf1
JT
236void promisor_remote_get_direct(struct repository *repo,
237 const struct object_id *oids,
238 int oid_nr)
9e27beaa
CC
239{
240 struct promisor_remote *r;
241 struct object_id *remaining_oids = (struct object_id *)oids;
242 int remaining_nr = oid_nr;
243 int to_free = 0;
301f1e3a 244 int i;
9e27beaa 245
db7ed741 246 if (oid_nr == 0)
00057bf1 247 return;
db7ed741 248
ef7dc2e9 249 promisor_remote_init(repo);
9e27beaa 250
ef7dc2e9 251 for (r = repo->promisor_remote_config->promisors; r; r = r->next) {
78cfdd0c 252 if (fetch_objects(repo, r->name, remaining_oids, remaining_nr) < 0) {
9e27beaa
CC
253 if (remaining_nr == 1)
254 continue;
255 remaining_nr = remove_fetched_oids(repo, &remaining_oids,
256 remaining_nr, to_free);
257 if (remaining_nr) {
258 to_free = 1;
259 continue;
260 }
261 }
301f1e3a
JT
262 goto all_fetched;
263 }
264
265 for (i = 0; i < remaining_nr; i++) {
266 if (is_promisor_object(&remaining_oids[i]))
267 die(_("could not fetch %s from promisor remote"),
268 oid_to_hex(&remaining_oids[i]));
9e27beaa
CC
269 }
270
301f1e3a 271all_fetched:
9e27beaa
CC
272 if (to_free)
273 free(remaining_oids);
9e27beaa 274}