summaryrefslogtreecommitdiff
path: root/src/commit.c
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2011-03-18 19:38:49 +0200
committerVicent Marti <tanoku@gmail.com>2011-03-20 21:45:11 +0200
commit72a3fe42fb7208712bbe8f0981f4c6274c05e9c3 (patch)
treeb073a1c36b3215d94b1e78a0f294d7aa30d949df /src/commit.c
parentbb3de0c472b2d5d6b8091c190bee3db79c4b5e27 (diff)
downloadlibgit2-72a3fe42fb7208712bbe8f0981f4c6274c05e9c3.tar.gz
I broke your bindings
Hey. Apologies in advance -- I broke your bindings. This is a major commit that includes a long-overdue redesign of the whole object-database structure. This is expected to be the last major external API redesign of the library until the first non-alpha release. Please get your bindings up to date with these changes. They will be included in the next minor release. Sorry again! Major features include: - Real caching and refcounting on parsed objects - Real caching and refcounting on objects read from the ODB - Streaming writes & reads from the ODB - Single-method writes for all object types - The external API is now partially thread-safe The speed increases are significant in all aspects, specially when reading an object several times from the ODB (revwalking) and when writing big objects to the ODB. Here's a full changelog for the external API: blob.h ------ - Remove `git_blob_new` - Remove `git_blob_set_rawcontent` - Remove `git_blob_set_rawcontent_fromfile` - Rename `git_blob_writefile` -> `git_blob_create_fromfile` - Change `git_blob_create_fromfile`: The `path` argument is now relative to the repository's working dir - Add `git_blob_create_frombuffer` commit.h -------- - Remove `git_commit_new` - Remove `git_commit_add_parent` - Remove `git_commit_set_message` - Remove `git_commit_set_committer` - Remove `git_commit_set_author` - Remove `git_commit_set_tree` - Add `git_commit_create` - Add `git_commit_create_v` - Add `git_commit_create_o` - Add `git_commit_create_ov` tag.h ----- - Remove `git_tag_new` - Remove `git_tag_set_target` - Remove `git_tag_set_name` - Remove `git_tag_set_tagger` - Remove `git_tag_set_message` - Add `git_tag_create` - Add `git_tag_create_o` tree.h ------ - Change `git_tree_entry_2object`: New signature is `(git_object **object_out, git_repository *repo, git_tree_entry *entry)` - Remove `git_tree_new` - Remove `git_tree_add_entry` - Remove `git_tree_remove_entry_byindex` - Remove `git_tree_remove_entry_byname` - Remove `git_tree_clearentries` - Remove `git_tree_entry_set_id` - Remove `git_tree_entry_set_name` - Remove `git_tree_entry_set_attributes` object.h ------------ - Remove `git_object_new - Remove `git_object_write` - Change `git_object_close`: This method is now *mandatory*. Not closing an object causes a memory leak. odb.h ----- - Remove type `git_rawobj` - Remove `git_rawobj_close` - Rename `git_rawobj_hash` -> `git_odb_hash` - Change `git_odb_hash`: New signature is `(git_oid *id, const void *data, size_t len, git_otype type)` - Add type `git_odb_object` - Add `git_odb_object_close` - Change `git_odb_read`: New signature is `(git_odb_object **out, git_odb *db, const git_oid *id)` - Change `git_odb_read_header`: New signature is `(size_t *len_p, git_otype *type_p, git_odb *db, const git_oid *id)` - Remove `git_odb_write` - Add `git_odb_open_wstream` - Add `git_odb_open_rstream` odb_backend.h ------------- - Change type `git_odb_backend`: New internal signatures are as follows int (* read)(void **, size_t *, git_otype *, struct git_odb_backend *, const git_oid *) int (* read_header)(size_t *, git_otype *, struct git_odb_backend *, const git_oid *) int (* writestream)(struct git_odb_stream **, struct git_odb_backend *, size_t, git_otype) int (* readstream)( struct git_odb_stream **, struct git_odb_backend *, const git_oid *) - Add type `git_odb_stream` - Add enum `git_odb_streammode` Signed-off-by: Vicent Marti <tanoku@gmail.com>
Diffstat (limited to 'src/commit.c')
-rw-r--r--src/commit.c268
1 files changed, 155 insertions, 113 deletions
diff --git a/src/commit.c b/src/commit.c
index 8da170ca..2670c2e0 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -29,9 +29,12 @@
#include "git2/signature.h"
#include "common.h"
+#include "odb.h"
#include "commit.h"
#include "signature.h"
+#include <stdarg.h>
+
#define COMMIT_BASIC_PARSE 0x0
#define COMMIT_FULL_PARSE 0x1
@@ -71,35 +74,165 @@ const git_oid *git_commit_id(git_commit *c)
return git_object_id((git_object *)c);
}
-int git_commit__writeback(git_commit *commit, git_odb_source *src)
+
+int git_commit_create_v(
+ git_oid *oid,
+ git_repository *repo,
+ const char *update_ref,
+ const git_signature *author,
+ const git_signature *committer,
+ const char *message,
+ const git_oid *tree_oid,
+ int parent_count,
+ ...)
{
- unsigned int i;
+ va_list ap;
+ int i, error;
+ const git_oid **oids;
- git__write_oid(src, "tree", &commit->tree_oid);
+ oids = git__malloc(parent_count * sizeof(git_oid *));
- for (i = 0; i < commit->parent_oids.length; ++i) {
- git_oid *parent_oid;
+ va_start(ap, parent_count);
+ for (i = 0; i < parent_count; ++i)
+ oids[i] = va_arg(ap, const git_oid *);
+ va_end(ap);
- parent_oid = git_vector_get(&commit->parent_oids, i);
- git__write_oid(src, "parent", parent_oid);
- }
+ error = git_commit_create(
+ oid, repo, update_ref, author, committer, message,
+ tree_oid, parent_count, oids);
+
+ free(oids);
+ return error;
+}
+
+int git_commit_create_ov(
+ git_oid *oid,
+ git_repository *repo,
+ const char *update_ref,
+ const git_signature *author,
+ const git_signature *committer,
+ const char *message,
+ const git_tree *tree,
+ int parent_count,
+ ...)
+{
+ va_list ap;
+ int i, error;
+ const git_oid **oids;
+
+ oids = git__malloc(parent_count * sizeof(git_oid *));
+
+ va_start(ap, parent_count);
+ for (i = 0; i < parent_count; ++i)
+ oids[i] = git_object_id(va_arg(ap, const git_object *));
+ va_end(ap);
+
+ error = git_commit_create(
+ oid, repo, update_ref, author, committer, message,
+ git_object_id((git_object *)tree),
+ parent_count, oids);
+
+ free(oids);
+ return error;
+}
+
+int git_commit_create_o(
+ git_oid *oid,
+ git_repository *repo,
+ const char *update_ref,
+ const git_signature *author,
+ const git_signature *committer,
+ const char *message,
+ const git_tree *tree,
+ int parent_count,
+ const git_commit *parents[])
+{
+ int i, error;
+ const git_oid **oids;
+
+ oids = git__malloc(parent_count * sizeof(git_oid *));
+
+ for (i = 0; i < parent_count; ++i)
+ oids[i] = git_object_id((git_object *)parents[i]);
+
+ error = git_commit_create(
+ oid, repo, update_ref, author, committer, message,
+ git_object_id((git_object *)tree),
+ parent_count, oids);
+
+ free(oids);
+ return error;
+}
- if (commit->author == NULL)
- return GIT_EMISSINGOBJDATA;
+int git_commit_create(
+ git_oid *oid,
+ git_repository *repo,
+ const char *update_ref,
+ const git_signature *author,
+ const git_signature *committer,
+ const char *message,
+ const git_oid *tree_oid,
+ int parent_count,
+ const git_oid *parents[])
+{
+ size_t final_size = 0;
+ int message_length, author_length, committer_length;
+
+ char *author_str, *committer_str;
+
+ int error, i;
+ git_odb_stream *stream;
+
+ message_length = strlen(message);
+ author_length = git_signature__write(&author_str, "author", author);
+ committer_length = git_signature__write(&committer_str, "committer", committer);
+
+ if (author_length < 0 || committer_length < 0)
+ return GIT_ENOMEM;
+
+ final_size += GIT_OID_LINE_LENGTH("tree");
+ final_size += GIT_OID_LINE_LENGTH("parent") * parent_count;
+ final_size += author_length;
+ final_size += committer_length;
+ final_size += 1 + message_length;
+
+ if ((error = git_odb_open_wstream(&stream, repo->db, final_size, GIT_OBJ_COMMIT)) < GIT_SUCCESS)
+ return error;
+
+ git__write_oid(stream, "tree", tree_oid);
- git_signature__write(src, "author", commit->author);
+ for (i = 0; i < parent_count; ++i)
+ git__write_oid(stream, "parent", parents[i]);
- if (commit->committer == NULL)
- return GIT_EMISSINGOBJDATA;
+ stream->write(stream, author_str, author_length);
+ free(author_str);
- git_signature__write(src, "committer", commit->committer);
+ stream->write(stream, committer_str, committer_length);
+ free(committer_str);
- if (commit->message != NULL) {
- git__source_write(src, "\n", 1);
- git__source_write(src, commit->message, strlen(commit->message));
+
+ stream->write(stream, "\n", 1);
+ stream->write(stream, message, message_length);
+
+ error = stream->finalize_write(oid, stream);
+ stream->free(stream);
+
+ if (error == GIT_SUCCESS && update_ref != NULL) {
+ git_reference *head;
+
+ error = git_reference_lookup(&head, repo, update_ref);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ if (git_reference_type(head) == GIT_REF_SYMBOLIC) {
+ if ((error = git_reference_resolve(&head, head)) < GIT_SUCCESS)
+ return error;
+ }
+
+ error = git_reference_set_oid(head, oid);
}
- return GIT_SUCCESS;
+ return error;
}
int commit_parse_buffer(git_commit *commit, void *data, size_t len)
@@ -110,12 +243,7 @@ int commit_parse_buffer(git_commit *commit, void *data, size_t len)
git_oid parent_oid;
int error;
- /* first parse; the vector hasn't been initialized yet */
- if (commit->parent_oids.contents == NULL) {
- git_vector_init(&commit->parent_oids, 4, NULL);
- }
-
- clear_parents(commit);
+ git_vector_init(&commit->parent_oids, 4, NULL);
if ((error = git__parse_oid(&commit->tree_oid, &buffer, buffer_end, "tree ")) < GIT_SUCCESS)
return error;
@@ -134,17 +262,11 @@ int commit_parse_buffer(git_commit *commit, void *data, size_t len)
return GIT_ENOMEM;
}
- if (commit->author)
- git_signature_free(commit->author);
-
commit->author = git__malloc(sizeof(git_signature));
if ((error = git_signature__parse(commit->author, &buffer, buffer_end, "author ")) < GIT_SUCCESS)
return error;
/* Always parse the committer; we need the commit time */
- if (commit->committer)
- git_signature_free(commit->committer);
-
commit->committer = git__malloc(sizeof(git_signature));
if ((error = git_signature__parse(commit->committer, &buffer, buffer_end, "committer ")) < GIT_SUCCESS)
return error;
@@ -176,11 +298,10 @@ int commit_parse_buffer(git_commit *commit, void *data, size_t len)
return GIT_SUCCESS;
}
-int git_commit__parse(git_commit *commit)
+int git_commit__parse(git_commit *commit, git_odb_object *obj)
{
- assert(commit && commit->object.source.open);
- return commit_parse_buffer(commit,
- commit->object.source.raw.data, commit->object.source.raw.len);
+ assert(commit);
+ return commit_parse_buffer(commit, obj->raw.data, obj->raw.len);
}
#define GIT_COMMIT_GETTER(_rvalue, _name, _return) \
@@ -218,82 +339,3 @@ int git_commit_parent(git_commit **parent, git_commit *commit, unsigned int n)
}
-
-int git_commit_set_tree(git_commit *commit, git_tree *tree)
-{
- const git_oid *oid;
-
- assert(commit && tree);
-
- if ((oid = git_object_id((git_object *)tree)) == NULL)
- return GIT_EMISSINGOBJDATA;
-
- commit->object.modified = 1;
- git_oid_cpy(&commit->tree_oid, oid);
- return GIT_SUCCESS;
-}
-
-int git_commit_add_parent(git_commit *commit, git_commit *new_parent)
-{
- const git_oid *parent_oid;
- git_oid *new_oid;
- assert(commit && new_parent);
-
- if ((parent_oid = git_object_id((git_object *)new_parent)) == NULL)
- return GIT_EMISSINGOBJDATA;
-
- new_oid = git__malloc(sizeof(git_oid));
- if (new_oid == NULL)
- return GIT_ENOMEM;
-
- commit->object.modified = 1;
- git_oid_cpy(new_oid, parent_oid);
- return git_vector_insert(&commit->parent_oids, new_oid);
-}
-
-void git_commit_set_author(git_commit *commit, const git_signature *author_sig)
-{
- assert(commit && author_sig);
- commit->object.modified = 1;
-
- git_signature_free(commit->author);
- commit->author = git_signature_dup(author_sig);
-}
-
-void git_commit_set_committer(git_commit *commit, const git_signature *committer_sig)
-{
- assert(commit && committer_sig);
- commit->object.modified = 1;
-
- git_signature_free(commit->committer);
- commit->committer = git_signature_dup(committer_sig);
-}
-
-void git_commit_set_message(git_commit *commit, const char *message)
-{
- const char *line_end;
- size_t message_len;
-
- commit->object.modified = 1;
-
- if (commit->message)
- free(commit->message);
-
- if (commit->message_short)
- free(commit->message_short);
-
- commit->message = git__strdup(message);
-
- /* Short message */
- if((line_end = strchr(message, '\n')) == NULL) {
- commit->message_short = git__strdup(message);
- return;
- }
-
- message_len = line_end - message;
-
- commit->message_short = git__malloc(message_len + 1);
- memcpy(commit->message_short, message, message_len);
- commit->message_short[message_len] = 0;
-}
-