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" | |
9e27beaa | 5 | #include "fetch-object.h" |
48de3158 CC |
6 | |
7 | static struct promisor_remote *promisors; | |
8 | static struct promisor_remote **promisors_tail = &promisors; | |
9 | ||
10 | static struct promisor_remote *promisor_remote_new(const char *remote_name) | |
11 | { | |
12 | struct promisor_remote *r; | |
13 | ||
14 | if (*remote_name == '/') { | |
15 | warning(_("promisor remote name cannot begin with '/': %s"), | |
16 | remote_name); | |
17 | return NULL; | |
18 | } | |
19 | ||
20 | FLEX_ALLOC_STR(r, name, remote_name); | |
21 | ||
22 | *promisors_tail = r; | |
23 | promisors_tail = &r->next; | |
24 | ||
25 | return r; | |
26 | } | |
27 | ||
28 | static struct promisor_remote *promisor_remote_lookup(const char *remote_name, | |
29 | struct promisor_remote **previous) | |
30 | { | |
31 | struct promisor_remote *r, *p; | |
32 | ||
33 | for (p = NULL, r = promisors; r; p = r, r = r->next) | |
34 | if (!strcmp(r->name, remote_name)) { | |
35 | if (previous) | |
36 | *previous = p; | |
37 | return r; | |
38 | } | |
39 | ||
40 | return NULL; | |
41 | } | |
42 | ||
faf2abf4 CC |
43 | static void promisor_remote_move_to_tail(struct promisor_remote *r, |
44 | struct promisor_remote *previous) | |
45 | { | |
46 | if (previous) | |
47 | previous->next = r->next; | |
48 | else | |
49 | promisors = r->next ? r->next : r; | |
50 | r->next = NULL; | |
51 | *promisors_tail = r; | |
52 | promisors_tail = &r->next; | |
53 | } | |
54 | ||
48de3158 CC |
55 | static int promisor_remote_config(const char *var, const char *value, void *data) |
56 | { | |
57 | const char *name; | |
58 | int namelen; | |
59 | const char *subkey; | |
60 | ||
61 | if (parse_config_key(var, "remote", &name, &namelen, &subkey) < 0) | |
62 | return 0; | |
63 | ||
64 | if (!strcmp(subkey, "promisor")) { | |
65 | char *remote_name; | |
66 | ||
67 | if (!git_config_bool(var, value)) | |
68 | return 0; | |
69 | ||
70 | remote_name = xmemdupz(name, namelen); | |
71 | ||
72 | if (!promisor_remote_lookup(remote_name, NULL)) | |
73 | promisor_remote_new(remote_name); | |
74 | ||
75 | free(remote_name); | |
76 | return 0; | |
77 | } | |
fa3d1b63 CC |
78 | if (!strcmp(subkey, "partialclonefilter")) { |
79 | struct promisor_remote *r; | |
80 | char *remote_name = xmemdupz(name, namelen); | |
81 | ||
82 | r = promisor_remote_lookup(remote_name, NULL); | |
83 | if (!r) | |
84 | r = promisor_remote_new(remote_name); | |
85 | ||
86 | free(remote_name); | |
87 | ||
88 | if (!r) | |
89 | return 0; | |
90 | ||
91 | return git_config_string(&r->partial_clone_filter, var, value); | |
92 | } | |
48de3158 CC |
93 | |
94 | return 0; | |
95 | } | |
96 | ||
9cfebc1f CC |
97 | static int initialized; |
98 | ||
48de3158 CC |
99 | static void promisor_remote_init(void) |
100 | { | |
48de3158 CC |
101 | if (initialized) |
102 | return; | |
103 | initialized = 1; | |
104 | ||
105 | git_config(promisor_remote_config, NULL); | |
faf2abf4 CC |
106 | |
107 | if (repository_format_partial_clone) { | |
108 | struct promisor_remote *o, *previous; | |
109 | ||
110 | o = promisor_remote_lookup(repository_format_partial_clone, | |
111 | &previous); | |
112 | if (o) | |
113 | promisor_remote_move_to_tail(o, previous); | |
114 | else | |
115 | promisor_remote_new(repository_format_partial_clone); | |
116 | } | |
48de3158 CC |
117 | } |
118 | ||
9cfebc1f CC |
119 | static void promisor_remote_clear(void) |
120 | { | |
121 | while (promisors) { | |
122 | struct promisor_remote *r = promisors; | |
123 | promisors = promisors->next; | |
124 | free(r); | |
125 | } | |
126 | ||
127 | promisors_tail = &promisors; | |
128 | } | |
129 | ||
130 | void promisor_remote_reinit(void) | |
131 | { | |
132 | initialized = 0; | |
133 | promisor_remote_clear(); | |
134 | promisor_remote_init(); | |
135 | } | |
136 | ||
48de3158 CC |
137 | struct promisor_remote *promisor_remote_find(const char *remote_name) |
138 | { | |
139 | promisor_remote_init(); | |
140 | ||
141 | if (!remote_name) | |
142 | return promisors; | |
143 | ||
144 | return promisor_remote_lookup(remote_name, NULL); | |
145 | } | |
146 | ||
147 | int has_promisor_remote(void) | |
148 | { | |
149 | return !!promisor_remote_find(NULL); | |
150 | } | |
9e27beaa CC |
151 | |
152 | static int remove_fetched_oids(struct repository *repo, | |
153 | struct object_id **oids, | |
154 | int oid_nr, int to_free) | |
155 | { | |
156 | int i, remaining_nr = 0; | |
157 | int *remaining = xcalloc(oid_nr, sizeof(*remaining)); | |
158 | struct object_id *old_oids = *oids; | |
159 | struct object_id *new_oids; | |
160 | ||
161 | for (i = 0; i < oid_nr; i++) | |
162 | if (oid_object_info_extended(repo, &old_oids[i], NULL, | |
163 | OBJECT_INFO_SKIP_FETCH_OBJECT)) { | |
164 | remaining[i] = 1; | |
165 | remaining_nr++; | |
166 | } | |
167 | ||
168 | if (remaining_nr) { | |
169 | int j = 0; | |
170 | new_oids = xcalloc(remaining_nr, sizeof(*new_oids)); | |
171 | for (i = 0; i < oid_nr; i++) | |
172 | if (remaining[i]) | |
173 | oidcpy(&new_oids[j++], &old_oids[i]); | |
174 | *oids = new_oids; | |
175 | if (to_free) | |
176 | free(old_oids); | |
177 | } | |
178 | ||
179 | free(remaining); | |
180 | ||
181 | return remaining_nr; | |
182 | } | |
183 | ||
184 | int promisor_remote_get_direct(struct repository *repo, | |
185 | const struct object_id *oids, | |
186 | int oid_nr) | |
187 | { | |
188 | struct promisor_remote *r; | |
189 | struct object_id *remaining_oids = (struct object_id *)oids; | |
190 | int remaining_nr = oid_nr; | |
191 | int to_free = 0; | |
192 | int res = -1; | |
193 | ||
194 | promisor_remote_init(); | |
195 | ||
196 | for (r = promisors; r; r = r->next) { | |
197 | if (fetch_objects(r->name, remaining_oids, remaining_nr) < 0) { | |
198 | if (remaining_nr == 1) | |
199 | continue; | |
200 | remaining_nr = remove_fetched_oids(repo, &remaining_oids, | |
201 | remaining_nr, to_free); | |
202 | if (remaining_nr) { | |
203 | to_free = 1; | |
204 | continue; | |
205 | } | |
206 | } | |
207 | res = 0; | |
208 | break; | |
209 | } | |
210 | ||
211 | if (to_free) | |
212 | free(remaining_oids); | |
213 | ||
214 | return res; | |
215 | } |