Line | Count | Source |
1 | | #include "git-compat-util.h" |
2 | | #include "abspath.h" |
3 | | #include "commit-graph.h" |
4 | | #include "config.h" |
5 | | #include "dir.h" |
6 | | #include "environment.h" |
7 | | #include "gettext.h" |
8 | | #include "hex.h" |
9 | | #include "khash.h" |
10 | | #include "lockfile.h" |
11 | | #include "loose.h" |
12 | | #include "midx.h" |
13 | | #include "object-file-convert.h" |
14 | | #include "object-file.h" |
15 | | #include "odb.h" |
16 | | #include "packfile.h" |
17 | | #include "path.h" |
18 | | #include "promisor-remote.h" |
19 | | #include "quote.h" |
20 | | #include "replace-object.h" |
21 | | #include "run-command.h" |
22 | | #include "setup.h" |
23 | | #include "strbuf.h" |
24 | | #include "strvec.h" |
25 | | #include "submodule.h" |
26 | | #include "tmp-objdir.h" |
27 | | #include "trace2.h" |
28 | | #include "write-or-die.h" |
29 | | |
30 | 0 | KHASH_INIT(odb_path_map, const char * /* key: odb_path */, |
31 | 0 | struct odb_source *, 1, fspathhash, fspatheq) |
32 | 0 |
|
33 | 0 | /* |
34 | 0 | * This is meant to hold a *small* number of objects that you would |
35 | 0 | * want odb_read_object() to be able to return, but yet you do not want |
36 | 0 | * to write them into the object store (e.g. a browse-only |
37 | 0 | * application). |
38 | 0 | */ |
39 | 0 | struct cached_object_entry { |
40 | 0 | struct object_id oid; |
41 | 0 | struct cached_object { |
42 | 0 | enum object_type type; |
43 | 0 | const void *buf; |
44 | 0 | unsigned long size; |
45 | 0 | } value; |
46 | 0 | }; |
47 | 0 |
|
48 | 0 | static const struct cached_object *find_cached_object(struct object_database *object_store, |
49 | 0 | const struct object_id *oid) |
50 | 0 | { |
51 | 0 | static const struct cached_object empty_tree = { |
52 | 0 | .type = OBJ_TREE, |
53 | 0 | .buf = "", |
54 | 0 | }; |
55 | 0 | const struct cached_object_entry *co = object_store->cached_objects; |
56 | |
|
57 | 0 | for (size_t i = 0; i < object_store->cached_object_nr; i++, co++) |
58 | 0 | if (oideq(&co->oid, oid)) |
59 | 0 | return &co->value; |
60 | | |
61 | 0 | if (oid->algo && oideq(oid, hash_algos[oid->algo].empty_tree)) |
62 | 0 | return &empty_tree; |
63 | | |
64 | 0 | return NULL; |
65 | 0 | } |
66 | | |
67 | | int odb_mkstemp(struct object_database *odb, |
68 | | struct strbuf *temp_filename, const char *pattern) |
69 | 0 | { |
70 | 0 | int fd; |
71 | | /* |
72 | | * we let the umask do its job, don't try to be more |
73 | | * restrictive except to remove write permission. |
74 | | */ |
75 | 0 | int mode = 0444; |
76 | 0 | repo_git_path_replace(odb->repo, temp_filename, "objects/%s", pattern); |
77 | 0 | fd = git_mkstemp_mode(temp_filename->buf, mode); |
78 | 0 | if (0 <= fd) |
79 | 0 | return fd; |
80 | | |
81 | | /* slow path */ |
82 | | /* some mkstemp implementations erase temp_filename on failure */ |
83 | 0 | repo_git_path_replace(odb->repo, temp_filename, "objects/%s", pattern); |
84 | 0 | safe_create_leading_directories(odb->repo, temp_filename->buf); |
85 | 0 | return xmkstemp_mode(temp_filename->buf, mode); |
86 | 0 | } |
87 | | |
88 | | /* |
89 | | * Return non-zero iff the path is usable as an alternate object database. |
90 | | */ |
91 | | static bool odb_is_source_usable(struct object_database *o, const char *path) |
92 | 0 | { |
93 | 0 | int r; |
94 | 0 | struct strbuf normalized_objdir = STRBUF_INIT; |
95 | 0 | bool usable = false; |
96 | |
|
97 | 0 | strbuf_realpath(&normalized_objdir, o->sources->path, 1); |
98 | | |
99 | | /* Detect cases where alternate disappeared */ |
100 | 0 | if (!is_directory(path)) { |
101 | 0 | error(_("object directory %s does not exist; " |
102 | 0 | "check .git/objects/info/alternates"), |
103 | 0 | path); |
104 | 0 | goto out; |
105 | 0 | } |
106 | | |
107 | | /* |
108 | | * Prevent the common mistake of listing the same |
109 | | * thing twice, or object directory itself. |
110 | | */ |
111 | 0 | if (!o->source_by_path) { |
112 | 0 | khiter_t p; |
113 | |
|
114 | 0 | o->source_by_path = kh_init_odb_path_map(); |
115 | 0 | assert(!o->sources->next); |
116 | 0 | p = kh_put_odb_path_map(o->source_by_path, o->sources->path, &r); |
117 | 0 | assert(r == 1); /* never used */ |
118 | 0 | kh_value(o->source_by_path, p) = o->sources; |
119 | 0 | } |
120 | |
|
121 | 0 | if (fspatheq(path, normalized_objdir.buf)) |
122 | 0 | goto out; |
123 | | |
124 | 0 | if (kh_get_odb_path_map(o->source_by_path, path) < kh_end(o->source_by_path)) |
125 | 0 | goto out; |
126 | | |
127 | 0 | usable = true; |
128 | |
|
129 | 0 | out: |
130 | 0 | strbuf_release(&normalized_objdir); |
131 | 0 | return usable; |
132 | 0 | } |
133 | | |
134 | | void parse_alternates(const char *string, |
135 | | int sep, |
136 | | const char *relative_base, |
137 | | struct strvec *out) |
138 | 0 | { |
139 | 0 | struct strbuf pathbuf = STRBUF_INIT; |
140 | 0 | struct strbuf buf = STRBUF_INIT; |
141 | |
|
142 | 0 | if (!string || !*string) |
143 | 0 | return; |
144 | | |
145 | 0 | while (*string) { |
146 | 0 | const char *end; |
147 | |
|
148 | 0 | strbuf_reset(&buf); |
149 | 0 | strbuf_reset(&pathbuf); |
150 | |
|
151 | 0 | if (*string == '#') { |
152 | | /* comment; consume up to next separator */ |
153 | 0 | end = strchrnul(string, sep); |
154 | 0 | } else if (*string == '"' && !unquote_c_style(&buf, string, &end)) { |
155 | | /* |
156 | | * quoted path; unquote_c_style has copied the |
157 | | * data for us and set "end". Broken quoting (e.g., |
158 | | * an entry that doesn't end with a quote) falls |
159 | | * back to the unquoted case below. |
160 | | */ |
161 | 0 | } else { |
162 | | /* normal, unquoted path */ |
163 | 0 | end = strchrnul(string, sep); |
164 | 0 | strbuf_add(&buf, string, end - string); |
165 | 0 | } |
166 | |
|
167 | 0 | if (*end) |
168 | 0 | end++; |
169 | 0 | string = end; |
170 | |
|
171 | 0 | if (!buf.len) |
172 | 0 | continue; |
173 | | |
174 | 0 | if (!is_absolute_path(buf.buf) && relative_base) { |
175 | 0 | strbuf_realpath(&pathbuf, relative_base, 1); |
176 | 0 | strbuf_addch(&pathbuf, '/'); |
177 | 0 | } |
178 | 0 | strbuf_addbuf(&pathbuf, &buf); |
179 | |
|
180 | 0 | strbuf_reset(&buf); |
181 | 0 | if (!strbuf_realpath(&buf, pathbuf.buf, 0)) { |
182 | 0 | error(_("unable to normalize alternate object path: %s"), |
183 | 0 | pathbuf.buf); |
184 | 0 | continue; |
185 | 0 | } |
186 | | |
187 | | /* |
188 | | * The trailing slash after the directory name is given by |
189 | | * this function at the end. Remove duplicates. |
190 | | */ |
191 | 0 | while (buf.len && buf.buf[buf.len - 1] == '/') |
192 | 0 | strbuf_setlen(&buf, buf.len - 1); |
193 | |
|
194 | 0 | strvec_push(out, buf.buf); |
195 | 0 | } |
196 | |
|
197 | 0 | strbuf_release(&pathbuf); |
198 | 0 | strbuf_release(&buf); |
199 | 0 | } |
200 | | |
201 | | static struct odb_source *odb_add_alternate_recursively(struct object_database *odb, |
202 | | const char *source, |
203 | | int depth) |
204 | 0 | { |
205 | 0 | struct odb_source *alternate = NULL; |
206 | 0 | struct strvec sources = STRVEC_INIT; |
207 | 0 | khiter_t pos; |
208 | 0 | int ret; |
209 | |
|
210 | 0 | if (!odb_is_source_usable(odb, source)) |
211 | 0 | goto error; |
212 | | |
213 | 0 | alternate = odb_source_new(odb, source, false); |
214 | | |
215 | | /* add the alternate entry */ |
216 | 0 | *odb->sources_tail = alternate; |
217 | 0 | odb->sources_tail = &(alternate->next); |
218 | |
|
219 | 0 | pos = kh_put_odb_path_map(odb->source_by_path, alternate->path, &ret); |
220 | 0 | if (!ret) |
221 | 0 | BUG("source must not yet exist"); |
222 | 0 | kh_value(odb->source_by_path, pos) = alternate; |
223 | | |
224 | | /* recursively add alternates */ |
225 | 0 | odb_source_read_alternates(alternate, &sources); |
226 | 0 | if (sources.nr && depth + 1 > 5) { |
227 | 0 | error(_("%s: ignoring alternate object stores, nesting too deep"), |
228 | 0 | source); |
229 | 0 | } else { |
230 | 0 | for (size_t i = 0; i < sources.nr; i++) |
231 | 0 | odb_add_alternate_recursively(odb, sources.v[i], depth + 1); |
232 | 0 | } |
233 | |
|
234 | 0 | error: |
235 | 0 | strvec_clear(&sources); |
236 | 0 | return alternate; |
237 | 0 | } |
238 | | |
239 | | void odb_add_to_alternates_file(struct object_database *odb, |
240 | | const char *dir) |
241 | 0 | { |
242 | 0 | int ret = odb_source_write_alternate(odb->sources, dir); |
243 | 0 | if (ret < 0) |
244 | 0 | die(NULL); |
245 | 0 | if (odb->loaded_alternates) |
246 | 0 | odb_add_alternate_recursively(odb, dir, 0); |
247 | 0 | } |
248 | | |
249 | | struct odb_source *odb_add_to_alternates_memory(struct object_database *odb, |
250 | | const char *dir) |
251 | 0 | { |
252 | | /* |
253 | | * Make sure alternates are initialized, or else our entry may be |
254 | | * overwritten when they are. |
255 | | */ |
256 | 0 | odb_prepare_alternates(odb); |
257 | 0 | return odb_add_alternate_recursively(odb, dir, 0); |
258 | 0 | } |
259 | | |
260 | | struct odb_source *odb_set_temporary_primary_source(struct object_database *odb, |
261 | | const char *dir, int will_destroy) |
262 | 0 | { |
263 | 0 | struct odb_source *source; |
264 | | |
265 | | /* |
266 | | * Make sure alternates are initialized, or else our entry may be |
267 | | * overwritten when they are. |
268 | | */ |
269 | 0 | odb_prepare_alternates(odb); |
270 | | |
271 | | /* |
272 | | * Make a new primary odb and link the old primary ODB in as an |
273 | | * alternate |
274 | | */ |
275 | 0 | source = odb_source_new(odb, dir, false); |
276 | | |
277 | | /* |
278 | | * Disable ref updates while a temporary odb is active, since |
279 | | * the objects in the database may roll back. |
280 | | */ |
281 | 0 | odb->repo->disable_ref_updates = true; |
282 | 0 | source->will_destroy = will_destroy; |
283 | 0 | source->next = odb->sources; |
284 | 0 | odb->sources = source; |
285 | 0 | return source->next; |
286 | 0 | } |
287 | | |
288 | | void odb_restore_primary_source(struct object_database *odb, |
289 | | struct odb_source *restore_source, |
290 | | const char *old_path) |
291 | 0 | { |
292 | 0 | struct odb_source *cur_source = odb->sources; |
293 | |
|
294 | 0 | if (strcmp(old_path, cur_source->path)) |
295 | 0 | BUG("expected %s as primary object store; found %s", |
296 | 0 | old_path, cur_source->path); |
297 | | |
298 | 0 | if (cur_source->next != restore_source) |
299 | 0 | BUG("we expect the old primary object store to be the first alternate"); |
300 | | |
301 | 0 | odb->repo->disable_ref_updates = false; |
302 | 0 | odb->sources = restore_source; |
303 | 0 | odb_source_free(cur_source); |
304 | 0 | } |
305 | | |
306 | | char *compute_alternate_path(const char *path, struct strbuf *err) |
307 | 0 | { |
308 | 0 | char *ref_git = NULL; |
309 | 0 | const char *repo; |
310 | 0 | int seen_error = 0; |
311 | |
|
312 | 0 | ref_git = real_pathdup(path, 0); |
313 | 0 | if (!ref_git) { |
314 | 0 | seen_error = 1; |
315 | 0 | strbuf_addf(err, _("path '%s' does not exist"), path); |
316 | 0 | goto out; |
317 | 0 | } |
318 | | |
319 | 0 | repo = read_gitfile(ref_git); |
320 | 0 | if (!repo) |
321 | 0 | repo = read_gitfile(mkpath("%s/.git", ref_git)); |
322 | 0 | if (repo) { |
323 | 0 | free(ref_git); |
324 | 0 | ref_git = xstrdup(repo); |
325 | 0 | } |
326 | |
|
327 | 0 | if (!repo && is_directory(mkpath("%s/.git/objects", ref_git))) { |
328 | 0 | char *ref_git_git = mkpathdup("%s/.git", ref_git); |
329 | 0 | free(ref_git); |
330 | 0 | ref_git = ref_git_git; |
331 | 0 | } else if (!is_directory(mkpath("%s/objects", ref_git))) { |
332 | 0 | struct strbuf sb = STRBUF_INIT; |
333 | 0 | seen_error = 1; |
334 | 0 | if (get_common_dir(&sb, ref_git)) { |
335 | 0 | strbuf_addf(err, |
336 | 0 | _("reference repository '%s' as a linked " |
337 | 0 | "checkout is not supported yet."), |
338 | 0 | path); |
339 | 0 | goto out; |
340 | 0 | } |
341 | | |
342 | 0 | strbuf_addf(err, _("reference repository '%s' is not a " |
343 | 0 | "local repository."), path); |
344 | 0 | goto out; |
345 | 0 | } |
346 | | |
347 | 0 | if (!access(mkpath("%s/shallow", ref_git), F_OK)) { |
348 | 0 | strbuf_addf(err, _("reference repository '%s' is shallow"), |
349 | 0 | path); |
350 | 0 | seen_error = 1; |
351 | 0 | goto out; |
352 | 0 | } |
353 | | |
354 | 0 | if (!access(mkpath("%s/info/grafts", ref_git), F_OK)) { |
355 | 0 | strbuf_addf(err, |
356 | 0 | _("reference repository '%s' is grafted"), |
357 | 0 | path); |
358 | 0 | seen_error = 1; |
359 | 0 | goto out; |
360 | 0 | } |
361 | | |
362 | 0 | out: |
363 | 0 | if (seen_error) { |
364 | 0 | FREE_AND_NULL(ref_git); |
365 | 0 | } |
366 | |
|
367 | 0 | return ref_git; |
368 | 0 | } |
369 | | |
370 | | struct odb_source *odb_find_source(struct object_database *odb, const char *obj_dir) |
371 | 0 | { |
372 | 0 | struct odb_source *source; |
373 | 0 | char *obj_dir_real = real_pathdup(obj_dir, 1); |
374 | 0 | struct strbuf odb_path_real = STRBUF_INIT; |
375 | |
|
376 | 0 | odb_prepare_alternates(odb); |
377 | 0 | for (source = odb->sources; source; source = source->next) { |
378 | 0 | strbuf_realpath(&odb_path_real, source->path, 1); |
379 | 0 | if (!strcmp(obj_dir_real, odb_path_real.buf)) |
380 | 0 | break; |
381 | 0 | } |
382 | |
|
383 | 0 | free(obj_dir_real); |
384 | 0 | strbuf_release(&odb_path_real); |
385 | |
|
386 | 0 | return source; |
387 | 0 | } |
388 | | |
389 | | struct odb_source *odb_find_source_or_die(struct object_database *odb, const char *obj_dir) |
390 | 0 | { |
391 | 0 | struct odb_source *source = odb_find_source(odb, obj_dir); |
392 | 0 | if (!source) |
393 | 0 | die(_("could not find object directory matching %s"), obj_dir); |
394 | 0 | return source; |
395 | 0 | } |
396 | | |
397 | | void odb_add_submodule_source_by_path(struct object_database *odb, |
398 | | const char *path) |
399 | 0 | { |
400 | 0 | string_list_insert(&odb->submodule_source_paths, path); |
401 | 0 | } |
402 | | |
403 | | static void fill_alternate_refs_command(struct repository *repo, |
404 | | struct child_process *cmd, |
405 | | const char *repo_path) |
406 | 0 | { |
407 | 0 | const char *value; |
408 | |
|
409 | 0 | if (!repo_config_get_value(repo, "core.alternateRefsCommand", &value)) { |
410 | 0 | cmd->use_shell = 1; |
411 | |
|
412 | 0 | strvec_push(&cmd->args, value); |
413 | 0 | strvec_push(&cmd->args, repo_path); |
414 | 0 | } else { |
415 | 0 | cmd->git_cmd = 1; |
416 | |
|
417 | 0 | strvec_pushf(&cmd->args, "--git-dir=%s", repo_path); |
418 | 0 | strvec_push(&cmd->args, "for-each-ref"); |
419 | 0 | strvec_push(&cmd->args, "--format=%(objectname)"); |
420 | |
|
421 | 0 | if (!repo_config_get_value(repo, "core.alternateRefsPrefixes", &value)) { |
422 | 0 | strvec_push(&cmd->args, "--"); |
423 | 0 | strvec_split(&cmd->args, value); |
424 | 0 | } |
425 | 0 | } |
426 | |
|
427 | 0 | strvec_pushv(&cmd->env, (const char **)local_repo_env); |
428 | 0 | cmd->out = -1; |
429 | 0 | } |
430 | | |
431 | | static void read_alternate_refs(struct repository *repo, |
432 | | const char *path, |
433 | | odb_for_each_alternate_ref_fn *cb, |
434 | | void *payload) |
435 | 0 | { |
436 | 0 | struct child_process cmd = CHILD_PROCESS_INIT; |
437 | 0 | struct strbuf line = STRBUF_INIT; |
438 | 0 | FILE *fh; |
439 | |
|
440 | 0 | fill_alternate_refs_command(repo, &cmd, path); |
441 | |
|
442 | 0 | if (start_command(&cmd)) |
443 | 0 | return; |
444 | | |
445 | 0 | fh = xfdopen(cmd.out, "r"); |
446 | 0 | while (strbuf_getline_lf(&line, fh) != EOF) { |
447 | 0 | struct object_id oid; |
448 | 0 | const char *p; |
449 | |
|
450 | 0 | if (parse_oid_hex_algop(line.buf, &oid, &p, repo->hash_algo) || *p) { |
451 | 0 | warning(_("invalid line while parsing alternate refs: %s"), |
452 | 0 | line.buf); |
453 | 0 | break; |
454 | 0 | } |
455 | | |
456 | 0 | cb(&oid, payload); |
457 | 0 | } |
458 | |
|
459 | 0 | fclose(fh); |
460 | 0 | finish_command(&cmd); |
461 | 0 | strbuf_release(&line); |
462 | 0 | } |
463 | | |
464 | | struct alternate_refs_data { |
465 | | odb_for_each_alternate_ref_fn *fn; |
466 | | void *payload; |
467 | | }; |
468 | | |
469 | | static int refs_from_alternate_cb(struct odb_source *alternate, |
470 | | void *payload) |
471 | 0 | { |
472 | 0 | struct strbuf path = STRBUF_INIT; |
473 | 0 | size_t base_len; |
474 | 0 | struct alternate_refs_data *cb = payload; |
475 | |
|
476 | 0 | if (!strbuf_realpath(&path, alternate->path, 0)) |
477 | 0 | goto out; |
478 | 0 | if (!strbuf_strip_suffix(&path, "/objects")) |
479 | 0 | goto out; |
480 | 0 | base_len = path.len; |
481 | | |
482 | | /* Is this a git repository with refs? */ |
483 | 0 | strbuf_addstr(&path, "/refs"); |
484 | 0 | if (!is_directory(path.buf)) |
485 | 0 | goto out; |
486 | 0 | strbuf_setlen(&path, base_len); |
487 | |
|
488 | 0 | read_alternate_refs(alternate->odb->repo, path.buf, cb->fn, cb->payload); |
489 | |
|
490 | 0 | out: |
491 | 0 | strbuf_release(&path); |
492 | 0 | return 0; |
493 | 0 | } |
494 | | |
495 | | void odb_for_each_alternate_ref(struct object_database *odb, |
496 | | odb_for_each_alternate_ref_fn cb, void *payload) |
497 | 0 | { |
498 | 0 | struct alternate_refs_data data; |
499 | 0 | data.fn = cb; |
500 | 0 | data.payload = payload; |
501 | 0 | odb_for_each_alternate(odb, refs_from_alternate_cb, &data); |
502 | 0 | } |
503 | | |
504 | | int odb_for_each_alternate(struct object_database *odb, |
505 | | odb_for_each_alternate_fn cb, void *payload) |
506 | 0 | { |
507 | 0 | struct odb_source *alternate; |
508 | 0 | int r = 0; |
509 | |
|
510 | 0 | odb_prepare_alternates(odb); |
511 | 0 | for (alternate = odb->sources->next; alternate; alternate = alternate->next) { |
512 | 0 | r = cb(alternate, payload); |
513 | 0 | if (r) |
514 | 0 | break; |
515 | 0 | } |
516 | 0 | return r; |
517 | 0 | } |
518 | | |
519 | | void odb_prepare_alternates(struct object_database *odb) |
520 | 0 | { |
521 | 0 | struct strvec sources = STRVEC_INIT; |
522 | |
|
523 | 0 | if (odb->loaded_alternates) |
524 | 0 | return; |
525 | | |
526 | 0 | parse_alternates(odb->alternate_db, PATH_SEP, NULL, &sources); |
527 | 0 | odb_source_read_alternates(odb->sources, &sources); |
528 | 0 | for (size_t i = 0; i < sources.nr; i++) |
529 | 0 | odb_add_alternate_recursively(odb, sources.v[i], 0); |
530 | |
|
531 | 0 | odb->loaded_alternates = 1; |
532 | |
|
533 | 0 | strvec_clear(&sources); |
534 | 0 | } |
535 | | |
536 | | int odb_has_alternates(struct object_database *odb) |
537 | 0 | { |
538 | 0 | odb_prepare_alternates(odb); |
539 | 0 | return !!odb->sources->next; |
540 | 0 | } |
541 | | |
542 | | int obj_read_use_lock = 0; |
543 | | pthread_mutex_t obj_read_mutex; |
544 | | |
545 | | void enable_obj_read_lock(void) |
546 | 0 | { |
547 | 0 | if (obj_read_use_lock) |
548 | 0 | return; |
549 | | |
550 | 0 | obj_read_use_lock = 1; |
551 | 0 | init_recursive_mutex(&obj_read_mutex); |
552 | 0 | } |
553 | | |
554 | | void disable_obj_read_lock(void) |
555 | 0 | { |
556 | 0 | if (!obj_read_use_lock) |
557 | 0 | return; |
558 | | |
559 | 0 | obj_read_use_lock = 0; |
560 | 0 | pthread_mutex_destroy(&obj_read_mutex); |
561 | 0 | } |
562 | | |
563 | | int fetch_if_missing = 1; |
564 | | |
565 | | static int register_all_submodule_sources(struct object_database *odb) |
566 | 0 | { |
567 | 0 | int ret = odb->submodule_source_paths.nr; |
568 | |
|
569 | 0 | for (size_t i = 0; i < odb->submodule_source_paths.nr; i++) |
570 | 0 | odb_add_to_alternates_memory(odb, |
571 | 0 | odb->submodule_source_paths.items[i].string); |
572 | 0 | if (ret) { |
573 | 0 | string_list_clear(&odb->submodule_source_paths, 0); |
574 | 0 | trace2_data_intmax("submodule", odb->repo, |
575 | 0 | "register_all_submodule_sources/registered", ret); |
576 | 0 | if (git_env_bool("GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB", 0)) |
577 | 0 | BUG("register_all_submodule_sources() called"); |
578 | 0 | } |
579 | 0 | return ret; |
580 | 0 | } |
581 | | |
582 | | static int do_oid_object_info_extended(struct object_database *odb, |
583 | | const struct object_id *oid, |
584 | | struct object_info *oi, unsigned flags) |
585 | 0 | { |
586 | 0 | const struct cached_object *co; |
587 | 0 | const struct object_id *real = oid; |
588 | 0 | int already_retried = 0; |
589 | |
|
590 | 0 | if (flags & OBJECT_INFO_LOOKUP_REPLACE) |
591 | 0 | real = lookup_replace_object(odb->repo, oid); |
592 | |
|
593 | 0 | if (is_null_oid(real)) |
594 | 0 | return -1; |
595 | | |
596 | 0 | co = find_cached_object(odb, real); |
597 | 0 | if (co) { |
598 | 0 | if (oi) { |
599 | 0 | if (oi->typep) |
600 | 0 | *(oi->typep) = co->type; |
601 | 0 | if (oi->sizep) |
602 | 0 | *(oi->sizep) = co->size; |
603 | 0 | if (oi->disk_sizep) |
604 | 0 | *(oi->disk_sizep) = 0; |
605 | 0 | if (oi->delta_base_oid) |
606 | 0 | oidclr(oi->delta_base_oid, odb->repo->hash_algo); |
607 | 0 | if (oi->contentp) |
608 | 0 | *oi->contentp = xmemdupz(co->buf, co->size); |
609 | 0 | if (oi->mtimep) |
610 | 0 | *oi->mtimep = 0; |
611 | 0 | oi->whence = OI_CACHED; |
612 | 0 | } |
613 | 0 | return 0; |
614 | 0 | } |
615 | | |
616 | 0 | odb_prepare_alternates(odb); |
617 | |
|
618 | 0 | while (1) { |
619 | 0 | struct odb_source *source; |
620 | |
|
621 | 0 | for (source = odb->sources; source; source = source->next) |
622 | 0 | if (!odb_source_read_object_info(source, real, oi, flags)) |
623 | 0 | return 0; |
624 | | |
625 | | /* |
626 | | * When the object hasn't been found we try a second read and |
627 | | * tell the sources so. This may cause them to invalidate |
628 | | * caches or reload on-disk state. |
629 | | */ |
630 | 0 | if (!(flags & OBJECT_INFO_QUICK)) { |
631 | 0 | for (source = odb->sources; source; source = source->next) |
632 | 0 | if (!odb_source_read_object_info(source, real, oi, |
633 | 0 | flags | OBJECT_INFO_SECOND_READ)) |
634 | 0 | return 0; |
635 | 0 | } |
636 | | |
637 | | /* |
638 | | * This might be an attempt at accessing a submodule object as |
639 | | * if it were in main object store (having called |
640 | | * `odb_add_submodule_source_by_path()` on that submodule's |
641 | | * ODB). If any such ODBs exist, register them and try again. |
642 | | */ |
643 | 0 | if (register_all_submodule_sources(odb)) |
644 | | /* We added some alternates; retry */ |
645 | 0 | continue; |
646 | | |
647 | | /* Check if it is a missing object */ |
648 | 0 | if (fetch_if_missing && repo_has_promisor_remote(odb->repo) && |
649 | 0 | !already_retried && |
650 | 0 | !(flags & OBJECT_INFO_SKIP_FETCH_OBJECT)) { |
651 | 0 | promisor_remote_get_direct(odb->repo, real, 1); |
652 | 0 | already_retried = 1; |
653 | 0 | continue; |
654 | 0 | } |
655 | | |
656 | 0 | if (flags & OBJECT_INFO_DIE_IF_CORRUPT) { |
657 | 0 | const struct packed_git *p; |
658 | 0 | if ((flags & OBJECT_INFO_LOOKUP_REPLACE) && !oideq(real, oid)) |
659 | 0 | die(_("replacement %s not found for %s"), |
660 | 0 | oid_to_hex(real), oid_to_hex(oid)); |
661 | 0 | if ((p = has_packed_and_bad(odb->repo, real))) |
662 | 0 | die(_("packed object %s (stored in %s) is corrupt"), |
663 | 0 | oid_to_hex(real), p->pack_name); |
664 | 0 | } |
665 | 0 | return -1; |
666 | 0 | } |
667 | 0 | } |
668 | | |
669 | | static int oid_object_info_convert(struct repository *r, |
670 | | const struct object_id *input_oid, |
671 | | struct object_info *input_oi, unsigned flags) |
672 | 0 | { |
673 | 0 | const struct git_hash_algo *input_algo = &hash_algos[input_oid->algo]; |
674 | 0 | int do_die = flags & OBJECT_INFO_DIE_IF_CORRUPT; |
675 | 0 | enum object_type type; |
676 | 0 | struct object_id oid, delta_base_oid; |
677 | 0 | struct object_info new_oi, *oi; |
678 | 0 | unsigned long size; |
679 | 0 | void *content; |
680 | 0 | int ret; |
681 | |
|
682 | 0 | if (repo_oid_to_algop(r, input_oid, r->hash_algo, &oid)) { |
683 | 0 | if (do_die) |
684 | 0 | die(_("missing mapping of %s to %s"), |
685 | 0 | oid_to_hex(input_oid), r->hash_algo->name); |
686 | 0 | return -1; |
687 | 0 | } |
688 | | |
689 | | /* Is new_oi needed? */ |
690 | 0 | oi = input_oi; |
691 | 0 | if (input_oi && (input_oi->delta_base_oid || input_oi->sizep || |
692 | 0 | input_oi->contentp)) { |
693 | 0 | new_oi = *input_oi; |
694 | | /* Does delta_base_oid need to be converted? */ |
695 | 0 | if (input_oi->delta_base_oid) |
696 | 0 | new_oi.delta_base_oid = &delta_base_oid; |
697 | | /* Will the attributes differ when converted? */ |
698 | 0 | if (input_oi->sizep || input_oi->contentp) { |
699 | 0 | new_oi.contentp = &content; |
700 | 0 | new_oi.sizep = &size; |
701 | 0 | new_oi.typep = &type; |
702 | 0 | } |
703 | 0 | oi = &new_oi; |
704 | 0 | } |
705 | |
|
706 | 0 | ret = odb_read_object_info_extended(r->objects, &oid, oi, flags); |
707 | 0 | if (ret) |
708 | 0 | return -1; |
709 | 0 | if (oi == input_oi) |
710 | 0 | return ret; |
711 | | |
712 | 0 | if (new_oi.contentp) { |
713 | 0 | struct strbuf outbuf = STRBUF_INIT; |
714 | |
|
715 | 0 | if (type != OBJ_BLOB) { |
716 | 0 | ret = convert_object_file(r, &outbuf, |
717 | 0 | r->hash_algo, input_algo, |
718 | 0 | content, size, type, !do_die); |
719 | 0 | free(content); |
720 | 0 | if (ret == -1) |
721 | 0 | return -1; |
722 | 0 | size = outbuf.len; |
723 | 0 | content = strbuf_detach(&outbuf, NULL); |
724 | 0 | } |
725 | 0 | if (input_oi->sizep) |
726 | 0 | *input_oi->sizep = size; |
727 | 0 | if (input_oi->contentp) |
728 | 0 | *input_oi->contentp = content; |
729 | 0 | else |
730 | 0 | free(content); |
731 | 0 | if (input_oi->typep) |
732 | 0 | *input_oi->typep = type; |
733 | 0 | } |
734 | 0 | if (new_oi.delta_base_oid == &delta_base_oid) { |
735 | 0 | if (repo_oid_to_algop(r, &delta_base_oid, input_algo, |
736 | 0 | input_oi->delta_base_oid)) { |
737 | 0 | if (do_die) |
738 | 0 | die(_("missing mapping of %s to %s"), |
739 | 0 | oid_to_hex(&delta_base_oid), |
740 | 0 | input_algo->name); |
741 | 0 | return -1; |
742 | 0 | } |
743 | 0 | } |
744 | 0 | input_oi->whence = new_oi.whence; |
745 | 0 | input_oi->u = new_oi.u; |
746 | 0 | return ret; |
747 | 0 | } |
748 | | |
749 | | int odb_read_object_info_extended(struct object_database *odb, |
750 | | const struct object_id *oid, |
751 | | struct object_info *oi, |
752 | | enum object_info_flags flags) |
753 | 0 | { |
754 | 0 | int ret; |
755 | |
|
756 | 0 | if (oid->algo && (hash_algo_by_ptr(odb->repo->hash_algo) != oid->algo)) |
757 | 0 | return oid_object_info_convert(odb->repo, oid, oi, flags); |
758 | | |
759 | 0 | obj_read_lock(); |
760 | 0 | ret = do_oid_object_info_extended(odb, oid, oi, flags); |
761 | 0 | obj_read_unlock(); |
762 | 0 | return ret; |
763 | 0 | } |
764 | | |
765 | | |
766 | | /* returns enum object_type or negative */ |
767 | | int odb_read_object_info(struct object_database *odb, |
768 | | const struct object_id *oid, |
769 | | unsigned long *sizep) |
770 | 0 | { |
771 | 0 | enum object_type type; |
772 | 0 | struct object_info oi = OBJECT_INFO_INIT; |
773 | |
|
774 | 0 | oi.typep = &type; |
775 | 0 | oi.sizep = sizep; |
776 | 0 | if (odb_read_object_info_extended(odb, oid, &oi, |
777 | 0 | OBJECT_INFO_LOOKUP_REPLACE) < 0) |
778 | 0 | return -1; |
779 | 0 | return type; |
780 | 0 | } |
781 | | |
782 | | int odb_pretend_object(struct object_database *odb, |
783 | | void *buf, unsigned long len, enum object_type type, |
784 | | struct object_id *oid) |
785 | 0 | { |
786 | 0 | struct cached_object_entry *co; |
787 | 0 | char *co_buf; |
788 | |
|
789 | 0 | hash_object_file(odb->repo->hash_algo, buf, len, type, oid); |
790 | 0 | if (odb_has_object(odb, oid, 0) || |
791 | 0 | find_cached_object(odb, oid)) |
792 | 0 | return 0; |
793 | | |
794 | 0 | ALLOC_GROW(odb->cached_objects, |
795 | 0 | odb->cached_object_nr + 1, odb->cached_object_alloc); |
796 | 0 | co = &odb->cached_objects[odb->cached_object_nr++]; |
797 | 0 | co->value.size = len; |
798 | 0 | co->value.type = type; |
799 | 0 | co_buf = xmalloc(len); |
800 | 0 | memcpy(co_buf, buf, len); |
801 | 0 | co->value.buf = co_buf; |
802 | 0 | oidcpy(&co->oid, oid); |
803 | 0 | return 0; |
804 | 0 | } |
805 | | |
806 | | void *odb_read_object(struct object_database *odb, |
807 | | const struct object_id *oid, |
808 | | enum object_type *type, |
809 | | unsigned long *size) |
810 | 0 | { |
811 | 0 | struct object_info oi = OBJECT_INFO_INIT; |
812 | 0 | unsigned flags = OBJECT_INFO_DIE_IF_CORRUPT | OBJECT_INFO_LOOKUP_REPLACE; |
813 | 0 | void *data; |
814 | |
|
815 | 0 | oi.typep = type; |
816 | 0 | oi.sizep = size; |
817 | 0 | oi.contentp = &data; |
818 | 0 | if (odb_read_object_info_extended(odb, oid, &oi, flags)) |
819 | 0 | return NULL; |
820 | | |
821 | 0 | return data; |
822 | 0 | } |
823 | | |
824 | | void *odb_read_object_peeled(struct object_database *odb, |
825 | | const struct object_id *oid, |
826 | | enum object_type required_type, |
827 | | unsigned long *size, |
828 | | struct object_id *actual_oid_return) |
829 | 0 | { |
830 | 0 | enum object_type type; |
831 | 0 | void *buffer; |
832 | 0 | unsigned long isize; |
833 | 0 | struct object_id actual_oid; |
834 | |
|
835 | 0 | oidcpy(&actual_oid, oid); |
836 | 0 | while (1) { |
837 | 0 | int ref_length = -1; |
838 | 0 | const char *ref_type = NULL; |
839 | |
|
840 | 0 | buffer = odb_read_object(odb, &actual_oid, &type, &isize); |
841 | 0 | if (!buffer) |
842 | 0 | return NULL; |
843 | 0 | if (type == required_type) { |
844 | 0 | *size = isize; |
845 | 0 | if (actual_oid_return) |
846 | 0 | oidcpy(actual_oid_return, &actual_oid); |
847 | 0 | return buffer; |
848 | 0 | } |
849 | | /* Handle references */ |
850 | 0 | else if (type == OBJ_COMMIT) |
851 | 0 | ref_type = "tree "; |
852 | 0 | else if (type == OBJ_TAG) |
853 | 0 | ref_type = "object "; |
854 | 0 | else { |
855 | 0 | free(buffer); |
856 | 0 | return NULL; |
857 | 0 | } |
858 | 0 | ref_length = strlen(ref_type); |
859 | |
|
860 | 0 | if (ref_length + odb->repo->hash_algo->hexsz > isize || |
861 | 0 | memcmp(buffer, ref_type, ref_length) || |
862 | 0 | get_oid_hex_algop((char *) buffer + ref_length, &actual_oid, |
863 | 0 | odb->repo->hash_algo)) { |
864 | 0 | free(buffer); |
865 | 0 | return NULL; |
866 | 0 | } |
867 | 0 | free(buffer); |
868 | | /* Now we have the ID of the referred-to object in |
869 | | * actual_oid. Check again. */ |
870 | 0 | } |
871 | 0 | } |
872 | | |
873 | | int odb_has_object(struct object_database *odb, const struct object_id *oid, |
874 | | enum has_object_flags flags) |
875 | 0 | { |
876 | 0 | unsigned object_info_flags = 0; |
877 | |
|
878 | 0 | if (!startup_info->have_repository) |
879 | 0 | return 0; |
880 | 0 | if (!(flags & HAS_OBJECT_RECHECK_PACKED)) |
881 | 0 | object_info_flags |= OBJECT_INFO_QUICK; |
882 | 0 | if (!(flags & HAS_OBJECT_FETCH_PROMISOR)) |
883 | 0 | object_info_flags |= OBJECT_INFO_SKIP_FETCH_OBJECT; |
884 | |
|
885 | 0 | return odb_read_object_info_extended(odb, oid, NULL, object_info_flags) >= 0; |
886 | 0 | } |
887 | | |
888 | | int odb_freshen_object(struct object_database *odb, |
889 | | const struct object_id *oid) |
890 | 0 | { |
891 | 0 | struct odb_source *source; |
892 | 0 | odb_prepare_alternates(odb); |
893 | 0 | for (source = odb->sources; source; source = source->next) |
894 | 0 | if (odb_source_freshen_object(source, oid)) |
895 | 0 | return 1; |
896 | 0 | return 0; |
897 | 0 | } |
898 | | |
899 | | int odb_for_each_object(struct object_database *odb, |
900 | | const struct object_info *request, |
901 | | odb_for_each_object_cb cb, |
902 | | void *cb_data, |
903 | | unsigned flags) |
904 | 0 | { |
905 | 0 | int ret; |
906 | |
|
907 | 0 | odb_prepare_alternates(odb); |
908 | 0 | for (struct odb_source *source = odb->sources; source; source = source->next) { |
909 | 0 | if (flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY && !source->local) |
910 | 0 | continue; |
911 | | |
912 | 0 | ret = odb_source_for_each_object(source, request, cb, cb_data, flags); |
913 | 0 | if (ret) |
914 | 0 | return ret; |
915 | 0 | } |
916 | | |
917 | 0 | return 0; |
918 | 0 | } |
919 | | |
920 | | int odb_count_objects(struct object_database *odb, |
921 | | enum odb_count_objects_flags flags, |
922 | | unsigned long *out) |
923 | 0 | { |
924 | 0 | struct odb_source *source; |
925 | 0 | unsigned long count = 0; |
926 | 0 | int ret; |
927 | |
|
928 | 0 | if (odb->object_count_valid && odb->object_count_flags == flags) { |
929 | 0 | *out = odb->object_count; |
930 | 0 | return 0; |
931 | 0 | } |
932 | | |
933 | 0 | odb_prepare_alternates(odb); |
934 | 0 | for (source = odb->sources; source; source = source->next) { |
935 | 0 | unsigned long c; |
936 | |
|
937 | 0 | ret = odb_source_count_objects(source, flags, &c); |
938 | 0 | if (ret < 0) |
939 | 0 | goto out; |
940 | | |
941 | 0 | count += c; |
942 | 0 | } |
943 | | |
944 | 0 | odb->object_count = count; |
945 | 0 | odb->object_count_valid = 1; |
946 | 0 | odb->object_count_flags = flags; |
947 | |
|
948 | 0 | *out = count; |
949 | 0 | ret = 0; |
950 | |
|
951 | 0 | out: |
952 | 0 | return ret; |
953 | 0 | } |
954 | | |
955 | | void odb_assert_oid_type(struct object_database *odb, |
956 | | const struct object_id *oid, enum object_type expect) |
957 | 0 | { |
958 | 0 | enum object_type type = odb_read_object_info(odb, oid, NULL); |
959 | 0 | if (type < 0) |
960 | 0 | die(_("%s is not a valid object"), oid_to_hex(oid)); |
961 | 0 | if (type != expect) |
962 | 0 | die(_("%s is not a valid '%s' object"), oid_to_hex(oid), |
963 | 0 | type_name(expect)); |
964 | 0 | } |
965 | | |
966 | | int odb_write_object_ext(struct object_database *odb, |
967 | | const void *buf, unsigned long len, |
968 | | enum object_type type, |
969 | | struct object_id *oid, |
970 | | struct object_id *compat_oid, |
971 | | unsigned flags) |
972 | 0 | { |
973 | 0 | return odb_source_write_object(odb->sources, buf, len, type, |
974 | 0 | oid, compat_oid, flags); |
975 | 0 | } |
976 | | |
977 | | int odb_write_object_stream(struct object_database *odb, |
978 | | struct odb_write_stream *stream, size_t len, |
979 | | struct object_id *oid) |
980 | 0 | { |
981 | 0 | return odb_source_write_object_stream(odb->sources, stream, len, oid); |
982 | 0 | } |
983 | | |
984 | | struct object_database *odb_new(struct repository *repo, |
985 | | const char *primary_source, |
986 | | const char *secondary_sources) |
987 | 0 | { |
988 | 0 | struct object_database *o = xmalloc(sizeof(*o)); |
989 | 0 | char *to_free = NULL; |
990 | |
|
991 | 0 | memset(o, 0, sizeof(*o)); |
992 | 0 | o->repo = repo; |
993 | 0 | pthread_mutex_init(&o->replace_mutex, NULL); |
994 | 0 | string_list_init_dup(&o->submodule_source_paths); |
995 | |
|
996 | 0 | if (!primary_source) |
997 | 0 | primary_source = to_free = xstrfmt("%s/objects", repo->commondir); |
998 | 0 | o->sources = odb_source_new(o, primary_source, true); |
999 | 0 | o->sources_tail = &o->sources->next; |
1000 | 0 | o->alternate_db = xstrdup_or_null(secondary_sources); |
1001 | |
|
1002 | 0 | free(to_free); |
1003 | |
|
1004 | 0 | return o; |
1005 | 0 | } |
1006 | | |
1007 | | void odb_close(struct object_database *o) |
1008 | 0 | { |
1009 | 0 | struct odb_source *source; |
1010 | 0 | for (source = o->sources; source; source = source->next) |
1011 | 0 | odb_source_close(source); |
1012 | 0 | close_commit_graph(o); |
1013 | 0 | } |
1014 | | |
1015 | | static void odb_free_sources(struct object_database *o) |
1016 | 0 | { |
1017 | 0 | while (o->sources) { |
1018 | 0 | struct odb_source *next; |
1019 | |
|
1020 | 0 | next = o->sources->next; |
1021 | 0 | odb_source_free(o->sources); |
1022 | 0 | o->sources = next; |
1023 | 0 | } |
1024 | 0 | kh_destroy_odb_path_map(o->source_by_path); |
1025 | 0 | o->source_by_path = NULL; |
1026 | 0 | } |
1027 | | |
1028 | | void odb_free(struct object_database *o) |
1029 | 0 | { |
1030 | 0 | if (!o) |
1031 | 0 | return; |
1032 | | |
1033 | 0 | free(o->alternate_db); |
1034 | |
|
1035 | 0 | oidmap_clear(&o->replace_map, 1); |
1036 | 0 | pthread_mutex_destroy(&o->replace_mutex); |
1037 | |
|
1038 | 0 | odb_close(o); |
1039 | 0 | odb_free_sources(o); |
1040 | |
|
1041 | 0 | for (size_t i = 0; i < o->cached_object_nr; i++) |
1042 | 0 | free((char *) o->cached_objects[i].value.buf); |
1043 | 0 | free(o->cached_objects); |
1044 | |
|
1045 | 0 | string_list_clear(&o->submodule_source_paths, 0); |
1046 | |
|
1047 | 0 | free(o); |
1048 | 0 | } |
1049 | | |
1050 | | void odb_reprepare(struct object_database *o) |
1051 | 0 | { |
1052 | 0 | struct odb_source *source; |
1053 | |
|
1054 | 0 | obj_read_lock(); |
1055 | | |
1056 | | /* |
1057 | | * Reprepare alt odbs, in case the alternates file was modified |
1058 | | * during the course of this process. This only _adds_ odbs to |
1059 | | * the linked list, so existing odbs will continue to exist for |
1060 | | * the lifetime of the process. |
1061 | | */ |
1062 | 0 | o->loaded_alternates = 0; |
1063 | 0 | odb_prepare_alternates(o); |
1064 | |
|
1065 | 0 | for (source = o->sources; source; source = source->next) |
1066 | 0 | odb_source_reprepare(source); |
1067 | |
|
1068 | 0 | o->object_count_valid = 0; |
1069 | |
|
1070 | 0 | obj_read_unlock(); |
1071 | 0 | } |
1072 | | |
1073 | | struct odb_transaction *odb_transaction_begin(struct object_database *odb) |
1074 | 0 | { |
1075 | 0 | if (odb->transaction) |
1076 | 0 | return NULL; |
1077 | | |
1078 | 0 | odb->transaction = odb_transaction_files_begin(odb->sources); |
1079 | |
|
1080 | 0 | return odb->transaction; |
1081 | 0 | } |
1082 | | |
1083 | | void odb_transaction_commit(struct odb_transaction *transaction) |
1084 | 0 | { |
1085 | 0 | if (!transaction) |
1086 | 0 | return; |
1087 | | |
1088 | | /* |
1089 | | * Ensure the transaction ending matches the pending transaction. |
1090 | | */ |
1091 | 0 | ASSERT(transaction == transaction->source->odb->transaction); |
1092 | | |
1093 | 0 | transaction->commit(transaction); |
1094 | | transaction->source->odb->transaction = NULL; |
1095 | 0 | free(transaction); |
1096 | 0 | } |