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.
diff --git a/src/odb.c b/src/odb.c index 890e6e2..0c8cf84 100644 --- a/src/odb.c +++ b/src/odb.c
@@ -900,11 +900,12 @@ 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 9d9bffd..0293a22 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c
@@ -610,7 +610,7 @@ 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 @@ 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 5a57864..a11b5aa 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c
@@ -355,7 +355,7 @@ 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 e8bde71..9bc77d3 100644 --- a/src/pack.c +++ b/src/pack.c
@@ -514,6 +514,13 @@ } 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 cfa6d46..c7cc130 100644 --- a/tests/object/lookup.c +++ b/tests/object/lookup.c
@@ -63,3 +63,22 @@ 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)); +}