Raw
1 #include "git-compat-util.h"
2 #include "abspath.h"
3 #include "chdir-notify.h"
4 #include "dir.h"
5 #include "git-zlib.h"
6 #include "list-objects-filter-options.h"
7 #include "mergesort.h"
8 #include "midx.h"
9 #include "odb/source-packed.h"
10 #include "odb/streaming.h"
11 #include "packfile.h"
12 #include "pack-bitmap.h"
13
14 static int find_pack_entry(struct odb_source_packed *store,
15 const struct object_id *oid,
16 struct pack_entry *e)
17 {
18 struct packfile_list_entry *l;
19
20 odb_source_prepare(&store->base, 0);
21 if (store->midx && fill_midx_entry(store->midx, oid, e))
22 return 1;
23
24 for (l = store->packs.head; l; l = l->next) {
25 struct packed_git *p = l->pack;
26
27 if (!p->multi_pack_index && packfile_fill_entry(p, oid, e)) {
28 if (!store->skip_mru_updates)
29 packfile_list_prepend(&store->packs, p);
30 return 1;
31 }
32 }
33
34 return 0;
35 }
36
37 static int odb_source_packed_read_object_info(struct odb_source *source,
38 const struct object_id *oid,
39 struct object_info *oi,
40 enum object_info_flags flags)
41 {
42 struct odb_source_packed *packed = odb_source_packed_downcast(source);
43 struct pack_entry e;
44 int ret;
45
46 /*
47 * In case the first read didn't surface the object, we have to reload
48 * packfiles. This may cause us to discover new packfiles that have
49 * been added since the last time we have prepared the packfile store.
50 */
51 if (flags & OBJECT_INFO_SECOND_READ)
52 odb_source_prepare(source, ODB_PREPARE_FLUSH_CACHES);
53
54 if (!find_pack_entry(packed, oid, &e))
55 return 1;
56
57 /*
58 * We know that the caller doesn't actually need the
59 * information below, so return early.
60 */
61 if (!oi)
62 return 0;
63
64 ret = packed_object_info(packed, e.p, e.offset, oi);
65 if (ret < 0) {
66 mark_bad_packed_object(e.p, oid);
67 return -1;
68 }
69
70 return 0;
71 }
72
73 static int odb_source_packed_read_object_stream(struct odb_read_stream **out,
74 struct odb_source *source,
75 const struct object_id *oid)
76 {
77 struct odb_source_packed *packed = odb_source_packed_downcast(source);
78 struct pack_entry e;
79
80 if (!find_pack_entry(packed, oid, &e))
81 return -1;
82
83 return packfile_read_object_stream(out, oid, e.p, e.offset);
84 }
85
86 struct odb_source_packed_for_each_object_wrapper_data {
87 struct odb_source_packed *store;
88 const struct object_info *request;
89 odb_for_each_object_cb cb;
90 void *cb_data;
91 };
92
93 static int odb_source_packed_for_each_object_wrapper(const struct object_id *oid,
94 struct packed_git *pack,
95 uint32_t index_pos,
96 void *cb_data)
97 {
98 struct odb_source_packed_for_each_object_wrapper_data *data = cb_data;
99
100 if (data->request) {
101 off_t offset = nth_packed_object_offset(pack, index_pos);
102 struct object_info oi = *data->request;
103
104 if (packed_object_info_with_index_pos(data->store, pack, offset,
105 &index_pos, &oi) < 0) {
106 mark_bad_packed_object(pack, oid);
107 return -1;
108 }
109
110 return data->cb(oid, &oi, data->cb_data);
111 } else {
112 return data->cb(oid, NULL, data->cb_data);
113 }
114 }
115
116 static int match_hash(unsigned len, const unsigned char *a, const unsigned char *b)
117 {
118 do {
119 if (*a != *b)
120 return 0;
121 a++;
122 b++;
123 len -= 2;
124 } while (len > 1);
125 if (len)
126 if ((*a ^ *b) & 0xf0)
127 return 0;
128 return 1;
129 }
130
131 static bool should_exclude_pack(struct packed_git *p, enum odb_for_each_object_flags flags)
132 {
133 if ((flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
134 return true;
135 if ((flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY) &&
136 !p->pack_promisor)
137 return true;
138 if ((flags & ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS) &&
139 p->pack_keep_in_core)
140 return true;
141 if ((flags & ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS) &&
142 p->pack_keep)
143 return true;
144 return false;
145 }
146
147 static int for_each_prefixed_object_in_midx(
148 struct odb_source_packed *source,
149 struct multi_pack_index *m,
150 const struct odb_for_each_object_options *opts,
151 struct odb_source_packed_for_each_object_wrapper_data *data)
152 {
153 bool pack_errors = false;
154 int ret;
155
156 for (; m; m = m->base_midx) {
157 uint32_t num, i, first = 0;
158 int len = opts->prefix_hex_len > m->source->base.odb->repo->hash_algo->hexsz ?
159 m->source->base.odb->repo->hash_algo->hexsz : opts->prefix_hex_len;
160
161 if (!m->num_objects)
162 continue;
163
164 num = m->num_objects + m->num_objects_in_base;
165
166 bsearch_one_midx(opts->prefix, m, &first);
167
168 /*
169 * At this point, "first" is the location of the lowest
170 * object with an object name that could match "opts->prefix".
171 * See if we have 0, 1 or more objects that actually match(es).
172 */
173 for (i = first; i < num; i++) {
174 const struct object_id *current = NULL;
175 struct packed_git *pack;
176 struct object_id oid;
177
178 current = nth_midxed_object_oid(&oid, m, i);
179
180 if (!match_hash(len, opts->prefix->hash, current->hash))
181 break;
182
183 if (opts->flags || data->request) {
184 uint32_t pack_id = nth_midxed_pack_int_id(m, i);
185
186 if (prepare_midx_pack(m, pack_id)) {
187 pack_errors = true;
188 continue;
189 }
190
191 pack = nth_midxed_pack(m, pack_id);
192 if (should_exclude_pack(pack, opts->flags))
193 continue;
194 }
195
196 if (data->request) {
197 struct object_info oi = *data->request;
198 off_t offset = nth_midxed_offset(m, i);
199
200 ret = packed_object_info(source, pack, offset, &oi);
201 if (ret)
202 goto out;
203
204 ret = data->cb(&oid, &oi, data->cb_data);
205 if (ret)
206 goto out;
207 } else {
208 ret = data->cb(&oid, NULL, data->cb_data);
209 if (ret)
210 goto out;
211 }
212 }
213 }
214
215 ret = 0;
216
217 out:
218 if (!ret && pack_errors)
219 ret = -1;
220 return ret;
221 }
222
223 static int for_each_prefixed_object_in_pack(
224 struct odb_source_packed *source,
225 struct packed_git *p,
226 const struct odb_for_each_object_options *opts,
227 struct odb_source_packed_for_each_object_wrapper_data *data)
228 {
229 uint32_t num, i, first = 0;
230 int len = opts->prefix_hex_len > p->repo->hash_algo->hexsz ?
231 p->repo->hash_algo->hexsz : opts->prefix_hex_len;
232 int ret;
233
234 num = p->num_objects;
235 bsearch_pack(opts->prefix, p, &first);
236
237 /*
238 * At this point, "first" is the location of the lowest object
239 * with an object name that could match "bin_pfx". See if we have
240 * 0, 1 or more objects that actually match(es).
241 */
242 for (i = first; i < num; i++) {
243 struct object_id oid;
244
245 nth_packed_object_id(&oid, p, i);
246 if (!match_hash(len, opts->prefix->hash, oid.hash))
247 break;
248
249 if (data->request) {
250 struct object_info oi = *data->request;
251 off_t offset = nth_packed_object_offset(p, i);
252
253 ret = packed_object_info(source, p, offset, &oi);
254 if (ret)
255 goto out;
256
257 ret = data->cb(&oid, &oi, data->cb_data);
258 if (ret)
259 goto out;
260 } else {
261 ret = data->cb(&oid, NULL, data->cb_data);
262 if (ret)
263 goto out;
264 }
265 }
266
267 ret = 0;
268
269 out:
270 return ret;
271 }
272
273 static int odb_source_packed_for_each_prefixed_object(
274 struct odb_source_packed *store,
275 const struct odb_for_each_object_options *opts,
276 struct odb_source_packed_for_each_object_wrapper_data *data)
277 {
278 struct packfile_list_entry *e;
279 struct multi_pack_index *m;
280 bool pack_errors = false;
281 int ret;
282
283 store->skip_mru_updates = true;
284
285 m = get_multi_pack_index(store);
286 if (m) {
287 ret = for_each_prefixed_object_in_midx(store, m, opts, data);
288 if (ret)
289 goto out;
290 }
291
292 for (e = packfile_store_get_packs(store); e; e = e->next) {
293 if (e->pack->multi_pack_index)
294 continue;
295 if (should_exclude_pack(e->pack, opts->flags))
296 continue;
297
298 if (open_pack_index(e->pack)) {
299 pack_errors = true;
300 continue;
301 }
302
303 if (!e->pack->num_objects)
304 continue;
305
306 ret = for_each_prefixed_object_in_pack(store, e->pack, opts, data);
307 if (ret)
308 goto out;
309 }
310
311 ret = 0;
312
313 out:
314 store->skip_mru_updates = false;
315 if (!ret && pack_errors)
316 ret = -1;
317 return ret;
318 }
319
320 struct bitmapped_for_each_object_data {
321 struct odb_source_packed *packed;
322 const struct object_info *request;
323 const struct odb_for_each_object_options *opts;
324 odb_for_each_object_cb cb;
325 void *cb_data;
326 };
327
328 static int bitmapped_for_each_object(const struct object_id *oid,
329 enum object_type type UNUSED,
330 int flags UNUSED,
331 uint32_t hash UNUSED,
332 struct packed_git *pack,
333 off_t offset,
334 void *cb_data)
335 {
336 struct bitmapped_for_each_object_data *data = cb_data;
337
338 if (should_exclude_pack(pack, data->opts->flags))
339 return 0;
340
341 if (data->request) {
342 struct object_info oi = *data->request;
343 if (packed_object_info(data->packed, pack, offset, &oi) < 0)
344 return -1;
345 return data->cb(oid, &oi, data->cb_data);
346 }
347
348 return data->cb(oid, NULL, data->cb_data);
349 }
350
351 static int odb_source_packed_for_each_object(struct odb_source *source,
352 const struct object_info *request,
353 odb_for_each_object_cb cb,
354 void *cb_data,
355 const struct odb_for_each_object_options *opts)
356 {
357 struct odb_source_packed *packed = odb_source_packed_downcast(source);
358 struct odb_source_packed_for_each_object_wrapper_data data = {
359 .store = packed,
360 .request = request,
361 .cb = cb,
362 .cb_data = cb_data,
363 };
364 struct bitmap_index *bitmap = NULL;
365 struct packfile_list_entry *e;
366 int pack_errors = 0, ret;
367
368 if (opts->prefix)
369 return odb_source_packed_for_each_prefixed_object(packed, opts, &data);
370
371 if (opts->filter &&
372 opts->filter->choice != LOFC_DISABLED &&
373 can_filter_bitmap(opts->filter))
374 bitmap = prepare_bitmap_git_for_source(packed);
375 if (bitmap) {
376 struct bitmapped_for_each_object_data bitmap_data = {
377 .packed = packed,
378 .request = request,
379 .opts = opts,
380 .cb = cb,
381 .cb_data = cb_data,
382 };
383
384 ret = for_each_bitmapped_object(bitmap, opts->filter,
385 bitmapped_for_each_object,
386 &bitmap_data);
387 if (ret)
388 goto out;
389 }
390
391 packed->skip_mru_updates = true;
392
393 for (e = packfile_store_get_packs(packed); e; e = e->next) {
394 struct packed_git *p = e->pack;
395
396 if (should_exclude_pack(p, opts->flags))
397 continue;
398
399 /*
400 * Objects covered by the bitmap have already been yielded
401 * above; skip them here to avoid duplicates.
402 */
403 if (bitmap && bitmap_index_contains_pack(bitmap, p))
404 continue;
405
406 if (open_pack_index(p)) {
407 pack_errors = 1;
408 continue;
409 }
410
411 ret = for_each_object_in_pack(p, odb_source_packed_for_each_object_wrapper,
412 &data, opts->flags);
413 if (ret)
414 goto out;
415 }
416
417 ret = 0;
418
419 out:
420 packed->skip_mru_updates = false;
421 free_bitmap_index(bitmap);
422
423 if (!ret && pack_errors)
424 ret = -1;
425 return ret;
426 }
427
428 static int odb_source_packed_count_objects(struct odb_source *source,
429 enum odb_count_objects_flags flags UNUSED,
430 unsigned long *out)
431 {
432 struct odb_source_packed *packed = odb_source_packed_downcast(source);
433 struct packfile_list_entry *e;
434 struct multi_pack_index *m;
435 unsigned long count = 0;
436 int ret;
437
438 m = get_multi_pack_index(packed);
439 if (m)
440 count += m->num_objects + m->num_objects_in_base;
441
442 for (e = packfile_store_get_packs(packed); e; e = e->next) {
443 if (e->pack->multi_pack_index)
444 continue;
445 if (open_pack_index(e->pack)) {
446 ret = -1;
447 goto out;
448 }
449
450 count += e->pack->num_objects;
451 }
452
453 *out = count;
454 ret = 0;
455
456 out:
457 return ret;
458 }
459
460 static int extend_abbrev_len(const struct object_id *a,
461 const struct object_id *b,
462 unsigned *out)
463 {
464 unsigned len = oid_common_prefix_hexlen(a, b);
465 if (len != hash_algos[a->algo].hexsz && len >= *out)
466 *out = len + 1;
467 return 0;
468 }
469
470 static void find_abbrev_len_for_midx(struct multi_pack_index *m,
471 const struct object_id *oid,
472 unsigned min_len,
473 unsigned *out)
474 {
475 unsigned len = min_len;
476
477 for (; m; m = m->base_midx) {
478 int match = 0;
479 uint32_t num, first = 0;
480 struct object_id found_oid;
481
482 if (!m->num_objects)
483 continue;
484
485 num = m->num_objects + m->num_objects_in_base;
486 match = bsearch_one_midx(oid, m, &first);
487
488 /*
489 * first is now the position in the packfile where we
490 * would insert the object ID if it does not exist (or the
491 * position of the object ID if it does exist). Hence, we
492 * consider a maximum of two objects nearby for the
493 * abbreviation length.
494 */
495
496 if (!match) {
497 if (nth_midxed_object_oid(&found_oid, m, first))
498 extend_abbrev_len(&found_oid, oid, &len);
499 } else if (first < num - 1) {
500 if (nth_midxed_object_oid(&found_oid, m, first + 1))
501 extend_abbrev_len(&found_oid, oid, &len);
502 }
503 if (first > 0) {
504 if (nth_midxed_object_oid(&found_oid, m, first - 1))
505 extend_abbrev_len(&found_oid, oid, &len);
506 }
507 }
508
509 *out = len;
510 }
511
512 static void find_abbrev_len_for_pack(struct packed_git *p,
513 const struct object_id *oid,
514 unsigned min_len,
515 unsigned *out)
516 {
517 int match;
518 uint32_t num, first = 0;
519 struct object_id found_oid;
520 unsigned len = min_len;
521
522 num = p->num_objects;
523 match = bsearch_pack(oid, p, &first);
524
525 /*
526 * first is now the position in the packfile where we would insert
527 * the object ID if it does not exist (or the position of mad->hash if
528 * it does exist). Hence, we consider a maximum of two objects
529 * nearby for the abbreviation length.
530 */
531 if (!match) {
532 if (!nth_packed_object_id(&found_oid, p, first))
533 extend_abbrev_len(&found_oid, oid, &len);
534 } else if (first < num - 1) {
535 if (!nth_packed_object_id(&found_oid, p, first + 1))
536 extend_abbrev_len(&found_oid, oid, &len);
537 }
538 if (first > 0) {
539 if (!nth_packed_object_id(&found_oid, p, first - 1))
540 extend_abbrev_len(&found_oid, oid, &len);
541 }
542
543 *out = len;
544 }
545
546 static int odb_source_packed_find_abbrev_len(struct odb_source *source,
547 const struct object_id *oid,
548 unsigned min_len,
549 unsigned *out)
550 {
551 struct odb_source_packed *packed = odb_source_packed_downcast(source);
552 struct packfile_list_entry *e;
553 struct multi_pack_index *m;
554
555 m = get_multi_pack_index(packed);
556 if (m)
557 find_abbrev_len_for_midx(m, oid, min_len, &min_len);
558
559 for (e = packfile_store_get_packs(packed); e; e = e->next) {
560 if (e->pack->multi_pack_index)
561 continue;
562 if (open_pack_index(e->pack) || !e->pack->num_objects)
563 continue;
564
565 find_abbrev_len_for_pack(e->pack, oid, min_len, &min_len);
566 }
567
568 *out = min_len;
569 return 0;
570 }
571
572 static int odb_source_packed_freshen_object(struct odb_source *source,
573 const struct object_id *oid,
574 const time_t *mtime)
575 {
576 struct odb_source_packed *packed = odb_source_packed_downcast(source);
577 struct utimbuf times, *timesp = NULL;
578 struct pack_entry e;
579
580 if (mtime) {
581 times.actime = *mtime;
582 times.modtime = *mtime;
583 timesp = &times;
584 }
585
586 if (!find_pack_entry(packed, oid, &e))
587 return 0;
588 if (e.p->is_cruft)
589 return 0;
590 if (e.p->freshened)
591 return 1;
592 if (utime(e.p->pack_name, timesp))
593 return 0;
594 e.p->freshened = 1;
595
596 return 1;
597 }
598
599 static int odb_source_packed_write_object(struct odb_source *source UNUSED,
600 const void *buf UNUSED,
601 size_t len UNUSED,
602 enum object_type type UNUSED,
603 const struct object_id *oid UNUSED,
604 const struct object_id *compat_oid UNUSED,
605 const time_t *mtime UNUSED,
606 unsigned flags UNUSED)
607 {
608 return error("packed backend cannot write objects");
609 }
610
611 static int odb_source_packed_write_object_stream(struct odb_source *source UNUSED,
612 struct odb_write_stream *stream UNUSED,
613 size_t len UNUSED,
614 struct object_id *oid UNUSED)
615 {
616 return error("packed backend cannot write object streams");
617 }
618
619 static int odb_source_packed_begin_transaction(struct odb_source *source UNUSED,
620 struct odb_transaction **out UNUSED,
621 enum odb_transaction_flags flags UNUSED)
622 {
623 return error("packed backend cannot begin transactions");
624 }
625
626 static int odb_source_packed_read_alternates(struct odb_source *source UNUSED,
627 struct strvec *out UNUSED)
628 {
629 return 0;
630 }
631
632 static int odb_source_packed_write_alternate(struct odb_source *source UNUSED,
633 const char *alternate UNUSED)
634 {
635 return error("packed backend cannot write alternates");
636 }
637
638 void (*report_garbage)(unsigned seen_bits, const char *path);
639
640 static void report_helper(const struct string_list *list,
641 int seen_bits, int first, int last)
642 {
643 if (seen_bits == (PACKDIR_FILE_PACK|PACKDIR_FILE_IDX))
644 return;
645
646 for (; first < last; first++)
647 report_garbage(seen_bits, list->items[first].string);
648 }
649
650 static void report_pack_garbage(struct string_list *list)
651 {
652 int baselen = -1, first = 0, seen_bits = 0;
653
654 if (!report_garbage)
655 return;
656
657 string_list_sort(list);
658
659 for (size_t i = 0; i < list->nr; i++) {
660 const char *path = list->items[i].string;
661 if (baselen != -1 &&
662 strncmp(path, list->items[first].string, baselen)) {
663 report_helper(list, seen_bits, first, i);
664 baselen = -1;
665 seen_bits = 0;
666 }
667 if (baselen == -1) {
668 const char *dot = strrchr(path, '.');
669 if (!dot) {
670 report_garbage(PACKDIR_FILE_GARBAGE, path);
671 continue;
672 }
673 baselen = dot - path + 1;
674 first = i;
675 }
676 if (!strcmp(path + baselen, "pack"))
677 seen_bits |= 1;
678 else if (!strcmp(path + baselen, "idx"))
679 seen_bits |= 2;
680 }
681 report_helper(list, seen_bits, first, list->nr);
682 }
683
684 struct prepare_pack_data {
685 struct odb_source_packed *source;
686 struct string_list *garbage;
687 };
688
689 static void prepare_pack(const char *full_name, size_t full_name_len,
690 const char *file_name, void *_data)
691 {
692 struct prepare_pack_data *data = (struct prepare_pack_data *)_data;
693 size_t base_len = full_name_len;
694
695 if (strip_suffix_mem(full_name, &base_len, ".idx") &&
696 !(data->source->midx &&
697 midx_contains_pack(data->source->midx, file_name))) {
698 char *trimmed_path = xstrndup(full_name, full_name_len);
699 packfile_store_load_pack(data->source,
700 trimmed_path, data->source->base.local);
701 free(trimmed_path);
702 }
703
704 if (!report_garbage)
705 return;
706
707 if (!strcmp(file_name, "multi-pack-index") ||
708 !strcmp(file_name, "multi-pack-index.d"))
709 return;
710 if (starts_with(file_name, "multi-pack-index") &&
711 (ends_with(file_name, ".bitmap") || ends_with(file_name, ".rev")))
712 return;
713 if (ends_with(file_name, ".idx") ||
714 ends_with(file_name, ".rev") ||
715 ends_with(file_name, ".pack") ||
716 ends_with(file_name, ".bitmap") ||
717 ends_with(file_name, ".keep") ||
718 ends_with(file_name, ".promisor") ||
719 ends_with(file_name, ".mtimes"))
720 string_list_append(data->garbage, full_name);
721 else
722 report_garbage(PACKDIR_FILE_GARBAGE, full_name);
723 }
724
725 static void prepare_packed_git_one(struct odb_source_packed *source)
726 {
727 struct string_list garbage = STRING_LIST_INIT_DUP;
728 struct prepare_pack_data data = {
729 .source = source,
730 .garbage = &garbage,
731 };
732
733 for_each_file_in_pack_dir(source->base.path, prepare_pack, &data);
734
735 report_pack_garbage(data.garbage);
736 string_list_clear(data.garbage, 0);
737 }
738
739 DEFINE_LIST_SORT(static, sort_packs, struct packfile_list_entry, next);
740
741 static int sort_pack(const struct packfile_list_entry *a,
742 const struct packfile_list_entry *b)
743 {
744 int st;
745
746 /*
747 * Local packs tend to contain objects specific to our
748 * variant of the project than remote ones. In addition,
749 * remote ones could be on a network mounted filesystem.
750 * Favor local ones for these reasons.
751 */
752 st = a->pack->pack_local - b->pack->pack_local;
753 if (st)
754 return -st;
755
756 /*
757 * Younger packs tend to contain more recent objects,
758 * and more recent objects tend to get accessed more
759 * often.
760 */
761 if (a->pack->mtime < b->pack->mtime)
762 return 1;
763 else if (a->pack->mtime == b->pack->mtime)
764 return 0;
765 return -1;
766 }
767
768 static void odb_source_packed_prepare(struct odb_source *source,
769 enum odb_prepare_flags flags)
770 {
771 struct odb_source_packed *packed = odb_source_packed_downcast(source);
772
773 if (flags & ODB_PREPARE_FLUSH_CACHES)
774 packed->initialized = false;
775 if (packed->initialized)
776 return;
777
778 prepare_multi_pack_index_one(packed);
779 prepare_packed_git_one(packed);
780
781 sort_packs(&packed->packs.head, sort_pack);
782 for (struct packfile_list_entry *e = packed->packs.head; e; e = e->next)
783 if (!e->next)
784 packed->packs.tail = e;
785
786 packed->initialized = true;
787 }
788
789 static void odb_source_packed_reparent(const char *name UNUSED,
790 const char *old_cwd,
791 const char *new_cwd,
792 void *cb_data)
793 {
794 struct odb_source_packed *packed = cb_data;
795 char *path = reparent_relative_path(old_cwd, new_cwd,
796 packed->base.path);
797 free(packed->base.path);
798 packed->base.path = path;
799 }
800
801 static void odb_source_packed_close(struct odb_source *source)
802 {
803 struct odb_source_packed *packed = odb_source_packed_downcast(source);
804
805 for (struct packfile_list_entry *e = packed->packs.head; e; e = e->next) {
806 if (e->pack->do_not_close)
807 BUG("want to close pack marked 'do-not-close'");
808 close_pack(e->pack);
809 }
810 if (packed->midx)
811 close_midx(packed->midx);
812 packed->midx = NULL;
813 }
814
815 static void odb_source_packed_free(struct odb_source *source)
816 {
817 struct odb_source_packed *packed = odb_source_packed_downcast(source);
818
819 chdir_notify_unregister(NULL, odb_source_packed_reparent, packed);
820
821 for (struct packfile_list_entry *e = packed->packs.head; e; e = e->next)
822 free(e->pack);
823 packfile_list_clear(&packed->packs);
824
825 strmap_clear(&packed->packs_by_path, 0);
826 odb_source_release(&packed->base);
827 free(packed);
828 }
829
830 struct odb_source_packed *odb_source_packed_new(struct object_database *odb,
831 const char *path,
832 bool local)
833 {
834 struct odb_source_packed *packed;
835
836 CALLOC_ARRAY(packed, 1);
837 odb_source_init(&packed->base, odb, ODB_SOURCE_PACKED, path, local);
838 strmap_init(&packed->packs_by_path);
839
840 packed->base.free = odb_source_packed_free;
841 packed->base.close = odb_source_packed_close;
842 packed->base.prepare = odb_source_packed_prepare;
843 packed->base.read_object_info = odb_source_packed_read_object_info;
844 packed->base.read_object_stream = odb_source_packed_read_object_stream;
845 packed->base.for_each_object = odb_source_packed_for_each_object;
846 packed->base.count_objects = odb_source_packed_count_objects;
847 packed->base.find_abbrev_len = odb_source_packed_find_abbrev_len;
848 packed->base.freshen_object = odb_source_packed_freshen_object;
849 packed->base.write_object = odb_source_packed_write_object;
850 packed->base.write_object_stream = odb_source_packed_write_object_stream;
851 packed->base.begin_transaction = odb_source_packed_begin_transaction;
852 packed->base.read_alternates = odb_source_packed_read_alternates;
853 packed->base.write_alternate = odb_source_packed_write_alternate;
854
855 if (!is_absolute_path(path))
856 chdir_notify_register(NULL, odb_source_packed_reparent, packed);
857
858 return packed;
859 }