From 5fe874632df9c70022e2ea47a01876780f8b3d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 22 Apr 2016 18:12:09 +0200 Subject: odb: allow asking for the size alone Reading a packed object's type can be expensive if it's deeply chained. Allow a caller to skip that part of the lookup if they don't care or know the type through other means. --- src/odb.c | 5 +++-- src/odb_loose.c | 5 +++-- src/odb_pack.c | 2 +- src/pack.c | 7 +++++++ tests/object/lookup.c | 19 +++++++++++++++++++ 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/odb.c b/src/odb.c index 890e6e2f8..0c8cf84f0 100644 --- a/src/odb.c +++ b/src/odb.c @@ -900,11 +900,12 @@ int git_odb__read_header_or_object( int error = GIT_ENOTFOUND; git_odb_object *object; - assert(db && id && out && len_p && type_p); + assert(db && id && out && len_p); if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) { *len_p = object->cached.size; - *type_p = object->cached.type; + if (type_p) + *type_p = object->cached.type; *out = object; return 0; } diff --git a/src/odb_loose.c b/src/odb_loose.c index 9d9bffd21..0293a2263 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -610,7 +610,7 @@ static int loose_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_ git_rawobj raw; int error; - assert(backend && oid); + assert(len_p && backend && oid); raw.len = 0; raw.type = GIT_OBJ_BAD; @@ -620,7 +620,8 @@ static int loose_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_ oid, GIT_OID_HEXSZ); } else if ((error = read_header_loose(&raw, &object_path)) == 0) { *len_p = raw.len; - *type_p = raw.type; + if (type_p) + *type_p = raw.type; } git_buf_free(&object_path); diff --git a/src/odb_pack.c b/src/odb_pack.c index 5a57864ad..a11b5aad9 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -355,7 +355,7 @@ static int pack_backend__read_header( struct git_pack_entry e; int error; - assert(len_p && type_p && backend && oid); + assert(len_p && backend && oid); if ((error = pack_entry_find(&e, (struct pack_backend *)backend, oid)) < 0) return error; diff --git a/src/pack.c b/src/pack.c index e7003e66d..0578d852e 100644 --- a/src/pack.c +++ b/src/pack.c @@ -513,6 +513,13 @@ int git_packfile_resolve_header( } else *size_p = size; + /* + * If the caller isn't interested in the type, we can return + * now instead of trying to resolve the deltas. + */ + if (type_p == NULL) + return 0; + while (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) { curpos = base_offset; error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos); diff --git a/tests/object/lookup.c b/tests/object/lookup.c index cfa6d4678..c7cc13015 100644 --- a/tests/object/lookup.c +++ b/tests/object/lookup.c @@ -63,3 +63,22 @@ void test_object_lookup__lookup_wrong_type_eventually_returns_enotfound(void) GIT_ENOTFOUND, git_object_lookup(&object, g_repo, &oid, GIT_OBJ_TAG)); } +void test_object_lookup__read_only_size(void) +{ + git_odb *odb; + git_oid id; + size_t len; + const char *obj1 = "e90810b8df3e80c413d903f631643c716887138d"; + const char *obj2 = "08b041783f40edfe12bb406c9c9a8a040177c125"; + + + cl_git_pass(git_repository_odb__weakptr(&odb, g_repo)); + + /* This object is packed */ + cl_git_pass(git_oid_fromstr(&id, obj1)); + cl_git_pass(git_odb_read_header(&len, NULL, odb, &id)); + + /* This object is loose */ + cl_git_pass(git_oid_fromstr(&id, obj2)); + cl_git_pass(git_odb_read_header(&len, NULL, odb, &id)); +} -- cgit v1.2.1