diff --git a/src/git/tree.h b/src/git/tree.h index bec49f245..9e2d0776a 100644 --- a/src/git/tree.h +++ b/src/git/tree.h @@ -113,8 +113,9 @@ GIT_EXTERN(git_object *) git_tree_entry_2object(git_tree_entry *entry); * @iparam id OID for the tree entry * @param filename Filename for the tree entry * @param attributes UNIX file attributes for the entry + * @return 0 on success; otherwise error code */ -GIT_EXTERN(void) git_tree_add_entry(git_tree *tree, const git_oid *id, const char *filename, int attributes); +GIT_EXTERN(int) git_tree_add_entry(git_tree *tree, const git_oid *id, const char *filename, int attributes); /** * Remove an entry by its index. diff --git a/src/tree.c b/src/tree.c index b809290b2..28bc035d2 100644 --- a/src/tree.c +++ b/src/tree.c @@ -29,17 +29,24 @@ #include "tree.h" #include "git/repository.h" -static void resize_tree_array(git_tree *tree) +static int resize_tree_array(git_tree *tree) { git_tree_entry **new_entries; - tree->array_size = tree->array_size * 2; + tree->array_size *= 2; + if (tree->array_size == 0) + tree->array_size = 8; new_entries = git__malloc(tree->array_size * sizeof(git_tree_entry *)); + if (new_entries == NULL) + return GIT_ENOMEM; + memcpy(new_entries, tree->entries, tree->entry_count * sizeof(git_tree_entry *)); free(tree->entries); tree->entries = new_entries; + + return GIT_SUCCESS; } int entry_cmp(const void *key, const void *array_member) @@ -166,17 +173,18 @@ size_t git_tree_entrycount(git_tree *tree) return tree->entry_count; } -void git_tree_add_entry(git_tree *tree, const git_oid *id, const char *filename, int attributes) +int git_tree_add_entry(git_tree *tree, const git_oid *id, const char *filename, int attributes) { git_tree_entry *entry; assert(tree && id && filename); if (tree->entry_count >= tree->array_size) - resize_tree_array(tree); + if (resize_tree_array(tree) < 0) + return GIT_ENOMEM; if ((entry = git__malloc(sizeof(git_tree_entry))) == NULL) - return; + return GIT_ENOMEM; memset(entry, 0x0, sizeof(git_tree_entry)); @@ -189,6 +197,7 @@ void git_tree_add_entry(git_tree *tree, const git_oid *id, const char *filename, entry_resort(tree); tree->object.modified = 1; + return GIT_SUCCESS; } int git_tree_remove_entry_byindex(git_tree *tree, int idx) @@ -277,11 +286,15 @@ int git_tree__parse(git_tree *tree) tree->array_size = (tree->object.source.raw.len / avg_entry_size) + 1; tree->entries = git__malloc(tree->array_size * sizeof(git_tree_entry *)); + if (tree->entries == NULL) + return GIT_ENOMEM; + while (buffer < buffer_end) { git_tree_entry *entry; if (tree->entry_count >= tree->array_size) - resize_tree_array(tree); + if (resize_tree_array(tree) < 0) + return GIT_ENOMEM; entry = git__malloc(sizeof(git_tree_entry)); if (entry == NULL) { diff --git a/tests/t0902-modify.c b/tests/t0902-modify.c index a321165b7..60a5cd728 100644 --- a/tests/t0902-modify.c +++ b/tests/t0902-modify.c @@ -9,6 +9,39 @@ static const char *odb_dir = "../resources/sample-odb"; static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd"; +BEGIN_TEST(tree_in_memory_add_test) + const unsigned int entry_count = 128; + + + git_odb *db; + git_repository *repo; + git_tree *tree; + unsigned int i; + git_oid entry_id; + + must_pass(git_odb_open(&db, odb_dir)); + + repo = git_repository_alloc(db); + must_be_true(repo != NULL); + + tree = git_tree_new(repo); + must_be_true(tree != NULL); + + git_oid_mkstr(&entry_id, tree_oid); + for (i = 0; i < entry_count; ++i) { + char filename[32]; + sprintf(filename, "file%d.txt", i); + must_pass(git_tree_add_entry(tree, &entry_id, filename, 040000)); + } + + must_be_true(git_tree_entrycount(tree) == entry_count); + must_pass(git_object_write((git_object *)tree)); + must_pass(remove_loose_object(odb_dir, (git_object *)tree)); + + git_repository_free(repo); + git_odb_close(db); +END_TEST + BEGIN_TEST(tree_add_entry_test) git_odb *db; git_oid id;