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));
+}