1818#define MIDX_HASH_LEN 20
1919#define MIDX_MIN_SIZE (MIDX_HEADER_SIZE + MIDX_HASH_LEN)
2020
21- #define MIDX_MAX_CHUNKS 2
21+ #define MIDX_MAX_CHUNKS 3
2222#define MIDX_CHUNK_ALIGNMENT 4
2323#define MIDX_CHUNKID_PACKNAMES 0x504e414d /* "PNAM" */
24+ #define MIDX_CHUNKID_OIDFANOUT 0x4f494446 /* "OIDF" */
2425#define MIDX_CHUNKID_OIDLOOKUP 0x4f49444c /* "OIDL" */
2526#define MIDX_CHUNKLOOKUP_WIDTH (sizeof(uint32_t) + sizeof(uint64_t))
27+ #define MIDX_CHUNK_FANOUT_SIZE (sizeof(uint32_t) * 256)
2628
2729static char * get_midx_filename (const char * object_dir )
2830{
@@ -102,6 +104,10 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir)
102104 m -> chunk_pack_names = m -> data + chunk_offset ;
103105 break ;
104106
107+ case MIDX_CHUNKID_OIDFANOUT :
108+ m -> chunk_oid_fanout = (uint32_t * )(m -> data + chunk_offset );
109+ break ;
110+
105111 case MIDX_CHUNKID_OIDLOOKUP :
106112 m -> chunk_oid_lookup = m -> data + chunk_offset ;
107113 break ;
@@ -121,9 +127,13 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir)
121127
122128 if (!m -> chunk_pack_names )
123129 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" ));
124132 if (!m -> chunk_oid_lookup )
125133 die (_ ("multi-pack-index missing required OID lookup chunk" ));
126134
135+ m -> num_objects = ntohl (m -> chunk_oid_fanout [255 ]);
136+
127137 m -> pack_names = xcalloc (m -> num_packs , sizeof (* m -> pack_names ));
128138
129139 cur_pack_name = (const char * )m -> chunk_pack_names ;
@@ -389,6 +399,35 @@ static size_t write_midx_pack_names(struct hashfile *f,
389399 return written ;
390400}
391401
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+
392431static size_t write_midx_oid_lookup (struct hashfile * f , unsigned char hash_len ,
393432 struct pack_midx_entry * objects ,
394433 uint32_t nr_objects )
@@ -461,17 +500,21 @@ int write_midx_file(const char *object_dir)
461500 FREE_AND_NULL (midx_name );
462501
463502 cur_chunk = 0 ;
464- num_chunks = 2 ;
503+ num_chunks = 3 ;
465504
466505 written = write_midx_header (f , num_chunks , packs .nr );
467506
468507 chunk_ids [cur_chunk ] = MIDX_CHUNKID_PACKNAMES ;
469508 chunk_offsets [cur_chunk ] = written + (num_chunks + 1 ) * MIDX_CHUNKLOOKUP_WIDTH ;
470509
471510 cur_chunk ++ ;
472- chunk_ids [cur_chunk ] = MIDX_CHUNKID_OIDLOOKUP ;
511+ chunk_ids [cur_chunk ] = MIDX_CHUNKID_OIDFANOUT ;
473512 chunk_offsets [cur_chunk ] = chunk_offsets [cur_chunk - 1 ] + packs .pack_name_concat_len ;
474513
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+
475518 cur_chunk ++ ;
476519 chunk_ids [cur_chunk ] = 0 ;
477520 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)
505548 written += write_midx_pack_names (f , packs .names , packs .nr );
506549 break ;
507550
551+ case MIDX_CHUNKID_OIDFANOUT :
552+ written += write_midx_oid_fanout (f , entries , nr_entries );
553+ break ;
554+
508555 case MIDX_CHUNKID_OIDLOOKUP :
509556 written += write_midx_oid_lookup (f , MIDX_HASH_LEN , entries , nr_entries );
510557 break ;
0 commit comments