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