2 #include "object-store.h"
3 #include "promisor-remote.h"
7 static char *repository_format_partial_clone
;
8 static const char *core_partial_clone_filter_default
;
10 void set_repository_format_partial_clone(char *partial_clone
)
12 repository_format_partial_clone
= xstrdup_or_null(partial_clone
);
15 static int fetch_refs(const char *remote_name
, struct ref
*ref
)
17 struct remote
*remote
;
18 struct transport
*transport
;
19 int original_fetch_if_missing
= fetch_if_missing
;
23 remote
= remote_get(remote_name
);
25 die(_("Remote with no URL"));
26 transport
= transport_get(remote
, remote
->url
[0]);
28 transport_set_option(transport
, TRANS_OPT_FROM_PROMISOR
, "1");
29 transport_set_option(transport
, TRANS_OPT_NO_DEPENDENTS
, "1");
30 res
= transport_fetch_refs(transport
, ref
);
31 fetch_if_missing
= original_fetch_if_missing
;
36 static int fetch_objects(const char *remote_name
,
37 const struct object_id
*oids
,
40 struct ref
*ref
= NULL
;
43 for (i
= 0; i
< oid_nr
; i
++) {
44 struct ref
*new_ref
= alloc_ref(oid_to_hex(&oids
[i
]));
45 oidcpy(&new_ref
->old_oid
, &oids
[i
]);
46 new_ref
->exact_oid
= 1;
50 return fetch_refs(remote_name
, ref
);
53 static struct promisor_remote
*promisors
;
54 static struct promisor_remote
**promisors_tail
= &promisors
;
56 static struct promisor_remote
*promisor_remote_new(const char *remote_name
)
58 struct promisor_remote
*r
;
60 if (*remote_name
== '/') {
61 warning(_("promisor remote name cannot begin with '/': %s"),
66 FLEX_ALLOC_STR(r
, name
, remote_name
);
69 promisors_tail
= &r
->next
;
74 static struct promisor_remote
*promisor_remote_lookup(const char *remote_name
,
75 struct promisor_remote
**previous
)
77 struct promisor_remote
*r
, *p
;
79 for (p
= NULL
, r
= promisors
; r
; p
= r
, r
= r
->next
)
80 if (!strcmp(r
->name
, remote_name
)) {
89 static void promisor_remote_move_to_tail(struct promisor_remote
*r
,
90 struct promisor_remote
*previous
)
96 previous
->next
= r
->next
;
98 promisors
= r
->next
? r
->next
: r
;
101 promisors_tail
= &r
->next
;
104 static int promisor_remote_config(const char *var
, const char *value
, void *data
)
110 if (!strcmp(var
, "core.partialclonefilter"))
111 return git_config_string(&core_partial_clone_filter_default
,
114 if (parse_config_key(var
, "remote", &name
, &namelen
, &subkey
) < 0)
117 if (!strcmp(subkey
, "promisor")) {
120 if (!git_config_bool(var
, value
))
123 remote_name
= xmemdupz(name
, namelen
);
125 if (!promisor_remote_lookup(remote_name
, NULL
))
126 promisor_remote_new(remote_name
);
131 if (!strcmp(subkey
, "partialclonefilter")) {
132 struct promisor_remote
*r
;
133 char *remote_name
= xmemdupz(name
, namelen
);
135 r
= promisor_remote_lookup(remote_name
, NULL
);
137 r
= promisor_remote_new(remote_name
);
144 return git_config_string(&r
->partial_clone_filter
, var
, value
);
150 static int initialized
;
152 static void promisor_remote_init(void)
158 git_config(promisor_remote_config
, NULL
);
160 if (repository_format_partial_clone
) {
161 struct promisor_remote
*o
, *previous
;
163 o
= promisor_remote_lookup(repository_format_partial_clone
,
166 promisor_remote_move_to_tail(o
, previous
);
168 promisor_remote_new(repository_format_partial_clone
);
172 static void promisor_remote_clear(void)
175 struct promisor_remote
*r
= promisors
;
176 promisors
= promisors
->next
;
180 promisors_tail
= &promisors
;
183 void promisor_remote_reinit(void)
186 promisor_remote_clear();
187 promisor_remote_init();
190 struct promisor_remote
*promisor_remote_find(const char *remote_name
)
192 promisor_remote_init();
197 return promisor_remote_lookup(remote_name
, NULL
);
200 int has_promisor_remote(void)
202 return !!promisor_remote_find(NULL
);
205 static int remove_fetched_oids(struct repository
*repo
,
206 struct object_id
**oids
,
207 int oid_nr
, int to_free
)
209 int i
, remaining_nr
= 0;
210 int *remaining
= xcalloc(oid_nr
, sizeof(*remaining
));
211 struct object_id
*old_oids
= *oids
;
212 struct object_id
*new_oids
;
214 for (i
= 0; i
< oid_nr
; i
++)
215 if (oid_object_info_extended(repo
, &old_oids
[i
], NULL
,
216 OBJECT_INFO_SKIP_FETCH_OBJECT
)) {
223 new_oids
= xcalloc(remaining_nr
, sizeof(*new_oids
));
224 for (i
= 0; i
< oid_nr
; i
++)
226 oidcpy(&new_oids
[j
++], &old_oids
[i
]);
237 int promisor_remote_get_direct(struct repository
*repo
,
238 const struct object_id
*oids
,
241 struct promisor_remote
*r
;
242 struct object_id
*remaining_oids
= (struct object_id
*)oids
;
243 int remaining_nr
= oid_nr
;
247 promisor_remote_init();
249 for (r
= promisors
; r
; r
= r
->next
) {
250 if (fetch_objects(r
->name
, remaining_oids
, remaining_nr
) < 0) {
251 if (remaining_nr
== 1)
253 remaining_nr
= remove_fetched_oids(repo
, &remaining_oids
,
254 remaining_nr
, to_free
);
265 free(remaining_oids
);