@@ -59,8 +59,7 @@ void git_test_write_commit_graph_or_die(void)
59
59
60
60
#define GRAPH_HEADER_SIZE 8
61
61
#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 \
64
63
+ GRAPH_FANOUT_SIZE + the_hash_algo->rawsz)
65
64
66
65
#define CORRECTED_COMMIT_DATE_OFFSET_OVERFLOW (1ULL << 31)
@@ -298,15 +297,43 @@ static int verify_commit_graph_lite(struct commit_graph *g)
298
297
return 0 ;
299
298
}
300
299
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
+
301
329
struct commit_graph * parse_commit_graph (struct repository * r ,
302
330
void * graph_map , size_t graph_size )
303
331
{
304
- const unsigned char * data , * chunk_lookup ;
305
- uint32_t i ;
332
+ const unsigned char * data ;
306
333
struct commit_graph * graph ;
307
- uint64_t next_chunk_offset ;
308
334
uint32_t graph_signature ;
309
335
unsigned char graph_version , hash_version ;
336
+ struct chunkfile * cf = NULL ;
310
337
311
338
if (!graph_map )
312
339
return NULL ;
@@ -347,116 +374,36 @@ struct commit_graph *parse_commit_graph(struct repository *r,
347
374
graph -> data_len = graph_size ;
348
375
349
376
if (graph_size < GRAPH_HEADER_SIZE +
350
- (graph -> num_chunks + 1 ) * GRAPH_CHUNKLOOKUP_WIDTH +
377
+ (graph -> num_chunks + 1 ) * CHUNK_TOC_ENTRY_SIZE +
351
378
GRAPH_FANOUT_SIZE + the_hash_algo -> rawsz ) {
352
379
error (_ ("commit-graph file is too small to hold %u chunks" ),
353
380
graph -> num_chunks );
354
381
free (graph );
355
382
return NULL ;
356
383
}
357
384
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 );
393
386
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 ;
446
390
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 );
455
401
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 );
460
407
}
461
408
462
409
if (graph -> chunk_bloom_indexes && graph -> chunk_bloom_data ) {
@@ -473,9 +420,11 @@ struct commit_graph *parse_commit_graph(struct repository *r,
473
420
if (verify_commit_graph_lite (graph ))
474
421
goto free_and_return ;
475
422
423
+ free_chunkfile (cf );
476
424
return graph ;
477
425
478
426
free_and_return :
427
+ free_chunkfile (cf );
479
428
free (graph -> bloom_filter_settings );
480
429
free (graph );
481
430
return NULL ;
0 commit comments