mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-06 09:41:04 +00:00
Merge pull request #1350 from arrbee/fix-1292
Add explicit entrycount to tree builder
This commit is contained in:
commit
6ec37f7232
113
src/tree.c
113
src/tree.c
@ -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)
|
|||||||
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
|
|||||||
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(
|
|||||||
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(
|
|||||||
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)
|
|||||||
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(
|
|||||||
|
|
||||||
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)
|
|||||||
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
|
|||||||
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))
|
||||||
|
error = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (git_buf_oom(&tree))
|
if (!error &&
|
||||||
goto on_error;
|
!(error = git_repository_odb__weakptr(&odb, repo)))
|
||||||
|
error = git_odb_write(oid, odb, tree.ptr, tree.size, GIT_OBJ_TREE);
|
||||||
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)
|
|
||||||
goto on_error;
|
|
||||||
|
|
||||||
git_buf_free(&tree);
|
git_buf_free(&tree);
|
||||||
return 0;
|
return error;
|
||||||
|
|
||||||
on_error:
|
|
||||||
git_buf_free(&tree);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_treebuilder_filter(
|
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(
|
|||||||
{
|
{
|
||||||
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(
|
|||||||
}
|
}
|
||||||
|
|
||||||
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(
|
|||||||
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 {
|
|||||||
|
|
||||||
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user