Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4416aa7

Browse files
committed
odb: Implement new helper to read types without refreshing
1 parent 9a78665 commit 4416aa7

File tree

1 file changed

+104
-45
lines changed

1 file changed

+104
-45
lines changed

src/odb.c

Lines changed: 104 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -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);
5253
static 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+
5483
int 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+
819876
int 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

885921
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,
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+
9471006
static 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

Comments
 (0)