@@ -47,6 +47,7 @@ typedef struct loose_backend {
47
47
git_odb_backend parent ;
48
48
49
49
git_odb_backend_loose_options options ;
50
+ size_t oid_hexsize ;
50
51
51
52
size_t objects_dirlen ;
52
53
char objects_dir [GIT_FLEX_ARRAY ];
@@ -56,13 +57,19 @@ typedef struct loose_backend {
56
57
* in order to locate objects matching a short oid.
57
58
*/
58
59
typedef struct {
60
+ loose_backend * backend ;
61
+
59
62
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 ];
61
66
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 ];
66
73
} loose_locate_object_state ;
67
74
68
75
@@ -75,20 +82,17 @@ typedef struct {
75
82
static int object_file_name (
76
83
git_str * name , const loose_backend * be , const git_oid * id )
77
84
{
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 ;
85
87
86
88
git_str_set (name , be -> objects_dir , be -> objects_dirlen );
87
89
git_fs_path_to_dir (name );
88
90
89
- /* loose object filename: aa/aaa... (41 bytes) */
91
+ if (git_str_grow_by (name , path_size + 1 ) < 0 )
92
+ return -1 ;
93
+
90
94
git_oid_pathfmt (name -> ptr + name -> size , id );
91
- name -> size += GIT_OID_SHA1_HEXSIZE + 1 ;
95
+ name -> size += path_size ;
92
96
name -> ptr [name -> size ] = '\0' ;
93
97
94
98
return 0 ;
@@ -460,8 +464,9 @@ static int locate_object(
460
464
/* Explore an entry of a directory and see if it matches a short oid */
461
465
static int fn_locate_object_short_oid (void * state , git_str * pathbuf ) {
462
466
loose_locate_object_state * sstate = (loose_locate_object_state * )state ;
467
+ size_t hex_size = sstate -> backend -> oid_hexsize ;
463
468
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 ) {
465
470
/* Entry cannot be an object. Continue to next entry */
466
471
return 0 ;
467
472
}
@@ -476,7 +481,9 @@ static int fn_locate_object_short_oid(void *state, git_str *pathbuf) {
476
481
if (!sstate -> found ) {
477
482
sstate -> res_oid [0 ] = sstate -> short_oid [0 ];
478
483
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 );
480
487
}
481
488
sstate -> found ++ ;
482
489
}
@@ -502,7 +509,7 @@ static int locate_object_short_oid(
502
509
int error ;
503
510
504
511
/* 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 );
506
513
GIT_ERROR_CHECK_ALLOC_ADD (& alloc_len , alloc_len , 3 );
507
514
if (git_str_grow (object_location , alloc_len ) < 0 )
508
515
return -1 ;
@@ -526,6 +533,7 @@ static int locate_object_short_oid(
526
533
return git_odb__error_notfound ("no matching loose object for prefix" ,
527
534
short_oid , len );
528
535
536
+ state .backend = backend ;
529
537
state .dir_len = git_str_len (object_location );
530
538
state .short_oid_len = len ;
531
539
state .found = 0 ;
@@ -544,12 +552,12 @@ static int locate_object_short_oid(
544
552
return git_odb__error_ambiguous ("multiple matches in loose objects" );
545
553
546
554
/* 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 );
548
556
if (error )
549
557
return error ;
550
558
551
559
/* 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 );
553
561
GIT_ERROR_CHECK_ALLOC_ADD (& alloc_len , alloc_len , 2 );
554
562
555
563
git_str_truncate (object_location , dir_len );
@@ -558,20 +566,12 @@ static int locate_object_short_oid(
558
566
559
567
git_oid_pathfmt (object_location -> ptr + dir_len , res_oid );
560
568
561
- object_location -> size += GIT_OID_SHA1_HEXSIZE + 1 ;
569
+ object_location -> size += backend -> oid_hexsize + 1 ;
562
570
object_location -> ptr [object_location -> size ] = '\0' ;
<
6377
tr class="diff-line-row">563
571
564
572
return 0 ;
565
573
}
566
574
567
-
568
-
569
-
570
-
571
-
572
-
573
-
574
-
575
575
/***********************************************************
576
576
*
577
577
* 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
594
594
595
595
if (locate_object (& object_path , (loose_backend * )backend , oid ) < 0 ) {
596
596
error = git_odb__error_notfound ("no matching loose object" ,
597
- oid , GIT_OID_SHA1_HEXSIZE );
597
+ oid , (( struct loose_backend * ) backend ) -> oid_hexsize );
598
598
} else if ((error = read_header_loose (& raw , & object_path )) == 0 ) {
599
599
* len_p = raw .len ;
600
600
* type_p = raw .type ;
@@ -616,7 +616,7 @@ static int loose_backend__read(void **buffer_p, size_t *len_p, git_object_t *typ
616
616
617
617
if (locate_object (& object_path , (loose_backend * )backend , oid ) < 0 ) {
618
618
error = git_odb__error_notfound ("no matching loose object" ,
619
- oid , GIT_OID_SHA1_HEXSIZE );
619
+ oid , (( struct loose_backend * ) backend ) -> oid_hexsize );
620
620
} else if ((error = read_loose (& raw , & object_path )) == 0 ) {
621
621
* buffer_p = raw .data ;
622
622
* len_p = raw .len ;
@@ -633,17 +633,19 @@ static int loose_backend__read_prefix(
633
633
void * * buffer_p ,
634
634
size_t * len_p ,
635
635
git_object_t * type_p ,
636
- git_odb_backend * backend ,
636
+ git_odb_backend * _backend ,
637
637
const git_oid * short_oid ,
638
638
size_t len )
639
639
{
640
+ struct loose_backend * backend = (struct loose_backend * )_backend ;
640
641
int error = 0 ;
641
642
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 );
643
645
644
- if (len == GIT_OID_SHA1_HEXSIZE ) {
646
+ if (len == backend -> oid_hexsize ) {
645
647
/* 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 );
647
649
if (!error )
648
650
git_oid_cpy (out_oid , short_oid );
649
651
} else {
@@ -702,15 +704,18 @@ static int loose_backend__exists_prefix(
702
704
}
703
705
704
706
struct foreach_state {
707
+ struct loose_backend * backend ;
705
708
size_t dir_len ;
706
709
git_odb_foreach_cb cb ;
707
710
void * data ;
708
711
};
709
712
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 )
711
714
{
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 )
714
719
return -1 ;
715
720
716
721
if (ptr [2 ] != '/' ) {
@@ -724,15 +729,15 @@ GIT_INLINE(int) filename_to_oid(git_oid *oid, const char *ptr)
724
729
oid -> id [0 ] = (unsigned char ) v ;
725
730
726
731
ptr += 3 ;
727
- for (i = 0 ; i < 38 ; i += 2 ) {
732
+ for (i = 0 ; i < backend -> oid_hexsize - 2 ; i += 2 ) {
728
733
v = (git__fromhex (ptr [i ]) << 4 ) | git__fromhex (ptr [i + 1 ]);
729
734
if (v < 0 )
730
735
return -1 ;
731
736
732
737
oid -> id [1 + i /2 ] = (unsigned char ) v ;
733
738
}
734
739
735
- oid -> type = GIT_OID_SHA1 ;
740
+ oid -> type = backend -> options . oid_type ;
736
741
737
742
return 0 ;
738
743
}
@@ -742,7 +747,7 @@ static int foreach_object_dir_cb(void *_state, git_str *path)
742
747
git_oid oid ;
743
748
struct foreach_state * state = (struct foreach_state * ) _state ;
744
749
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 )
746
751
return 0 ;
747
752
748
753
return git_error_set_after_callback_function (
@@ -779,6 +784,7 @@ static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb
779
784
return -1 ;
780
785
781
786
memset (& state , 0 , sizeof (state ));
787
+ state .backend = backend ;
782
788
state .cb = cb ;
783
789
state .data = data ;
784
790
state .dir_len = git_str_len (& buf );
@@ -999,6 +1005,7 @@ static int loose_backend__readstream(
999
1005
loose_readstream * stream = NULL ;
1000
1006
git_hash_ctx * hash_ctx = NULL ;
1001
1007
git_str object_path = GIT_STR_INIT ;
1008
+ git_hash_algorithm_t algorithm ;
1002
1009
obj_hdr hdr ;
1003
1010
int error = 0 ;
1004
1011
@@ -1015,7 +1022,7 @@ static int loose_backend__readstream(
1015
1022
1016
1023
if (locate_object (& object_path , backend , oid ) < 0 ) {
1017
1024
error = git_odb__error_notfound ("no matching loose object" ,
1018
- oid , GIT_OID_SHA1_HEXSIZE );
1025
+ oid , backend -> oid_hexsize );
1019
1026
goto done ;
1020
1027
}
1021
1028
@@ -1025,9 +1032,11 @@ static int loose_backend__readstream(
1025
1032
hash_ctx = git__malloc (sizeof (git_hash_ctx ));
1026
1033
GIT_ERROR_CHECK_ALLOC (hash_ctx );
1027
1034
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 )
1031
1040
goto done ;
1032
1041
1033
1042
/* check for a packlike loose object */
@@ -1145,6 +1154,9 @@ static void normalize_options(
1145
1154
1146
1155
if (opts -> file_mode == 0 )
1147
1156
opts -> file_mode = GIT_OBJECT_FILE_MODE ;
1157
+
1158
+ if (opts -> oid_type == 0 )
1159
+ opts -> oid_type = GIT_OID_DEFAULT ;
1148
1160
}
1149
1161
1150
1162
int git_odb_backend_loose (
@@ -1173,6 +1185,7 @@ int git_odb_backend_loose(
1173
1185
backend -> objects_dir [backend -> objects_dirlen ++ ] = '/' ;
1174
1186
1175
1187
normalize_options (& backend -> options , opts );
1188
+ backend -> oid_hexsize = git_oid_hexsize (backend -> options .oid_type );
1176
1189
1177
1190
backend -> parent .read = & loose_backend__read ;
1178
1191
backend -> parent .write = & loose_backend__write ;
0 commit comments