summaryrefslogtreecommitdiff
path: root/src/object.c
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2012-09-10 12:24:05 -0700
committerRussell Belfer <rb@github.com>2012-09-10 12:24:05 -0700
commitc6ac28fdc57d04a9a5eba129cfd267c7adde43b3 (patch)
tree180cf940b152faebf95dc415ce4ff1dd3ec8d8bd /src/object.c
parente597b1890ebd43e398d84b7bf4ca366365b24d27 (diff)
downloadlibgit2-c6ac28fdc57d04a9a5eba129cfd267c7adde43b3.tar.gz
Reorg internal odb read header and object lookup
Often `git_odb_read_header` will "fail" and have to read the entire object into memory instead of just the header. When this happens, the object is loaded and then disposed of immediately, which makes it difficult to efficiently use the header information to decide if the object should be loaded (since attempting to do so will often result in loading the object twice). This commit takes the existing code and reorganizes it to have two new functions: - `git_odb__read_header_or_object` which acts just like the old read header function except that it returns the object, too, if it was forced to load the whole thing. It then becomes the callers responsibility to free the `git_odb_object`. - `git_object__from_odb_object` which was extracted from the old `git_object_lookup` and creates a subclass of `git_object` from an existing `git_odb_object` (separating the ODB lookup from the `git_object` creation). This allows you to use the first header reading function efficiently without instantiating the `git_odb_object` twice. There is no net change to the behavior of any of the existing functions, but this allows internal code to tap into the ODB lookup and object creation to be more efficient.
Diffstat (limited to 'src/object.c')
-rw-r--r--src/object.c98
1 files changed, 54 insertions, 44 deletions
diff --git a/src/object.c b/src/object.c
index 5130d97ac..2e45eb86a 100644
--- a/src/object.c
+++ b/src/object.c
@@ -77,6 +77,58 @@ static int create_object(git_object **object_out, git_otype type)
return 0;
}
+int git_object__from_odb_object(
+ git_object **object_out,
+ git_repository *repo,
+ git_odb_object *odb_obj,
+ git_otype type)
+{
+ int error;
+ git_object *object = NULL;
+
+ if (type != GIT_OBJ_ANY && type != odb_obj->raw.type) {
+ giterr_set(GITERR_ODB, "The requested type does not match the type in the ODB");
+ return GIT_ENOTFOUND;
+ }
+
+ type = odb_obj->raw.type;
+
+ if ((error = create_object(&object, type)) < 0)
+ return error;
+
+ /* Initialize parent object */
+ git_oid_cpy(&object->cached.oid, &odb_obj->cached.oid);
+ object->repo = repo;
+
+ switch (type) {
+ case GIT_OBJ_COMMIT:
+ error = git_commit__parse((git_commit *)object, odb_obj);
+ break;
+
+ case GIT_OBJ_TREE:
+ error = git_tree__parse((git_tree *)object, odb_obj);
+ break;
+
+ case GIT_OBJ_TAG:
+ error = git_tag__parse((git_tag *)object, odb_obj);
+ break;
+
+ case GIT_OBJ_BLOB:
+ error = git_blob__parse((git_blob *)object, odb_obj);
+ break;
+
+ default:
+ break;
+ }
+
+ if (error < 0)
+ git_object__free(object);
+ else
+ *object_out = git_cache_try_store(&repo->objects, object);
+
+ return error;
+}
+
int git_object_lookup_prefix(
git_object **object_out,
git_repository *repo,
@@ -148,53 +200,11 @@ int git_object_lookup_prefix(
if (error < 0)
return error;
- if (type != GIT_OBJ_ANY && type != odb_obj->raw.type) {
- git_odb_object_free(odb_obj);
- giterr_set(GITERR_ODB, "The given type does not match the type on the ODB");
- return GIT_ENOTFOUND;
- }
-
- type = odb_obj->raw.type;
-
- if (create_object(&object, type) < 0) {
- git_odb_object_free(odb_obj);
- return -1;
- }
-
- /* Initialize parent object */
- git_oid_cpy(&object->cached.oid, &odb_obj->cached.oid);
- object->repo = repo;
-
- switch (type) {
- case GIT_OBJ_COMMIT:
- error = git_commit__parse((git_commit *)object, odb_obj);
- break;
-
- case GIT_OBJ_TREE:
- error = git_tree__parse((git_tree *)object, odb_obj);
- break;
-
- case GIT_OBJ_TAG:
- error = git_tag__parse((git_tag *)object, odb_obj);
- break;
-
- case GIT_OBJ_BLOB:
- error = git_blob__parse((git_blob *)object, odb_obj);
- break;
-
- default:
- break;
- }
+ error = git_object__from_odb_object(object_out, repo, odb_obj, type);
git_odb_object_free(odb_obj);
- if (error < 0) {
- git_object__free(object);
- return -1;
- }
-
- *object_out = git_cache_try_store(&repo->objects, object);
- return 0;
+ return error;
}
int git_object_lookup(git_object **object_out, git_repository *repo, const git_oid *id, git_otype type) {