1- #include "cache.h"
2- #include "config.h"
3- #include "dir.h"
41#include "git-compat-util.h"
2+ #include "config.h"
53#include "lockfile.h"
64#include "pack.h"
75#include "packfile.h"
@@ -230,8 +228,7 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
230228 const unsigned char * data , * chunk_lookup ;
231229 uint32_t i ;
232230 struct commit_graph * graph ;
233- uint64_t last_chunk_offset ;
234- uint32_t last_chunk_id ;
231+ uint64_t next_chunk_offset ;
235232 uint32_t graph_signature ;
236233 unsigned char graph_version , hash_version ;
237234
@@ -271,24 +268,26 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
271268 graph -> data = graph_map ;
272269 graph -> data_len = graph_size ;
273270
274- last_chunk_id = 0 ;
275- last_chunk_offset = 8 ;
271+ if (graph_size < GRAPH_HEADER_SIZE +
272+ (graph -> num_chunks + 1 ) * GRAPH_CHUNKLOOKUP_WIDTH +
273+ GRAPH_FANOUT_SIZE + the_hash_algo -> rawsz ) {
274+ error (_ ("commit-graph file is too small to hold %u chunks" ),
275+ graph -> num_chunks );
276+ free (graph );
277+ return NULL ;
278+ }
279+
276280 chunk_lookup = data + 8 ;
281+ next_chunk_offset = get_be64 (chunk_lookup + 4 );
277282 for (i = 0 ; i < graph -> num_chunks ; i ++ ) {
278283 uint32_t chunk_id ;
279- uint64_t chunk_offset ;
284+ uint64_t chunk_offset = next_chunk_offset ;
280285 int chunk_repeated = 0 ;
281286
282- if (data + graph_size - chunk_lookup <
283- GRAPH_CHUNKLOOKUP_WIDTH ) {
284- error (_ ("commit-graph chunk lookup table entry missing; file may be incomplete" ));
285- goto free_and_return ;
286- }
287-
288287 chunk_id = get_be32 (chunk_lookup + 0 );
289- chunk_offset = get_be64 (chunk_lookup + 4 );
290288
291289 chunk_lookup += GRAPH_CHUNKLOOKUP_WIDTH ;
290+ next_chunk_offset = get_be64 (chunk_lookup + 4 );
292291
293292 if (chunk_offset > graph_size - the_hash_algo -> rawsz ) {
294293 error (_ ("commit-graph improper chunk offset %08x%08x" ), (uint32_t )(chunk_offset >> 32 ),
@@ -307,8 +306,11 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
307306 case GRAPH_CHUNKID_OIDLOOKUP :
308307 if (graph -> chunk_oid_lookup )
309308 chunk_repeated = 1 ;
310- else
309+ else {
311310 graph -> chunk_oid_lookup = data + chunk_offset ;
311+ graph -> num_commits = (next_chunk_offset - chunk_offset )
312+ / graph -> hash_len ;
313+ }
312314 break ;
313315
314316 case GRAPH_CHUNKID_DATA :
@@ -362,15 +364,6 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
362364 error (_ ("commit-graph chunk id %08x appears multiple times" ), chunk_id );
363365 goto free_and_return ;
364366 }
365-
366- if (last_chunk_id == GRAPH_CHUNKID_OIDLOOKUP )
367- {
368- graph -> num_commits = (chunk_offset - last_chunk_offset )
369- / graph -> hash_len ;
370- }
371-
372- last_chunk_id = chunk_id ;
373- last_chunk_offset = chunk_offset ;
374367 }
375368
376369 if (graph -> chunk_bloom_indexes && graph -> chunk_bloom_data ) {
@@ -1535,17 +1528,22 @@ static int write_graph_chunk_base(struct hashfile *f,
15351528 return 0 ;
15361529}
15371530
1531+ struct chunk_info {
1532+ uint32_t id ;
1533+ uint64_t size ;
1534+ };
1535+
15381536static int write_commit_graph_file (struct write_commit_graph_context * ctx )
15391537{
15401538 uint32_t i ;
15411539 int fd ;
15421540 struct hashfile * f ;
15431541 struct lock_file lk = LOCK_INIT ;
1544- uint32_t chunk_ids [MAX_NUM_CHUNKS + 1 ];
1545- uint64_t chunk_offsets [MAX_NUM_CHUNKS + 1 ];
1542+ struct chunk_info chunks [MAX_NUM_CHUNKS + 1 ];
15461543 const unsigned hashsz = the_hash_algo -> rawsz ;
15471544 struct strbuf progress_title = STRBUF_INIT ;
15481545 int num_chunks = 3 ;
1546+ uint64_t chunk_offset ;
15491547 struct object_id file_hash ;
15501548 const struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS ;
15511549
@@ -1593,51 +1591,34 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
15931591 f = hashfd (lk .tempfile -> fd , lk .tempfile -> filename .buf );
15941592 }
15951593
1596- chunk_ids [0 ] = GRAPH_CHUNKID_OIDFANOUT ;
1597- chunk_ids [1 ] = GRAPH_CHUNKID_OIDLOOKUP ;
1598- chunk_ids [2 ] = GRAPH_CHUNKID_DATA ;
1594+ chunks [0 ].id = GRAPH_CHUNKID_OIDFANOUT ;
1595+ chunks [0 ].size = GRAPH_FANOUT_SIZE ;
1596+ chunks [1 ].id = GRAPH_CHUNKID_OIDLOOKUP ;
1597+ chunks [1 ].size = hashsz * ctx -> commits .nr ;
1598+ chunks [2 ].id = GRAPH_CHUNKID_DATA ;
1599+ chunks [2 ].size = (hashsz + 16 ) * ctx -> commits .nr ;
15991600 if (ctx -> num_extra_edges ) {
1600- chunk_ids [num_chunks ] = GRAPH_CHUNKID_EXTRAEDGES ;
1601+ chunks [num_chunks ].id = GRAPH_CHUNKID_EXTRAEDGES ;
1602+ chunks [num_chunks ].size = 4 * ctx -> num_extra_edges ;
16011603 num_chunks ++ ;
16021604 }
16031605 if (ctx -> changed_paths ) {
1604- chunk_ids [num_chunks ] = GRAPH_CHUNKID_BLOOMINDEXES ;
1606+ chunks [num_chunks ].id = GRAPH_CHUNKID_BLOOMINDEXES ;
1607+ chunks [num_chunks ].size = sizeof (uint32_t ) * ctx -> commits .nr ;
16051608 num_chunks ++ ;
1606- chunk_ids [num_chunks ] = GRAPH_CHUNKID_BLOOMDATA ;
1609+ chunks [num_chunks ].id = GRAPH_CHUNKID_BLOOMDATA ;
1610+ chunks [num_chunks ].size = sizeof (uint32_t ) * 3
1611+ + ctx -> total_bloom_filter_data_size ;
16071612 num_chunks ++ ;
16081613 }
16091614 if (ctx -> num_commit_graphs_after > 1 ) {
1610- chunk_ids [num_chunks ] = GRAPH_CHUNKID_BASE ;
1615+ chunks [num_chunks ].id = GRAPH_CHUNKID_BASE ;
1616+ chunks [num_chunks ].size = hashsz * (ctx -> num_commit_graphs_after - 1 );
16111617 num_chunks ++ ;
16121618 }
16131619
1614- chunk_ids [num_chunks ] = 0 ;
1615-
1616- chunk_offsets [0 ] = 8 + (num_chunks + 1 ) * GRAPH_CHUNKLOOKUP_WIDTH ;
1617- chunk_offsets [1 ] = chunk_offsets [0 ] + GRAPH_FANOUT_SIZE ;
1618- chunk_offsets [2 ] = chunk_offsets [1 ] + hashsz * ctx -> commits .nr ;
1619- chunk_offsets [3 ] = chunk_offsets [2 ] + (hashsz + 16 ) * ctx -> commits .nr ;
1620-
1621- num_chunks = 3 ;
1622- if (ctx -> num_extra_edges ) {
1623- chunk_offsets [num_chunks + 1 ] = chunk_offsets [num_chunks ] +
1624- 4 * ctx -> num_extra_edges ;
1625- num_chunks ++ ;
1626- }
1627- if (ctx -> changed_paths ) {
1628- chunk_offsets [num_chunks + 1 ] = chunk_offsets [num_chunks ] +
1629- sizeof (uint32_t ) * ctx -> commits .nr ;
1630- num_chunks ++ ;
1631-
1632- chunk_offsets [num_chunks + 1 ] = chunk_offsets [num_chunks ] +
1633- sizeof (uint32_t ) * 3 + ctx -> total_bloom_filter_data_size ;
1634- num_chunks ++ ;
1635- }
1636- if (ctx -> num_commit_graphs_after > 1 ) {
1637- chunk_offsets [num_chunks + 1 ] = chunk_offsets [num_chunks ] +
1638- hashsz * (ctx -> num_commit_graphs_after - 1 );
1639- num_chunks ++ ;
1640- }
1620+ chunks [num_chunks ].id = 0 ;
1621+ chunks [num_chunks ].size = 0 ;
16411622
16421623 hashwrite_be32 (f , GRAPH_SIGNATURE );
16431624
@@ -1646,13 +1627,16 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
16461627 hashwrite_u8 (f , num_chunks );
16471628 hashwrite_u8 (f , ctx -> num_commit_graphs_after - 1 );
16481629
1630+ chunk_offset = 8 + (num_chunks + 1 ) * GRAPH_CHUNKLOOKUP_WIDTH ;
16491631 for (i = 0 ; i <= num_chunks ; i ++ ) {
16501632 uint32_t chunk_write [3 ];
16511633
1652- chunk_write [0 ] = htonl (chunk_ids [i ]);
1653- chunk_write [1 ] = htonl (chunk_offsets [ i ] >> 32 );
1654- chunk_write [2 ] = htonl (chunk_offsets [ i ] & 0xffffffff );
1634+ chunk_write [0 ] = htonl (chunks [i ]. id );
1635+ chunk_write [1 ] = htonl (chunk_offset >> 32 );
1636+ chunk_write [2 ] = htonl (chunk_offset & 0xffffffff );
16551637 hashwrite (f , chunk_write , 12 );
1638+
1639+ chunk_offset += chunks [i ].size ;
16561640 }
16571641
16581642 if (ctx -> report_progress ) {
0 commit comments