rebase: deprecate --rebase-merges=""
[git/debian.git] / promisor-remote.c
blob1db566982ec6c10afb94837d22a4c7f39b1f36bf
1 #include "cache.h"
2 #include "hex.h"
3 #include "object-store.h"
4 #include "promisor-remote.h"
5 #include "config.h"
6 #include "transport.h"
7 #include "strvec.h"
8 #include "packfile.h"
10 struct promisor_remote_config {
11 struct promisor_remote *promisors;
12 struct promisor_remote **promisors_tail;
15 static int fetch_objects(struct repository *repo,
16 const char *remote_name,
17 const struct object_id *oids,
18 int oid_nr)
20 struct child_process child = CHILD_PROCESS_INIT;
21 int i;
22 FILE *child_in;
24 child.git_cmd = 1;
25 child.in = -1;
26 if (repo != the_repository)
27 prepare_other_repo_env(&child.env, repo->gitdir);
28 strvec_pushl(&child.args, "-c", "fetch.negotiationAlgorithm=noop",
29 "fetch", remote_name, "--no-tags",
30 "--no-write-fetch-head", "--recurse-submodules=no",
31 "--filter=blob:none", "--stdin", NULL);
32 if (start_command(&child))
33 die(_("promisor-remote: unable to fork off fetch subprocess"));
34 child_in = xfdopen(child.in, "w");
36 trace2_data_intmax("promisor", repo, "fetch_count", oid_nr);
38 for (i = 0; i < oid_nr; i++) {
39 if (fputs(oid_to_hex(&oids[i]), child_in) < 0)
40 die_errno(_("promisor-remote: could not write to fetch subprocess"));
41 if (fputc('\n', child_in) < 0)
42 die_errno(_("promisor-remote: could not write to fetch subprocess"));
45 if (fclose(child_in) < 0)
46 die_errno(_("promisor-remote: could not close stdin to fetch subprocess"));
47 return finish_command(&child) ? -1 : 0;
50 static struct promisor_remote *promisor_remote_new(struct promisor_remote_config *config,
51 const char *remote_name)
53 struct promisor_remote *r;
55 if (*remote_name == '/') {
56 warning(_("promisor remote name cannot begin with '/': %s"),
57 remote_name);
58 return NULL;
61 FLEX_ALLOC_STR(r, name, remote_name);
63 *config->promisors_tail = r;
64 config->promisors_tail = &r->next;
66 return r;
69 static struct promisor_remote *promisor_remote_lookup(struct promisor_remote_config *config,
70 const char *remote_name,
71 struct promisor_remote **previous)
73 struct promisor_remote *r, *p;
75 for (p = NULL, r = config->promisors; r; p = r, r = r->next)
76 if (!strcmp(r->name, remote_name)) {
77 if (previous)
78 *previous = p;
79 return r;
82 return NULL;
85 static void promisor_remote_move_to_tail(struct promisor_remote_config *config,
86 struct promisor_remote *r,
87 struct promisor_remote *previous)
89 if (!r->next)
90 return;
92 if (previous)
93 previous->next = r->next;
94 else
95 config->promisors = r->next ? r->next : r;
96 r->next = NULL;
97 *config->promisors_tail = r;
98 config->promisors_tail = &r->next;
101 static int promisor_remote_config(const char *var, const char *value, void *data)
103 struct promisor_remote_config *config = data;
104 const char *name;
105 size_t namelen;
106 const char *subkey;
108 if (parse_config_key(var, "remote", &name, &namelen, &subkey) < 0)
109 return 0;
111 if (!strcmp(subkey, "promisor")) {
112 char *remote_name;
114 if (!git_config_bool(var, value))
115 return 0;
117 remote_name = xmemdupz(name, namelen);
119 if (!promisor_remote_lookup(config, remote_name, NULL))
120 promisor_remote_new(config, remote_name);
122 free(remote_name);
123 return 0;
125 if (!strcmp(subkey, "partialclonefilter")) {
126 struct promisor_remote *r;
127 char *remote_name = xmemdupz(name, namelen);
129 r = promisor_remote_lookup(config, remote_name, NULL);
130 if (!r)
131 r = promisor_remote_new(config, remote_name);
133 free(remote_name);
135 if (!r)
136 return 0;
138 return git_config_string(&r->partial_clone_filter, var, value);
141 return 0;
144 static void promisor_remote_init(struct repository *r)
146 struct promisor_remote_config *config;
148 if (r->promisor_remote_config)
149 return;
150 config = r->promisor_remote_config =
151 xcalloc(1, sizeof(*r->promisor_remote_config));
152 config->promisors_tail = &config->promisors;
154 repo_config(r, promisor_remote_config, config);
156 if (r->repository_format_partial_clone) {
157 struct promisor_remote *o, *previous;
159 o = promisor_remote_lookup(config,
160 r->repository_format_partial_clone,
161 &previous);
162 if (o)
163 promisor_remote_move_to_tail(config, o, previous);
164 else
165 promisor_remote_new(config, r->repository_format_partial_clone);
169 void promisor_remote_clear(struct promisor_remote_config *config)
171 while (config->promisors) {
172 struct promisor_remote *r = config->promisors;
173 config->promisors = config->promisors->next;
174 free(r);
177 config->promisors_tail = &config->promisors;
180 void repo_promisor_remote_reinit(struct repository *r)
182 promisor_remote_clear(r->promisor_remote_config);
183 FREE_AND_NULL(r->promisor_remote_config);
184 promisor_remote_init(r);
187 struct promisor_remote *repo_promisor_remote_find(struct repository *r,
188 const char *remote_name)
190 promisor_remote_init(r);
192 if (!remote_name)
193 return r->promisor_remote_config->promisors;
195 return promisor_remote_lookup(r->promisor_remote_config, remote_name, NULL);
198 int repo_has_promisor_remote(struct repository *r)
200 return !!repo_promisor_remote_find(r, NULL);
203 static int remove_fetched_oids(struct repository *repo,
204 struct object_id **oids,
205 int oid_nr, int to_free)
207 int i, remaining_nr = 0;
208 int *remaining = xcalloc(oid_nr, sizeof(*remaining));
209 struct object_id *old_oids = *oids;
210 struct object_id *new_oids;
212 for (i = 0; i < oid_nr; i++)
213 if (oid_object_info_extended(repo, &old_oids[i], NULL,
214 OBJECT_INFO_SKIP_FETCH_OBJECT)) {
215 remaining[i] = 1;
216 remaining_nr++;
219 if (remaining_nr) {
220 int j = 0;
221 CALLOC_ARRAY(new_oids, remaining_nr);
222 for (i = 0; i < oid_nr; i++)
223 if (remaining[i])
224 oidcpy(&new_oids[j++], &old_oids[i]);
225 *oids = new_oids;
226 if (to_free)
227 free(old_oids);
230 free(remaining);
232 return remaining_nr;
235 void promisor_remote_get_direct(struct repository *repo,
236 const struct object_id *oids,
237 int oid_nr)
239 struct promisor_remote *r;
240 struct object_id *remaining_oids = (struct object_id *)oids;
241 int remaining_nr = oid_nr;
242 int to_free = 0;
243 int i;
245 if (oid_nr == 0)
246 return;
248 promisor_remote_init(repo);
250 for (r = repo->promisor_remote_config->promisors; r; r = r->next) {
251 if (fetch_objects(repo, r->name, remaining_oids, remaining_nr) < 0) {
252 if (remaining_nr == 1)
253 continue;
254 remaining_nr = remove_fetched_oids(repo, &remaining_oids,
255 remaining_nr, to_free);
256 if (remaining_nr) {
257 to_free = 1;
258 continue;
261 goto all_fetched;
264 for (i = 0; i < remaining_nr; i++) {
265 if (is_promisor_object(&remaining_oids[i]))
266 die(_("could not fetch %s from promisor remote"),
267 oid_to_hex(&remaining_oids[i]));
270 all_fetched:
271 if (to_free)
272 free(remaining_oids);