summaryrefslogtreecommitdiff
path: root/src/tree.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/tree.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/tree.c')
-rw-r--r--src/tree.c191
1 files changed, 10 insertions, 181 deletions
diff --git a/src/tree.c b/src/tree.c
index 307d41b0d..31b286e69 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -41,9 +41,11 @@ int entry_search_cmp(const void *key, const void *array_member)
return strcmp(filename, entry->filename);
}
+#if 0
static int valid_attributes(const int attributes) {
return attributes >= 0 && attributes <= MAX_FILEMODE;
}
+#endif
int entry_sort_cmp(const void *a, const void *b)
{
@@ -56,13 +58,10 @@ int entry_sort_cmp(const void *a, const void *b)
entry_b->attr & 040000);
}
-void git_tree_clear_entries(git_tree *tree)
+void git_tree__free(git_tree *tree)
{
unsigned int i;
- if (tree == NULL)
- return;
-
for (i = 0; i < tree->entries.length; ++i) {
git_tree_entry *e;
e = git_vector_get(&tree->entries, i);
@@ -71,32 +70,6 @@ void git_tree_clear_entries(git_tree *tree)
free(e);
}
- git_vector_clear(&tree->entries);
- tree->object.modified = 1;
-}
-
-
-git_tree *git_tree__new(void)
-{
- git_tree *tree;
-
- tree = git__malloc(sizeof(struct git_tree));
- if (tree == NULL)
- return NULL;
-
- memset(tree, 0x0, sizeof(struct git_tree));
-
- if (git_vector_init(&tree->entries, DEFAULT_TREE_SIZE, entry_sort_cmp) < GIT_SUCCESS) {
- free(tree);
- return NULL;
- }
-
- return tree;
-}
-
-void git_tree__free(git_tree *tree)
-{
- git_tree_clear_entries(tree);
git_vector_free(&tree->entries);
free(tree);
}
@@ -106,37 +79,6 @@ const git_oid *git_tree_id(git_tree *c)
return git_object_id((git_object *)c);
}
-int git_tree_entry_set_attributes(git_tree_entry *entry, unsigned int attr)
-{
- assert(entry && entry->owner);
-
- if (!valid_attributes(attr)) {
- return GIT_ERROR;
- }
-
- entry->attr = attr;
- entry->owner->object.modified = 1;
- return GIT_SUCCESS;
-}
-
-void git_tree_entry_set_name(git_tree_entry *entry, const char *name)
-{
- assert(entry && entry->owner);
-
- free(entry->filename);
- entry->filename = git__strdup(name);
- git_vector_sort(&entry->owner->entries);
- entry->owner->object.modified = 1;
-}
-
-void git_tree_entry_set_id(git_tree_entry *entry, const git_oid *oid)
-{
- assert(entry && entry->owner);
-
- git_oid_cpy(&entry->oid, oid);
- entry->owner->object.modified = 1;
-}
-
unsigned int git_tree_entry_attributes(git_tree_entry *entry)
{
return entry->attr;
@@ -154,15 +96,10 @@ const git_oid *git_tree_entry_id(git_tree_entry *entry)
return &entry->oid;
}
-int git_tree_entry_2object(git_object **object_out, git_tree_entry *entry)
+int git_tree_entry_2object(git_object **object_out, git_repository *repo, git_tree_entry *entry)
{
assert(entry && object_out);
- return git_object_lookup(object_out, entry->owner->object.repo, &entry->oid, GIT_OBJ_ANY);
-}
-
-static void sort_entries(git_tree *tree)
-{
- git_vector_sort(&tree->entries);
+ return git_object_lookup(object_out, repo, &entry->oid, GIT_OBJ_ANY);
}
git_tree_entry *git_tree_entry_byname(git_tree *tree, const char *filename)
@@ -171,8 +108,6 @@ git_tree_entry *git_tree_entry_byname(git_tree *tree, const char *filename)
assert(tree && filename);
- sort_entries(tree);
-
idx = git_vector_bsearch2(&tree->entries, entry_search_cmp, filename);
if (idx == GIT_ENOTFOUND)
return NULL;
@@ -183,9 +118,6 @@ git_tree_entry *git_tree_entry_byname(git_tree *tree, const char *filename)
git_tree_entry *git_tree_entry_byindex(git_tree *tree, int idx)
{
assert(tree);
-
- sort_entries(tree);
-
return git_vector_get(&tree->entries, (unsigned int)idx);
}
@@ -195,107 +127,12 @@ size_t git_tree_entrycount(git_tree *tree)
return tree->entries.length;
}
-int git_tree_add_entry(git_tree_entry **entry_out, git_tree *tree, const git_oid *id, const char *filename, int attributes)
-{
- git_tree_entry *entry;
-
- assert(tree && id && filename);
- if (!valid_attributes(attributes)) {
- return GIT_ERROR;
- }
-
- if ((entry = git__malloc(sizeof(git_tree_entry))) == NULL)
- return GIT_ENOMEM;
-
- memset(entry, 0x0, sizeof(git_tree_entry));
-
- entry->filename = git__strdup(filename);
- git_oid_cpy(&entry->oid, id);
- entry->attr = attributes;
- entry->owner = tree;
-
- if (git_vector_insert(&tree->entries, entry) < 0)
- return GIT_ENOMEM;
-
- if (entry_out != NULL)
- *entry_out = entry;
-
- tree->object.modified = 1;
- return GIT_SUCCESS;
-}
-
-int git_tree_remove_entry_byindex(git_tree *tree, int idx)
-{
- git_tree_entry *remove_ptr;
-
- assert(tree);
-
- sort_entries(tree);
-
- remove_ptr = git_vector_get(&tree->entries, (unsigned int)idx);
- if (remove_ptr == NULL)
- return GIT_ENOTFOUND;
-
- free(remove_ptr->filename);
- free(remove_ptr);
-
- tree->object.modified = 1;
-
- return git_vector_remove(&tree->entries, (unsigned int)idx);
-}
-
-int git_tree_remove_entry_byname(git_tree *tree, const char *filename)
-{
- int idx;
-
- assert(tree && filename);
-
- sort_entries(tree);
-
- idx = git_vector_bsearch2(&tree->entries, entry_search_cmp, filename);
- if (idx == GIT_ENOTFOUND)
- return GIT_ENOTFOUND;
-
- return git_tree_remove_entry_byindex(tree, idx);
-}
-
-int git_tree__writeback(git_tree *tree, git_odb_source *src)
-{
- size_t i;
- char filemode[MAX_FILEMODE_BYTES + 1 + 1];
-
- assert(tree && src);
-
- if (tree->entries.length == 0)
- return GIT_EMISSINGOBJDATA;
-
- sort_entries(tree);
-
- for (i = 0; i < tree->entries.length; ++i) {
- git_tree_entry *entry;
-
- entry = git_vector_get(&tree->entries, i);
-
- snprintf(filemode, sizeof(filemode), "%o ", entry->attr);
-
- git__source_write(src, filemode, strlen(filemode));
- git__source_write(src, entry->filename, strlen(entry->filename) + 1);
- git__source_write(src, entry->oid.id, GIT_OID_RAWSZ);
- }
-
- return GIT_SUCCESS;
-}
-
-
static int tree_parse_buffer(git_tree *tree, char *buffer, char *buffer_end)
{
- static const size_t avg_entry_size = 40;
- unsigned int expected_size;
int error = GIT_SUCCESS;
- expected_size = (tree->object.source.raw.len / avg_entry_size) + 1;
-
- git_tree_clear_entries(tree);
+ if (git_vector_init(&tree->entries, DEFAULT_TREE_SIZE, entry_sort_cmp) < GIT_SUCCESS)
+ return GIT_ENOMEM;
while (buffer < buffer_end) {
git_tree_entry *entry;
@@ -309,7 +146,6 @@ static int tree_parse_buffer(git_tree *tree, char *buffer, char *buffer_end)
if (git_vector_insert(&tree->entries, entry) < GIT_SUCCESS)
return GIT_ENOMEM;
- entry->owner = tree;
entry->attr = strtol(buffer, &buffer, 8);
if (*buffer++ != ' ') {
@@ -336,16 +172,9 @@ static int tree_parse_buffer(git_tree *tree, char *buffer, char *buffer_end)
return error;
}
-int git_tree__parse(git_tree *tree)
+int git_tree__parse(git_tree *tree, git_odb_object *obj)
{
- char *buffer, *buffer_end;
-
- assert(tree && tree->object.source.open);
- assert(!tree->object.in_memory);
-
- buffer = tree->object.source.raw.data;
- buffer_end = buffer + tree->object.source.raw.len;
-
- return tree_parse_buffer(tree, buffer, buffer_end);
+ assert(tree);
+ return tree_parse_buffer(tree, (char *)obj->raw.data, (char *)obj->raw.data + obj->raw.len);
}