mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-30 22:24:56 +00:00
odb: Implement new helper to read types without refreshing
This commit is contained in:
parent
9a78665005
commit
4416aa7749
153
src/odb.c
153
src/odb.c
@ -49,8 +49,37 @@ static git_cache *odb_cache(git_odb *odb)
|
|||||||
return &odb->own_cache;
|
return &odb->own_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int odb_otype_fast(git_otype *type_p, git_odb *db, const git_oid *id);
|
||||||
static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_depth);
|
static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_depth);
|
||||||
|
|
||||||
|
static git_otype odb_hardcoded_type(const git_oid *id)
|
||||||
|
{
|
||||||
|
static git_oid empty_blob = {{ 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,
|
||||||
|
0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91 }};
|
||||||
|
static git_oid empty_tree = {{ 0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
|
||||||
|
0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04 }};
|
||||||
|
|
||||||
|
if (!git_oid_cmp(id, &empty_blob))
|
||||||
|
return GIT_OBJ_BLOB;
|
||||||
|
|
||||||
|
if (!git_oid_cmp(id, &empty_tree))
|
||||||
|
return GIT_OBJ_TREE;
|
||||||
|
|
||||||
|
return GIT_OBJ_BAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int odb_read_hardcoded(git_rawobj *raw, const git_oid *id)
|
||||||
|
{
|
||||||
|
git_otype type = odb_hardcoded_type(id);
|
||||||
|
if (type == GIT_OBJ_BAD)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
raw->type = type;
|
||||||
|
raw->len = 0;
|
||||||
|
raw->data = git__calloc(1, sizeof(uint8_t));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int git_odb__format_object_header(char *hdr, size_t n, git_off_t obj_len, git_otype obj_type)
|
int git_odb__format_object_header(char *hdr, size_t n, git_off_t obj_len, git_otype obj_type)
|
||||||
{
|
{
|
||||||
const char *type_str = git_object_type2string(obj_type);
|
const char *type_str = git_object_type2string(obj_type);
|
||||||
@ -747,7 +776,7 @@ int git_odb_expand_ids(
|
|||||||
git_odb_expand_id *ids,
|
git_odb_expand_id *ids,
|
||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
size_t len, i;
|
size_t i;
|
||||||
|
|
||||||
assert(db && ids);
|
assert(db && ids);
|
||||||
|
|
||||||
@ -760,7 +789,7 @@ int git_odb_expand_ids(
|
|||||||
|
|
||||||
/* if we were given a full object ID, simply look it up */
|
/* if we were given a full object ID, simply look it up */
|
||||||
if (query->length >= GIT_OID_HEXSZ) {
|
if (query->length >= GIT_OID_HEXSZ) {
|
||||||
error = git_odb_read_header(&len, &actual_type, db, &query->id);
|
error = odb_otype_fast(&actual_type, db, &query->id);
|
||||||
git_oid_cpy(&actual_id, &query->id);
|
git_oid_cpy(&actual_id, &query->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,7 +800,7 @@ int git_odb_expand_ids(
|
|||||||
else if (query->length >= GIT_OID_MINPREFIXLEN) {
|
else if (query->length >= GIT_OID_MINPREFIXLEN) {
|
||||||
error = odb_exists_prefix_1(&actual_id, db, &query->id, query->length, false);
|
error = odb_exists_prefix_1(&actual_id, db, &query->id, query->length, false);
|
||||||
if (!error)
|
if (!error)
|
||||||
error = git_odb_read_header(&len, &actual_type, db, &actual_id);
|
error = odb_otype_fast(&actual_type, db, &actual_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure that the looked up type matches the type we were expecting */
|
/* 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
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int odb_read_header_1(
|
||||||
|
size_t *len_p, git_otype *type_p, git_odb *db,
|
||||||
|
const git_oid *id, bool only_refreshed)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
int error = GIT_PASSTHROUGH;
|
||||||
|
git_otype ht;
|
||||||
|
|
||||||
|
if (!only_refreshed && (ht = odb_hardcoded_type(id)) != GIT_OBJ_BAD) {
|
||||||
|
*type_p = ht;
|
||||||
|
*len_p = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < db->backends.length && error < 0; ++i) {
|
||||||
|
backend_internal *internal = git_vector_get(&db->backends, i);
|
||||||
|
git_odb_backend *b = internal->backend;
|
||||||
|
|
||||||
|
if (only_refreshed && !b->refresh)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (b->read_header != NULL)
|
||||||
|
error = b->read_header(len_p, type_p, b, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
int git_odb__read_header_or_object(
|
int git_odb__read_header_or_object(
|
||||||
git_odb_object **out, size_t *len_p, git_otype *type_p,
|
git_odb_object **out, size_t *len_p, git_otype *type_p,
|
||||||
git_odb *db, const git_oid *id)
|
git_odb *db, const git_oid *id)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
int error = GIT_ENOTFOUND;
|
int error = GIT_ENOTFOUND;
|
||||||
git_odb_object *object;
|
git_odb_object *object;
|
||||||
|
|
||||||
@ -834,52 +890,32 @@ int git_odb__read_header_or_object(
|
|||||||
}
|
}
|
||||||
|
|
||||||
*out = NULL;
|
*out = NULL;
|
||||||
|
error = odb_read_header_1(len_p, type_p, db, id, false);
|
||||||
|
|
||||||
for (i = 0; i < db->backends.length && error < 0; ++i) {
|
if (error == GIT_ENOTFOUND && !git_odb_refresh(db))
|
||||||
backend_internal *internal = git_vector_get(&db->backends, i);
|
error = odb_read_header_1(len_p, type_p, db, id, true);
|
||||||
git_odb_backend *b = internal->backend;
|
|
||||||
|
|
||||||
if (b->read_header != NULL)
|
if (error == GIT_ENOTFOUND)
|
||||||
error = b->read_header(len_p, type_p, b, id);
|
return git_odb__error_notfound("cannot read header for", id, GIT_OID_HEXSZ);
|
||||||
|
|
||||||
|
/* we found the header; return early */
|
||||||
|
if (!error)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (error == GIT_PASSTHROUGH) {
|
||||||
|
/*
|
||||||
|
* no backend has header-reading functionality
|
||||||
|
* so try using `git_odb_read` instead
|
||||||
|
*/
|
||||||
|
error = git_odb_read(&object, db, id);
|
||||||
|
if (!error) {
|
||||||
|
*len_p = object->cached.size;
|
||||||
|
*type_p = object->cached.type;
|
||||||
|
*out = object;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error || error == GIT_PASSTHROUGH)
|
return error;
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* no backend could read only the header.
|
|
||||||
* try reading the whole object and freeing the contents
|
|
||||||
*/
|
|
||||||
if ((error = git_odb_read(&object, db, id)) < 0)
|
|
||||||
return error; /* error already set - pass along */
|
|
||||||
|
|
||||||
*len_p = object->cached.size;
|
|
||||||
*type_p = object->cached.type;
|
|
||||||
*out = object;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static git_oid empty_blob = {{ 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b,
|
|
||||||
0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91 }};
|
|
||||||
static git_oid empty_tree = {{ 0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
|
|
||||||
0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04 }};
|
|
||||||
|
|
||||||
static int hardcoded_objects(git_rawobj *raw, const git_oid *id)
|
|
||||||
{
|
|
||||||
if (!git_oid_cmp(id, &empty_blob)) {
|
|
||||||
raw->type = GIT_OBJ_BLOB;
|
|
||||||
raw->len = 0;
|
|
||||||
raw->data = git__calloc(1, sizeof(uint8_t));
|
|
||||||
return 0;
|
|
||||||
} else if (!git_oid_cmp(id, &empty_tree)) {
|
|
||||||
raw->type = GIT_OBJ_TREE;
|
|
||||||
raw->len = 0;
|
|
||||||
raw->data = git__calloc(1, sizeof(uint8_t));
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return GIT_ENOTFOUND;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
|
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,
|
|||||||
git_odb_object *object;
|
git_odb_object *object;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
if (!hardcoded_objects(&raw, id))
|
if (!only_refreshed && odb_read_hardcoded(&raw, id) == 0)
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
for (i = 0; i < db->backends.length && !found; ++i) {
|
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)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int odb_otype_fast(git_otype *type_p, git_odb *db, const git_oid *id)
|
||||||
|
{
|
||||||
|
git_odb_object *object;
|
||||||
|
size_t _unused;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) {
|
||||||
|
*type_p = object->cached.type;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = odb_read_header_1(&_unused, type_p, db, id, false);
|
||||||
|
|
||||||
|
if (error == GIT_PASSTHROUGH) {
|
||||||
|
error = odb_read_1(&object, db, id, false);
|
||||||
|
if (!error)
|
||||||
|
*type_p = object->cached.type;
|
||||||
|
git_odb_object_free(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
static int read_prefix_1(git_odb_object **out, git_odb *db,
|
static int read_prefix_1(git_odb_object **out, git_odb *db,
|
||||||
const git_oid *key, size_t len, bool only_refreshed)
|
const git_oid *key, size_t len, bool only_refreshed)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user