@@ -49,8 +49,37 @@ static git_cache *odb_cache(git_odb *odb)
49
49
return & odb -> own_cache ;
50
50
}
51
51
52
+ static int odb_otype_fast (git_otype * type_p , git_odb * db , const git_oid * id );
52
53
static int load_alternates (git_odb * odb , const char * objects_dir , int alternate_depth );
53
54
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
+
54
83
int git_odb__format_object_header (char * hdr , size_t n , git_off_t obj_len , git_otype obj_type )
55
84
{
56
85
const char * type_str = git_object_type2string (obj_type );
@@ -747,7 +776,7 @@ int git_odb_expand_ids(
747
776
git_odb_expand_id * ids ,
748
777
size_t count )
749
778
{
750
- size_t len , i ;
779
+ size_t i ;
751
780
752
781
assert (db && ids );
753
782
@@ -760,7 +789,7 @@ int git_odb_expand_ids(
760
789
761
790
/* if we were given a full object ID, simply look it up */
762
791
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 );
764
793
git_oid_cpy (& actual_id , & query -> id );
765
794
}
766
795
@@ -771,7 +800,7 @@ int git_odb_expand_ids(
771
800
else if (query -> length >= GIT_OID_MINPREFIXLEN ) {
772
801
error = odb_exists_prefix_1 (& actual_id , db , & query -> id , query -> length , false);
773
802
if (!error )
774
- error = git_odb_read_header ( & len , & actual_type , db , & actual_id );
803
+ error = odb_otype_fast ( & actual_type , db , & actual_id );
775
804
}
776
805
777
806
/* 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
816
845
return error ;
817
846
}
818
847
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
+
819
876
int git_odb__read_header_or_object (
820
877
git_odb_object * * out , size_t * len_p , git_otype * type_p ,
821
878
git_odb * db , const git_oid * id )
822
879
{
823
- size_t i ;
824
880
int error = GIT_ENOTFOUND ;
825
881
git_odb_object * object ;
826
882
@@ -834,52 +890,32 @@ int git_odb__read_header_or_object(
834
890
}
835
891
836
892
* out = NULL ;
893
+ error = odb_read_header_1 (len_p , type_p , db , id , false);
837
894
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);
841
897
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 );
845
900
846
- if (!error || error == GIT_PASSTHROUGH )
901
+ /* we found the header; return early */
902
+ if (!error )
847
903
return 0 ;
848
904
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
+ }
882
916
}
917
+
918
+ return error ;
883
919
}
884
920
885
921
static 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,
890
926
git_odb_object * object ;
891
927
bool found = false;
892
928
893
- if (!hardcoded_objects (& raw , id ))
929
+ if (!only_refreshed && odb_read_hardcoded (& raw , id ) == 0 )
894
930
found = true;
895
931
896
932
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)
944
980
return error ;
945
981
}
946
982
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
+
947
1006
static int read_prefix_1 (git_odb_object * * out , git_odb * db ,
948
1007
const git_oid * key , size_t len , bool only_refreshed )
949
1008
{
0 commit comments