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"
@@ -284,8 +282,7 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
284282 const unsigned char * data , * chunk_lookup ;
285283 uint32_t i ;
286284 struct commit_graph * graph ;
287- uint64_t last_chunk_offset ;
288- uint32_t last_chunk_id ;
285+ uint64_t next_chunk_offset ;
289286 uint32_t graph_signature ;
290287 unsigned char graph_version , hash_version ;
291288
@@ -325,24 +322,26 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
325322 graph -> data = graph_map ;
326323 graph -> data_len = graph_size ;
327324
328- last_chunk_id = 0 ;
329- last_chunk_offset = 8 ;
325+ if (graph_size < GRAPH_HEADER_SIZE +
326+ (graph -> num_chunks + 1 ) * GRAPH_CHUNKLOOKUP_WIDTH +
327+ GRAPH_FANOUT_SIZE + the_hash_algo -> rawsz ) {
328+ error (_ ("commit-graph file is too small to hold %u chunks" ),
329+ graph -> num_chunks );
330+ free (graph );
331+ return NULL ;
332+ }
333+
330334 chunk_lookup = data + 8 ;
335+ next_chunk_offset = get_be64 (chunk_lookup + 4 );
331336 for (i = 0 ; i < graph -> num_chunks ; i ++ ) {
332337 uint32_t chunk_id ;
333- uint64_t chunk_offset ;
338+ uint64_t chunk_offset = next_chunk_offset ;
334339 int chunk_repeated = 0 ;
335340
336- if (data + graph_size - chunk_lookup <
337- GRAPH_CHUNKLOOKUP_WIDTH ) {
338- error (_ ("commit-graph chunk lookup table entry missing; file may be incomplete" ));
339- goto free_and_return ;
340- }
341-
342341 chunk_id = get_be32 (chunk_lookup + 0 );
343- chunk_offset = get_be64 (chunk_lookup + 4 );
344342
345343 chunk_lookup += GRAPH_CHUNKLOOKUP_WIDTH ;
344+ next_chunk_offset = get_be64 (chunk_lookup + 4 );
346345
347346 if (chunk_offset > graph_size - the_hash_algo -> rawsz ) {
348347 error (_ ("commit-graph improper chunk offset %08x%08x" ), (uint32_t )(chunk_offset >> 32 ),
@@ -361,8 +360,11 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
361360 case GRAPH_CHUNKID_OIDLOOKUP :
362361 if (graph -> chunk_oid_lookup )
363362 chunk_repeated = 1 ;
364- else
363+ else {
365364 graph -> chunk_oid_lookup = data + chunk_offset ;
365+ graph -> num_commits = (next_chunk_offset - chunk_offset )
366+ / graph -> hash_len ;
367+ }
366368 break ;
367369
368370 case GRAPH_CHUNKID_DATA :
@@ -416,15 +418,6 @@ struct commit_graph *parse_commit_graph(void *graph_map, size_t graph_size)
416418 error (_ ("commit-graph chunk id %08x appears multiple times" ), chunk_id );
417419 goto free_and_return ;
418420 }
419-
420- if (last_chunk_id == GRAPH_CHUNKID_OIDLOOKUP )
421- {
422- graph -> num_commits = (chunk_offset - last_chunk_offset )
423- / graph -> hash_len ;
424- }
425-
426- last_chunk_id = chunk_id ;
427- last_chunk_offset = chunk_offset ;
428421 }
429422
430423 if (graph -> chunk_bloom_indexes && graph -> chunk_bloom_data ) {
@@ -1602,17 +1595,22 @@ static int write_graph_chunk_base(struct hashfile *f,
16021595 return 0 ;
16031596}
16041597
1598+ struct chunk_info {
1599+ uint32_t id ;
1600+ uint64_t size ;
1601+ };
1602+
16051603static int write_commit_graph_file (struct write_commit_graph_context * ctx )
16061604{
16071605 uint32_t i ;
16081606 int fd ;
16091607 struct hashfile * f ;
16101608 struct lock_file lk = LOCK_INIT ;
1611- uint32_t chunk_ids [MAX_NUM_CHUNKS + 1 ];
1612- uint64_t chunk_offsets [MAX_NUM_CHUNKS + 1 ];
1609+ struct chunk_info chunks [MAX_NUM_CHUNKS + 1 ];
16131610 const unsigned hashsz = the_hash_algo -> rawsz ;
16141611 struct strbuf progress_title = STRBUF_INIT ;
16151612 int num_chunks = 3 ;
1613+ uint64_t chunk_offset ;
16161614 struct object_id file_hash ;
16171615 const struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS ;
16181616
@@ -1660,51 +1658,34 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
16601658 f = hashfd (lk .tempfile -> fd , lk .tempfile -> filename .buf );
16611659 }
16621660
1663- chunk_ids [0 ] = GRAPH_CHUNKID_OIDFANOUT ;
1664- chunk_ids [1 ] = GRAPH_CHUNKID_OIDLOOKUP ;
1665- chunk_ids [2 ] = GRAPH_CHUNKID_DATA ;
1661+ chunks [0 ].id = GRAPH_CHUNKID_OIDFANOUT ;
1662+ chunks [0 ].size = GRAPH_FANOUT_SIZE ;
1663+ chunks [1 ].id = GRAPH_CHUNKID_OIDLOOKUP ;
1664+ chunks [1 ].size = hashsz * ctx -> commits .nr ;
1665+ chunks [2 ].id = GRAPH_CHUNKID_DATA ;
1666+ chunks [2 ].size = (hashsz + 16 ) * ctx -> commits .nr ;
16661667 if (ctx -> num_extra_edges ) {
1667- chunk_ids [num_chunks ] = GRAPH_CHUNKID_EXTRAEDGES ;
1668+ chunks [num_chunks ].id = GRAPH_CHUNKID_EXTRAEDGES ;
1669+ chunks [num_chunks ].size = 4 * ctx -> num_extra_edges ;
16681670 num_chunks ++ ;
16691671 }
16701672 if (ctx -> changed_paths ) {
1671- chunk_ids [num_chunks ] = GRAPH_CHUNKID_BLOOMINDEXES ;
1673+ chunks [num_chunks ].id = GRAPH_CHUNKID_BLOOMINDEXES ;
1674+ chunks [num_chunks ].size = sizeof (uint32_t ) * ctx -> commits .nr ;
16721675 num_chunks ++ ;
1673- chunk_ids [num_chunks ] = GRAPH_CHUNKID_BLOOMDATA ;
1676+ chunks [num_chunks ].id = GRAPH_CHUNKID_BLOOMDATA ;
1677+ chunks [num_chunks ].size = sizeof (uint32_t ) * 3
1678+ + ctx -> total_bloom_filter_data_size ;
16741679 num_chunks ++ ;
16751680 }
16761681 if (ctx -> num_commit_graphs_after > 1 ) {
1677- chunk_ids [num_chunks ] = GRAPH_CHUNKID_BASE ;
1682+ chunks [num_chunks ].id = GRAPH_CHUNKID_BASE ;
1683+ chunks [num_chunks ].size = hashsz * (ctx -> num_commit_graphs_after - 1 );
16781684 num_chunks ++ ;
16791685 }
16801686
1681- chunk_ids [num_chunks ] = 0 ;
1682-
1683- chunk_offsets [0 ] = 8 + (num_chunks + 1 ) * GRAPH_CHUNKLOOKUP_WIDTH ;
1684- chunk_offsets [1 ] = chunk_offsets [0 ] + GRAPH_FANOUT_SIZE ;
1685- chunk_offsets [2 ] = chunk_offsets [1 ] + hashsz * ctx -> commits .nr ;
1686- chunk_offsets [3 ] = chunk_offsets [2 ] + (hashsz + 16 ) * ctx -> commits .nr ;
1687-
1688- num_chunks = 3 ;
1689- if (ctx -> num_extra_edges ) {
1690- chunk_offsets [num_chunks + 1 ] = chunk_offsets [num_chunks ] +
1691- 4 * ctx -> num_extra_edges ;
1692- num_chunks ++ ;
1693- }
1694- if (ctx -> changed_paths ) {
1695- chunk_offsets [num_chunks + 1 ] = chunk_offsets [num_chunks ] +
1696- sizeof (uint32_t ) * ctx -> commits .nr ;
1697- num_chunks ++ ;
1698-
1699- chunk_offsets [num_chunks + 1 ] = chunk_offsets [num_chunks ] +
1700- sizeof (uint32_t ) * 3 + ctx -> total_bloom_filter_data_size ;
1701- num_chunks ++ ;
1702- }
1703- if (ctx -> num_commit_graphs_after > 1 ) {
1704- chunk_offsets [num_chunks + 1 ] = chunk_offsets [num_chunks ] +
1705- hashsz * (ctx -> num_commit_graphs_after - 1 );
1706- num_chunks ++ ;
1707- }
1687+ chunks [num_chunks ].id = 0 ;
1688+ chunks [num_chunks ].size = 0 ;
17081689
17091690 hashwrite_be32 (f , GRAPH_SIGNATURE );
17101691
@@ -1713,13 +1694,16 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
17131694 hashwrite_u8 (f , num_chunks );
17141695 hashwrite_u8 (f , ctx -> num_commit_graphs_after - 1 );
17151696
1697+ chunk_offset = 8 + (num_chunks + 1 ) * GRAPH_CHUNKLOOKUP_WIDTH ;
17161698 for (i = 0 ; i <= num_chunks ; i ++ ) {
17171699 uint32_t chunk_write [3 ];
17181700
1719- chunk_write [0 ] = htonl (chunk_ids [i ]);
1720- chunk_write [1 ] = htonl (chunk_offsets [ i ] >> 32 );
1721- chunk_write [2 ] = htonl (chunk_offsets [ i ] & 0xffffffff );
1701+ chunk_write [0 ] = htonl (chunks [i ]. id );
1702+ chunk_write [1 ] = htonl (chunk_offset >> 32 );
1703+ chunk_write [2 ] = htonl (chunk_offset & 0xffffffff );
17221704 hashwrite (f , chunk_write , 12 );
1705+
1706+ chunk_offset += chunks [i ].size ;
17231707 }
17241708
17251709 if (ctx -> report_progress ) {
0 commit comments