diff options
| -rw-r--r-- | src/object.c | 65 | ||||
| -rw-r--r-- | src/object.h | 11 |
2 files changed, 68 insertions, 8 deletions
diff --git a/src/object.c b/src/object.c index 48f561384..c1f3ea919 100644 --- a/src/object.c +++ b/src/object.c @@ -12,6 +12,7 @@ #include "repository.h" #include "commit.h" +#include "hash.h" #include "tree.h" #include "blob.h" #include "oid.h" @@ -19,38 +20,86 @@ bool git_object__strict_input_validation = true; +extern int git_odb_hash(git_oid *out, const void *data, size_t len, git_otype type); + typedef struct { const char *str; /* type name string */ size_t size; /* size in bytes of the object structure */ int (*parse)(void *self, git_odb_object *obj); + int (*parse_raw)(void *self, const char *data, size_t size); void (*free)(void *self); } git_object_def; static git_object_def git_objects_table[] = { /* 0 = GIT_OBJ__EXT1 */ - { "", 0, NULL, NULL }, + { "", 0, NULL, NULL, NULL }, /* 1 = GIT_OBJ_COMMIT */ - { "commit", sizeof(git_commit), git_commit__parse, git_commit__free }, + { "commit", sizeof(git_commit), git_commit__parse, git_commit__parse_raw, git_commit__free }, /* 2 = GIT_OBJ_TREE */ - { "tree", sizeof(git_tree), git_tree__parse, git_tree__free }, + { "tree", sizeof(git_tree), git_tree__parse, git_tree__parse_raw, git_tree__free }, /* 3 = GIT_OBJ_BLOB */ - { "blob", sizeof(git_blob), git_blob__parse, git_blob__free }, + { "blob", sizeof(git_blob), git_blob__parse, git_blob__parse_raw, git_blob__free }, /* 4 = GIT_OBJ_TAG */ - { "tag", sizeof(git_tag), git_tag__parse, git_tag__free }, + { "tag", sizeof(git_tag), git_tag__parse, git_tag__parse_raw, git_tag__free }, /* 5 = GIT_OBJ__EXT2 */ - { "", 0, NULL, NULL }, + { "", 0, NULL, NULL, NULL }, /* 6 = GIT_OBJ_OFS_DELTA */ - { "OFS_DELTA", 0, NULL, NULL }, + { "OFS_DELTA", 0, NULL, NULL, NULL }, /* 7 = GIT_OBJ_REF_DELTA */ - { "REF_DELTA", 0, NULL, NULL }, + { "REF_DELTA", 0, NULL, NULL, NULL }, }; +int git_object__from_raw( + git_object **object_out, + const char *data, + size_t size, + git_otype type) +{ + git_object_def *def; + git_object *object; + size_t object_size; + int error; + + assert(object_out); + *object_out = NULL; + + /* Validate type match */ + if (type != GIT_OBJ_BLOB && type != GIT_OBJ_TREE && type != GIT_OBJ_COMMIT && type != GIT_OBJ_TAG) { + giterr_set(GITERR_INVALID, "the requested type is invalid"); + return GIT_ENOTFOUND; + } + + if ((object_size = git_object__size(type)) == 0) { + giterr_set(GITERR_INVALID, "the requested type is invalid"); + return GIT_ENOTFOUND; + } + + /* Allocate and initialize base object */ + object = git__calloc(1, object_size); + GITERR_CHECK_ALLOC(object); + object->cached.flags = GIT_CACHE_STORE_PARSED; + object->cached.type = type; + git_odb_hash(&object->cached.oid, data, size, type); + + /* Parse raw object data */ + def = &git_objects_table[type]; + assert(def->free && def->parse_raw); + + if ((error = def->parse_raw(object, data, size)) < 0) + def->free(object); + + git_cached_obj_incref(object); + *object_out = object; + + return 0; +} + int git_object__from_odb_object( git_object **object_out, git_repository *repo, diff --git a/src/object.h b/src/object.h index e46c9cafa..f5cbbf763 100644 --- a/src/object.h +++ b/src/object.h @@ -22,6 +22,17 @@ struct git_object { /* fully free the object; internal method, DO NOT EXPORT */ void git_object__free(void *object); +/* + * Parse object from raw data. Note that the resulting object is + * tied to the lifetime of the data, as some objects simply point + * into it. + */ +int git_object__from_raw( + git_object **object_out, + const char *data, + size_t size, + git_otype type); + int git_object__from_odb_object( git_object **object_out, git_repository *repo, |
