2 #include "object-store.h"
3 #include "promisor-remote.h"
8 static char *repository_format_partial_clone
;
9 static const char *core_partial_clone_filter_default
;
11 void set_repository_format_partial_clone(char *partial_clone
)
13 repository_format_partial_clone
= xstrdup_or_null(partial_clone
);
16 static int fetch_objects(const char *remote_name
,
17 const struct object_id
*oids
,
20 struct child_process child
= CHILD_PROCESS_INIT
;
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");
34 for (i
= 0; i
< oid_nr
; i
++) {
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"));
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;
46 static struct promisor_remote
*promisors
;
47 static struct promisor_remote
**promisors_tail
= &promisors
;
49 static struct promisor_remote
*promisor_remote_new(const char *remote_name
)
51 struct promisor_remote
*r
;
53 if (*remote_name
== '/') {
54 warning(_("promisor remote name cannot begin with '/': %s"),
59 FLEX_ALLOC_STR(r
, name
, remote_name
);
62 promisors_tail
= &r
->next
;
67 static struct promisor_remote
*promisor_remote_lookup(const char *remote_name
,
68 struct promisor_remote
**previous
)
70 struct promisor_remote
*r
, *p
;
72 for (p
= NULL
, r
= promisors
; r
; p
= r
, r
= r
->next
)
73 if (!strcmp(r
->name
, remote_name
)) {
82 static void promisor_remote_move_to_tail(struct promisor_remote
*r
,
83 struct promisor_remote
*previous
)
89 previous
->next
= r
->next
;
91 promisors
= r
->next
? r
->next
: r
;
94 promisors_tail
= &r
->next
;
97 static int promisor_remote_config(const char *var
, const char *value
, void *data
)
103 if (!strcmp(var
, "core.partialclonefilter"))
104 return git_config_string(&core_partial_clone_filter_default
,
107 if (parse_config_key(var
, "remote", &name
, &namelen
, &subkey
) < 0)
110 if (!strcmp(subkey
, "promisor")) {
113 if (!git_config_bool(var
, value
))
116 remote_name
= xmemdupz(name
, namelen
);
118 if (!promisor_remote_lookup(remote_name
, NULL
))
119 promisor_remote_new(remote_name
);
124 if (!strcmp(subkey
, "partialclonefilter")) {
125 struct promisor_remote
*r
;
126 char *remote_name
= xmemdupz(name
, namelen
);
128 r
= promisor_remote_lookup(remote_name
, NULL
);
130 r
= promisor_remote_new(remote_name
);
137 return git_config_string(&r
->partial_clone_filter
, var
, value
);
143 static int initialized
;
145 static void promisor_remote_init(void)
151 git_config(promisor_remote_config
, NULL
);
153 if (repository_format_partial_clone
) {
154 struct promisor_remote
*o
, *previous
;
156 o
= promisor_remote_lookup(repository_format_partial_clone
,
159 promisor_remote_move_to_tail(o
, previous
);
161 promisor_remote_new(repository_format_partial_clone
);
165 static void promisor_remote_clear(void)
168 struct promisor_remote
*r
= promisors
;
169 promisors
= promisors
->next
;
173 promisors_tail
= &promisors
;
176 void promisor_remote_reinit(void)
179 promisor_remote_clear();
180 promisor_remote_init();
183 struct promisor_remote
*promisor_remote_find(const char *remote_name
)
185 promisor_remote_init();
190 return promisor_remote_lookup(remote_name
, NULL
);
193 int has_promisor_remote(void)
195 return !!promisor_remote_find(NULL
);
198 static int remove_fetched_oids(struct repository
*repo
,
199 struct object_id
**oids
,
200 int oid_nr
, int to_free
)
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
;
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
)) {
216 new_oids
= xcalloc(remaining_nr
, sizeof(*new_oids
));
217 for (i
= 0; i
< oid_nr
; i
++)
219 oidcpy(&new_oids
[j
++], &old_oids
[i
]);
230 int promisor_remote_get_direct(struct repository
*repo
,
231 const struct object_id
*oids
,
234 struct promisor_remote
*r
;
235 struct object_id
*remaining_oids
= (struct object_id
*)oids
;
236 int remaining_nr
= oid_nr
;
243 promisor_remote_init();
245 for (r
= promisors
; r
; r
= r
->next
) {
246 if (fetch_objects(r
->name
, remaining_oids
, remaining_nr
) < 0) {
247 if (remaining_nr
== 1)
249 remaining_nr
= remove_fetched_oids(repo
, &remaining_oids
,
250 remaining_nr
, to_free
);
261 free(remaining_oids
);