@@ -115,19 +115,20 @@ static int midx_parse_oid_lookup(
115115 struct git_midx_chunk * chunk_oid_lookup )
116116{
117117 uint32_t i ;
118- unsigned char * oid , * prev_oid , zero_oid [GIT_OID_SHA1_SIZE ] = {0 };
118+ unsigned char * oid , * prev_oid , zero_oid [GIT_OID_MAX_SIZE ] = {0 };
119+ size_t oid_size = git_oid_size (idx -> oid_type );
119120
120121 if (chunk_oid_lookup -> offset == 0 )
121122 return midx_error ("missing OID Lookup chunk" );
122123 if (chunk_oid_lookup -> length == 0 )
123124 return midx_error ("empty OID Lookup chunk" );
124- if (chunk_oid_lookup -> length != idx -> num_objects * GIT_OID_SHA1_SIZE )
125+ if (chunk_oid_lookup -> length != idx -> num_objects * oid_size )
125126 return midx_error ("OID Lookup chunk has wrong length" );
126127
127128 idx -> oid_lookup = oid = (unsigned char * )(data + chunk_oid_lookup -> offset );
128129 prev_oid = zero_oid ;
129- for (i = 0 ; i < idx -> num_objects ; ++ i , oid += GIT_OID_SHA1_SIZE ) {
130- if (git_oid_raw_cmp (prev_oid , oid , GIT_OID_SHA1_SIZE ) >= 0 )
130+ for (i = 0 ; i < idx -> num_objects ; ++ i , oid += oid_size ) {
131+ if (git_oid_raw_cmp (prev_oid , oid , oid_size ) >= 0 )
131132 return midx_error ("OID Lookup index is non-monotonic" );
132133 prev_oid = oid ;
133134 }
@@ -178,7 +179,7 @@ int git_midx_parse(
178179 struct git_midx_chunk * last_chunk ;
179180 uint32_t i ;
180181 off64_t last_chunk_offset , chunk_offset , trailer_offset ;
181- size_t checksum_size ;
182+ size_t checksum_size , oid_size ;
182183 int error ;
183184 struct git_midx_chunk chunk_packfile_names = {0 },
184185 chunk_oid_fanout = {0 },
@@ -188,7 +189,9 @@ int git_midx_parse(
188189
189190 GIT_ASSERT_ARG (idx );
190191
191- if (size < sizeof (struct git_midx_header ) + GIT_OID_SHA1_SIZE )
192+ oid_size = git_oid_size (idx -> oid_type );
193+
194+ if (size < sizeof (struct git_midx_header ) + oid_size )
192195 return midx_error ("multi-pack index is too short" );
193196
194197 hdr = ((struct git_midx_header * )data );
@@ -209,7 +212,7 @@ int git_midx_parse(
209212 sizeof (struct git_midx_header ) +
210213 (1 + hdr -> chunks ) * 12 ;
211214
212- checksum_size = GIT_HASH_SHA1_SIZE ;
215+ checksum_size = oid_size ;
213216 trailer_offset = size - checksum_size ;
214217
215218 if (trailer_offset < last_chunk_offset )
@@ -287,15 +290,18 @@ int git_midx_parse(
287290}
288291
289292int git_midx_open (
290- git_midx_file * * idx_out ,
291- const char * path )
293+ git_midx_file * * idx_out ,
294+ const char * path ,
295+ git_oid_t oid_type )
292296{
293297 git_midx_file * idx ;
294298 git_file fd = -1 ;
295299 size_t idx_size ;
296300 struct stat st ;
297301 int error ;
298302
303+ GIT_ASSERT_ARG (idx_out && path && oid_type );
304+
299305 /* TODO: properly open the file without access time using O_NOATIME */
300306 fd = git_futils_open_ro (path );
301307 if (fd < 0 )
@@ -317,6 +323,8 @@ int git_midx_open(
317323 idx = git__calloc (1 , sizeof (git_midx_file ));
318324 GIT_ERROR_CHECK_ALLOC (idx );
319325
326+ idx -> oid_type = oid_type ;
327+
320328 error = git_str_sets (& idx -> filename , path );
321329 if (error < 0 )
322330 return error ;
@@ -344,7 +352,7 @@ bool git_midx_needs_refresh(
344352 git_file fd = -1 ;
345353 struct stat st ;
346354 ssize_t bytes_read ;
347- unsigned char checksum [GIT_HASH_SHA1_SIZE ];
355+ unsigned char checksum [GIT_HASH_MAX_SIZE ];
348356 size_t checksum_size ;
349357
350358 /* TODO: properly open the file without access time using O_NOATIME */
@@ -364,8 +372,8 @@ bool git_midx_needs_refresh(
364372 return true;
365373 }
366374
367- checksum_size = GIT_HASH_SHA1_SIZE ;
368- bytes_read = p_pread (fd , checksum , checksum_size , st .st_size - GIT_OID_SHA1_SIZE );
375+ checksum_size = git_oid_size ( idx -> oid_type ) ;
376+ bytes_read = p_pread (fd , checksum , checksum_size , st .st_size - checksum_size );
369377 p_close (fd );
370378
371379 if (bytes_read != (ssize_t )checksum_size )
@@ -381,38 +389,41 @@ int git_midx_entry_find(
381389 size_t len )
382390{
383391 int pos , found = 0 ;
384- size_t pack_index ;
392+ size_t pack_index , oid_size , oid_hexsize ;
385393 uint32_t hi , lo ;
386394 unsigned char * current = NULL ;
387395 const unsigned char * object_offset ;
388396 off64_t offset ;
389397
390398 GIT_ASSERT_ARG (idx );
391399
400+ oid_size = git_oid_size (idx -> oid_type );
401+ oid_hexsize = git_oid_hexsize (idx -> oid_type );
402+
392403 hi = ntohl (idx -> oid_fanout [(int )short_oid -> id [0 ]]);
393404 lo = ((short_oid -> id [0 ] == 0x0 ) ? 0 : ntohl (idx -> oid_fanout [(int )short_oid -> id [0 ] - 1 ]));
394405
395- pos = git_pack__lookup_id (idx -> oid_lookup , GIT_OID_SHA1_SIZE , lo , hi , short_oid -> id , GIT_OID_SHA1 );
406+ pos = git_pack__lookup_id (idx -> oid_lookup , oid_size , lo , hi , short_oid -> id , idx -> oid_type );
396407
397408 if (pos >= 0 ) {
398409 /* An object matching exactly the oid was found */
399410 found = 1 ;
400- current = idx -> oid_lookup + (pos * GIT_OID_SHA1_SIZE );
411+ current = idx -> oid_lookup + (pos * oid_size );
401412 } else {
402413 /* No object was found */
403414 /* pos refers to the object with the "closest" oid to short_oid */
404415 pos = -1 - pos ;
405416 if (pos < (int )idx -> num_objects ) {
406- current = idx -> oid_lookup + (pos * GIT_OID_SHA1_SIZE );
417+ current = idx -> oid_lookup + (pos * oid_size );
407418
408419 if (!git_oid_raw_ncmp (short_oid -> id , current , len ))
409420 found = 1 ;
410421 }
411422 }
412423
413- if (found && len != GIT_OID_SHA1_HEXSIZE && pos + 1 < (int )idx -> num_objects ) {
424+ if (found && len != oid_hexsize && pos + 1 < (int )idx -> num_objects ) {
414425 /* Check for ambiguousity */
415- const unsigned char * next = current + GIT_OID_SHA1_SIZE ;
426+ const unsigned char * next = current + oid_size ;
416427
417428 if (!git_oid_raw_ncmp (short_oid -> id , next , len ))
418429 found = 2 ;
@@ -443,7 +454,7 @@ int git_midx_entry_find(
443454 return midx_error ("invalid index into the packfile names table" );
444455 e -> pack_index = pack_index ;
445456 e -> offset = offset ;
446- git_oid__fromraw (& e -> sha1 , current , GIT_OID_SHA1 );
457+ git_oid__fromraw (& e -> sha1 , current , idx -> oid_type );
447458 return 0 ;
448459}
449460
@@ -453,13 +464,15 @@ int git_midx_foreach_entry(
453464 void * data )
454465{
455466 git_oid oid ;
456- size_t i ;
467+ size_t oid_size , i ;
457468 int error ;
458469
459470 GIT_ASSERT_ARG (idx );
460471
472+ oid_size = git_oid_size (idx -> oid_type );
473+
461474 for (i = 0 ; i < idx -> num_objects ; ++ i ) {
462- if ((error = git_oid__fromraw (& oid , & idx -> oid_lookup [i * GIT_OID_SHA1_SIZE ], GIT_OID_SHA1 )) < 0 )
475+ if ((error = git_oid__fromraw (& oid , & idx -> oid_lookup [i * oid_size ], idx -> oid_type )) < 0 )
463476 return error ;
464477
465478 if ((error = cb (& oid , data )) != 0 )
@@ -501,9 +514,21 @@ static int packfile__cmp(const void *a_, const void *b_)
501514
502515int git_midx_writer_new (
503516 git_midx_writer * * out ,
504- const char * pack_dir )
517+ const char * pack_dir
518+ #ifdef GIT_EXPERIMENTAL_SHA256
519+ , git_oid_t oid_type
520+ #endif
521+ )
505522{
506- git_midx_writer * w = git__calloc (1 , sizeof (git_midx_writer ));
523+ git_midx_writer * w ;
524+
525+ #ifndef GIT_EXPERIMENTAL_SHA256
526+ git_oid_t oid_type = GIT_OID_SHA1 ;
527+ #endif
528+
529+ GIT_ASSERT_ARG (out && pack_dir && oid_type );
530+
531+ w = git__calloc (1 , sizeof (git_midx_writer ));
507532 GIT_ERROR_CHECK_ALLOC (w );
508533
509534 if (git_str_sets (& w -> pack_dir , pack_dir ) < 0 ) {
@@ -518,6 +543,8 @@ int git_midx_writer_new(
518543 return -1 ;
519544 }
520545
546+ w -> oid_type = oid_type ;
547+
521548 * out = w ;
522549 return 0 ;
523550}
@@ -662,12 +689,13 @@ static int midx_write(
662689 oid_lookup = GIT_STR_INIT ,
663690 object_offsets = GIT_STR_INIT ,
664691 object_large_offsets = GIT_STR_INIT ;
665- unsigned char checksum [GIT_HASH_SHA1_SIZE ];
666- size_t checksum_size ;
692+ unsigned char checksum [GIT_HASH_MAX_SIZE ];
693+ size_t checksum_size , oid_size ;
667694 git_midx_entry * entry ;
668695 object_entry_array_t object_entries_array = GIT_ARRAY_INIT ;
669696 git_vector object_entries = GIT_VECTOR_INIT ;
670697 git_hash_ctx ctx ;
698+ git_hash_algorithm_t checksum_type ;
671699 struct midx_write_hash_context hash_cb_data = {0 };
672700
673701 hdr .signature = htonl (MIDX_SIGNATURE );
@@ -679,10 +707,14 @@ static int midx_write(
679707 hash_cb_data .cb_data = cb_data ;
680708 hash_cb_data .ctx = & ctx ;
681709
682- checksum_size = GIT_HASH_SHA1_SIZE ;
683- error = git_hash_ctx_init (& ctx , GIT_HASH_ALGORITHM_SHA1 );
684- if (error < 0 )
710+ oid_size = git_oid_size (w -> oid_type );
711+
712+ GIT_ASSERT ((checksum_type = git_oid_algorithm (w -> oid_type )));
713+ checksum_size = git_hash_size (checksum_type );
714+
715+ if ((error = git_hash_ctx_init (& ctx , checksum_type )) < 0 )
685716 return error ;
717+
686718 cb_data = & hash_cb_data ;
687719 write_cb = midx_write_hash ;
688720
@@ -749,7 +781,9 @@ static int midx_write(
749781
750782 /* Fill the OID Lookup table. */
751783 git_vector_foreach (& object_entries , i , entry ) {
752- error = git_str_put (& oid_lookup , (char * )& entry -> sha1 .id , GIT_OID_SHA1_SIZE );
784+ error = git_str_put (& oid_lookup ,
785+ (char * )& entry -> sha1 .id , oid_size );
786+
753787 if (error < 0 )
754788 goto cleanup ;
755789 }
0 commit comments