From 599f2849bad898c5dfd212e0629f79783f75b700 Mon Sep 17 00:00:00 2001 From: Clemens Buchacher Date: Mon, 26 Dec 2011 18:37:31 +0100 Subject: [PATCH] add git_index_read_tree --- include/git2/index.h | 11 +++++++++ src/index.c | 42 ++++++++++++++++++++++++++++++++ tests-clay/index/read_tree.c | 46 ++++++++++++++++++++++++++++++++++++ tests-clay/index/rename.c | 11 +-------- tests-clay/testlib.c | 20 ++++++++++++++++ tests-clay/testlib.h | 6 +++++ 6 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 tests-clay/index/read_tree.c create mode 100644 tests-clay/testlib.c create mode 100644 tests-clay/testlib.h diff --git a/include/git2/index.h b/include/git2/index.h index 5e9c34d4b..627d6c4fd 100644 --- a/include/git2/index.h +++ b/include/git2/index.h @@ -301,6 +301,17 @@ GIT_EXTERN(const git_index_entry_unmerged *) git_index_get_unmerged_byindex(git_ */ GIT_EXTERN(int) git_index_entry_stage(const git_index_entry *entry); +/** + * Read a tree into the index file + * + * The current index contents will be replaced by the specified tree. + * + * @param index an existing index object + * @param tree tree to read + * @return GIT_SUCCESS or an error code + */ +GIT_EXTERN(int) git_index_read_tree(git_index *index, git_tree *tree); + /** @} */ GIT_END_DECL #endif diff --git a/src/index.c b/src/index.c index 43e8efa57..9f9a08f0d 100644 --- a/src/index.c +++ b/src/index.c @@ -10,6 +10,7 @@ #include "common.h" #include "repository.h" #include "index.h" +#include "tree.h" #include "tree-cache.h" #include "hash.h" #include "git2/odb.h" @@ -936,3 +937,44 @@ int git_index_entry_stage(const git_index_entry *entry) { return (entry->flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT; } + +static int read_tree_cb(const char *root, git_tree_entry *tentry, void *data) +{ + int ret = GIT_SUCCESS; + git_index *index = data; + git_index_entry *entry = NULL; + git_buf path = GIT_BUF_INIT; + + if (entry_is_tree(tentry)) + goto exit; + + ret = git_buf_joinpath(&path, root, tentry->filename); + if (ret < GIT_SUCCESS) + goto exit; + + entry = git__calloc(1, sizeof(git_index_entry)); + if (!entry) { + ret = GIT_ENOMEM; + goto exit; + } + + entry->mode = tentry->attr; + entry->oid = tentry->oid; + entry->path = git_buf_detach(&path); + + ret = index_insert(index, entry, 0); + +exit: + git_buf_free(&path); + + if (ret < GIT_SUCCESS) + index_entry_free(entry); + return ret; +} + +int git_index_read_tree(git_index *index, git_tree *tree) +{ + git_index_clear(index); + + return git_tree_walk(tree, read_tree_cb, GIT_TREEWALK_POST, index); +} diff --git a/tests-clay/index/read_tree.c b/tests-clay/index/read_tree.c new file mode 100644 index 000000000..d884c8d51 --- /dev/null +++ b/tests-clay/index/read_tree.c @@ -0,0 +1,46 @@ +#include "clay_libgit2.h" +#include "testlib.h" +#include "posix.h" + +/* Test that reading and writing a tree is a no-op */ +void test_index_read_tree__read_write_involution(void) +{ + git_repository *repo; + git_index *index; + git_oid tree_oid; + git_tree *tree; + git_oid expected; + + p_mkdir("read_tree", 0700); + + cl_git_pass(git_repository_init(&repo, "./read_tree", 0)); + cl_git_pass(git_repository_index(&index, repo)); + + cl_assert(git_index_entrycount(index) == 0); + + p_mkdir("./read_tree/abc", 0700); + + /* Sort order: '-' < '/' < '_' */ + file_create("./read_tree/abc-d", NULL); + file_create("./read_tree/abc/d", NULL); + file_create("./read_tree/abc_d", NULL); + + cl_git_pass(git_index_add(index, "abc-d", 0)); + cl_git_pass(git_index_add(index, "abc_d", 0)); + cl_git_pass(git_index_add(index, "abc/d", 0)); + + /* write-tree */ + cl_git_pass(git_tree_create_fromindex(&expected, index)); + + /* read-tree */ + git_tree_lookup(&tree, repo, &expected); + cl_git_pass(git_index_read_tree(index, tree)); + + cl_git_pass(git_tree_create_fromindex(&tree_oid, index)); + cl_assert(git_oid_cmp(&expected, &tree_oid) == 0); + + git_index_free(index); + git_repository_free(repo); + + cl_fixture_cleanup("read_tree"); +} diff --git a/tests-clay/index/rename.c b/tests-clay/index/rename.c index f81125434..c949fa7f2 100644 --- a/tests-clay/index/rename.c +++ b/tests-clay/index/rename.c @@ -1,16 +1,7 @@ #include "clay_libgit2.h" +#include "testlib.h" #include "posix.h" -static void file_create(const char *filename, const char *content) -{ - int fd; - - fd = p_creat(filename, 0666); - cl_assert(fd != 0); - cl_git_pass(p_write(fd, content, strlen(content))); - cl_git_pass(p_close(fd)); -} - void test_index_rename__single_file(void) { git_repository *repo; diff --git a/tests-clay/testlib.c b/tests-clay/testlib.c new file mode 100644 index 000000000..d45fc2c26 --- /dev/null +++ b/tests-clay/testlib.c @@ -0,0 +1,20 @@ +#include "clay.h" +#include "testlib.h" +#include "posix.h" + +void file_create(const char *filename, const char *content) +{ + int fd; + + fd = p_creat(filename, 0666); + cl_assert(fd != 0); + + if (content) { + cl_must_pass(p_write(fd, content, strlen(content))); + } else { + cl_must_pass(p_write(fd, filename, strlen(filename))); + cl_must_pass(p_write(fd, "\n", 1)); + } + + cl_must_pass(p_close(fd)); +} diff --git a/tests-clay/testlib.h b/tests-clay/testlib.h new file mode 100644 index 000000000..2e8867c12 --- /dev/null +++ b/tests-clay/testlib.h @@ -0,0 +1,6 @@ +#ifndef INCLUDE_testlib_h__ +#define INCLUDE_testlib_h__ + +void file_create(const char *filename, const char *content); + +#endif