1 #define USE_THE_REPOSITORY_VARIABLE
3 #include "git-compat-util.h"
6 #include "object-store-ll.h"
7 #include "promisor-remote.h"
10 #include "transport.h"
13 #include "environment.h"
15 struct promisor_remote_config
{
16 struct promisor_remote
*promisors
;
17 struct promisor_remote
**promisors_tail
;
20 static int fetch_objects(struct repository
*repo
,
21 const char *remote_name
,
22 const struct object_id
*oids
,
25 struct child_process child
= CHILD_PROCESS_INIT
;
30 if (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT
, 0)) {
31 static int warning_shown
;
34 warning(_("lazy fetching disabled; some objects may not be available"));
41 if (repo
!= the_repository
)
42 prepare_other_repo_env(&child
.env
, repo
->gitdir
);
43 strvec_pushl(&child
.args
, "-c", "fetch.negotiationAlgorithm=noop",
44 "fetch", remote_name
, "--no-tags",
45 "--no-write-fetch-head", "--recurse-submodules=no",
46 "--filter=blob:none", "--stdin", NULL
);
47 if (!git_config_get_bool("promisor.quiet", &quiet
) && quiet
)
48 strvec_push(&child
.args
, "--quiet");
49 if (start_command(&child
))
50 die(_("promisor-remote: unable to fork off fetch subprocess"));
51 child_in
= xfdopen(child
.in
, "w");
53 trace2_data_intmax("promisor", repo
, "fetch_count", oid_nr
);
55 for (i
= 0; i
< oid_nr
; i
++) {
56 if (fputs(oid_to_hex(&oids
[i
]), child_in
) < 0)
57 die_errno(_("promisor-remote: could not write to fetch subprocess"));
58 if (fputc('\n', child_in
) < 0)
59 die_errno(_("promisor-remote: could not write to fetch subprocess"));
62 if (fclose(child_in
) < 0)
63 die_errno(_("promisor-remote: could not close stdin to fetch subprocess"));
64 return finish_command(&child
) ? -1 : 0;
67 static struct promisor_remote
*promisor_remote_new(struct promisor_remote_config
*config
,
68 const char *remote_name
)
70 struct promisor_remote
*r
;
72 if (*remote_name
== '/') {
73 warning(_("promisor remote name cannot begin with '/': %s"),
78 FLEX_ALLOC_STR(r
, name
, remote_name
);
80 *config
->promisors_tail
= r
;
81 config
->promisors_tail
= &r
->next
;
86 static struct promisor_remote
*promisor_remote_lookup(struct promisor_remote_config
*config
,
87 const char *remote_name
,
88 struct promisor_remote
**previous
)
90 struct promisor_remote
*r
, *p
;
92 for (p
= NULL
, r
= config
->promisors
; r
; p
= r
, r
= r
->next
)
93 if (!strcmp(r
->name
, remote_name
)) {
102 static void promisor_remote_move_to_tail(struct promisor_remote_config
*config
,
103 struct promisor_remote
*r
,
104 struct promisor_remote
*previous
)
110 previous
->next
= r
->next
;
112 config
->promisors
= r
->next
? r
->next
: r
;
114 *config
->promisors_tail
= r
;
115 config
->promisors_tail
= &r
->next
;
118 static int promisor_remote_config(const char *var
, const char *value
,
119 const struct config_context
*ctx UNUSED
,
122 struct promisor_remote_config
*config
= data
;
127 if (parse_config_key(var
, "remote", &name
, &namelen
, &subkey
) < 0)
130 if (!strcmp(subkey
, "promisor")) {
133 if (!git_config_bool(var
, value
))
136 remote_name
= xmemdupz(name
, namelen
);
138 if (!promisor_remote_lookup(config
, remote_name
, NULL
))
139 promisor_remote_new(config
, remote_name
);
144 if (!strcmp(subkey
, "partialclonefilter")) {
145 struct promisor_remote
*r
;
146 char *remote_name
= xmemdupz(name
, namelen
);
148 r
= promisor_remote_lookup(config
, remote_name
, NULL
);
150 r
= promisor_remote_new(config
, remote_name
);
157 FREE_AND_NULL(r
->partial_clone_filter
);
158 return git_config_string(&r
->partial_clone_filter
, var
, value
);
164 static void promisor_remote_init(struct repository
*r
)
166 struct promisor_remote_config
*config
;
168 if (r
->promisor_remote_config
)
170 config
= r
->promisor_remote_config
=
171 xcalloc(1, sizeof(*r
->promisor_remote_config
));
172 config
->promisors_tail
= &config
->promisors
;
174 repo_config(r
, promisor_remote_config
, config
);
176 if (r
->repository_format_partial_clone
) {
177 struct promisor_remote
*o
, *previous
;
179 o
= promisor_remote_lookup(config
,
180 r
->repository_format_partial_clone
,
183 promisor_remote_move_to_tail(config
, o
, previous
);
185 promisor_remote_new(config
, r
->repository_format_partial_clone
);
189 void promisor_remote_clear(struct promisor_remote_config
*config
)
191 while (config
->promisors
) {
192 struct promisor_remote
*r
= config
->promisors
;
193 free(r
->partial_clone_filter
);
194 config
->promisors
= config
->promisors
->next
;
198 config
->promisors_tail
= &config
->promisors
;
201 void repo_promisor_remote_reinit(struct repository
*r
)
203 promisor_remote_clear(r
->promisor_remote_config
);
204 FREE_AND_NULL(r
->promisor_remote_config
);
205 promisor_remote_init(r
);
208 struct promisor_remote
*repo_promisor_remote_find(struct repository
*r
,
209 const char *remote_name
)
211 promisor_remote_init(r
);
214 return r
->promisor_remote_config
->promisors
;
216 return promisor_remote_lookup(r
->promisor_remote_config
, remote_name
, NULL
);
219 int repo_has_promisor_remote(struct repository
*r
)
221 return !!repo_promisor_remote_find(r
, NULL
);
224 static int remove_fetched_oids(struct repository
*repo
,
225 struct object_id
**oids
,
226 int oid_nr
, int to_free
)
228 int i
, remaining_nr
= 0;
229 int *remaining
= xcalloc(oid_nr
, sizeof(*remaining
));
230 struct object_id
*old_oids
= *oids
;
231 struct object_id
*new_oids
;
233 for (i
= 0; i
< oid_nr
; i
++)
234 if (oid_object_info_extended(repo
, &old_oids
[i
], NULL
,
235 OBJECT_INFO_SKIP_FETCH_OBJECT
)) {
242 CALLOC_ARRAY(new_oids
, remaining_nr
);
243 for (i
= 0; i
< oid_nr
; i
++)
245 oidcpy(&new_oids
[j
++], &old_oids
[i
]);
256 void promisor_remote_get_direct(struct repository
*repo
,
257 const struct object_id
*oids
,
260 struct promisor_remote
*r
;
261 struct object_id
*remaining_oids
= (struct object_id
*)oids
;
262 int remaining_nr
= oid_nr
;
269 promisor_remote_init(repo
);
271 for (r
= repo
->promisor_remote_config
->promisors
; r
; r
= r
->next
) {
272 if (fetch_objects(repo
, r
->name
, remaining_oids
, remaining_nr
) < 0) {
273 if (remaining_nr
== 1)
275 remaining_nr
= remove_fetched_oids(repo
, &remaining_oids
,
276 remaining_nr
, to_free
);
285 for (i
= 0; i
< remaining_nr
; i
++) {
286 if (is_promisor_object(&remaining_oids
[i
]))
287 die(_("could not fetch %s from promisor remote"),
288 oid_to_hex(&remaining_oids
[i
]));
293 free(remaining_oids
);