@@ -49,8 +49,37 @@ static git_cache *odb_cache(git_odb *odb)
4949 return & odb -> own_cache ;
5050}
5151
52+ static int odb_otype_fast (git_otype * type_p , git_odb * db , const git_oid * id );
5253static int load_alternates (git_odb * odb , const char * objects_dir , int alternate_depth );
5354
55+ static git_otype odb_hardcoded_type (const git_oid * id )
56+ {
57+ static git_oid empty_blob = {{ 0xe6 , 0x9d , 0xe2 , 0x9b , 0xb2 , 0xd1 , 0xd6 , 0x43 , 0x4b , 0x8b ,
58+ 0x29 , 0xae , 0x77 , 0x5a , 0xd8 , 0xc2 , 0xe4 , 0x8c , 0x53 , 0x91 }};
59+ static git_oid empty_tree = {{ 0x4b , 0x82 , 0x5d , 0xc6 , 0x42 , 0xcb , 0x6e , 0xb9 , 0xa0 , 0x60 ,
60+ 0xe5 , 0x4b , 0xf8 , 0xd6 , 0x92 , 0x88 , 0xfb , 0xee , 0x49 , 0x04 }};
61+
62+ if (!git_oid_cmp (id , & empty_blob ))
63+ return GIT_OBJ_BLOB ;
64+
65+ if (!git_oid_cmp (id , & empty_tree ))
66+ return GIT_OBJ_TREE ;
67+
68+ return GIT_OBJ_BAD ;
69+ }
70+
71+ static int odb_read_hardcoded (git_rawobj * raw , const git_oid * id )
72+ {
73+ git_otype type = odb_hardcoded_type (id );
74+ if (type == GIT_OBJ_BAD )
75+ return -1 ;
76+
77+ raw -> type = type ;
78+ raw -> len = 0 ;
79+ raw -> data = git__calloc (1 , sizeof (uint8_t ));
80+ return 0 ;
81+ }
82+
5483int git_odb__format_object_header (char * hdr , size_t n , git_off_t obj_len , git_otype obj_type )
5584{
5685 const char * type_str = git_object_type2string (obj_type );
@@ -747,7 +776,7 @@ int git_odb_expand_ids(
747776 git_odb_expand_id * ids ,
748777 size_t count )
749778{
750- size_t len , i ;
779+ size_t i ;
751780
752781 assert (db && ids );
753782
@@ -760,7 +789,7 @@ int git_odb_expand_ids(
760789
761790 /* if we were given a full object ID, simply look it up */
762791 if (query -> length >= GIT_OID_HEXSZ ) {
763- error = git_odb_read_header ( & len , & actual_type , db , & query -> id );
792+ error = odb_otype_fast ( & actual_type , db , & query -> id );
764793 git_oid_cpy (& actual_id , & query -> id );
765794 }
766795
@@ -771,7 +800,7 @@ int git_odb_expand_ids(
771800 else if (query -> length >= GIT_OID_MINPREFIXLEN ) {
772801 error = odb_exists_prefix_1 (& actual_id , db , & query -> id , query -> length , false);
773802 if (!error )
774- error = git_odb_read_header ( & len , & actual_type , db , & actual_id );
803+ error = odb_otype_fast ( & actual_type , db , & actual_id );
775804 }
776805
777806 /* Ensure that the looked up type matches the type we were expecting */
@@ -816,11 +845,38 @@ int git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *db, const git
816845 return error ;
817846}
818847
848+ static int odb_read_header_1 (
849+ size_t * len_p , git_otype * type_p , git_odb * db ,
850+ const git_oid * id , bool only_refreshed )
851+ {
852+ size_t i ;
853+ int error = GIT_PASSTHROUGH ;
854+ git_otype ht ;
855+
856+ if (!only_refreshed && (ht = odb_hardcoded_type (id )) != GIT_OBJ_BAD ) {
857+ * type_p = ht ;
858+ * len_p = 0 ;
859+ return 0 ;
860+ }
861+
862+ for (i = 0 ; i < db -> backends .length && error < 0 ; ++ i ) {
863+ backend_internal * internal = git_vector_get (& db -> backends , i );
864+ git_odb_backend * b = internal -> backend ;
865+
866+ if (only_refreshed && !b -> refresh )
867+ continue ;
868+
869+ if (b -> read_header != NULL )
870+ error = b -> read_header (len_p , type_p , b , id );
871+ }
872+
873+ return error ;
874+ }
875+
819876int git_odb__read_header_or_object (
820877 git_odb_object * * out , size_t * len_p , git_otype * type_p ,
821878 git_odb * db , const git_oid * id )
822879{
823- size_t i ;
824880 int error = GIT_ENOTFOUND ;
825881 git_odb_object * object ;
826882
@@ -834,52 +890,32 @@ int git_odb__read_header_or_object(
834890 }
835891
836892 * out = NULL ;
893+ error = odb_read_header_1 (len_p , type_p , db , id , false);
837894
838- for (i = 0 ; i < db -> backends .length && error < 0 ; ++ i ) {
839- backend_internal * internal = git_vector_get (& db -> backends , i );
840- git_odb_backend * b = internal -> backend ;
895+ if (error == GIT_ENOTFOUND && !git_odb_refresh (db ))
896+ error = odb_read_header_1 (len_p , type_p , db , id , true);
841897
842- if (b -> read_header != NULL )
843- error = b -> read_header (len_p , type_p , b , id );
844- }
898+ if (error == GIT_ENOTFOUND )
899+ return git_odb__error_notfound ("cannot read header for" , id , GIT_OID_HEXSZ );
845900
846- if (!error || error == GIT_PASSTHROUGH )
901+ /* we found the header; return early */
902+ if (!error )
847903 return 0 ;
848904
849- /*
850- * no backend could read only the header.
851- * try reading the whole object and freeing the contents
852- */
853- if ((error = git_odb_read (& object , db , id )) < 0 )
854- return error ; /* error already set - pass along */
855-
856- * len_p = object -> cached .size ;
857- * type_p = object -> cached .type ;
858- * out = object ;
859-
860- return 0 ;
861- }
862-
863- static git_oid empty_blob = {{ 0xe6 , 0x9d , 0xe2 , 0x9b , 0xb2 , 0xd1 , 0xd6 , 0x43 , 0x4b , 0x8b ,
864- 0x29 , 0xae , 0x77 , 0x5a , 0xd8 , 0xc2 , 0xe4 , 0x8c , 0x53 , 0x91 }};
865- static git_oid empty_tree = {{ 0x4b , 0x82 , 0x5d , 0xc6 , 0x42 , 0xcb , 0x6e , 0xb9 , 0xa0 , 0x60 ,
866- 0xe5 , 0x4b , 0xf8 , 0xd6 , 0x92 , 0x88 , 0xfb , 0xee , 0x49 , 0x04 }};
867-
868- static int hardcoded_objects (git_rawobj * raw , const git_oid * id )
869- {
870- if (!git_oid_cmp (id , & empty_blob )) {
871- raw -> type = GIT_OBJ_BLOB ;
872- raw -> len = 0 ;
873- raw -> data = git__calloc (1 , sizeof (uint8_t ));
874- return 0 ;
875- } else if (!git_oid_cmp (id , & empty_tree )) {
876- raw -> type = GIT_OBJ_TREE ;
877- raw -> len = 0 ;
878- raw -> data = git__calloc (1 , sizeof (uint8_t ));
879- return 0 ;
880- } else {
881- return GIT_ENOTFOUND ;
905+ if (error == GIT_PASSTHROUGH ) {
906+ /*
907+ * no backend has header-reading functionality
908+ * so try using `git_odb_read` instead
909+ */
910+ error = git_odb_read (& object , db , id );
911+ if (!error ) {
912+ * len_p = object -> cached .size ;
913+ * type_p = object -> cached .type ;
914+ * out = object ;
915+ }
882916 }
917+
918+ return error ;
883919}
884920
885921static int odb_read_1 (git_odb_object * * out , git_odb * db , const git_oid * id ,
@@ -890,7 +926,7 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
890926 git_odb_object * object ;
891927 bool found = false;
892928
893- if (!hardcoded_objects (& raw , id ))
929+ if (!only_refreshed && odb_read_hardcoded (& raw , id ) == 0 )
894930 found = true;
895931
896932 for (i = 0 ; i < db -> backends .length && !found ; ++ i ) {
@@ -944,6 +980,29 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
944980 return error ;
945981}
946982
983+ static int odb_otype_fast (git_otype * type_p , git_odb * db , const git_oid * id )
984+ {
985+ git_odb_object * object ;
986+ size_t _unused ;
987+ int error ;
988+
989+ if ((object = git_cache_get_raw (odb_cache (db ), id )) != NULL ) {
990+ * type_p = object -> cached .type ;
991+ return 0 ;
992+ }
993+
994+ error = odb_read_header_1 (& _unused , type_p , db , id , false);
995+
996+ if (error == GIT_PASSTHROUGH ) {
997+ error = odb_read_1 (& object , db , id , false);
998+ if (!error )
999+ * type_p = object -> cached .type ;
1000+ git_odb_object_free (object );
1001+ }
1002+
1003+ return error ;
1004+ }
1005+
9471006static int read_prefix_1 (git_odb_object * * out , git_odb * db ,
9481007 const git_oid * key , size_t len , bool only_refreshed )
9491008{
0 commit comments