@@ -179,6 +179,23 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir)
179
179
return NULL ;
180
180
}
181
181
182
+ static void close_midx (struct multi_pack_index * m )
183
+ {
184
+ uint32_t i ;
185
+ munmap ((unsigned char * )m -> data , m -> data_len );
186
+ close (m -> fd );
187
+ m -> fd = -1 ;
188
+
189
+ for (i = 0 ; i < m -> num_packs ; i ++ ) {
190
+ if (m -> packs [i ]) {
191
+ close_pack (m -> packs [i ]);
192
+ free (m -> packs );
193
+ }
194
+ }
195
+ FREE_AND_NULL (m -> packs );
196
+ FREE_AND_NULL (m -> pack_names );
197
+ }
198
+
182
199
static int prepare_midx_pack (struct multi_pack_index * m , uint32_t pack_int_id )
183
200
{
184
201
struct strbuf pack_name = STRBUF_INIT ;
@@ -278,6 +295,29 @@ int fill_midx_entry(const struct object_id *oid, struct pack_entry *e, struct mu
278
295
return nth_midxed_pack_entry (m , e , pos );
279
296
}
280
297
298
+ int midx_contains_pack (struct multi_pack_index * m , const char * idx_name )
299
+ {
300
+ uint32_t first = 0 , last = m -> num_packs ;
301
+
302
+ while (first < last ) {
303
+ uint32_t mid = first + (last - first ) / 2 ;
304
+ const char * current ;
305
+ int cmp ;
306
+
307
+ current = m -> pack_names [mid ];
308
+ cmp = strcmp (idx_name , current );
309
+ if (!cmp )
310
+ return 1 ;
311
+ if (cmp > 0 ) {
312
+ first = mid + 1 ;
313
+ continue ;
314
+ }
315
+ last = mid ;
316
+ }
317
+
318
+ return 0 ;
319
+ }
320
+
281
321
int prepare_multi_pack_index_one (struct repository * r , const char * object_dir )
282
322
{
283
323
struct multi_pack_index * m = r -> objects -> multi_pack_index ;
@@ -326,6 +366,7 @@ struct pack_list {
326
366
uint32_t alloc_list ;
327
367
uint32_t alloc_names ;
328
368
size_t pack_name_concat_len ;
369
+ struct multi_pack_index * m ;
329
370
};
330
371
331
372
static void add_pack_to_midx (const char * full_path , size_t full_path_len ,
@@ -334,6 +375,9 @@ static void add_pack_to_midx(const char *full_path, size_t full_path_len,
334
375
struct pack_list * packs = (struct pack_list * )data ;
335
376
336
377
if (ends_with (file_name , ".idx" )) {
378
+ if (packs -> m && midx_contains_pack (packs -> m , file_name ))
379
+ return ;
380
+
337
381
ALLOC_GROW (packs -> list , packs -> nr + 1 , packs -> alloc_list );
338
382
ALLOC_GROW (packs -> names , packs -> nr + 1 , packs -> alloc_names );
339
383
@@ -419,6 +463,23 @@ static int midx_oid_compare(const void *_a, const void *_b)
419
463
return a -> pack_int_id - b -> pack_int_id ;
420
464
}
421
465
466
+ static int nth_midxed_pack_midx_entry (struct multi_pack_index * m ,
467
+ uint32_t * pack_perm ,
468
+ struct pack_midx_entry * e ,
469
+ uint32_t pos )
470
+ {
471
+ if (pos >= m -> num_objects )
472
+ return 1 ;
473
+
474
+ nth_midxed_object_oid (& e -> oid , m , pos );
475
+ e -> pack_int_id = pack_perm [nth_midxed_pack_int_id (m , pos )];
476
+ e -> offset = nth_midxed_offset (m , pos );
477
+
478
+ /* consider objects in midx to be from "old" packs */
479
+ e -> pack_mtime = 0 ;
480
+ return 0 ;
481
+ }
482
+
422
483
static void fill_pack_entry (uint32_t pack_int_id ,
423
484
struct packed_git * p ,
424
485
uint32_t cur_object ,
@@ -444,7 +505,8 @@ static void fill_pack_entry(uint32_t pack_int_id,
444
505
* Copy only the de-duplicated entries (selected by most-recent modified time
445
506
* of a packfile containing the object).
446
507
*/
447
- static struct pack_midx_entry * get_sorted_entries (struct packed_git * * p ,
508
+ static struct pack_midx_entry * get_sorted_entries (struct multi_pack_index * m ,
509
+ struct packed_git * * p ,
448
510
uint32_t * perm ,
449
511
uint32_t nr_packs ,
450
512
uint32_t * nr_objects )
@@ -453,8 +515,9 @@ static struct pack_midx_entry *get_sorted_entries(struct packed_git **p,
453
515
uint32_t alloc_fanout , alloc_objects , total_objects = 0 ;
454
516
struct pack_midx_entry * entries_by_fanout = NULL ;
455
517
struct pack_midx_entry * deduplicated_entries = NULL ;
518
+ uint32_t start_pack = m ? m -> num_packs : 0 ;
456
519
457
- for (cur_pack = 0 ; cur_pack < nr_packs ; cur_pack ++ )
520
+ for (cur_pack = start_pack ; cur_pack < nr_packs ; cur_pack ++ )
458
521
total_objects += p [cur_pack ]-> num_objects ;
459
522
460
523
/*
@@ -471,7 +534,23 @@ static struct pack_midx_entry *get_sorted_entries(struct packed_git **p,
471
534
for (cur_fanout = 0 ; cur_fanout < 256 ; cur_fanout ++ ) {
472
535
uint32_t nr_fanout = 0 ;
473
536
474
- for (cur_pack = 0 ; cur_pack < nr_packs ; cur_pack ++ ) {
537
+ if (m ) {
538
+ uint32_t start = 0 , end ;
539
+
540
+ if (cur_fanout )
541
+ start = ntohl (m -> chunk_oid_fanout [cur_fanout - 1 ]);
542
+ end = ntohl (m -> chunk_oid_fanout [cur_fanout ]);
543
+
544
+ for (cur_object = start ; cur_object < end ; cur_object ++ ) {
545
+ ALLOC_GROW (entries_by_fanout , nr_fanout + 1 , alloc_fanout );
546
+ nth_midxed_pack_midx_entry (m , perm ,
547
+ & entries_by_fanout [nr_fanout ],
548
+ cur_object );
549
+ nr_fanout ++ ;
550
+ }
551
+ }
552
+
553
+ for (cur_pack = start_pack ; cur_pack < nr_packs ; cur_pack ++ ) {
475
554
uint32_t start = 0 , end ;
476
555
477
556
if (cur_fanout )
@@ -667,24 +746,43 @@ int write_midx_file(const char *object_dir)
667
746
midx_name );
668
747
}
669
748
749
+ packs .m = load_multi_pack_index (object_dir );
750
+
670
751
packs .nr = 0 ;
671
- packs .alloc_list = 16 ;
672
- packs .alloc_names = 16 ;
752
+ packs .alloc_list = packs . m ? packs . m -> num_packs : 16 ;
753
+ packs .alloc_names = packs . alloc_list ;
673
754
packs .list = NULL ;
755
+ packs .names = NULL ;
674
756
packs .pack_name_concat_len = 0 ;
675
757
ALLOC_ARRAY (packs .list , packs .alloc_list );
676
758
ALLOC_ARRAY (packs .names , packs .alloc_names );
677
759
760
+ if (packs .m ) {
761
+ for (i = 0 ; i < packs .m -> num_packs ; i ++ ) {
762
+ ALLOC_GROW (packs .list , packs .nr + 1 , packs .alloc_list );
763
+ ALLOC_GROW (packs .names , packs .nr + 1 , packs .alloc_names );
764
+
765
+ packs .list [packs .nr ] = NULL ;
766
+ packs .names [packs .nr ] = xstrdup (packs .m -> pack_names [i ]);
767
+ packs .pack_name_concat_len += strlen (packs .names [packs .nr ]) + 1 ;
768
+ packs .nr ++ ;
769
+ }
770
+ }
771
+
678
772
for_each_file_in_pack_dir (object_dir , add_pack_to_midx , & packs );
679
773
774
+ if (packs .m && packs .nr == packs .m -> num_packs )
775
+ goto cleanup ;
776
+
680
777
if (packs .pack_name_concat_len % MIDX_CHUNK_ALIGNMENT )
681
778
packs .pack_name_concat_len += MIDX_CHUNK_ALIGNMENT -
682
779
(packs .pack_name_concat_len % MIDX_CHUNK_ALIGNMENT );
683
780
684
781
ALLOC_ARRAY (pack_perm , packs .nr );
685
782
sort_packs_by_name (packs .names , packs .nr , pack_perm );
686
783
687
- entries = get_sorted_entries (packs .list , pack_perm , packs .nr , & nr_entries );
784
+ entries = get_sorted_entries (packs .m , packs .list , pack_perm , packs .nr , & nr_entries );
785
+
688
786
for (i = 0 ; i < nr_entries ; i ++ ) {
689
787
if (entries [i ].offset > 0x7fffffff )
690
788
num_large_offsets ++ ;
@@ -696,6 +794,9 @@ int write_midx_file(const char *object_dir)
696
794
f = hashfd (lk .tempfile -> fd , lk .tempfile -> filename .buf );
697
795
FREE_AND_NULL (midx_name );
698
796
797
+ if (packs .m )
798
+ close_midx (packs .m );
799
+
699
800
cur_chunk = 0 ;
700
801
num_chunks = large_offsets_needed ? 5 : 4 ;
701
802
@@ -787,6 +888,7 @@ int write_midx_file(const char *object_dir)
787
888
finalize_hashfile (f , NULL , CSUM_FSYNC | CSUM_HASH_IN_STREAM );
788
889
commit_lock_file (& lk );
789
890
891
+ cleanup :
790
892
for (i = 0 ; i < packs .nr ; i ++ ) {
791
893
if (packs .list [i ]) {
792
894
close_pack (packs .list [i ]);
@@ -798,5 +900,7 @@ int write_midx_file(const char *object_dir)
798
900
free (packs .list );
799
901
free (packs .names );
800
902
free (entries );
903
+ free (pack_perm );
904
+ free (midx_name );
801
905
return 0 ;
802
906
}
0 commit comments