/src/git/odb/source-loose.c
Line | Count | Source |
1 | | #include "git-compat-util.h" |
2 | | #include "abspath.h" |
3 | | #include "chdir-notify.h" |
4 | | #include "gettext.h" |
5 | | #include "hex.h" |
6 | | #include "loose.h" |
7 | | #include "object-file.h" |
8 | | #include "object-file-convert.h" |
9 | | #include "odb.h" |
10 | | #include "odb/source-files.h" |
11 | | #include "odb/source-loose.h" |
12 | | #include "odb/streaming.h" |
13 | | #include "oidtree.h" |
14 | | #include "path.h" |
15 | | #include "progress.h" |
16 | | #include "repository.h" |
17 | | #include "strbuf.h" |
18 | | #include "tempfile.h" |
19 | | #include "write-or-die.h" |
20 | | |
21 | | static int append_loose_object(const struct object_id *oid, |
22 | | const char *path UNUSED, |
23 | | void *data) |
24 | 0 | { |
25 | 0 | oidtree_insert(data, oid, NULL); |
26 | 0 | return 0; |
27 | 0 | } |
28 | | |
29 | | static struct oidtree *odb_source_loose_cache(struct odb_source_loose *loose, |
30 | | const struct object_id *oid) |
31 | 0 | { |
32 | 0 | int subdir_nr = oid->hash[0]; |
33 | 0 | struct strbuf buf = STRBUF_INIT; |
34 | 0 | size_t word_bits = bitsizeof(loose->subdir_seen[0]); |
35 | 0 | size_t word_index = subdir_nr / word_bits; |
36 | 0 | size_t mask = (size_t)1u << (subdir_nr % word_bits); |
37 | 0 | uint32_t *bitmap; |
38 | |
|
39 | 0 | if (subdir_nr < 0 || |
40 | 0 | (size_t) subdir_nr >= bitsizeof(loose->subdir_seen)) |
41 | 0 | BUG("subdir_nr out of range"); |
42 | | |
43 | 0 | bitmap = &loose->subdir_seen[word_index]; |
44 | 0 | if (*bitmap & mask) |
45 | 0 | return loose->cache; |
46 | 0 | if (!loose->cache) { |
47 | 0 | ALLOC_ARRAY(loose->cache, 1); |
48 | 0 | oidtree_init(loose->cache); |
49 | 0 | } |
50 | 0 | strbuf_addstr(&buf, loose->base.path); |
51 | 0 | for_each_file_in_obj_subdir(subdir_nr, &buf, |
52 | 0 | loose->base.odb->repo->hash_algo, |
53 | 0 | append_loose_object, |
54 | 0 | NULL, NULL, |
55 | 0 | loose->cache); |
56 | 0 | *bitmap |= mask; |
57 | 0 | strbuf_release(&buf); |
58 | 0 | return loose->cache; |
59 | 0 | } |
60 | | |
61 | | static int quick_has_loose(struct odb_source_loose *loose, |
62 | | const struct object_id *oid) |
63 | 0 | { |
64 | 0 | return !!oidtree_contains(odb_source_loose_cache(loose, oid), oid); |
65 | 0 | } |
66 | | |
67 | | static int read_object_info_from_path(struct odb_source_loose *loose, |
68 | | const char *path, |
69 | | const struct object_id *oid, |
70 | | struct object_info *oi, |
71 | | enum object_info_flags flags, |
72 | | struct strbuf *errmsg) |
73 | 0 | { |
74 | 0 | int ret; |
75 | 0 | int fd; |
76 | 0 | unsigned long mapsize; |
77 | 0 | void *map = NULL; |
78 | 0 | git_zstream stream, *stream_to_end = NULL; |
79 | 0 | char hdr[MAX_HEADER_LEN]; |
80 | 0 | size_t size_scratch; |
81 | 0 | enum object_type type_scratch; |
82 | 0 | struct stat st; |
83 | | |
84 | | /* |
85 | | * If we don't care about type or size, then we don't |
86 | | * need to look inside the object at all. Note that we |
87 | | * do not optimize out the stat call, even if the |
88 | | * caller doesn't care about the disk-size, since our |
89 | | * return value implicitly indicates whether the |
90 | | * object even exists. |
91 | | */ |
92 | 0 | if (!oi || (!oi->typep && !oi->sizep && !oi->contentp)) { |
93 | 0 | struct stat st; |
94 | |
|
95 | 0 | if ((!oi || (!oi->disk_sizep && !oi->mtimep)) && (flags & OBJECT_INFO_QUICK)) { |
96 | 0 | ret = quick_has_loose(loose, oid) ? 0 : ODB_READ_NOT_FOUND; |
97 | 0 | goto out; |
98 | 0 | } |
99 | | |
100 | 0 | if (lstat(path, &st) < 0) { |
101 | 0 | if (errno == ENOENT) { |
102 | 0 | ret = ODB_READ_NOT_FOUND; |
103 | 0 | goto out; |
104 | 0 | } |
105 | | |
106 | 0 | ret = -1; |
107 | 0 | goto out; |
108 | 0 | } |
109 | | |
110 | 0 | if (oi) { |
111 | 0 | if (oi->disk_sizep) |
112 | 0 | *oi->disk_sizep = st.st_size; |
113 | 0 | if (oi->mtimep) |
114 | 0 | *oi->mtimep = st.st_mtime; |
115 | 0 | } |
116 | |
|
117 | 0 | ret = 0; |
118 | 0 | goto out; |
119 | 0 | } |
120 | | |
121 | 0 | fd = git_open(path); |
122 | 0 | if (fd < 0) { |
123 | 0 | if (errno == ENOENT) { |
124 | 0 | ret = ODB_READ_NOT_FOUND; |
125 | 0 | goto out; |
126 | 0 | } |
127 | | |
128 | 0 | ret = error_errno(_("unable to open loose object %s"), oid_to_hex(oid)); |
129 | 0 | goto out; |
130 | 0 | } |
131 | | |
132 | 0 | if (fstat(fd, &st)) { |
133 | 0 | close(fd); |
134 | 0 | ret = -1; |
135 | 0 | goto out; |
136 | 0 | } |
137 | | |
138 | 0 | mapsize = xsize_t(st.st_size); |
139 | 0 | if (!mapsize) { |
140 | 0 | close(fd); |
141 | 0 | ret = error(_("object file %s is empty"), path); |
142 | 0 | goto out; |
143 | 0 | } |
144 | | |
145 | 0 | map = xmmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0); |
146 | 0 | close(fd); |
147 | 0 | if (!map) { |
148 | 0 | ret = -1; |
149 | 0 | goto out; |
150 | 0 | } |
151 | | |
152 | 0 | if (oi->disk_sizep) |
153 | 0 | *oi->disk_sizep = mapsize; |
154 | 0 | if (oi->mtimep) |
155 | 0 | *oi->mtimep = st.st_mtime; |
156 | |
|
157 | 0 | stream_to_end = &stream; |
158 | |
|
159 | 0 | switch (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr))) { |
160 | 0 | case ULHR_OK: |
161 | 0 | if (!oi->sizep) |
162 | 0 | oi->sizep = &size_scratch; |
163 | 0 | if (!oi->typep) |
164 | 0 | oi->typep = &type_scratch; |
165 | |
|
166 | 0 | if (parse_loose_header(hdr, oi) < 0) { |
167 | 0 | ret = error(_("unable to parse %s header"), oid_to_hex(oid)); |
168 | 0 | goto out; |
169 | 0 | } |
170 | | |
171 | 0 | if (*oi->typep < 0) |
172 | 0 | die(_("invalid object type")); |
173 | | |
174 | 0 | if (oi->contentp) { |
175 | 0 | *oi->contentp = unpack_loose_rest(&stream, hdr, *oi->sizep, oid); |
176 | 0 | if (!*oi->contentp) { |
177 | 0 | ret = -1; |
178 | 0 | goto out; |
179 | 0 | } |
180 | 0 | } |
181 | | |
182 | 0 | break; |
183 | 0 | case ULHR_BAD: |
184 | 0 | ret = error(_("unable to unpack %s header"), |
185 | 0 | oid_to_hex(oid)); |
186 | 0 | goto out; |
187 | 0 | case ULHR_TOO_LONG: |
188 | 0 | ret = error(_("header for %s too long, exceeds %d bytes"), |
189 | 0 | oid_to_hex(oid), MAX_HEADER_LEN); |
190 | 0 | goto out; |
191 | 0 | } |
192 | | |
193 | 0 | ret = 0; |
194 | |
|
195 | 0 | out: |
196 | 0 | if (ret && ret != ODB_READ_NOT_FOUND && errmsg) |
197 | 0 | strbuf_addf(errmsg, _("loose object %s (stored in %s) is corrupt"), |
198 | 0 | oid_to_hex(oid), path); |
199 | 0 | if (stream_to_end) |
200 | 0 | git_inflate_end(stream_to_end); |
201 | 0 | if (map) |
202 | 0 | munmap(map, mapsize); |
203 | 0 | if (oi) { |
204 | 0 | if (oi->sizep == &size_scratch) |
205 | 0 | oi->sizep = NULL; |
206 | 0 | if (oi->typep == &type_scratch) |
207 | 0 | oi->typep = NULL; |
208 | 0 | if (oi->delta_base_oid) |
209 | 0 | oidclr(oi->delta_base_oid, loose->base.odb->repo->hash_algo); |
210 | 0 | if (oi->source_infop && !ret) |
211 | 0 | oi->source_infop->source = &loose->base; |
212 | 0 | } |
213 | |
|
214 | 0 | return ret; |
215 | 0 | } |
216 | | |
217 | | static enum odb_read_status odb_source_loose_read_object_info(struct odb_source *source, |
218 | | const struct object_id *oid, |
219 | | struct object_info *oi, |
220 | | enum object_info_flags flags, |
221 | | struct strbuf *errmsg) |
222 | 0 | { |
223 | 0 | struct odb_source_loose *loose = odb_source_loose_downcast(source); |
224 | 0 | static struct strbuf buf = STRBUF_INIT; |
225 | | |
226 | | /* |
227 | | * The second read shouldn't cause new loose objects to show up, unless |
228 | | * there was a race condition with a secondary process. We don't care |
229 | | * about this case though, so we simply skip reading loose objects a |
230 | | * second time. |
231 | | */ |
232 | 0 | if (flags & OBJECT_INFO_SECOND_READ) |
233 | 0 | return ODB_READ_NOT_FOUND; |
234 | | |
235 | 0 | odb_loose_path(loose, &buf, oid); |
236 | 0 | return read_object_info_from_path(loose, buf.buf, oid, oi, flags, errmsg); |
237 | 0 | } |
238 | | |
239 | | /* |
240 | | * Find "oid" as a loose object in given source, open the object and return its |
241 | | * file descriptor. Returns the file descriptor on success, negative on failure. |
242 | | * |
243 | | * The "path" out-parameter will give the path of the object we found (if any). |
244 | | * Note that it may point to static storage and is only valid until another |
245 | | * call to open_loose_object(). |
246 | | */ |
247 | | static int open_loose_object(struct odb_source_loose *loose, |
248 | | const struct object_id *oid, const char **path) |
249 | 0 | { |
250 | 0 | static struct strbuf buf = STRBUF_INIT; |
251 | 0 | int fd; |
252 | |
|
253 | 0 | *path = odb_loose_path(loose, &buf, oid); |
254 | 0 | fd = git_open(*path); |
255 | 0 | if (fd >= 0) |
256 | 0 | return fd; |
257 | | |
258 | 0 | return -1; |
259 | 0 | } |
260 | | |
261 | | static void *odb_source_loose_map_object(struct odb_source_loose *loose, |
262 | | const struct object_id *oid, |
263 | | unsigned long *size) |
264 | 0 | { |
265 | 0 | const char *p; |
266 | 0 | int fd = open_loose_object(loose, oid, &p); |
267 | 0 | void *map = NULL; |
268 | 0 | struct stat st; |
269 | |
|
270 | 0 | if (fd < 0) |
271 | 0 | return NULL; |
272 | | |
273 | 0 | if (!fstat(fd, &st)) { |
274 | 0 | *size = xsize_t(st.st_size); |
275 | 0 | if (!*size) { |
276 | | /* mmap() is forbidden on empty files */ |
277 | 0 | error(_("object file %s is empty"), p); |
278 | 0 | goto out; |
279 | 0 | } |
280 | | |
281 | 0 | map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0); |
282 | 0 | } |
283 | | |
284 | 0 | out: |
285 | 0 | close(fd); |
286 | 0 | return map; |
287 | 0 | } |
288 | | |
289 | | struct odb_loose_read_stream { |
290 | | struct odb_stream base; |
291 | | git_zstream z; |
292 | | enum { |
293 | | ODB_LOOSE_READ_STREAM_INUSE, |
294 | | ODB_LOOSE_READ_STREAM_DONE, |
295 | | ODB_LOOSE_READ_STREAM_ERROR, |
296 | | } z_state; |
297 | | void *mapped; |
298 | | unsigned long mapsize; |
299 | | char hdr[32]; |
300 | | int hdr_avail; |
301 | | int hdr_used; |
302 | | }; |
303 | | |
304 | | static ssize_t read_istream_loose(struct odb_stream *_st, char *buf, size_t sz) |
305 | 0 | { |
306 | 0 | struct odb_loose_read_stream *st = |
307 | 0 | container_of(_st, struct odb_loose_read_stream, base); |
308 | 0 | size_t total_read = 0; |
309 | |
|
310 | 0 | switch (st->z_state) { |
311 | 0 | case ODB_LOOSE_READ_STREAM_DONE: |
312 | 0 | return 0; |
313 | 0 | case ODB_LOOSE_READ_STREAM_ERROR: |
314 | 0 | return -1; |
315 | 0 | default: |
316 | 0 | break; |
317 | 0 | } |
318 | | |
319 | 0 | if (st->hdr_used < st->hdr_avail) { |
320 | 0 | size_t to_copy = st->hdr_avail - st->hdr_used; |
321 | 0 | if (sz < to_copy) |
322 | 0 | to_copy = sz; |
323 | 0 | memcpy(buf, st->hdr + st->hdr_used, to_copy); |
324 | 0 | st->hdr_used += to_copy; |
325 | 0 | total_read += to_copy; |
326 | 0 | } |
327 | |
|
328 | 0 | while (total_read < sz) { |
329 | 0 | int status; |
330 | |
|
331 | 0 | st->z.next_out = (unsigned char *)buf + total_read; |
332 | 0 | st->z.avail_out = sz - total_read; |
333 | 0 | status = git_inflate(&st->z, Z_FINISH); |
334 | |
|
335 | 0 | total_read = st->z.next_out - (unsigned char *)buf; |
336 | |
|
337 | 0 | if (status == Z_STREAM_END) { |
338 | 0 | git_inflate_end(&st->z); |
339 | 0 | st->z_state = ODB_LOOSE_READ_STREAM_DONE; |
340 | 0 | break; |
341 | 0 | } |
342 | 0 | if (status != Z_OK && (status != Z_BUF_ERROR || total_read < sz)) { |
343 | 0 | git_inflate_end(&st->z); |
344 | 0 | st->z_state = ODB_LOOSE_READ_STREAM_ERROR; |
345 | 0 | return -1; |
346 | 0 | } |
347 | 0 | } |
348 | 0 | return total_read; |
349 | 0 | } |
350 | | |
351 | | static int close_istream_loose(struct odb_stream *_st) |
352 | 0 | { |
353 | 0 | struct odb_loose_read_stream *st = |
354 | 0 | container_of(_st, struct odb_loose_read_stream, base); |
355 | |
|
356 | 0 | if (st->z_state == ODB_LOOSE_READ_STREAM_INUSE) |
357 | 0 | git_inflate_end(&st->z); |
358 | 0 | munmap(st->mapped, st->mapsize); |
359 | 0 | return 0; |
360 | 0 | } |
361 | | |
362 | | static int odb_source_loose_read_object_stream(struct odb_stream **out, |
363 | | struct odb_source *source, |
364 | | const struct object_id *oid) |
365 | 0 | { |
366 | 0 | struct odb_source_loose *loose = odb_source_loose_downcast(source); |
367 | 0 | struct object_info oi = OBJECT_INFO_INIT; |
368 | 0 | struct odb_loose_read_stream *st; |
369 | 0 | unsigned long mapsize; |
370 | 0 | void *mapped; |
371 | |
|
372 | 0 | mapped = odb_source_loose_map_object(loose, oid, &mapsize); |
373 | 0 | if (!mapped) |
374 | 0 | return -1; |
375 | | |
376 | | /* |
377 | | * Note: we must allocate this structure early even though we may still |
378 | | * fail. This is because we need to initialize the zlib stream, and it |
379 | | * is not possible to copy the stream around after the fact because it |
380 | | * has self-referencing pointers. |
381 | | */ |
382 | 0 | CALLOC_ARRAY(st, 1); |
383 | |
|
384 | 0 | switch (unpack_loose_header(&st->z, mapped, mapsize, st->hdr, |
385 | 0 | sizeof(st->hdr))) { |
386 | 0 | case ULHR_OK: |
387 | 0 | break; |
388 | 0 | case ULHR_BAD: |
389 | 0 | case ULHR_TOO_LONG: |
390 | 0 | goto error; |
391 | 0 | } |
392 | | |
393 | 0 | oi.sizep = &st->base.size; |
394 | 0 | oi.typep = &st->base.type; |
395 | |
|
396 | 0 | if (parse_loose_header(st->hdr, &oi) < 0 || st->base.type < 0) |
397 | 0 | goto error; |
398 | | |
399 | 0 | st->mapped = mapped; |
400 | 0 | st->mapsize = mapsize; |
401 | 0 | st->hdr_used = strlen(st->hdr) + 1; |
402 | 0 | st->hdr_avail = st->z.total_out; |
403 | 0 | st->z_state = ODB_LOOSE_READ_STREAM_INUSE; |
404 | 0 | st->base.close = close_istream_loose; |
405 | 0 | st->base.read = read_istream_loose; |
406 | |
|
407 | 0 | *out = &st->base; |
408 | |
|
409 | 0 | return 0; |
410 | 0 | error: |
411 | 0 | git_inflate_end(&st->z); |
412 | 0 | munmap(mapped, mapsize); |
413 | 0 | free(st); |
414 | 0 | return -1; |
415 | 0 | } |
416 | | |
417 | | struct for_each_object_wrapper_data { |
418 | | struct odb_source_loose *loose; |
419 | | const struct object_info *request; |
420 | | odb_for_each_object_cb cb; |
421 | | void *cb_data; |
422 | | }; |
423 | | |
424 | | static int for_each_object_wrapper_cb(const struct object_id *oid, |
425 | | const char *path, |
426 | | void *cb_data) |
427 | 0 | { |
428 | 0 | struct for_each_object_wrapper_data *data = cb_data; |
429 | |
|
430 | 0 | if (data->request) { |
431 | 0 | struct object_info oi = *data->request; |
432 | |
|
433 | 0 | if (read_object_info_from_path(data->loose, path, oid, &oi, 0, NULL) < 0) |
434 | 0 | return -1; |
435 | | |
436 | 0 | return data->cb(oid, &oi, data->cb_data); |
437 | 0 | } else { |
438 | 0 | return data->cb(oid, NULL, data->cb_data); |
439 | 0 | } |
440 | 0 | } |
441 | | |
442 | | static int for_each_prefixed_object_wrapper_cb(const struct object_id *oid, |
443 | | void *node_data UNUSED, |
444 | | void *cb_data) |
445 | 0 | { |
446 | 0 | struct for_each_object_wrapper_data *data = cb_data; |
447 | 0 | if (data->request) { |
448 | 0 | struct object_info oi = *data->request; |
449 | |
|
450 | 0 | if (odb_source_read_object_info(&data->loose->base, |
451 | 0 | oid, &oi, 0, NULL) < 0) |
452 | 0 | return -1; |
453 | | |
454 | 0 | return data->cb(oid, &oi, data->cb_data); |
455 | 0 | } else { |
456 | 0 | return data->cb(oid, NULL, data->cb_data); |
457 | 0 | } |
458 | 0 | } |
459 | | |
460 | | static int odb_source_loose_for_each_object(struct odb_source *source, |
461 | | const struct object_info *request, |
462 | | odb_for_each_object_cb cb, |
463 | | void *cb_data, |
464 | | const struct odb_for_each_object_options *opts) |
465 | 0 | { |
466 | 0 | struct odb_source_loose *loose = odb_source_loose_downcast(source); |
467 | 0 | struct for_each_object_wrapper_data data = { |
468 | 0 | .loose = loose, |
469 | 0 | .request = request, |
470 | 0 | .cb = cb, |
471 | 0 | .cb_data = cb_data, |
472 | 0 | }; |
473 | | |
474 | | /* There are no loose promisor objects, so we can return immediately. */ |
475 | 0 | if ((opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY)) |
476 | 0 | return 0; |
477 | 0 | if ((opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !source->local) |
478 | 0 | return 0; |
479 | | |
480 | 0 | if (opts->prefix) |
481 | 0 | return oidtree_each(odb_source_loose_cache(loose, opts->prefix), |
482 | 0 | opts->prefix, opts->prefix_hex_len, |
483 | 0 | for_each_prefixed_object_wrapper_cb, &data); |
484 | | |
485 | 0 | return for_each_loose_file_in_source(source, for_each_object_wrapper_cb, |
486 | 0 | NULL, NULL, &data); |
487 | 0 | } |
488 | | |
489 | | struct find_abbrev_len_data { |
490 | | const struct object_id *oid; |
491 | | unsigned len; |
492 | | }; |
493 | | |
494 | | static int find_abbrev_len_cb(const struct object_id *oid, |
495 | | struct object_info *oi UNUSED, |
496 | | void *cb_data) |
497 | 0 | { |
498 | 0 | struct find_abbrev_len_data *data = cb_data; |
499 | 0 | unsigned len = oid_common_prefix_hexlen(oid, data->oid); |
500 | 0 | if (len != hash_algos[oid->algo].hexsz && len >= data->len) |
501 | 0 | data->len = len + 1; |
502 | 0 | return 0; |
503 | 0 | } |
504 | | |
505 | | static int odb_source_loose_find_abbrev_len(struct odb_source *source, |
506 | | const struct object_id *oid, |
507 | | unsigned min_len, |
508 | | unsigned *out) |
509 | 0 | { |
510 | 0 | struct odb_source_loose *loose = odb_source_loose_downcast(source); |
511 | 0 | struct odb_for_each_object_options opts = { |
512 | 0 | .prefix = oid, |
513 | 0 | .prefix_hex_len = min_len, |
514 | 0 | }; |
515 | 0 | struct find_abbrev_len_data data = { |
516 | 0 | .oid = oid, |
517 | 0 | .len = min_len, |
518 | 0 | }; |
519 | 0 | int ret; |
520 | |
|
521 | 0 | ret = odb_source_for_each_object(&loose->base, NULL, find_abbrev_len_cb, |
522 | 0 | &data, &opts); |
523 | 0 | *out = data.len; |
524 | |
|
525 | 0 | return ret; |
526 | 0 | } |
527 | | |
528 | | static int count_loose_object(const struct object_id *oid UNUSED, |
529 | | struct object_info *oi UNUSED, |
530 | | void *payload) |
531 | 0 | { |
532 | 0 | unsigned long *count = payload; |
533 | 0 | (*count)++; |
534 | 0 | return 0; |
535 | 0 | } |
536 | | |
537 | | static int odb_source_loose_count_objects(struct odb_source *source, |
538 | | enum odb_count_objects_flags flags, |
539 | | unsigned long *out) |
540 | 0 | { |
541 | 0 | struct odb_source_loose *loose = odb_source_loose_downcast(source); |
542 | 0 | const unsigned hexsz = source->odb->repo->hash_algo->hexsz - 2; |
543 | 0 | char *path = NULL; |
544 | 0 | DIR *dir = NULL; |
545 | 0 | int ret; |
546 | |
|
547 | 0 | if (flags & ODB_COUNT_OBJECTS_APPROXIMATE) { |
548 | 0 | unsigned long count = 0; |
549 | 0 | struct dirent *ent; |
550 | |
|
551 | 0 | path = xstrfmt("%s/17", source->path); |
552 | |
|
553 | 0 | dir = opendir(path); |
554 | 0 | if (!dir) { |
555 | 0 | if (errno == ENOENT) { |
556 | 0 | *out = 0; |
557 | 0 | ret = 0; |
558 | 0 | goto out; |
559 | 0 | } |
560 | | |
561 | 0 | ret = error_errno("cannot open object shard '%s'", path); |
562 | 0 | goto out; |
563 | 0 | } |
564 | | |
565 | 0 | while ((ent = readdir(dir)) != NULL) { |
566 | 0 | if (strspn(ent->d_name, "0123456789abcdef") != hexsz || |
567 | 0 | ent->d_name[hexsz] != '\0') |
568 | 0 | continue; |
569 | 0 | count++; |
570 | 0 | } |
571 | |
|
572 | 0 | *out = count * 256; |
573 | 0 | ret = 0; |
574 | 0 | } else { |
575 | 0 | struct odb_for_each_object_options opts = { 0 }; |
576 | 0 | *out = 0; |
577 | 0 | ret = odb_source_for_each_object(&loose->base, NULL, count_loose_object, |
578 | 0 | out, &opts); |
579 | 0 | } |
580 | | |
581 | 0 | out: |
582 | 0 | if (dir) |
583 | 0 | closedir(dir); |
584 | 0 | free(path); |
585 | 0 | return ret; |
586 | 0 | } |
587 | | |
588 | | static int odb_source_loose_freshen_object(struct odb_source *source, |
589 | | const struct object_id *oid, |
590 | | const time_t *mtime) |
591 | 0 | { |
592 | 0 | struct odb_source_loose *loose = odb_source_loose_downcast(source); |
593 | 0 | static struct strbuf path = STRBUF_INIT; |
594 | 0 | odb_loose_path(loose, &path, oid); |
595 | 0 | return !!check_and_freshen_file(path.buf, 1, mtime); |
596 | 0 | } |
597 | | |
598 | | /* Finalize a file on disk, and close it. */ |
599 | | static void close_loose_object(struct odb_source_loose *loose, |
600 | | int fd, const char *filename) |
601 | 0 | { |
602 | 0 | if (loose->base.will_destroy) |
603 | 0 | goto out; |
604 | | |
605 | 0 | if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT)) |
606 | 0 | odb_transaction_files_fsync(loose->base.odb->transaction, fd, filename); |
607 | 0 | else if (fsync_object_files > 0) |
608 | 0 | fsync_or_die(fd, filename); |
609 | 0 | else |
610 | 0 | fsync_component_or_die(FSYNC_COMPONENT_LOOSE_OBJECT, fd, |
611 | 0 | filename); |
612 | |
|
613 | 0 | out: |
614 | 0 | if (close(fd) != 0) |
615 | 0 | die_errno(_("error when closing loose object file")); |
616 | 0 | } |
617 | | |
618 | | /* Size of directory component, including the ending '/' */ |
619 | | static inline int directory_size(const char *filename) |
620 | 0 | { |
621 | 0 | const char *s = strrchr(filename, '/'); |
622 | 0 | if (!s) |
623 | 0 | return 0; |
624 | 0 | return s - filename + 1; |
625 | 0 | } |
626 | | |
627 | | /* |
628 | | * This creates a temporary file in the same directory as the final |
629 | | * 'filename' |
630 | | * |
631 | | * We want to avoid cross-directory filename renames, because those |
632 | | * can have problems on various filesystems (FAT, NFS, Coda). |
633 | | */ |
634 | | static int create_tmpfile(struct repository *repo, |
635 | | struct strbuf *tmp, const char *filename) |
636 | 0 | { |
637 | 0 | int fd, dirlen = directory_size(filename); |
638 | |
|
639 | 0 | strbuf_reset(tmp); |
640 | 0 | strbuf_add(tmp, filename, dirlen); |
641 | 0 | strbuf_addstr(tmp, "tmp_obj_XXXXXX"); |
642 | 0 | fd = git_mkstemp_mode(tmp->buf, 0444); |
643 | 0 | if (fd < 0 && dirlen && errno == ENOENT) { |
644 | | /* |
645 | | * Make sure the directory exists; note that the contents |
646 | | * of the buffer are undefined after mkstemp returns an |
647 | | * error, so we have to rewrite the whole buffer from |
648 | | * scratch. |
649 | | */ |
650 | 0 | strbuf_reset(tmp); |
651 | 0 | strbuf_add(tmp, filename, dirlen - 1); |
652 | 0 | if (mkdir(tmp->buf, 0777) && errno != EEXIST) |
653 | 0 | return -1; |
654 | 0 | if (adjust_shared_perm(repo, tmp->buf)) |
655 | 0 | return -1; |
656 | | |
657 | | /* Try again */ |
658 | 0 | strbuf_addstr(tmp, "/tmp_obj_XXXXXX"); |
659 | 0 | fd = git_mkstemp_mode(tmp->buf, 0444); |
660 | 0 | } |
661 | 0 | return fd; |
662 | 0 | } |
663 | | |
664 | | /** |
665 | | * Common steps for loose object writers to start writing loose |
666 | | * objects: |
667 | | * |
668 | | * - Create tmpfile for the loose object. |
669 | | * - Setup zlib stream for compression. |
670 | | * - Start to feed header to zlib stream. |
671 | | * |
672 | | * Returns a "fd", which should later be provided to |
673 | | * end_loose_object_common(). |
674 | | */ |
675 | | static int start_loose_object_common(struct odb_source_loose *loose, |
676 | | struct strbuf *tmp_file, |
677 | | const char *filename, unsigned flags, |
678 | | git_zstream *stream, |
679 | | unsigned char *buf, size_t buflen, |
680 | | struct git_hash_ctx *c, struct git_hash_ctx *compat_c, |
681 | | char *hdr, int hdrlen) |
682 | 0 | { |
683 | 0 | const struct git_hash_algo *algo = loose->base.odb->repo->hash_algo; |
684 | 0 | const struct git_hash_algo *compat = loose->base.odb->repo->compat_hash_algo; |
685 | 0 | int fd; |
686 | 0 | struct repo_config_values *cfg = repo_config_values(loose->base.odb->repo); |
687 | |
|
688 | 0 | fd = create_tmpfile(loose->base.odb->repo, tmp_file, filename); |
689 | 0 | if (fd < 0) { |
690 | 0 | if (flags & ODB_WRITE_OBJECT_SILENT) |
691 | 0 | return -1; |
692 | 0 | else if (errno == EACCES) |
693 | 0 | return error(_("insufficient permission for adding " |
694 | 0 | "an object to repository database %s"), |
695 | 0 | loose->base.path); |
696 | 0 | else |
697 | 0 | return error_errno( |
698 | 0 | _("unable to create temporary file")); |
699 | 0 | } |
700 | | |
701 | | /* Setup zlib stream for compression */ |
702 | 0 | git_deflate_init(stream, cfg->zlib_compression_level); |
703 | 0 | stream->next_out = buf; |
704 | 0 | stream->avail_out = buflen; |
705 | 0 | git_hash_init(c, algo); |
706 | 0 | if (compat && compat_c) |
707 | 0 | git_hash_init(compat_c, compat); |
708 | | |
709 | | /* Start to feed header to zlib stream */ |
710 | 0 | stream->next_in = (unsigned char *)hdr; |
711 | 0 | stream->avail_in = hdrlen; |
712 | 0 | while (git_deflate(stream, 0) == Z_OK) |
713 | 0 | ; /* nothing */ |
714 | 0 | git_hash_update(c, hdr, hdrlen); |
715 | 0 | if (compat && compat_c) |
716 | 0 | git_hash_update(compat_c, hdr, hdrlen); |
717 | |
|
718 | 0 | return fd; |
719 | 0 | } |
720 | | |
721 | | /** |
722 | | * Common steps for the inner git_deflate() loop for writing loose |
723 | | * objects. Returns what git_deflate() returns. |
724 | | */ |
725 | | static int write_loose_object_common(struct odb_source_loose *loose, |
726 | | struct git_hash_ctx *c, struct git_hash_ctx *compat_c, |
727 | | git_zstream *stream, const int flush, |
728 | | unsigned char *in0, const int fd, |
729 | | unsigned char *compressed, |
730 | | const size_t compressed_len) |
731 | 0 | { |
732 | 0 | const struct git_hash_algo *compat = loose->base.odb->repo->compat_hash_algo; |
733 | 0 | int ret; |
734 | |
|
735 | 0 | ret = git_deflate(stream, flush ? Z_FINISH : 0); |
736 | 0 | git_hash_update(c, in0, stream->next_in - in0); |
737 | 0 | if (compat && compat_c) |
738 | 0 | git_hash_update(compat_c, in0, stream->next_in - in0); |
739 | 0 | if (write_in_full(fd, compressed, stream->next_out - compressed) < 0) |
740 | 0 | die_errno(_("unable to write loose object file")); |
741 | 0 | stream->next_out = compressed; |
742 | 0 | stream->avail_out = compressed_len; |
743 | |
|
744 | 0 | return ret; |
745 | 0 | } |
746 | | |
747 | | /** |
748 | | * Common steps for loose object writers to end writing loose objects: |
749 | | * |
750 | | * - End the compression of zlib stream. |
751 | | * - Get the calculated oid to "oid". |
752 | | */ |
753 | | static int end_loose_object_common(struct odb_source_loose *loose, |
754 | | struct git_hash_ctx *c, struct git_hash_ctx *compat_c, |
755 | | git_zstream *stream, struct object_id *oid, |
756 | | struct object_id *compat_oid) |
757 | 0 | { |
758 | 0 | const struct git_hash_algo *compat = loose->base.odb->repo->compat_hash_algo; |
759 | 0 | int ret; |
760 | |
|
761 | 0 | ret = git_deflate_end_gently(stream); |
762 | 0 | if (ret != Z_OK) |
763 | 0 | return ret; |
764 | 0 | git_hash_final_oid(oid, c); |
765 | 0 | if (compat && compat_c) |
766 | 0 | git_hash_final_oid(compat_oid, compat_c); |
767 | |
|
768 | 0 | return Z_OK; |
769 | 0 | } |
770 | | |
771 | | static int write_loose_object(struct odb_source_loose *loose, |
772 | | const struct object_id *oid, char *hdr, |
773 | | int hdrlen, const void *buf, unsigned long len, |
774 | | const time_t *mtime, unsigned flags) |
775 | 0 | { |
776 | 0 | int fd, ret; |
777 | 0 | unsigned char compressed[4096]; |
778 | 0 | git_zstream stream; |
779 | 0 | struct git_hash_ctx c; |
780 | 0 | struct object_id parano_oid; |
781 | 0 | static struct strbuf tmp_file = STRBUF_INIT; |
782 | 0 | static struct strbuf filename = STRBUF_INIT; |
783 | |
|
784 | 0 | if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT)) |
785 | 0 | odb_transaction_files_prepare(loose->base.odb->transaction); |
786 | |
|
787 | 0 | odb_loose_path(loose, &filename, oid); |
788 | |
|
789 | 0 | fd = start_loose_object_common(loose, &tmp_file, filename.buf, flags, |
790 | 0 | &stream, compressed, sizeof(compressed), |
791 | 0 | &c, NULL, hdr, hdrlen); |
792 | 0 | if (fd < 0) |
793 | 0 | return -1; |
794 | | |
795 | | /* Then the data itself.. */ |
796 | 0 | stream.next_in = (void *)buf; |
797 | 0 | stream.avail_in = len; |
798 | 0 | do { |
799 | 0 | unsigned char *in0 = stream.next_in; |
800 | |
|
801 | 0 | ret = write_loose_object_common(loose, &c, NULL, &stream, 1, in0, fd, |
802 | 0 | compressed, sizeof(compressed)); |
803 | 0 | } while (ret == Z_OK); |
804 | |
|
805 | 0 | if (ret != Z_STREAM_END) |
806 | 0 | die(_("unable to deflate new object %s (%d)"), oid_to_hex(oid), |
807 | 0 | ret); |
808 | 0 | ret = end_loose_object_common(loose, &c, NULL, &stream, ¶no_oid, NULL); |
809 | 0 | if (ret != Z_OK) |
810 | 0 | die(_("deflateEnd on object %s failed (%d)"), oid_to_hex(oid), |
811 | 0 | ret); |
812 | 0 | if (!oideq(oid, ¶no_oid)) |
813 | 0 | die(_("confused by unstable object source data for %s"), |
814 | 0 | oid_to_hex(oid)); |
815 | | |
816 | 0 | close_loose_object(loose, fd, tmp_file.buf); |
817 | |
|
818 | 0 | if (mtime) { |
819 | 0 | struct utimbuf utb = { |
820 | 0 | .actime = *mtime, |
821 | 0 | .modtime = *mtime, |
822 | 0 | }; |
823 | |
|
824 | 0 | if (utime(tmp_file.buf, &utb) < 0 && |
825 | 0 | !(flags & ODB_WRITE_OBJECT_SILENT)) |
826 | 0 | warning_errno(_("failed utime() on %s"), tmp_file.buf); |
827 | 0 | } |
828 | |
|
829 | 0 | return finalize_object_file_flags(loose->base.odb->repo, tmp_file.buf, filename.buf, |
830 | 0 | FOF_SKIP_COLLISION_CHECK); |
831 | 0 | } |
832 | | |
833 | | static int odb_source_loose_write_object(struct odb_source *source, |
834 | | const void *buf, size_t len, |
835 | | enum object_type type, |
836 | | const struct object_id *oid, |
837 | | const struct object_id *compat_oid, |
838 | | const time_t *mtime, |
839 | | enum odb_write_object_flags flags) |
840 | 0 | { |
841 | 0 | struct odb_source_loose *loose = odb_source_loose_downcast(source); |
842 | 0 | char hdr[MAX_HEADER_LEN]; |
843 | 0 | int hdrlen; |
844 | |
|
845 | 0 | hdrlen = format_object_header(hdr, sizeof(hdr), type, len); |
846 | |
|
847 | 0 | if (write_loose_object(loose, oid, hdr, hdrlen, buf, len, mtime, flags)) |
848 | 0 | return -1; |
849 | | |
850 | 0 | if (compat_oid) |
851 | 0 | return repo_add_loose_object_map(loose, oid, compat_oid); |
852 | | |
853 | 0 | return 0; |
854 | 0 | } |
855 | | |
856 | | static int odb_source_loose_write_object_stream(struct odb_source *source, |
857 | | struct odb_stream *in_stream, |
858 | | struct object_id *oid) |
859 | 0 | { |
860 | 0 | struct odb_source_loose *loose = odb_source_loose_downcast(source); |
861 | 0 | const struct git_hash_algo *compat = loose->base.odb->repo->compat_hash_algo; |
862 | 0 | struct object_id compat_oid; |
863 | 0 | int fd, ret, err = 0, flush = 0; |
864 | 0 | unsigned char compressed[4096]; |
865 | 0 | git_zstream stream; |
866 | 0 | struct git_hash_ctx c, compat_c; |
867 | 0 | struct strbuf tmp_file = STRBUF_INIT; |
868 | 0 | struct strbuf filename = STRBUF_INIT; |
869 | 0 | unsigned char buf[8192]; |
870 | 0 | int dirlen; |
871 | 0 | bool is_finished = false; |
872 | 0 | char hdr[MAX_HEADER_LEN]; |
873 | 0 | int hdrlen; |
874 | |
|
875 | 0 | if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT)) |
876 | 0 | odb_transaction_files_prepare(loose->base.odb->transaction); |
877 | | |
878 | | /* Since oid is not determined, save tmp file to odb path. */ |
879 | 0 | strbuf_addf(&filename, "%s/", loose->base.path); |
880 | 0 | hdrlen = format_object_header(hdr, sizeof(hdr), in_stream->type, in_stream->size); |
881 | | |
882 | | /* |
883 | | * Common steps for write_loose_object and stream_loose_object to |
884 | | * start writing loose objects: |
885 | | * |
886 | | * - Create tmpfile for the loose object. |
887 | | * - Setup zlib stream for compression. |
888 | | * - Start to feed header to zlib stream. |
889 | | */ |
890 | 0 | fd = start_loose_object_common(loose, &tmp_file, filename.buf, 0, |
891 | 0 | &stream, compressed, sizeof(compressed), |
892 | 0 | &c, &compat_c, hdr, hdrlen); |
893 | 0 | if (fd < 0) { |
894 | 0 | err = -1; |
895 | 0 | goto cleanup; |
896 | 0 | } |
897 | | |
898 | | /* Then the data itself.. */ |
899 | 0 | do { |
900 | 0 | unsigned char *in0 = stream.next_in; |
901 | |
|
902 | 0 | if (!stream.avail_in && !is_finished) { |
903 | 0 | ssize_t read_len = odb_stream_read(in_stream, buf, |
904 | 0 | sizeof(buf)); |
905 | 0 | if (read_len < 0) { |
906 | 0 | close(fd); |
907 | 0 | err = -1; |
908 | 0 | goto cleanup; |
909 | 0 | } |
910 | | |
911 | | /* All data has been read. */ |
912 | 0 | if (!read_len) { |
913 | 0 | is_finished = true; |
914 | 0 | flush = 1; |
915 | 0 | } |
916 | |
|
917 | 0 | stream.avail_in = read_len; |
918 | 0 | stream.next_in = buf; |
919 | 0 | in0 = buf; |
920 | 0 | } |
921 | 0 | ret = write_loose_object_common(loose, &c, &compat_c, &stream, flush, in0, fd, |
922 | 0 | compressed, sizeof(compressed)); |
923 | | /* |
924 | | * Unlike write_loose_object(), we do not have the entire |
925 | | * buffer. If we get Z_BUF_ERROR due to too few input bytes, |
926 | | * then we'll replenish them in the next input_stream->read() |
927 | | * call when we loop. |
928 | | */ |
929 | 0 | } while (ret == Z_OK || ret == Z_BUF_ERROR); |
930 | | |
931 | 0 | if (stream.total_in != in_stream->size + hdrlen) |
932 | 0 | die(_("write stream object %"PRIuMAX" != %"PRIuMAX), (uintmax_t)stream.total_in, |
933 | 0 | (uintmax_t)in_stream->size + hdrlen); |
934 | | |
935 | | /* |
936 | | * Common steps for write_loose_object and stream_loose_object to |
937 | | * end writing loose object: |
938 | | * |
939 | | * - End the compression of zlib stream. |
940 | | * - Get the calculated oid. |
941 | | */ |
942 | 0 | if (ret != Z_STREAM_END) |
943 | 0 | die(_("unable to stream deflate new object (%d)"), ret); |
944 | 0 | ret = end_loose_object_common(loose, &c, &compat_c, &stream, oid, &compat_oid); |
945 | 0 | if (ret != Z_OK) |
946 | 0 | die(_("deflateEnd on stream object failed (%d)"), ret); |
947 | 0 | close_loose_object(loose, fd, tmp_file.buf); |
948 | |
|
949 | 0 | if (odb_freshen_object(loose->base.odb, oid)) { |
950 | 0 | unlink_or_warn(tmp_file.buf); |
951 | 0 | goto cleanup; |
952 | 0 | } |
953 | 0 | odb_loose_path(loose, &filename, oid); |
954 | | |
955 | | /* We finally know the object path, and create the missing dir. */ |
956 | 0 | dirlen = directory_size(filename.buf); |
957 | 0 | if (dirlen) { |
958 | 0 | struct strbuf dir = STRBUF_INIT; |
959 | 0 | strbuf_add(&dir, filename.buf, dirlen); |
960 | |
|
961 | 0 | if (safe_create_dir_in_gitdir(loose->base.odb->repo, dir.buf) && |
962 | 0 | errno != EEXIST) { |
963 | 0 | err = error_errno(_("unable to create directory %s"), dir.buf); |
964 | 0 | strbuf_release(&dir); |
965 | 0 | goto cleanup; |
966 | 0 | } |
967 | 0 | strbuf_release(&dir); |
968 | 0 | } |
969 | | |
970 | 0 | err = finalize_object_file_flags(loose->base.odb->repo, tmp_file.buf, filename.buf, |
971 | 0 | FOF_SKIP_COLLISION_CHECK); |
972 | 0 | if (!err && compat) |
973 | 0 | err = repo_add_loose_object_map(loose, oid, &compat_oid); |
974 | 0 | cleanup: |
975 | 0 | strbuf_release(&tmp_file); |
976 | 0 | strbuf_release(&filename); |
977 | 0 | return err; |
978 | 0 | } |
979 | | |
980 | | static int odb_source_loose_begin_transaction(struct odb_source *source UNUSED, |
981 | | struct odb_transaction **out UNUSED, |
982 | | enum odb_transaction_flags flags UNUSED) |
983 | 0 | { |
984 | | /* TODO: this is a known omission that we'll want to address eventually. */ |
985 | 0 | return error("loose source does not support transactions"); |
986 | 0 | } |
987 | | |
988 | | static int odb_source_loose_read_alternates(struct odb_source *source UNUSED, |
989 | | struct strvec *out UNUSED) |
990 | 0 | { |
991 | 0 | return 0; |
992 | 0 | } |
993 | | |
994 | | static void odb_source_loose_clear_cache(struct odb_source_loose *loose) |
995 | 0 | { |
996 | 0 | oidtree_clear(loose->cache); |
997 | 0 | FREE_AND_NULL(loose->cache); |
998 | 0 | memset(&loose->subdir_seen, 0, |
999 | 0 | sizeof(loose->subdir_seen)); |
1000 | 0 | } |
1001 | | |
1002 | | static void odb_source_loose_prepare(struct odb_source *source, |
1003 | | enum odb_prepare_flags flags) |
1004 | 0 | { |
1005 | 0 | struct odb_source_loose *loose = odb_source_loose_downcast(source); |
1006 | 0 | if (flags & ODB_PREPARE_FLUSH_CACHES) |
1007 | 0 | odb_source_loose_clear_cache(loose); |
1008 | 0 | } |
1009 | | |
1010 | | static void odb_source_loose_close(struct odb_source *source UNUSED) |
1011 | 0 | { |
1012 | | /* Nothing to do. */ |
1013 | 0 | } |
1014 | | |
1015 | | static void odb_source_loose_reparent(const char *old_cwd, |
1016 | | const char *new_cwd, |
1017 | | void *cb_data) |
1018 | 0 | { |
1019 | 0 | struct odb_source_loose *loose = cb_data; |
1020 | 0 | char *path = reparent_relative_path(old_cwd, new_cwd, |
1021 | 0 | loose->base.path); |
1022 | 0 | free(loose->base.path); |
1023 | 0 | loose->base.path = path; |
1024 | 0 | } |
1025 | | |
1026 | | static void odb_source_loose_free(struct odb_source *source) |
1027 | 0 | { |
1028 | 0 | struct odb_source_loose *loose = odb_source_loose_downcast(source); |
1029 | 0 | odb_source_loose_clear_cache(loose); |
1030 | 0 | loose_object_map_clear(&loose->map); |
1031 | 0 | chdir_notify_unregister(odb_source_loose_reparent, loose); |
1032 | 0 | odb_source_release(&loose->base); |
1033 | 0 | free(loose); |
1034 | 0 | } |
1035 | | |
1036 | | struct fsck_loose_data { |
1037 | | struct odb_source_loose *source; |
1038 | | struct odb_fsck_options *opts; |
1039 | | struct progress *progress; |
1040 | | bool error_found; |
1041 | | }; |
1042 | | |
1043 | | static int fsck_loose(const struct object_id *oid, const char *path, |
1044 | | void *cb_data) |
1045 | 0 | { |
1046 | 0 | struct fsck_loose_data *data = cb_data; |
1047 | 0 | enum object_type type = OBJ_NONE; |
1048 | 0 | size_t size; |
1049 | 0 | void *contents = NULL; |
1050 | 0 | int eaten = 0; |
1051 | 0 | struct object_info oi = OBJECT_INFO_INIT; |
1052 | 0 | struct object_id real_oid = *null_oid(data->source->base.odb->repo->hash_algo); |
1053 | 0 | int err = 0; |
1054 | |
|
1055 | 0 | oi.sizep = &size; |
1056 | 0 | oi.typep = &type; |
1057 | |
|
1058 | 0 | if (read_loose_object(data->source->base.odb->repo, |
1059 | 0 | path, oid, &real_oid, &contents, &oi) < 0) { |
1060 | 0 | if (contents && !oideq(&real_oid, oid)) |
1061 | 0 | err = error(_("%s: hash-path mismatch, found at: %s"), |
1062 | 0 | oid_to_hex(&real_oid), path); |
1063 | 0 | else |
1064 | 0 | err = error(_("%s: object corrupt or missing: %s"), |
1065 | 0 | oid_to_hex(oid), path); |
1066 | 0 | } |
1067 | 0 | if (err < 0) |
1068 | 0 | goto out; |
1069 | | |
1070 | 0 | if (!contents && type != OBJ_BLOB) |
1071 | 0 | BUG("read_loose_object streamed a non-blob"); |
1072 | | |
1073 | 0 | if (data->opts->object_cb(oid, type, size, contents, &eaten, |
1074 | 0 | data->opts->object_payload)) { |
1075 | 0 | err = -1; |
1076 | 0 | goto out; |
1077 | 0 | } |
1078 | | |
1079 | 0 | out: |
1080 | 0 | if (err) |
1081 | 0 | data->error_found = true; |
1082 | 0 | if (!eaten) |
1083 | 0 | free(contents); |
1084 | 0 | return 0; /* keep checking other objects, even if we saw an error */ |
1085 | 0 | } |
1086 | | |
1087 | | static int fsck_cruft(const char *basename, const char *path, |
1088 | | void *data UNUSED) |
1089 | 0 | { |
1090 | 0 | if (!starts_with(basename, "tmp_obj_")) |
1091 | 0 | fprintf_ln(stderr, _("bad sha1 file: %s"), path); |
1092 | 0 | return 0; |
1093 | 0 | } |
1094 | | |
1095 | | static int fsck_subdir(unsigned int nr, const char *path UNUSED, void *cb_data) |
1096 | 0 | { |
1097 | 0 | struct fsck_loose_data *data = cb_data; |
1098 | 0 | display_progress(data->progress, nr + 1); |
1099 | 0 | return 0; |
1100 | 0 | } |
1101 | | |
1102 | | static int odb_source_loose_fsck(struct odb_source *source, |
1103 | | struct odb_fsck_options *opts) |
1104 | 0 | { |
1105 | 0 | struct odb_source_loose *loose = odb_source_loose_downcast(source); |
1106 | 0 | struct fsck_loose_data data = { |
1107 | 0 | .source = loose, |
1108 | 0 | .opts = opts, |
1109 | 0 | }; |
1110 | |
|
1111 | 0 | if (opts->flags & ODB_FSCK_VERBOSE) |
1112 | 0 | fprintf_ln(stderr, _("Checking object directory")); |
1113 | |
|
1114 | 0 | if (opts->flags & ODB_FSCK_PROGRESS) |
1115 | 0 | data.progress = start_progress(source->odb->repo, |
1116 | 0 | _("Checking object directories"), 256); |
1117 | |
|
1118 | 0 | for_each_loose_file_in_source(source, fsck_loose, |
1119 | 0 | fsck_cruft, fsck_subdir, &data); |
1120 | 0 | display_progress(data.progress, 256); |
1121 | 0 | stop_progress(&data.progress); |
1122 | |
|
1123 | 0 | return data.error_found ? -1 : 0; |
1124 | 0 | } |
1125 | | |
1126 | | struct odb_source_loose *odb_source_loose_new(struct object_database *odb, |
1127 | | const char *path, |
1128 | | bool local) |
1129 | 0 | { |
1130 | 0 | struct odb_source_loose *loose; |
1131 | |
|
1132 | 0 | CALLOC_ARRAY(loose, 1); |
1133 | 0 | odb_source_init(&loose->base, odb, ODB_SOURCE_LOOSE, path, local); |
1134 | |
|
1135 | 0 | loose->base.free = odb_source_loose_free; |
1136 | 0 | loose->base.close = odb_source_loose_close; |
1137 | 0 | loose->base.prepare = odb_source_loose_prepare; |
1138 | 0 | loose->base.fsck = odb_source_loose_fsck; |
1139 | 0 | loose->base.read_object_info = odb_source_loose_read_object_info; |
1140 | 0 | loose->base.read_object_stream = odb_source_loose_read_object_stream; |
1141 | 0 | loose->base.for_each_object = odb_source_loose_for_each_object; |
1142 | 0 | loose->base.find_abbrev_len = odb_source_loose_find_abbrev_len; |
1143 | 0 | loose->base.count_objects = odb_source_loose_count_objects; |
1144 | 0 | loose->base.freshen_object = odb_source_loose_freshen_object; |
1145 | 0 | loose->base.write_object = odb_source_loose_write_object; |
1146 | 0 | loose->base.write_object_stream = odb_source_loose_write_object_stream; |
1147 | 0 | loose->base.begin_transaction = odb_source_loose_begin_transaction; |
1148 | 0 | loose->base.read_alternates = odb_source_loose_read_alternates; |
1149 | |
|
1150 | 0 | if (!is_absolute_path(loose->base.path)) |
1151 | 0 | chdir_notify_register(odb_source_loose_reparent, loose); |
1152 | |
|
1153 | 0 | loose_object_map_load(loose); |
1154 | |
|
1155 | 0 | return loose; |
1156 | 0 | } |