diff options
author | Vicent Marti <tanoku@gmail.com> | 2010-09-20 21:39:11 +0300 |
---|---|---|
committer | Vicent Marti <tanoku@gmail.com> | 2010-09-20 21:39:11 +0300 |
commit | d45b4a9a1bcbb157a4f02cf5ed23fde5222db9c8 (patch) | |
tree | 554847491982e4256559938b1dab33730b2cffcb /src | |
parent | 0c3596f18a6f07d8a61f8d6e2fd730a276a51599 (diff) | |
download | libgit2-d45b4a9a1bcbb157a4f02cf5ed23fde5222db9c8.tar.gz |
Add support for in-memory objects
All repository objects can now be created from scratch in memory using
either the git_object_new() method, or the corresponding git_XXX_new()
for each object.
So far, only git_commits can be written back to disk once created in
memory.
Signed-off-by: Vicent Marti <tanoku@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/commit.c | 7 | ||||
-rw-r--r-- | src/git/commit.h | 12 | ||||
-rw-r--r-- | src/git/repository.h | 44 | ||||
-rw-r--r-- | src/git/tag.h | 12 | ||||
-rw-r--r-- | src/git/tree.h | 12 | ||||
-rw-r--r-- | src/repository.c | 77 | ||||
-rw-r--r-- | src/repository.h | 4 | ||||
-rw-r--r-- | src/tag.c | 9 | ||||
-rw-r--r-- | src/tree.c | 9 |
9 files changed, 157 insertions, 29 deletions
diff --git a/src/commit.c b/src/commit.c index 7cb8f24f8..90a30e020 100644 --- a/src/commit.c +++ b/src/commit.c @@ -63,9 +63,14 @@ void git_commit__free(git_commit *commit) free(commit); } +git_commit *git_commit_new(git_repository *repo) +{ + return (git_commit *)git_object_new(repo, GIT_OBJ_COMMIT); +} + const git_oid *git_commit_id(git_commit *c) { - return &c->object.id; + return git_object_id((git_object *)c); } int git_commit__parse(git_commit *commit) diff --git a/src/git/commit.h b/src/git/commit.h index 4387925da..a584273a1 100644 --- a/src/git/commit.h +++ b/src/git/commit.h @@ -30,6 +30,18 @@ typedef struct git_commit git_commit; */ GIT_EXTERN(git_commit *) git_commit_lookup(git_repository *repo, const git_oid *id); +/* + * Create a new in-memory git_commit. + * + * The commit object must be manually filled using + * setter methods before it can be written to its + * repository. + * + * @param repo The repository where the object will reside + * @return the object if creation was posible; NULL otherwise + */ +GIT_EXTERN(git_commit *) git_commit_new(git_repository *repo); + /** * Get the id of a commit. * @param commit a previously loaded commit. diff --git a/src/git/repository.h b/src/git/repository.h index 33bb2fcef..9417d7b51 100644 --- a/src/git/repository.h +++ b/src/git/repository.h @@ -57,9 +57,53 @@ GIT_EXTERN(git_object *) git_repository_lookup(git_repository *repo, const git_o */ GIT_EXTERN(git_odb *) git_repository_database(git_repository *repo); +/* + * Create a new in-memory repository object with + * the given type. + * + * The object's attributes can be filled in using the + * correspondign setter methods. + * + * The object will be written back to given git_repository + * when the git_object_write() function is called; objects + * cannot be written to disk until all their main + * attributes have been properly filled. + * + * Objects are instantiated with no SHA1 id; their id + * will be automatically generated when writing to the + * repository. + * + * @parem repo Repository where the object belongs + * @param type Type of the object to be created + * @return the new object + */ +GIT_EXTERN(git_object *) git_object_new(git_repository *repo, git_otype type); + +/* + * Write back an object to disk. + * + * The object will be written to its corresponding + * repository. + * + * If the object has no changes since it was first + * read from the repository, no actions will take place. + * + * If the object has been modified since it was read from + * the repository, or it has been created from scratch + * in memory, it will be written to the repository and + * its SHA1 ID will be updated accordingly. + * + * @param object Git object to write back + * @return 0 on success; otherwise an error code + */ +int git_object_write(git_object *object); + /** * Get the id (SHA1) of a repository object * + * In-memory objects created by git_object_new() do not + * have a SHA1 ID until they are written on a repository. + * * @param obj the repository object * @return the SHA1 id */ diff --git a/src/git/tag.h b/src/git/tag.h index a6efabb0e..33e3d6f26 100644 --- a/src/git/tag.h +++ b/src/git/tag.h @@ -29,6 +29,18 @@ typedef struct git_tag git_tag; */ GIT_EXTERN(git_tag *) git_tag_lookup(git_repository *repo, const git_oid *id); +/* + * Create a new in-memory git_tag. + * + * The tag object must be manually filled using + * setter methods before it can be written to its + * repository. + * + * @param repo The repository where the object will reside + * @return the object if creation was posible; NULL otherwise + */ +GIT_EXTERN(git_tag *) git_tag_new(git_repository *repo); + /** * Get the id of a tag. * @param tag a previously loaded tag. diff --git a/src/git/tree.h b/src/git/tree.h index 646c085bb..32fd6527a 100644 --- a/src/git/tree.h +++ b/src/git/tree.h @@ -32,6 +32,18 @@ typedef struct git_tree git_tree; */ GIT_EXTERN(git_tree *) git_tree_lookup(git_repository *repo, const git_oid *id); +/* + * Create a new in-memory git_tree. + * + * The tree object must be manually filled using + * setter methods before it can be written to its + * repository. + * + * @param repo The repository where the object will reside + * @return the object if creation was posible; NULL otherwise + */ +GIT_EXTERN(git_tree *) git_tree_new(git_repository *repo); + /** * Get the id of a tree. * @param tree a previously loaded tree. diff --git a/src/repository.c b/src/repository.c index f353ce06b..dc1fe0e9d 100644 --- a/src/repository.c +++ b/src/repository.c @@ -32,6 +32,15 @@ static const int default_table_size = 32; static const double max_load_factor = 0.65; +static const size_t object_sizes[] = { + 0, + sizeof(git_commit), + sizeof(git_tree), + sizeof(git_object), /* TODO: sizeof(git_blob) */ + sizeof(git_tag) +}; + + uint32_t git_object_hash(const void *key) { uint32_t r; @@ -160,7 +169,7 @@ int git__source_write(git_odb_source *source, const void *bytes, size_t len) return GIT_SUCCESS; } -void git_object__source_prepare_write(git_object *object) +static void prepare_write(git_object *object) { const size_t base_size = 4096; /* 4Kb base size */ @@ -175,10 +184,9 @@ void git_object__source_prepare_write(git_object *object) object->source.written_bytes = 0; object->source.open = 1; - object->source.out_of_sync = 1; } -int git_object__source_writeback(git_object *object) +static int write_back(git_object *object) { int error; git_oid new_id; @@ -188,8 +196,7 @@ int git_object__source_writeback(git_object *object) if (!object->source.open) return GIT_ERROR; - if (!object->source.out_of_sync) - return GIT_SUCCESS; + assert(object->modified); object->source.raw.len = object->source.written_bytes; @@ -198,7 +205,9 @@ int git_object__source_writeback(git_object *object) if ((error = git_odb_write(&new_id, object->repo->db, &object->source.raw)) < 0) return error; - git_hashtable_remove(object->repo->objects, &object->id); + if (!object->in_memory) + git_hashtable_remove(object->repo->objects, &object->id); + git_oid_cpy(&object->id, &new_id); git_hashtable_insert(object->repo->objects, &object->id, object); @@ -206,6 +215,7 @@ int git_object__source_writeback(git_object *object) object->source.written_bytes = 0; object->modified = 0; + object->in_memory = 0; git_object__source_close(object); return GIT_SUCCESS; @@ -215,9 +225,9 @@ int git_object__source_open(git_object *object) { int error; - assert(object); + assert(object && !object->in_memory); - if (object->source.open && object->source.out_of_sync) + if (object->source.open) git_object__source_close(object); if (object->source.open) @@ -228,7 +238,6 @@ int git_object__source_open(git_object *object) return error; object->source.open = 1; - object->source.out_of_sync = 0; return GIT_SUCCESS; } @@ -239,7 +248,6 @@ void git_object__source_close(git_object *object) if (!object->source.open) { git_obj_close(&object->source.raw); object->source.open = 0; - object->source.out_of_sync = 0; } } @@ -253,7 +261,7 @@ int git_object_write(git_object *object) if (object->modified == 0) return GIT_SUCCESS; - git_object__source_prepare_write(object); + prepare_write(object); source = &object->source; switch (source->raw.type) { @@ -265,14 +273,15 @@ int git_object_write(git_object *object) case GIT_OBJ_TAG: default: error = GIT_ERROR; + break; } if (error < 0) { git_object__source_close(object); return error; } - - return git_object__source_writeback(object); + + return write_back(object); } void git_object_free(git_object *object) @@ -310,6 +319,10 @@ git_odb *git_repository_database(git_repository *repo) const git_oid *git_object_id(git_object *obj) { assert(obj); + + if (obj->in_memory) + return NULL; + return &obj->id; } @@ -319,16 +332,38 @@ git_otype git_object_type(git_object *obj) return obj->source.raw.type; } -git_object *git_repository_lookup(git_repository *repo, const git_oid *id, git_otype type) +git_object *git_object_new(git_repository *repo, git_otype type) { - static const size_t object_sizes[] = { - 0, - sizeof(git_commit), - sizeof(git_tree), - sizeof(git_object), /* TODO: sizeof(git_blob) */ - sizeof(git_tag) - }; + git_object *object = NULL; + switch (type) { + case GIT_OBJ_COMMIT: + case GIT_OBJ_TAG: + case GIT_OBJ_TREE: + case GIT_OBJ_BLOB: + break; + + default: + return NULL; + } + + object = git__malloc(object_sizes[type]); + + if (object == NULL) + return NULL; + + memset(object, 0x0, object_sizes[type]); + object->repo = repo; + object->in_memory = 1; + object->modified = 1; + + object->source.raw.type = type; + + return object; +} + +git_object *git_repository_lookup(git_repository *repo, const git_oid *id, git_otype type) +{ git_object *object = NULL; git_rawobj obj_file; diff --git a/src/repository.h b/src/repository.h index 5074c614e..9a7bd24b8 100644 --- a/src/repository.h +++ b/src/repository.h @@ -12,7 +12,7 @@ typedef struct { git_rawobj raw; void *write_ptr; size_t written_bytes; - int open:1, out_of_sync:1; + int open:1; } git_odb_source; struct git_object { @@ -30,8 +30,6 @@ struct git_repository { int git_object__source_open(git_object *object); void git_object__source_close(git_object *object); -void git_object__source_prepare_write(git_object *object); -int git_object__source_writeback(git_object *object); int git__source_printf(git_odb_source *source, const char *format, ...); int git__source_write(git_odb_source *source, const void *bytes, size_t len); @@ -38,9 +38,14 @@ void git_tag__free(git_tag *tag) free(tag); } -const git_oid *git_tag_id(git_tag *t) +git_tag *git_tag_new(git_repository *repo) { - return &t->object.id; + return (git_tag *)git_object_new(repo, GIT_OBJ_TAG); +} + +const git_oid *git_tag_id(git_tag *c) +{ + return git_object_id((git_object *)c); } const git_object *git_tag_target(git_tag *t) diff --git a/src/tree.c b/src/tree.c index f1c191c32..670f99838 100644 --- a/src/tree.c +++ b/src/tree.c @@ -40,9 +40,14 @@ void git_tree__free(git_tree *tree) free(tree); } -const git_oid *git_tree_id(git_tree *tree) +git_tree *git_tree_new(git_repository *repo) { - return &tree->object.id; + return (git_tree *)git_object_new(repo, GIT_OBJ_TREE); +} + +const git_oid *git_tree_id(git_tree *c) +{ + return git_object_id((git_object *)c); } git_tree *git_tree_lookup(git_repository *repo, const git_oid *id) |