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