18
18
#define MIDX_HASH_LEN 20
19
19
#define MIDX_MIN_SIZE (MIDX_HEADER_SIZE + MIDX_HASH_LEN)
20
20
21
- #define MIDX_MAX_CHUNKS 2
21
+ #define MIDX_MAX_CHUNKS 3
22
22
#define MIDX_CHUNK_ALIGNMENT 4
23
23
#define MIDX_CHUNKID_PACKNAMES 0x504e414d /* "PNAM" */
24
+ #define MIDX_CHUNKID_OIDFANOUT 0x4f494446 /* "OIDF" */
24
25
#define MIDX_CHUNKID_OIDLOOKUP 0x4f49444c /* "OIDL" */
25
26
#define MIDX_CHUNKLOOKUP_WIDTH (sizeof(uint32_t) + sizeof(uint64_t))
27
+ #define MIDX_CHUNK_FANOUT_SIZE (sizeof(uint32_t) * 256)
26
28
27
29
static char * get_midx_filename (const char * object_dir )
28
30
{
@@ -102,6 +104,10 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir)
102
104
m -> chunk_pack_names = m -> data + chunk_offset ;
103
105
break ;
104
106
107
+ case MIDX_CHUNKID_OIDFANOUT :
108
+ m -> chunk_oid_fanout = (uint32_t * )(m -> data + chunk_offset );
109
+ break ;
110
+
105
111
case MIDX_CHUNKID_OIDLOOKUP :
106
112
m -> chunk_oid_lookup = m -> data + chunk_offset ;
107
113
break ;
@@ -121,9 +127,13 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir)
121
127
122
128
if (!m -> chunk_pack_names )
123
129
die (_ ("multi-pack-index missing required pack-name chunk" ));
130
+ if (!m -> chunk_oid_fanout )
131
+ die (_ ("multi-pack-index missing required OID fanout chunk" ));
124
132
if (!m -> chunk_oid_lookup )
125
133
die (_ ("multi-pack-index missing required OID lookup chunk" ));
126
134
135
+ m -> num_objects = ntohl (m -> chunk_oid_fanout [255 ]);
136
+
127
137
m -> pack_names = xcalloc (m -> num_packs , sizeof (* m -> pack_names ));
128
138
129
139
cur_pack_name = (const char * )m -> chunk_pack_names ;
@@ -389,6 +399,35 @@ static size_t write_midx_pack_names(struct hashfile *f,
389
399
return written ;
390
400
}
391
401
402
+ static size_t write_midx_oid_fanout (struct hashfile * f ,
403
+ struct pack_midx_entry * objects ,
404
+ uint32_t nr_objects )
405
+ {
406
+ struct pack_midx_entry * list = objects ;
407
+ struct pack_midx_entry * last = objects + nr_objects ;
408
+ uint32_t count = 0 ;
409
+ uint32_t i ;
410
+
411
+ /*
412
+ * Write the first-level table (the list is sorted,
413
+ * but we use a 256-entry lookup to be able to avoid
414
+ * having to do eight extra binary search iterations).
415
+ */
416
+ for (i = 0 ; i < 256 ; i ++ ) {
417
+ struct pack_midx_entry * next = list ;
418
+
419
+ while (next < last && next -> oid .hash [0 ] == i ) {
420
+ count ++ ;
421
+ next ++ ;
422
+ }
423
+
424
+ hashwrite_be32 (f , count );
425
+ list = next ;
426
+ }
427
+
428
+ return MIDX_CHUNK_FANOUT_SIZE ;
429
+ }
430
+
392
431
static size_t write_midx_oid_lookup (struct hashfile * f , unsigned char hash_len ,
393
432
struct pack_midx_entry * objects ,
394
433
uint32_t nr_objects )
@@ -461,17 +500,21 @@ int write_midx_file(const char *object_dir)
461
500
FREE_AND_NULL (midx_name );
462
501
463
502
cur_chunk = 0 ;
464
- num_chunks = 2 ;
503
+ num_chunks = 3 ;
465
504
466
505
written = write_midx_header (f , num_chunks , packs .nr );
467
506
468
507
chunk_ids [cur_chunk ] = MIDX_CHUNKID_PACKNAMES ;
469
508
chunk_offsets [cur_chunk ] = written + (num_chunks + 1 ) * MIDX_CHUNKLOOKUP_WIDTH ;
470
509
471
510
cur_chunk ++ ;
472
- chunk_ids [cur_chunk ] = MIDX_CHUNKID_OIDLOOKUP ;
511
+ chunk_ids [cur_chunk ] = MIDX_CHUNKID_OIDFANOUT ;
473
512
chunk_offsets [cur_chunk ] = chunk_offsets [cur_chunk - 1 ] + packs .pack_name_concat_len ;
474
513
514
+ cur_chunk ++ ;
515
+ chunk_ids [cur_chunk ] = MIDX_CHUNKID_OIDLOOKUP ;
516
+ chunk_offsets [cur_chunk ] = chunk_offsets [cur_chunk - 1 ] + MIDX_CHUNK_FANOUT_SIZE ;
517
+
475
518
cur_chunk ++ ;
476
519
chunk_ids [cur_chunk ] = 0 ;
477
520
chunk_offsets [cur_chunk ] = chunk_offsets [cur_chunk - 1 ] + nr_entries * MIDX_HASH_LEN ;
@@ -505,6 +548,10 @@ int write_midx_file(const char *object_dir)
505
548
written += write_midx_pack_names (f , packs .names , packs .nr );
506
549
break ;
507
550
551
+ case MIDX_CHUNKID_OIDFANOUT :
552
+ written += write_midx_oid_fanout (f , entries , nr_entries );
553
+ break ;
554
+
508
555
case MIDX_CHUNKID_OIDLOOKUP :
509
556
written += write_midx_oid_lookup (f , MIDX_HASH_LEN , entries , nr_entries );
510
557
break ;
0 commit comments