Commit 6ec37f72 by Vicent Martí

Merge pull request #1350 from arrbee/fix-1292

Add explicit entrycount to tree builder
parents f7511c2c e2237179
...@@ -216,12 +216,11 @@ git_tree_entry *git_tree_entry_dup(const git_tree_entry *entry) ...@@ -216,12 +216,11 @@ git_tree_entry *git_tree_entry_dup(const git_tree_entry *entry)
void git_tree__free(git_tree *tree) void git_tree__free(git_tree *tree)
{ {
unsigned int i; size_t i;
git_tree_entry *e;
for (i = 0; i < tree->entries.length; ++i) { git_vector_foreach(&tree->entries, i, e)
git_tree_entry *e = git_vector_get(&tree->entries, i);
git_tree_entry_free(e); git_tree_entry_free(e);
}
git_vector_free(&tree->entries); git_vector_free(&tree->entries);
git__free(tree); git__free(tree);
...@@ -355,7 +354,7 @@ size_t git_tree_entrycount(const git_tree *tree) ...@@ -355,7 +354,7 @@ size_t git_tree_entrycount(const git_tree *tree)
unsigned int git_treebuilder_entrycount(git_treebuilder *bld) unsigned int git_treebuilder_entrycount(git_treebuilder *bld)
{ {
assert(bld); assert(bld);
return (int)bld->entries.length; return (unsigned int)bld->entrycount;
} }
static int tree_error(const char *str, const char *path) static int tree_error(const char *str, const char *path)
...@@ -392,8 +391,10 @@ static int tree_parse_buffer(git_tree *tree, const char *buffer, const char *buf ...@@ -392,8 +391,10 @@ static int tree_parse_buffer(git_tree *tree, const char *buffer, const char *buf
entry = alloc_entry(buffer); entry = alloc_entry(buffer);
GITERR_CHECK_ALLOC(entry); GITERR_CHECK_ALLOC(entry);
if (git_vector_insert(&tree->entries, entry) < 0) if (git_vector_insert(&tree->entries, entry) < 0) {
git__free(entry);
return -1; return -1;
}
entry->attr = attr; entry->attr = attr;
} }
...@@ -450,9 +451,12 @@ static int append_entry( ...@@ -450,9 +451,12 @@ static int append_entry(
git_oid_cpy(&entry->oid, id); git_oid_cpy(&entry->oid, id);
entry->attr = (uint16_t)filemode; entry->attr = (uint16_t)filemode;
if (git_vector_insert(&bld->entries, entry) < 0) if (git_vector_insert(&bld->entries, entry) < 0) {
git__free(entry);
return -1; return -1;
}
bld->entrycount++;
return 0; return 0;
} }
...@@ -581,11 +585,6 @@ int git_tree__write_index( ...@@ -581,11 +585,6 @@ int git_tree__write_index(
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
static void sort_entries(git_treebuilder *bld)
{
git_vector_sort(&bld->entries);
}
int git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source) int git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source)
{ {
git_treebuilder *bld; git_treebuilder *bld;
...@@ -603,9 +602,9 @@ int git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source) ...@@ -603,9 +602,9 @@ int git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source)
goto on_error; goto on_error;
if (source != NULL) { if (source != NULL) {
for (i = 0; i < source->entries.length; ++i) { git_tree_entry *entry_src;
git_tree_entry *entry_src = source->entries.contents[i];
git_vector_foreach(&source->entries, i, entry_src) {
if (append_entry( if (append_entry(
bld, entry_src->filename, bld, entry_src->filename,
&entry_src->oid, &entry_src->oid,
...@@ -642,14 +641,20 @@ int git_treebuilder_insert( ...@@ -642,14 +641,20 @@ int git_treebuilder_insert(
if (!tree_key_search(&pos, &bld->entries, filename, strlen(filename))) { if (!tree_key_search(&pos, &bld->entries, filename, strlen(filename))) {
entry = git_vector_get(&bld->entries, pos); entry = git_vector_get(&bld->entries, pos);
if (entry->removed) if (entry->removed) {
entry->removed = 0; entry->removed = 0;
bld->entrycount++;
}
} else { } else {
entry = alloc_entry(filename); entry = alloc_entry(filename);
GITERR_CHECK_ALLOC(entry); GITERR_CHECK_ALLOC(entry);
if (git_vector_insert(&bld->entries, entry) < 0) if (git_vector_insert(&bld->entries, entry) < 0) {
git__free(entry);
return -1; return -1;
}
bld->entrycount++;
} }
git_oid_cpy(&entry->oid, id); git_oid_cpy(&entry->oid, id);
...@@ -691,24 +696,26 @@ int git_treebuilder_remove(git_treebuilder *bld, const char *filename) ...@@ -691,24 +696,26 @@ int git_treebuilder_remove(git_treebuilder *bld, const char *filename)
return tree_error("Failed to remove entry. File isn't in the tree", filename); return tree_error("Failed to remove entry. File isn't in the tree", filename);
remove_ptr->removed = 1; remove_ptr->removed = 1;
bld->entrycount--;
return 0; return 0;
} }
int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *bld) int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *bld)
{ {
unsigned int i; int error = 0;
size_t i;
git_buf tree = GIT_BUF_INIT; git_buf tree = GIT_BUF_INIT;
git_odb *odb; git_odb *odb;
assert(bld); assert(bld);
sort_entries(bld); git_vector_sort(&bld->entries);
/* Grow the buffer beforehand to an estimated size */ /* Grow the buffer beforehand to an estimated size */
git_buf_grow(&tree, bld->entries.length * 72); error = git_buf_grow(&tree, bld->entries.length * 72);
for (i = 0; i < bld->entries.length; ++i) { for (i = 0; i < bld->entries.length && !error; ++i) {
git_tree_entry *entry = bld->entries.contents[i]; git_tree_entry *entry = git_vector_get(&bld->entries, i);
if (entry->removed) if (entry->removed)
continue; continue;
...@@ -716,24 +723,17 @@ int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *b ...@@ -716,24 +723,17 @@ int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *b
git_buf_printf(&tree, "%o ", entry->attr); git_buf_printf(&tree, "%o ", entry->attr);
git_buf_put(&tree, entry->filename, entry->filename_len + 1); git_buf_put(&tree, entry->filename, entry->filename_len + 1);
git_buf_put(&tree, (char *)entry->oid.id, GIT_OID_RAWSZ); git_buf_put(&tree, (char *)entry->oid.id, GIT_OID_RAWSZ);
}
if (git_buf_oom(&tree))
goto on_error;
if (git_repository_odb__weakptr(&odb, repo) < 0)
goto on_error;
if (git_odb_write(oid, odb, tree.ptr, tree.size, GIT_OBJ_TREE) < 0) if (git_buf_oom(&tree))
goto on_error; error = -1;
}
git_buf_free(&tree); if (!error &&
return 0; !(error = git_repository_odb__weakptr(&odb, repo)))
error = git_odb_write(oid, odb, tree.ptr, tree.size, GIT_OBJ_TREE);
on_error:
git_buf_free(&tree); git_buf_free(&tree);
return -1; return error;
} }
void git_treebuilder_filter( void git_treebuilder_filter(
...@@ -741,28 +741,31 @@ void git_treebuilder_filter( ...@@ -741,28 +741,31 @@ void git_treebuilder_filter(
git_treebuilder_filter_cb filter, git_treebuilder_filter_cb filter,
void *payload) void *payload)
{ {
unsigned int i; size_t i;
git_tree_entry *entry;
assert(bld && filter); assert(bld && filter);
for (i = 0; i < bld->entries.length; ++i) { git_vector_foreach(&bld->entries, i, entry) {
git_tree_entry *entry = bld->entries.contents[i]; if (!entry->removed && filter(entry, payload)) {
if (!entry->removed && filter(entry, payload))
entry->removed = 1; entry->removed = 1;
bld->entrycount--;
}
} }
} }
void git_treebuilder_clear(git_treebuilder *bld) void git_treebuilder_clear(git_treebuilder *bld)
{ {
unsigned int i; size_t i;
git_tree_entry *e;
assert(bld); assert(bld);
for (i = 0; i < bld->entries.length; ++i) { git_vector_foreach(&bld->entries, i, e)
git_tree_entry *e = bld->entries.contents[i];
git_tree_entry_free(e); git_tree_entry_free(e);
}
git_vector_clear(&bld->entries); git_vector_clear(&bld->entries);
bld->entrycount = 0;
} }
void git_treebuilder_free(git_treebuilder *bld) void git_treebuilder_free(git_treebuilder *bld)
...@@ -856,16 +859,17 @@ static int tree_walk( ...@@ -856,16 +859,17 @@ static int tree_walk(
{ {
int error = 0; int error = 0;
size_t i; size_t i;
const git_tree_entry *entry;
for (i = 0; i < tree->entries.length; ++i) { git_vector_foreach(&tree->entries, i, entry) {
const git_tree_entry *entry = tree->entries.contents[i];
if (preorder) { if (preorder) {
error = callback(path->ptr, entry, payload); error = callback(path->ptr, entry, payload);
if (error > 0) if (error > 0)
continue; continue;
if (error < 0) if (error < 0) {
giterr_clear();
return GIT_EUSER; return GIT_EUSER;
}
} }
if (git_tree_entry__is_tree(entry)) { if (git_tree_entry__is_tree(entry)) {
...@@ -892,6 +896,7 @@ static int tree_walk( ...@@ -892,6 +896,7 @@ static int tree_walk(
} }
if (!preorder && callback(path->ptr, entry, payload) < 0) { if (!preorder && callback(path->ptr, entry, payload) < 0) {
giterr_clear();
error = GIT_EUSER; error = GIT_EUSER;
break; break;
} }
...@@ -909,20 +914,14 @@ int git_tree_walk( ...@@ -909,20 +914,14 @@ int git_tree_walk(
int error = 0; int error = 0;
git_buf root_path = GIT_BUF_INIT; git_buf root_path = GIT_BUF_INIT;
switch (mode) { if (mode != GIT_TREEWALK_POST && mode != GIT_TREEWALK_PRE) {
case GIT_TREEWALK_POST:
error = tree_walk(tree, callback, &root_path, payload, false);
break;
case GIT_TREEWALK_PRE:
error = tree_walk(tree, callback, &root_path, payload, true);
break;
default:
giterr_set(GITERR_INVALID, "Invalid walking mode for tree walk"); giterr_set(GITERR_INVALID, "Invalid walking mode for tree walk");
return -1; return -1;
} }
error = tree_walk(
tree, callback, &root_path, payload, (mode == GIT_TREEWALK_PRE));
git_buf_free(&root_path); git_buf_free(&root_path);
return error; return error;
......
...@@ -27,6 +27,7 @@ struct git_tree { ...@@ -27,6 +27,7 @@ struct git_tree {
struct git_treebuilder { struct git_treebuilder {
git_vector entries; git_vector entries;
size_t entrycount; /* vector may contain "removed" entries */
}; };
GIT_INLINE(int) git_tree__dup(git_tree **dest, git_tree *source) GIT_INLINE(int) git_tree__dup(git_tree **dest, git_tree *source)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment