summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2016-04-22 18:12:09 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2016-04-22 18:12:09 +0200
commit5fe874632df9c70022e2ea47a01876780f8b3d02 (patch)
tree5ae8cb5782df1b75e7cd6ec89c1df2cbb984f01f
parent1dc449105b329ea4f8ea9982bc2da869d231c04a (diff)
downloadlibgit2-cmn/read-only-size.tar.gz
odb: allow asking for the size alonecmn/read-only-size
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.
-rw-r--r--src/odb.c5
-rw-r--r--src/odb_loose.c5
-rw-r--r--src/odb_pack.c2
-rw-r--r--src/pack.c7
-rw-r--r--tests/object/lookup.c19
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));
+}