diff options
author | Vicent Marti <tanoku@gmail.com> | 2011-03-18 19:38:49 +0200 |
---|---|---|
committer | Vicent Marti <tanoku@gmail.com> | 2011-03-20 21:45:11 +0200 |
commit | 72a3fe42fb7208712bbe8f0981f4c6274c05e9c3 (patch) | |
tree | b073a1c36b3215d94b1e78a0f294d7aa30d949df /src/commit.c | |
parent | bb3de0c472b2d5d6b8091c190bee3db79c4b5e27 (diff) | |
download | libgit2-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.c | 268 |
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; -} - |