@@ -47,6 +47,7 @@ typedef struct loose_backend {
4747 git_odb_backend parent ;
4848
4949 git_odb_backend_loose_options options ;
50+ size_t oid_hexsize ;
5051
5152 size_t objects_dirlen ;
5253 char objects_dir [GIT_FLEX_ARRAY ];
@@ -56,13 +57,19 @@ typedef struct loose_backend {
5657 * in order to locate objects matching a short oid.
5758 */
5859typedef struct {
60+ loose_backend * backend ;
61+
5962 size_t dir_len ;
60- unsigned char short_oid [GIT_OID_SHA1_HEXSIZE ]; /* hex formatted oid to match */
63+
64+ /* Hex formatted oid to match (and its length) */
65+ unsigned char short_oid [GIT_OID_MAX_HEXSIZE ];
6166 size_t short_oid_len ;
62- int found ; /* number of matching
63- * objects already found */
64- unsigned char res_oid [GIT_OID_SHA1_HEXSIZE ]; /* hex formatted oid of
65- * the object found */
67+
68+ /* Number of matching objects found so far */
69+ int found ;
70+
71+ /* Hex formatted oid of the object found */
72+ unsigned char res_oid [GIT_OID_MAX_HEXSIZE ];
6673} loose_locate_object_state ;
6774
6875
@@ -75,20 +82,17 @@ typedef struct {
7582static int object_file_name (
7683 git_str * name , const loose_backend * be , const git_oid * id )
7784{
78- size_t alloclen ;
79-
80- /* expand length for object root + 40 hex sha1 chars + 2 * '/' + '\0' */
81- GIT_ERROR_CHECK_ALLOC_ADD (& alloclen , be -> objects_dirlen , GIT_OID_SHA1_HEXSIZE );
82- GIT_ERROR_CHECK_ALLOC_ADD (& alloclen , alloclen , 3 );
83- if (git_str_grow (name , alloclen ) < 0 )
84- return -1 ;
85+ /* append loose object filename: aa/aaa... (41 bytes plus NUL) */
86+ size_t path_size = be -> oid_hexsize + 1 ;
8587
8688 git_str_set (name , be -> objects_dir , be -> objects_dirlen );
8789 git_fs_path_to_dir (name );
8890
89- /* loose object filename: aa/aaa... (41 bytes) */
91+ if (git_str_grow_by (name , path_size + 1 ) < 0 )
92+ return -1 ;
93+
9094 git_oid_pathfmt (name -> ptr + name -> size , id );
91- name -> size += GIT_OID_SHA1_HEXSIZE + 1 ;
95+ name -> size += path_size ;
9296 name -> ptr [name -> size ] = '\0' ;
9397
9498 return 0 ;
@@ -460,8 +464,9 @@ static int locate_object(
460464/* Explore an entry of a directory and see if it matches a short oid */
461465static int fn_locate_object_short_oid (void * state , git_str * pathbuf ) {
462466 loose_locate_object_state * sstate = (loose_locate_object_state * )state ;
467+ size_t hex_size = sstate -> backend -> oid_hexsize ;
463468
464- if (git_str_len (pathbuf ) - sstate -> dir_len != GIT_OID_SHA1_HEXSIZE - 2 ) {
469+ if (git_str_len (pathbuf ) - sstate -> dir_len != hex_size - 2 ) {
465470 /* Entry cannot be an object. Continue to next entry */
466471 return 0 ;
467472 }
@@ -476,7 +481,9 @@ static int fn_locate_object_short_oid(void *state, git_str *pathbuf) {
476481 if (!sstate -> found ) {
477482 sstate -> res_oid [0 ] = sstate -> short_oid [0 ];
478483 sstate -> res_oid [1 ] = sstate -> short_oid [1 ];
479- memcpy (sstate -> res_oid + 2 , pathbuf -> ptr + sstate -> dir_len , GIT_OID_SHA1_HEXSIZE - 2 );
484+ memcpy (sstate -> res_oid + 2 ,
485+ pathbuf -> ptr + sstate -> dir_len ,
486+ hex_size - 2 );
480487 }
481488 sstate -> found ++ ;
482489 }
@@ -502,7 +509,7 @@ static int locate_object_short_oid(
502509 int error ;
503510
504511 /* prealloc memory for OBJ_DIR/xx/xx..38x..xx */
505- GIT_ERROR_CHECK_ALLOC_ADD (& alloc_len , dir_len , GIT_OID_SHA1_HEXSIZE );
512+ GIT_ERROR_CHECK_ALLOC_ADD (& alloc_len , dir_len , backend -> oid_hexsize );
506513 GIT_ERROR_CHECK_ALLOC_ADD (& alloc_len , alloc_len , 3 );
507514 if (git_str_grow (object_location , alloc_len ) < 0 )
508515 return -1 ;
@@ -526,6 +533,7 @@ static int locate_object_short_oid(
526533 return git_odb__error_notfound ("no matching loose object for prefix" ,
527534 short_oid , len );
528535
536+ state .backend = backend ;
529537 state .dir_len = git_str_len (object_location );
530538 state .short_oid_len = len ;
531539 state .found = 0 ;
@@ -544,12 +552,12 @@ static int locate_object_short_oid(
544552 return git_odb__error_ambiguous ("multiple matches in loose objects" );
545553
546554 /* Convert obtained hex formatted oid to raw */
547- error = git_oid_fromstr (res_oid , (char * )state .res_oid , GIT_OID_SHA1 );
555+ error = git_oid_fromstr (res_oid , (char * )state .res_oid , backend -> options . oid_type );
548556 if (error )
549557 return error ;
550558
551559 /* Update the location according to the oid obtained */
552- GIT_ERROR_CHECK_ALLOC_ADD (& alloc_len , dir_len , GIT_OID_SHA1_HEXSIZE );
560+ GIT_ERROR_CHECK_ALLOC_ADD (& alloc_len , dir_len , backend -> oid_hexsize );
553561 GIT_ERROR_CHECK_ALLOC_ADD (& alloc_len , alloc_len , 2 );
554562
555563 git_str_truncate (object_location , dir_len );
@@ -558,20 +566,12 @@ static int locate_object_short_oid(
558566
559567 git_oid_pathfmt (object_location -> ptr + dir_len , res_oid );
560568
561- object_location -> size += GIT_OID_SHA1_HEXSIZE + 1 ;
569+ object_location -> size += backend -> oid_hexsize + 1 ;
562570 object_location -> ptr [object_location -> size ] = '\0' ;
563571
564572 return 0 ;
565573}
566574
567-
568-
569-
570-
571-
572-
573-
574-
575575/***********************************************************
576576 *
577577 * LOOSE BACKEND PUBLIC API
@@ -594,7 +594,7 @@ static int loose_backend__read_header(size_t *len_p, git_object_t *type_p, git_o
594594
595595 if (locate_object (& object_path , (loose_backend * )backend , oid ) < 0 ) {
596596 error = git_odb__error_notfound ("no matching loose object" ,
597- oid , GIT_OID_SHA1_HEXSIZE );
597+ oid , (( struct loose_backend * ) backend ) -> oid_hexsize );
598598 } else if ((error = read_header_loose (& raw , & object_path )) == 0 ) {
599599 * len_p = raw .len ;
600600 * type_p = raw .type ;
@@ -616,7 +616,7 @@ static int loose_backend__read(void **buffer_p, size_t *len_p, git_object_t *typ
616616
617617 if (locate_object (& object_path , (loose_backend * )backend , oid ) < 0 ) {
618618 error = git_odb__error_notfound ("no matching loose object" ,
619- oid , GIT_OID_SHA1_HEXSIZE );
619+ oid , (( struct loose_backend * ) backend ) -> oid_hexsize );
620620 } else if ((error = read_loose (& raw , & object_path )) == 0 ) {
621621 * buffer_p = raw .data ;
622622 * len_p = raw .len ;
@@ -633,17 +633,19 @@ static int loose_backend__read_prefix(
633633 void * * buffer_p ,
634634 size_t * len_p ,
635635 git_object_t * type_p ,
636- git_odb_backend * backend ,
636+ git_odb_backend * _backend ,
637637 const git_oid * short_oid ,
638638 size_t len )
639639{
640+ struct loose_backend * backend = (struct loose_backend * )_backend ;
640641 int error = 0 ;
641642
642- GIT_ASSERT_ARG (len >= GIT_OID_MINPREFIXLEN && len <= GIT_OID_SHA1_HEXSIZE );
643+ GIT_ASSERT_ARG (len >= GIT_OID_MINPREFIXLEN &&
644+ len <= backend -> oid_hexsize );
643645
644- if (len == GIT_OID_SHA1_HEXSIZE ) {
646+ if (len == backend -> oid_hexsize ) {
645647 /* We can fall back to regular read method */
646- error = loose_backend__read (buffer_p , len_p , type_p , backend , short_oid );
648+ error = loose_backend__read (buffer_p , len_p , type_p , _backend , short_oid );
647649 if (!error )
648650 git_oid_cpy (out_oid , short_oid );
649651 } else {
@@ -702,15 +704,18 @@ static int loose_backend__exists_prefix(
702704}
703705
704706struct foreach_state {
707+ struct loose_backend * backend ;
705708 size_t dir_len ;
706709 git_odb_foreach_cb cb ;
707710 void * data ;
708711};
709712
710- GIT_INLINE (int ) filename_to_oid (git_oid * oid , const char * ptr )
713+ GIT_INLINE (int ) filename_to_oid (struct loose_backend * backend , git_oid * oid , const char * ptr )
711714{
712- int v , i = 0 ;
713- if (strlen (ptr ) != GIT_OID_SHA1_HEXSIZE + 1 )
715+ int v ;
716+ size_t i = 0 ;
717+
718+ if (strlen (ptr ) != backend -> oid_hexsize + 1 )
714719 return -1 ;
715720
716721 if (ptr [2 ] != '/' ) {
@@ -724,15 +729,15 @@ GIT_INLINE(int) filename_to_oid(git_oid *oid, const char *ptr)
724729 oid -> id [0 ] = (unsigned char ) v ;
725730
726731 ptr += 3 ;
727- for (i = 0 ; i < 38 ; i += 2 ) {
732+ for (i = 0 ; i < backend -> oid_hexsize - 2 ; i += 2 ) {
728733 v = (git__fromhex (ptr [i ]) << 4 ) | git__fromhex (ptr [i + 1 ]);
729734 if (v < 0 )
730735 return -1 ;
731736
732737 oid -> id [1 + i /2 ] = (unsigned char ) v ;
733738 }
734739
735- oid -> type = GIT_OID_SHA1 ;
740+ oid -> type = backend -> options . oid_type ;
736741
737742 return 0 ;
738743}
@@ -742,7 +747,7 @@ static int foreach_object_dir_cb(void *_state, git_str *path)
742747 git_oid oid ;
743748 struct foreach_state * state = (struct foreach_state * ) _state ;
744749
745- if (filename_to_oid (& oid , path -> ptr + state -> dir_len ) < 0 )
750+ if (filename_to_oid (state -> backend , & oid , path -> ptr + state -> dir_len ) < 0 )
746751 return 0 ;
747752
748753 return git_error_set_after_callback_function (
@@ -779,6 +784,7 @@ static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb
779784 return -1 ;
780785
781786 memset (& state , 0 , sizeof (state ));
787+ state .backend = backend ;
782788 state .cb = cb ;
783789 state .data = data ;
784790 state .dir_len = git_str_len (& buf );
@@ -999,6 +1005,7 @@ static int loose_backend__readstream(
9991005 loose_readstream * stream = NULL ;
10001006 git_hash_ctx * hash_ctx = NULL ;
10011007 git_str object_path = GIT_STR_INIT ;
1008+ git_hash_algorithm_t algorithm ;
10021009 obj_hdr hdr ;
10031010 int error = 0 ;
10041011
@@ -1015,7 +1022,7 @@ static int loose_backend__readstream(
10151022
10161023 if (locate_object (& object_path , backend , oid ) < 0 ) {
10171024 error = git_odb__error_notfound ("no matching loose object" ,
1018- oid , GIT_OID_SHA1_HEXSIZE );
1025+ oid , backend -> oid_hexsize );
10191026 goto done ;
10201027 }
10211028
@@ -1025,9 +1032,11 @@ static int loose_backend__readstream(
10251032 hash_ctx = git__malloc (sizeof (git_hash_ctx ));
10261033 GIT_ERROR_CHECK_ALLOC (hash_ctx );
10271034
1028- if ((error = git_hash_ctx_init (hash_ctx , GIT_HASH_ALGORITHM_SHA1 )) < 0 ||
1029- (error = git_futils_mmap_ro_file (& stream -> map , object_path .ptr )) < 0 ||
1030- (error = git_zstream_init (& stream -> zstream , GIT_ZSTREAM_INFLATE )) < 0 )
1035+ algorithm = git_oid_algorithm (backend -> options .oid_type );
1036+
1037+ if ((error = git_hash_ctx_init (hash_ctx , algorithm )) < 0 ||
1038+ (error = git_futils_mmap_ro_file (& stream -> map , object_path .ptr )) < 0 ||
1039+ (error = git_zstream_init (& stream -> zstream , GIT_ZSTREAM_INFLATE )) < 0 )
10311040 goto done ;
10321041
10331042 /* check for a packlike loose object */
@@ -1145,6 +1154,9 @@ static void normalize_options(
11451154
11461155 if (opts -> file_mode == 0 )
11471156 opts -> file_mode = GIT_OBJECT_FILE_MODE ;
1157+
1158+ if (opts -> oid_type == 0 )
1159+ opts -> oid_type = GIT_OID_DEFAULT ;
11481160}
11491161
11501162int git_odb_backend_loose (
@@ -1173,6 +1185,7 @@ int git_odb_backend_loose(
11731185 backend -> objects_dir [backend -> objects_dirlen ++ ] = '/' ;
11741186
11751187 normalize_options (& backend -> options , opts );
1188+ backend -> oid_hexsize = git_oid_hexsize (backend -> options .oid_type );
11761189
11771190 backend -> parent .read = & loose_backend__read ;
11781191 backend -> parent .write = & loose_backend__write ;
0 commit comments