diff options
Diffstat (limited to 'src/object.c')
-rw-r--r-- | src/object.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/object.c b/src/object.c index c53a3acae..c9809c52a 100644 --- a/src/object.c +++ b/src/object.c @@ -209,6 +209,125 @@ void git_object__source_close(git_object *object) } } +static int create_object(git_object **object_out, git_otype type) +{ + git_object *object = NULL; + + assert(object_out); + + *object_out = NULL; + + switch (type) { + case GIT_OBJ_COMMIT: + case GIT_OBJ_TAG: + case GIT_OBJ_BLOB: + object = git__malloc(git_object__size(type)); + if (object == NULL) + return GIT_ENOMEM; + memset(object, 0x0, git_object__size(type)); + break; + + case GIT_OBJ_TREE: + object = (git_object *)git_tree__new(); + if (object == NULL) + return GIT_ENOMEM; + break; + + default: + return GIT_EINVALIDTYPE; + } + + *object_out = object; + return GIT_SUCCESS; +} + +int git_object_new(git_object **object_out, git_repository *repo, git_otype type) +{ + git_object *object = NULL; + int error; + + assert(object_out && repo); + + if ((error = create_object(&object, type)) < GIT_SUCCESS) + return error; + + object->repo = repo; + object->in_memory = 1; + object->modified = 1; + + object->source.raw.type = type; + + *object_out = object; + return GIT_SUCCESS; +} + +int git_object_lookup(git_object **object_out, git_repository *repo, const git_oid *id, git_otype type) +{ + git_object *object = NULL; + git_rawobj obj_file; + int error = GIT_SUCCESS; + + assert(repo && object_out && id); + + object = git_hashtable_lookup(repo->objects, id); + if (object != NULL) { + *object_out = object; + return GIT_SUCCESS; + } + + error = git_odb_read(&obj_file, repo->db, id); + if (error < GIT_SUCCESS) + return error; + + if (type != GIT_OBJ_ANY && type != obj_file.type) { + git_rawobj_close(&obj_file); + return GIT_EINVALIDTYPE; + } + + type = obj_file.type; + + if ((error = create_object(&object, type)) < GIT_SUCCESS) + return error; + + /* Initialize parent object */ + git_oid_cpy(&object->id, id); + object->repo = repo; + memcpy(&object->source.raw, &obj_file, sizeof(git_rawobj)); + object->source.open = 1; + + switch (type) { + case GIT_OBJ_COMMIT: + error = git_commit__parse((git_commit *)object); + break; + + case GIT_OBJ_TREE: + error = git_tree__parse((git_tree *)object); + break; + + case GIT_OBJ_TAG: + error = git_tag__parse((git_tag *)object); + break; + + case GIT_OBJ_BLOB: + error = git_blob__parse((git_blob *)object); + break; + + default: + break; + } + + if (error < GIT_SUCCESS) { + git_object_free(object); + return error; + } + + git_object__source_close(object); + git_hashtable_insert(repo->objects, &object->id, object); + + *object_out = object; + return GIT_SUCCESS; +} + int git_object_write(git_object *object) { int error; |