@@ -138,19 +138,22 @@ static int commit_graph_parse_oid_lookup(
138138 struct git_commit_graph_chunk * chunk_oid_lookup )
139139{
140140 uint32_t i ;
141- unsigned char * oid , * prev_oid , zero_oid [GIT_OID_SHA1_SIZE ] = {0 };
141+ unsigned char * oid , * prev_oid , zero_oid [GIT_OID_MAX_SIZE ] = {0 };
142+ size_t oid_size ;
143+
144+ oid_size = git_oid_size (file -> oid_type );
142145
143146 if (chunk_oid_lookup -> offset == 0 )
144147 return commit_graph_error ("missing OID Lookup chunk" );
145148 if (chunk_oid_lookup -> length == 0 )
146149 return commit_graph_error ("empty OID Lookup chunk" );
147- if (chunk_oid_lookup -> length != file -> num_commits * GIT_OID_SHA1_SIZE )
150+ if (chunk_oid_lookup -> length != file -> num_commits * oid_size )
148151 return commit_graph_error ("OID Lookup chunk has wrong length" );
149152
150153 file -> oid_lookup = oid = (unsigned char * )(data + chunk_oid_lookup -> offset );
151154 prev_oid = zero_oid ;
152- for (i = 0 ; i < file -> num_commits ; ++ i , oid += GIT_OID_SHA1_SIZE ) {
153- if (git_oid_raw_cmp (prev_oid , oid , GIT_OID_SHA1_SIZE ) >= 0 )
155+ for (i = 0 ; i < file -> num_commits ; ++ i , oid += oid_size ) {
156+ if (git_oid_raw_cmp (prev_oid , oid , oid_size ) >= 0 )
154157 return commit_graph_error ("OID Lookup index is non-monotonic" );
155158 prev_oid = oid ;
156159 }
@@ -163,11 +166,13 @@ static int commit_graph_parse_commit_data(
163166 const unsigned char * data ,
164167 struct git_commit_graph_chunk * chunk_commit_data )
165168{
169+ size_t oid_size = git_oid_size (file -> oid_type );
170+
166171 if (chunk_commit_data -> offset == 0 )
167172 return commit_graph_error ("missing Commit Data chunk" );
168173 if (chunk_commit_data -> length == 0 )
169174 return commit_graph_error ("empty Commit Data chunk" );
170- if (chunk_commit_data -> length != file -> num_commits * (GIT_OID_SHA1_SIZE + 16 ))
175+ if (chunk_commit_data -> length != file -> num_commits * (oid_size + 16 ))
171176 return commit_graph_error ("Commit Data chunk has wrong length" );
172177
173178 file -> commit_data = data + chunk_commit_data -> offset ;
@@ -209,7 +214,9 @@ int git_commit_graph_file_parse(
209214
210215 GIT_ASSERT_ARG (file );
211216
212- if (size < sizeof (struct git_commit_graph_header ) + GIT_OID_SHA1_SIZE )
217+ checksum_size = git_oid_size (file -> oid_type );
218+
219+ if (size < sizeof (struct git_commit_graph_header ) + checksum_size )
213220 return commit_graph_error ("commit-graph is too short" );
214221
215222 hdr = ((struct git_commit_graph_header * )data );
@@ -226,8 +233,7 @@ int git_commit_graph_file_parse(
226233 * headers, and a special zero chunk.
227234 */
228235 last_chunk_offset = sizeof (struct git_commit_graph_header ) + (1 + hdr -> chunks ) * 12 ;
229- trailer_offset = size - GIT_OID_SHA1_SIZE ;
230- checksum_size = GIT_HASH_SHA1_SIZE ;
236+ trailer_offset = size - checksum_size ;
231237
232238 if (trailer_offset < last_chunk_offset )
233239 return commit_graph_error ("wrong commit-graph size" );
@@ -295,25 +301,35 @@ int git_commit_graph_file_parse(
295301 return 0 ;
296302}
297303
298- int git_commit_graph_new (git_commit_graph * * cgraph_out , const char * objects_dir , bool open_file )
304+ int git_commit_graph_new (
305+ git_commit_graph * * cgraph_out ,
306+ const char * objects_dir ,
307+ bool open_file ,
308+ git_oid_t oid_type )
299309{
300310 git_commit_graph * cgraph = NULL ;
301311 int error = 0 ;
302312
303313 GIT_ASSERT_ARG (cgraph_out );
304314 GIT_ASSERT_ARG (objects_dir );
315+ GIT_ASSERT_ARG (oid_type );
305316
306317 cgraph = git__calloc (1 , sizeof (git_commit_graph ));
307318 GIT_ERROR_CHECK_ALLOC (cgraph );
308319
320+ cgraph -> oid_type = oid_type ;
321+
309322 error = git_str_joinpath (& cgraph -> filename , objects_dir , "info/commit-graph" );
310323 if (error < 0 )
311324 goto error ;
312325
313326 if (open_file ) {
314- error = git_commit_graph_file_open (& cgraph -> file , git_str_cstr (& cgraph -> filename ));
327+ error = git_commit_graph_file_open (& cgraph -> file ,
328+ git_str_cstr (& cgraph -> filename ), oid_type );
329+
315330 if (error < 0 )
316331 goto error ;
332+
317333 cgraph -> checked = 1 ;
318334 }
319335
@@ -326,31 +342,51 @@ int git_commit_graph_new(git_commit_graph **cgraph_out, const char *objects_dir,
326342}
327343
328344int git_commit_graph_validate (git_commit_graph * cgraph ) {
329- unsigned char checksum [GIT_HASH_SHA1_SIZE ];
330- size_t checksum_size = GIT_HASH_SHA1_SIZE ;
331- size_t trailer_offset = cgraph -> file -> graph_map .len - checksum_size ;
345+ unsigned char checksum [GIT_HASH_MAX_SIZE ];
346+ git_hash_algorithm_t checksum_type ;
347+ size_t checksum_size , trailer_offset ;
348+
349+ checksum_type = git_oid_algorithm (cgraph -> oid_type );
350+ checksum_size = git_hash_size (checksum_type );
351+ trailer_offset = cgraph -> file -> graph_map .len - checksum_size ;
332352
333353 if (cgraph -> file -> graph_map .len < checksum_size )
334354 return commit_graph_error ("map length too small" );
335355
336- if (git_hash_buf (checksum , cgraph -> file -> graph_map .data , trailer_offset , GIT_HASH_ALGORITHM_SHA1 ) < 0 )
356+ if (git_hash_buf (checksum , cgraph -> file -> graph_map .data , trailer_offset , checksum_type ) < 0 )
337357 return commit_graph_error ("could not calculate signature" );
338358 if (memcmp (checksum , cgraph -> file -> checksum , checksum_size ) != 0 )
339359 return commit_graph_error ("index signature mismatch" );
340360
341361 return 0 ;
342362}
343363
344- int git_commit_graph_open (git_commit_graph * * cgraph_out , const char * objects_dir )
364+ int git_commit_graph_open (
365+ git_commit_graph * * cgraph_out ,
366+ const char * objects_dir
367+ #ifdef GIT_EXPERIMENTAL_SHA256
368+ , git_oid_t oid_type
369+ #endif
370+ )
345371{
346- int error = git_commit_graph_new (cgraph_out , objects_dir , true);
347- if (!error ) {
372+ #ifndef GIT_EXPERIMENTAL_SHA256
373+ git_oid_t oid_type = GIT_OID_SHA1 ;
374+ #endif
375+ int error ;
376+
377+ error = git_commit_graph_new (cgraph_out , objects_dir , true,
378+ oid_type );
379+
380+ if (!error )
348381 return git_commit_graph_validate (* cgraph_out );
349- }
382+
350383 return error ;
351384}
352385
353- int git_commit_graph_file_open (git_commit_graph_file * * file_out , const char * path )
386+ int git_commit_graph_file_open (
387+ git_commit_graph_file * * file_out ,
388+ const char * path ,
389+ git_oid_t oid_type )
354390{
355391 git_commit_graph_file * file ;
356392 git_file fd = -1 ;
@@ -379,6 +415,8 @@ int git_commit_graph_file_open(git_commit_graph_file **file_out, const char *pat
379415 file = git__calloc (1 , sizeof (git_commit_graph_file ));
380416 GIT_ERROR_CHECK_ALLOC (file );
381417
418+ file -> oid_type = oid_type ;
419+
382420 error = git_futils_mmap_ro (& file -> graph_map , fd , 0 , cgraph_size );
383421 p_close (fd );
384422 if (error < 0 ) {
@@ -395,7 +433,9 @@ int git_commit_graph_file_open(git_commit_graph_file **file_out, const char *pat
395433 return 0 ;
396434}
397435
398- int git_commit_graph_get_file (git_commit_graph_file * * file_out , git_commit_graph * cgraph )
436+ int git_commit_graph_get_file (
437+ git_commit_graph_file * * file_out ,
438+ git_commit_graph * cgraph )
399439{
400440 if (!cgraph -> checked ) {
401441 int error = 0 ;
@@ -405,7 +445,8 @@ int git_commit_graph_get_file(git_commit_graph_file **file_out, git_commit_graph
405445 cgraph -> checked = 1 ;
406446
407447 /* Best effort */
408- error = git_commit_graph_file_open (& result , git_str_cstr (& cgraph -> filename ));
448+ error = git_commit_graph_file_open (& result ,
449+ git_str_cstr (& cgraph -> filename ), cgraph -> oid_type );
409450
410451 if (error < 0 )
411452 return error ;
@@ -441,6 +482,7 @@ static int git_commit_graph_entry_get_byindex(
441482 size_t pos )
442483{
443484 const unsigned char * commit_data ;
485+ size_t oid_size = git_oid_size (file -> oid_type );
444486
445487 GIT_ASSERT_ARG (e );
446488 GIT_ASSERT_ARG (file );
@@ -450,15 +492,15 @@ static int git_commit_graph_entry_get_byindex(
450492 return GIT_ENOTFOUND ;
451493 }
452494
453- commit_data = file -> commit_data + pos * (GIT_OID_SHA1_SIZE + 4 * sizeof (uint32_t ));
454- git_oid__fromraw (& e -> tree_oid , commit_data , GIT_OID_SHA1 );
455- e -> parent_indices [0 ] = ntohl (* ((uint32_t * )(commit_data + GIT_OID_SHA1_SIZE )));
495+ commit_data = file -> commit_data + pos * (oid_size + 4 * sizeof (uint32_t ));
496+ git_oid__fromraw (& e -> tree_oid , commit_data , file -> oid_type );
497+ e -> parent_indices [0 ] = ntohl (* ((uint32_t * )(commit_data + oid_size )));
456498 e -> parent_indices [1 ] = ntohl (
457- * ((uint32_t * )(commit_data + GIT_OID_SHA1_SIZE + sizeof (uint32_t ))));
499+ * ((uint32_t * )(commit_data + oid_size + sizeof (uint32_t ))));
458500 e -> parent_count = (e -> parent_indices [0 ] != GIT_COMMIT_GRAPH_MISSING_PARENT )
459501 + (e -> parent_indices [1 ] != GIT_COMMIT_GRAPH_MISSING_PARENT );
460- e -> generation = ntohl (* ((uint32_t * )(commit_data + GIT_OID_SHA1_SIZE + 2 * sizeof (uint32_t ))));
461- e -> commit_time = ntohl (* ((uint32_t * )(commit_data + GIT_OID_SHA1_SIZE + 3 * sizeof (uint32_t ))));
502+ e -> generation = ntohl (* ((uint32_t * )(commit_data + oid_size + 2 * sizeof (uint32_t ))));
503+ e -> commit_time = ntohl (* ((uint32_t * )(commit_data + oid_size + 3 * sizeof (uint32_t ))));
462504
463505 e -> commit_time |= (e -> generation & UINT64_C (0x3 )) << UINT64_C (32 );
464506 e -> generation >>= 2u ;
@@ -485,7 +527,7 @@ static int git_commit_graph_entry_get_byindex(
485527 }
486528 }
487529
488- git_oid__fromraw (& e -> sha1 , & file -> oid_lookup [pos * GIT_OID_SHA1_SIZE ], GIT_OID_SHA1 );
530+ git_oid__fromraw (& e -> sha1 , & file -> oid_lookup [pos * oid_size ], file -> oid_type );
489531 return 0 ;
490532}
491533
@@ -494,8 +536,8 @@ bool git_commit_graph_file_needs_refresh(const git_commit_graph_file *file, cons
494536 git_file fd = -1 ;
495537 struct stat st ;
496538 ssize_t bytes_read ;
497- unsigned char checksum [GIT_HASH_SHA1_SIZE ];
498- size_t checksum_size = GIT_HASH_SHA1_SIZE ;
539+ unsigned char checksum [GIT_HASH_MAX_SIZE ];
540+ size_t checksum_size = git_oid_size ( file -> oid_type ) ;
499541
500542 /* TODO: properly open the file without access time using O_NOATIME */
501543 fd = git_futils_open_ro (path );
@@ -530,35 +572,40 @@ int git_commit_graph_entry_find(
530572 int pos , found = 0 ;
531573 uint32_t hi , lo ;
532574 const unsigned char * current = NULL ;
575+ size_t oid_size , oid_hexsize ;
533576
534577 GIT_ASSERT_ARG (e );
535578 GIT_ASSERT_ARG (file );
536579 GIT_ASSERT_ARG (short_oid );
537580
581+ oid_size = git_oid_size (file -> oid_type );
582+ oid_hexsize = git_oid_hexsize (file -> oid_type );
583+
538584 hi = ntohl (file -> oid_fanout [(int )short_oid -> id [0 ]]);
539585 lo = ((short_oid -> id [0 ] == 0x0 ) ? 0 : ntohl (file -> oid_fanout [(int )short_oid -> id [0 ] - 1 ]));
540586
541- pos = git_pack__lookup_id (file -> oid_lookup , GIT_OID_SHA1_SIZE , lo , hi , short_oid -> id , GIT_OID_SHA1 );
587+ pos = git_pack__lookup_id (file -> oid_lookup , oid_size , lo , hi ,
588+ short_oid -> id , file -> oid_type );
542589
543590 if (pos >= 0 ) {
544591 /* An object matching exactly the oid was found */
545592 found = 1 ;
546- current = file -> oid_lookup + (pos * GIT_OID_SHA1_SIZE );
593+ current = file -> oid_lookup + (pos * oid_size );
547594 } else {
548595 /* No object was found */
549596 /* pos refers to the object with the "closest" oid to short_oid */
550597 pos = -1 - pos ;
551598 if (pos < (int )file -> num_commits ) {
552- current = file -> oid_lookup + (pos * GIT_OID_SHA1_SIZE );
599+ current = file -> oid_lookup + (pos * oid_size );
553600
554601 if (!git_oid_raw_ncmp (short_oid -> id , current , len ))
555602 found = 1 ;
556603 }
557604 }
558605
559- if (found && len != GIT_OID_SHA1_HEXSIZE && pos + 1 < (int )file -> num_commits ) {
606+ if (found && len != oid_hexsize && pos + 1 < (int )file -> num_commits ) {
560607 /* Check for ambiguousity */
561- const unsigned char * next = current + GIT_OID_SHA1_SIZE ;
608+ const unsigned char * next = current + oid_size ;
562609
563610 if (!git_oid_raw_ncmp (short_oid -> id , next , len ))
564611 found = 2 ;
@@ -637,11 +684,27 @@ static int packed_commit__cmp(const void *a_, const void *b_)
637684 return git_oid_cmp (& a -> sha1 , & b -> sha1 );
638685}
639686
640- int git_commit_graph_writer_new (git_commit_graph_writer * * out , const char * objects_info_dir )
687+ int git_commit_graph_writer_new (
688+ git_commit_graph_writer * * out ,
689+ const char * objects_info_dir
690+ #ifdef GIT_EXPERIMENTAL_SHA256
691+ , git_oid_t oid_type
692+ #endif
693+ )
641694{
642- git_commit_graph_writer * w = git__calloc (1 , sizeof (git_commit_graph_writer ));
695+ git_commit_graph_writer * w ;
696+
697+ #ifndef GIT_EXPERIMENTAL_SHA256
698+ git_oid_t oid_type = GIT_OID_SHA1 ;
699+ #endif
700+
701+ GIT_ASSERT_ARG (out && objects_info_dir && oid_type );
702+
703+ w = git__calloc (1 , sizeof (git_commit_graph_writer ));
643704 GIT_ERROR_CHECK_ALLOC (w );
644705
706+ w -> oid_type = oid_type ;
707+
645708 if (git_str_sets (& w -> objects_info_dir , objects_info_dir ) < 0 ) {
646709 git__free (w );
647710 return -1 ;
@@ -993,8 +1056,9 @@ static int commit_graph_write(
9931056 off64_t offset ;
9941057 git_str oid_lookup = GIT_STR_INIT , commit_data = GIT_STR_INIT ,
9951058 extra_edge_list = GIT_STR_INIT ;
996- unsigned char checksum [GIT_HASH_SHA1_SIZE ];
997- size_t checksum_size ;
1059+ unsigned char checksum [GIT_HASH_MAX_SIZE ];
1060+ git_hash_algorithm_t checksum_type ;
1061+ size_t checksum_size , oid_size ;
9981062 git_hash_ctx ctx ;
9991063 struct commit_graph_write_hash_context hash_cb_data = {0 };
10001064
@@ -1007,8 +1071,11 @@ static int commit_graph_write(
10071071 hash_cb_data .cb_data = cb_data ;
10081072 hash_cb_data .ctx = & ctx ;
10091073
1010- checksum_size = GIT_HASH_SHA1_SIZE ;
1011- error = git_hash_ctx_init (& ctx , GIT_HASH_ALGORITHM_SHA1 );
1074+ oid_size = git_oid_size (w -> oid_type );
1075+ checksum_type = git_oid_algorithm (w -> oid_type );
1076+ checksum_size = git_hash_size (checksum_type );
1077+
1078+ error = git_hash_ctx_init (& ctx , checksum_type );
10121079 if (error < 0 )
10131080 return error ;
10141081 cb_data = & hash_cb_data ;
@@ -1035,7 +1102,7 @@ static int commit_graph_write(
10351102 git_vector_foreach (& w -> commits , i , packed_commit ) {
10361103 error = git_str_put (& oid_lookup ,
10371104 (const char * )& packed_commit -> sha1 .id ,
1038- GIT_OID_SHA1_SIZE );
1105+ oid_size );
10391106
10401107 if (error < 0 )
10411108 goto cleanup ;
@@ -1052,7 +1119,7 @@ static int commit_graph_write(
10521119
10531120 error = git_str_put (& commit_data ,
10541121 (const char * )& packed_commit -> tree_oid .id ,
1055- GIT_OID_SHA1_SIZE );
1122+ oid_size );
10561123
10571124 if (error < 0 )
10581125 goto cleanup ;
0 commit comments