@@ -59,8 +59,7 @@ void git_test_write_commit_graph_or_die(void)
5959
6060#define GRAPH_HEADER_SIZE 8
6161#define GRAPH_FANOUT_SIZE (4 * 256)
62- #define GRAPH_CHUNKLOOKUP_WIDTH 12
63- #define GRAPH_MIN_SIZE (GRAPH_HEADER_SIZE + 4 * GRAPH_CHUNKLOOKUP_WIDTH \
62+ #define GRAPH_MIN_SIZE (GRAPH_HEADER_SIZE + 4 * CHUNK_TOC_ENTRY_SIZE \
6463 + GRAPH_FANOUT_SIZE + the_hash_algo->rawsz)
6564
6665#define CORRECTED_COMMIT_DATE_OFFSET_OVERFLOW (1ULL << 31)
@@ -298,15 +297,43 @@ static int verify_commit_graph_lite(struct commit_graph *g)
298297 return 0 ;
299298}
300299
300+ static int graph_read_oid_lookup (const unsigned char * chunk_start ,
301+ size_t chunk_size , void * data )
302+ {
303+ struct commit_graph * g = data ;
304+ g -> chunk_oid_lookup = chunk_start ;
305+ g -> num_commits = chunk_size / g -> hash_len ;
306+ return 0 ;
307+ }
308+
309+ static int graph_read_bloom_data (const unsigned char * chunk_start ,
310+ size_t chunk_size , void * data )
311+ {
312+ struct commit_graph * g = data ;
313+ uint32_t hash_version ;
314+ g -> chunk_bloom_data = chunk_start ;
315+ hash_version = get_be32 (chunk_start );
316+
317+ if (hash_version != 1 )
318+ return 0 ;
319+
320+ g -> bloom_filter_settings = xmalloc (sizeof (struct bloom_filter_settings ));
321+ g -> bloom_filter_settings -> hash_version = hash_version ;
322+ g -> bloom_filter_settings -> num_hashes = get_be32 (chunk_start + 4 );
323+ g -> bloom_filter_settings -> bits_per_entry = get_be32 (chunk_start + 8 );
324+ g -> bloom_filter_settings -> max_changed_paths = DEFAULT_BLOOM_MAX_CHANGES ;
325+
326+ return 0 ;
327+ }
328+
301329struct commit_graph * parse_commit_graph (struct repository * r ,
302330 void * graph_map , size_t graph_size )
303331{
304- const unsigned char * data , * chunk_lookup ;
305- uint32_t i ;
332+ const unsigned char * data ;
306333 struct commit_graph * graph ;
307- uint64_t next_chunk_offset ;
308334 uint32_t graph_signature ;
309335 unsigned char graph_version , hash_version ;
336+ struct chunkfile * cf = NULL ;
310337
311338 if (!graph_map )
312339 return NULL ;
@@ -347,116 +374,36 @@ struct commit_graph *parse_commit_graph(struct repository *r,
347374 graph -> data_len = graph_size ;
348375
349376 if (graph_size < GRAPH_HEADER_SIZE +
350- (graph -> num_chunks + 1 ) * GRAPH_CHUNKLOOKUP_WIDTH +
377+ (graph -> num_chunks + 1 ) * CHUNK_TOC_ENTRY_SIZE +
351378 GRAPH_FANOUT_SIZE + the_hash_algo -> rawsz ) {
352379 error (_ ("commit-graph file is too small to hold %u chunks" ),
353380 graph -> num_chunks );
354381 free (graph );
355382 return NULL ;
356383 }
357384
358- chunk_lookup = data + 8 ;
359- next_chunk_offset = get_be64 (chunk_lookup + 4 );
360- for (i = 0 ; i < graph -> num_chunks ; i ++ ) {
361- uint32_t chunk_id ;
362- uint64_t chunk_offset = next_chunk_offset ;
363- int chunk_repeated = 0 ;
364-
365- chunk_id = get_be32 (chunk_lookup + 0 );
366-
367- chunk_lookup += GRAPH_CHUNKLOOKUP_WIDTH ;
368- next_chunk_offset = get_be64 (chunk_lookup + 4 );
369-
370- if (chunk_offset > graph_size - the_hash_algo -> rawsz ) {
371- error (_ ("commit-graph improper chunk offset %08x%08x" ), (uint32_t )(chunk_offset >> 32 ),
372- (uint32_t )chunk_offset );
373- goto free_and_return ;
374- }
375-
376- switch (chunk_id ) {
377- case GRAPH_CHUNKID_OIDFANOUT :
378- if (graph -> chunk_oid_fanout )
379- chunk_repeated = 1 ;
380- else
381- graph -> chunk_oid_fanout = (uint32_t * )(data + chunk_offset );
382- break ;
383-
384- case GRAPH_CHUNKID_OIDLOOKUP :
385- if (graph -> chunk_oid_lookup )
386- chunk_repeated = 1 ;
387- else {
388- graph -> chunk_oid_lookup = data + chunk_offset ;
389- graph -> num_commits = (next_chunk_offset - chunk_offset )
390- / graph -> hash_len ;
391- }
392- break ;
385+ cf = init_chunkfile (NULL );
393386
394- case GRAPH_CHUNKID_DATA :
395- if (graph -> chunk_commit_data )
396- chunk_repeated = 1 ;
397- else
398- graph -> chunk_commit_data = data + chunk_offset ;
399- break ;
400-
401- case GRAPH_CHUNKID_GENERATION_DATA :
402- if (graph -> chunk_generation_data )
403- chunk_repeated = 1 ;
404- else
405- graph -> chunk_generation_data = data + chunk_offset ;
406- break ;
407-
408- case GRAPH_CHUNKID_GENERATION_DATA_OVERFLOW :
409- if (graph -> chunk_generation_data_overflow )
410- chunk_repeated = 1 ;
411- else
412- graph -> chunk_generation_data_overflow = data + chunk_offset ;
413- break ;
414-
415- case GRAPH_CHUNKID_EXTRAEDGES :
416- if (graph -> chunk_extra_edges )
417- chunk_repeated = 1 ;
418- else
419- graph -> chunk_extra_edges = data + chunk_offset ;
420- break ;
421-
422- case GRAPH_CHUNKID_BASE :
423- if (graph -> chunk_base_graphs )
424- chunk_repeated = 1 ;
425- else
426- graph -> chunk_base_graphs = data + chunk_offset ;
427- break ;
428-
429- case GRAPH_CHUNKID_BLOOMINDEXES :
430- if (graph -> chunk_bloom_indexes )
431- chunk_repeated = 1 ;
432- else if (r -> settings .commit_graph_read_changed_paths )
433- graph -> chunk_bloom_indexes = data + chunk_offset ;
434- break ;
435-
436- case GRAPH_CHUNKID_BLOOMDATA :
437- if (graph -> chunk_bloom_data )
438- chunk_repeated = 1 ;
439- else if (r -> settings .commit_graph_read_changed_paths ) {
440- uint32_t hash_version ;
441- graph -> chunk_bloom_data = data + chunk_offset ;
442- hash_version = get_be32 (data + chunk_offset );
443-
444- if (hash_version != 1 )
445- break ;
387+ if (read_table_of_contents (cf , graph -> data , graph_size ,
388+ GRAPH_HEADER_SIZE , graph -> num_chunks ))
389+ goto free_and_return ;
446390
447- graph -> bloom_filter_settings = xmalloc (sizeof (struct bloom_filter_settings ));
448- graph -> bloom_filter_settings -> hash_version = hash_version ;
449- graph -> bloom_filter_settings -> num_hashes = get_be32 (data + chunk_offset + 4 );
450- graph -> bloom_filter_settings -> bits_per_entry = get_be32 (data + chunk_offset + 8 );
451- graph -> bloom_filter_settings -> max_changed_paths = DEFAULT_BLOOM_MAX_CHANGES ;
452- }
453- break ;
454- }
391+ pair_chunk (cf , GRAPH_CHUNKID_OIDFANOUT ,
392+ (const unsigned char * * )& graph -> chunk_oid_fanout );
393+ read_chunk (cf , GRAPH_CHUNKID_OIDLOOKUP , graph_read_oid_lookup , graph );
394+ pair_chunk (cf , GRAPH_CHUNKID_DATA , & graph -> chunk_commit_data );
395+ pair_chunk (cf , GRAPH_CHUNKID_EXTRAEDGES , & graph -> chunk_extra_edges );
396+ pair_chunk (cf , GRAPH_CHUNKID_BASE , & graph -> chunk_base_graphs );
397+ pair_chunk (cf , GRAPH_CHUNKID_GENERATION_DATA ,
398+ & graph -> chunk_generation_data );
399+ pair_chunk (cf , GRAPH_CHUNKID_GENERATION_DATA_OVERFLOW ,
400+ & graph -> chunk_generation_data_overflow );
455401
456- if (chunk_repeated ) {
457- error (_ ("commit-graph chunk id %08x appears multiple times" ), chunk_id );
458- goto free_and_return ;
459- }
402+ if (r -> settings .commit_graph_read_changed_paths ) {
403+ pair_chunk (cf , GRAPH_CHUNKID_BLOOMINDEXES ,
404+ & graph -> chunk_bloom_indexes );
405+ read_chunk (cf , GRAPH_CHUNKID_BLOOMDATA ,
406+ graph_read_bloom_data , graph );
460407 }
461408
462409 if (graph -> chunk_bloom_indexes && graph -> chunk_bloom_data ) {
@@ -473,9 +420,11 @@ struct commit_graph *parse_commit_graph(struct repository *r,
473420 if (verify_commit_graph_lite (graph ))
474421 goto free_and_return ;
475422
423+ free_chunkfile (cf );
476424 return graph ;
477425
478426free_and_return :
427+ free_chunkfile (cf );
479428 free (graph -> bloom_filter_settings );
480429 free (graph );
481430 return NULL ;
0 commit comments