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