summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/diff_output.c13
-rw-r--r--src/object.c98
-rw-r--r--src/object.h39
-rw-r--r--src/odb.c24
-rw-r--r--src/odb.h8
-rw-r--r--src/repository.h25
6 files changed, 135 insertions, 72 deletions
diff --git a/src/diff_output.c b/src/diff_output.c
index 8873a4dc7..dbef7ddc1 100644
--- a/src/diff_output.c
+++ b/src/diff_output.c
@@ -292,6 +292,7 @@ static int get_blob_content(
git_blob **blob)
{
int error;
+ git_odb_object *odb_obj = NULL;
if (git_oid_iszero(&file->oid))
return 0;
@@ -303,7 +304,8 @@ static int get_blob_content(
/* peek at object header to avoid loading if too large */
if ((error = git_repository_odb__weakptr(&odb, ctxt->repo)) < 0 ||
- (error = git_odb_read_header(&len, &type, odb, &file->oid)) < 0)
+ (error = git_odb__read_header_or_object(
+ &odb_obj, &len, &type, odb, &file->oid)) < 0)
return error;
assert(type == GIT_OBJ_BLOB);
@@ -317,7 +319,14 @@ static int get_blob_content(
if (ctxt->delta->binary == 1)
return 0;
- if ((error = git_blob_lookup(blob, ctxt->repo, &file->oid)) < 0)
+ if (odb_obj != NULL) {
+ error = git_object__from_odb_object(
+ (git_object **)blob, ctxt->repo, odb_obj, GIT_OBJ_BLOB);
+ git_odb_object_free(odb_obj);
+ } else
+ error = git_blob_lookup(blob, ctxt->repo, &file->oid);
+
+ if (error)
return error;
map->data = (void *)git_blob_rawcontent(*blob);
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) {
diff --git a/src/object.h b/src/object.h
new file mode 100644
index 000000000..bc12aad04
--- /dev/null
+++ b/src/object.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009-2012 the libgit2 contributors
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_object_h__
+#define INCLUDE_object_h__
+
+/** Base git object for inheritance */
+struct git_object {
+ git_cached_obj cached;
+ git_repository *repo;
+ git_otype type;
+};
+
+/* fully free the object; internal method, DO NOT EXPORT */
+void git_object__free(void *object);
+
+GIT_INLINE(int) git_object__dup(git_object **dest, git_object *source)
+{
+ git_cached_obj_incref(source);
+ *dest = source;
+ return 0;
+}
+
+int git_object__from_odb_object(
+ git_object **object_out,
+ git_repository *repo,
+ git_odb_object *odb_obj,
+ git_otype type);
+
+int git_object__resolve_to_type(git_object **obj, git_otype type);
+
+int git_oid__parse(git_oid *oid, const char **buffer_out, const char *buffer_end, const char *header);
+
+void git_oid__writebuf(git_buf *buf, const char *header, const git_oid *oid);
+
+#endif
diff --git a/src/odb.c b/src/odb.c
index 83c7a80fc..0e03e40ee 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -514,19 +514,36 @@ int git_odb_exists(git_odb *db, const git_oid *id)
int git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *db, const git_oid *id)
{
+ int error;
+ git_odb_object *object;
+
+ error = git_odb__read_header_or_object(&object, len_p, type_p, db, id);
+
+ if (object)
+ git_odb_object_free(object);
+
+ return error;
+}
+
+int git_odb__read_header_or_object(
+ git_odb_object **out, size_t *len_p, git_otype *type_p,
+ git_odb *db, const git_oid *id)
+{
unsigned int i;
int error = GIT_ENOTFOUND;
git_odb_object *object;
- assert(db && id);
+ assert(db && id && out && len_p && type_p);
if ((object = git_cache_get(&db->cache, id)) != NULL) {
*len_p = object->raw.len;
*type_p = object->raw.type;
- git_odb_object_free(object);
+ *out = object;
return 0;
}
+ *out = NULL;
+
for (i = 0; i < db->backends.length && error < 0; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *b = internal->backend;
@@ -547,7 +564,8 @@ int git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *db, const git
*len_p = object->raw.len;
*type_p = object->raw.type;
- git_odb_object_free(object);
+ *out = object;
+
return 0;
}
diff --git a/src/odb.h b/src/odb.h
index 696e12943..e9e33dde8 100644
--- a/src/odb.h
+++ b/src/odb.h
@@ -84,4 +84,12 @@ int git_odb__error_notfound(const char *message, const git_oid *oid);
*/
int git_odb__error_ambiguous(const char *message);
+/*
+ * Attempt to read object header or just return whole object if it could
+ * not be read.
+ */
+int git_odb__read_header_or_object(
+ git_odb_object **out, size_t *len_p, git_otype *type_p,
+ git_odb *db, const git_oid *id);
+
#endif
diff --git a/src/repository.h b/src/repository.h
index 4695edf3a..82988ba0a 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -18,6 +18,7 @@
#include "refs.h"
#include "buffer.h"
#include "odb.h"
+#include "object.h"
#include "attr.h"
#include "strmap.h"
@@ -75,13 +76,6 @@ enum {
GIT_REPOSITORY_INIT__IS_REINIT = (1u << 18),
};
-/** Base git object for inheritance */
-struct git_object {
- git_cached_obj cached;
- git_repository *repo;
- git_otype type;
-};
-
/** Internal structure for repository object */
struct git_repository {
git_odb *_odb;
@@ -102,21 +96,6 @@ struct git_repository {
git_cvar_value cvar_cache[GIT_CVAR_CACHE_MAX];
};
-/* fully free the object; internal method, DO NOT EXPORT */
-void git_object__free(void *object);
-
-GIT_INLINE(int) git_object__dup(git_object **dest, git_object *source)
-{
- git_cached_obj_incref(source);
- *dest = source;
- return 0;
-}
-
-int git_object__resolve_to_type(git_object **obj, git_otype type);
-
-int git_oid__parse(git_oid *oid, const char **buffer_out, const char *buffer_end, const char *header);
-void git_oid__writebuf(git_buf *buf, const char *header, const git_oid *oid);
-
GIT_INLINE(git_attr_cache *) git_repository_attr_cache(git_repository *repo)
{
return &repo->attrcache;
@@ -136,7 +115,7 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo);
int git_repository_index__weakptr(git_index **out, git_repository *repo);
/*
- * CVAR cache
+ * CVAR cache
*
* Efficient access to the most used config variables of a repository.
* The cache is cleared everytime the config backend is replaced.