Commit 7a704309 by Vicent Martí

Merge remote-tracking branch 'drizzd/diff-index-tests' into development

Conflicts:
	tests-clay/clay.h
	tests-clay/clay_main.c
parents 9191a6d2 0fb3fba1
/tests-clay/clay.h
/tests-clay/clay_main.c
/apidocs
/trash-*.exe
/libgit2.pc
......
......@@ -49,6 +49,7 @@ OPTION (BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" ON)
OPTION (THREADSAFE "Build libgit2 as threadsafe" OFF)
OPTION (BUILD_TESTS "Build Tests" ON)
OPTION (BUILD_CLAY "Build Tests using the Clay suite" OFF)
OPTION (TAGS "Generate tags" OFF)
# Platform specific compilation flags
IF (MSVC)
......@@ -142,13 +143,22 @@ IF (BUILD_TESTS)
ENDIF ()
IF (BUILD_CLAY)
FIND_PACKAGE(PythonInterp REQUIRED)
SET(CLAY_FIXTURES "${CMAKE_CURRENT_SOURCE_DIR}/tests/resources/")
SET(CLAY_PATH "${CMAKE_CURRENT_SOURCE_DIR}/tests-clay")
ADD_DEFINITIONS(-DCLAY_FIXTURE_PATH=\"${CLAY_FIXTURES}\")
INCLUDE_DIRECTORIES(tests-clay)
FILE(GLOB_RECURSE SRC_TEST tests-clay/*.c)
INCLUDE_DIRECTORIES(${CLAY_PATH})
FILE(GLOB_RECURSE SRC_TEST ${CLAY_PATH}/*/*.c ${CLAY_PATH}/clay_helpers.c ${CLAY_PATH}/testlib.c)
ADD_EXECUTABLE(libgit2_clay ${SRC} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP})
ADD_CUSTOM_COMMAND(
OUTPUT ${CLAY_PATH}/clay_main.c ${CLAY_PATH}/clay.h
COMMAND ${PYTHON_EXECUTABLE} clay -vtap .
DEPENDS ${CLAY_PATH}/clay ${SRC_TEST}
WORKING_DIRECTORY ${CLAY_PATH}
)
ADD_EXECUTABLE(libgit2_clay ${SRC} ${CLAY_PATH}/clay_main.c ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP})
TARGET_LINK_LIBRARIES(libgit2_clay ${CMAKE_THREAD_LIBS_INIT})
IF (WIN32)
TARGET_LINK_LIBRARIES(libgit2_clay ws2_32)
......@@ -159,3 +169,22 @@ IF (BUILD_CLAY)
ENABLE_TESTING()
ADD_TEST(libgit2_clay libgit2_clay)
ENDIF ()
IF (TAGS)
FIND_PROGRAM(CTAGS ctags)
IF (NOT CTAGS)
message(FATAL_ERROR "Could not find ctags command")
ENDIF ()
FILE(GLOB_RECURSE SRC_ALL *.[ch])
ADD_CUSTOM_COMMAND(
OUTPUT tags
COMMAND ${CTAGS} -a ${SRC_ALL}
DEPENDS ${SRC_ALL}
)
ADD_CUSTOM_TARGET(
do_tags ALL
DEPENDS tags
)
ENDIF ()
......@@ -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
......@@ -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);
}
......@@ -349,9 +349,6 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo)
{
assert(out && repo);
if (repo->is_bare)
return git__throw(GIT_EBAREINDEX, "Cannot open index in bare repository");
if (repo->_index == NULL) {
int error;
git_buf index_path = GIT_BUF_INIT;
......
......@@ -15,8 +15,6 @@
#define MAX_FILEMODE 0777777
#define MAX_FILEMODE_BYTES 6
#define ENTRY_IS_TREE(e) ((e)->attr & 040000)
static int valid_attributes(const int attributes)
{
return attributes >= 0 && attributes <= MAX_FILEMODE;
......@@ -33,8 +31,8 @@ static int entry_sort_cmp(const void *a, const void *b)
const git_tree_entry *entry_b = (const git_tree_entry *)(b);
return git_futils_cmp_path(
entry_a->filename, entry_a->filename_len, ENTRY_IS_TREE(entry_a),
entry_b->filename, entry_b->filename_len, ENTRY_IS_TREE(entry_b));
entry_a->filename, entry_a->filename_len, entry_is_tree(entry_a),
entry_b->filename, entry_b->filename_len, entry_is_tree(entry_b));
}
......@@ -717,7 +715,7 @@ static int tree_walk_post(
if (callback(path->ptr, entry, payload) < 0)
continue;
if (ENTRY_IS_TREE(entry)) {
if (entry_is_tree(entry)) {
git_tree *subtree;
size_t path_len = path->size;
......@@ -961,15 +959,22 @@ static int cmp_tentry_ientry(git_tree_entry *tentry, git_index_entry *ientry)
return git_oid_cmp(&tentry->oid, &ientry->oid);
}
static void make_tentry(git_tree_entry *tentry, git_index_entry *ientry, git_buf *buf)
static void make_tentry(git_tree_entry *tentry, git_index_entry *ientry)
{
char *last_slash;
memset(tentry, 0x0, sizeof(git_tree_entry));
tentry->attr = ientry->mode;
last_slash = strrchr(ientry->path, '/');
if (last_slash)
last_slash++;
else
last_slash = ientry->path;
tentry->filename = last_slash;
git_oid_cpy(&tentry->oid, &ientry->oid);
if (buf != NULL) {
tentry->filename = buf->ptr;
tentry->filename_len = buf->size;
}
tentry->filename_len = strlen(tentry->filename);
}
static int diff_index_cb(const char *root, git_tree_entry *tentry, void *data)
......@@ -980,7 +985,7 @@ static int diff_index_cb(const char *root, git_tree_entry *tentry, void *data)
git_buf fn_buf = GIT_BUF_INIT;
int cmp, error = GIT_SUCCESS;
if (ENTRY_IS_TREE(tentry))
if (entry_is_tree(tentry))
return GIT_SUCCESS;
git_buf_puts(&fn_buf, root);
......@@ -993,25 +998,24 @@ static int diff_index_cb(const char *root, git_tree_entry *tentry, void *data)
/* Like with 'git diff-index', the index is the right side*/
cmp = strcmp(git_buf_cstr(&fn_buf), ientry->path);
git_buf_free(&fn_buf);
if (cmp == 0) {
cbdata->i++;
if (!cmp_tentry_ientry(tentry, ientry))
goto exit;
/* modification */
make_tentry(&fake_entry, ientry, &fn_buf);
make_tentry(&fake_entry, ientry);
if ((error = signal_modification(tentry, &fake_entry, cbdata->cb, cbdata->data)) < 0)
goto exit;
} else if (cmp < 0) {
/* deletion */
memcpy(&fake_entry, tentry, sizeof(git_tree_entry));
fake_entry.filename = fn_buf.ptr;
fake_entry.filename_len = fn_buf.size;
if ((error = signal_deletion(tentry, cbdata->cb, cbdata->data)) < 0)
goto exit;
} else {
/* addition */
cbdata->i++;
make_tentry(&fake_entry, ientry, &fn_buf);
make_tentry(&fake_entry, ientry);
if ((error = signal_addition(&fake_entry, cbdata->cb, cbdata->data)) < 0)
goto exit;
/*
......@@ -1024,7 +1028,6 @@ static int diff_index_cb(const char *root, git_tree_entry *tentry, void *data)
}
exit:
git_buf_free(&fn_buf);
return error;
}
......
......@@ -31,6 +31,11 @@ struct git_treebuilder {
};
GIT_INLINE(unsigned int) entry_is_tree(const struct git_tree_entry *e)
{
return e->attr & 040000;
}
void git_tree__free(git_tree *tree);
int git_tree__parse(git_tree *tree, git_odb_object *obj);
......
......@@ -9,13 +9,9 @@ https://github.com/tanoku/clay
* Write your modules and tests. Use good, meaningful names.
* Mix the tests:
./clay -vtap .
* Make sure you actually build the tests by setting:
BUILD_CLAY=ON
cmake -DBUILD_CLAY=ON build/
* Test:
......
#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");
}
#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;
......
......@@ -2,8 +2,8 @@
#include "tree.h"
#include "repository.h"
static unsigned int expect_idx;
static git_repository *repo;
static git_index *theindex;
static git_tree *atree, *btree;
static git_oid aoid, boid;
......@@ -27,9 +27,18 @@ static int diff_cb(const git_tree_diff_data *diff, void *data)
return GIT_SUCCESS;
}
static void test_diff(git_tree *a, git_tree *b, git_tree_diff_cb cb, void *data)
{
cl_must_pass(git_tree_diff(a, b, cb, data));
cl_git_pass(git_index_read_tree(theindex, b));
cl_git_pass(git_tree_diff_index_recursive(a, theindex, cb, data));
}
void test_object_tree_diff__initialize(void)
{
cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
cl_git_pass(git_repository_index(&theindex, repo));
}
void test_object_tree_diff__cleanup(void)
......@@ -58,7 +67,7 @@ void test_object_tree_diff__addition(void)
cl_must_pass(git_tree_lookup(&atree, repo, &aoid));
cl_must_pass(git_tree_lookup(&btree, repo, &boid));
cl_must_pass(git_tree_diff(atree, btree, diff_cb, &expect));
test_diff(atree, btree, diff_cb, &expect);
}
void test_object_tree_diff__deletion(void)
......@@ -79,7 +88,7 @@ void test_object_tree_diff__deletion(void)
cl_must_pass(git_tree_lookup(&atree, repo, &aoid));
cl_must_pass(git_tree_lookup(&btree, repo, &boid));
cl_must_pass(git_tree_diff(atree, btree, diff_cb, &expect));
test_diff(atree, btree, diff_cb, &expect);
}
void test_object_tree_diff__modification(void)
......@@ -101,13 +110,20 @@ void test_object_tree_diff__modification(void)
cl_must_pass(git_tree_lookup(&atree, repo, &aoid));
cl_must_pass(git_tree_lookup(&btree, repo, &boid));
cl_must_pass(git_tree_diff(atree, btree, diff_cb, &expect));
test_diff(atree, btree, diff_cb, &expect);
}
struct diff_more_data {
git_tree_diff_data expect[3];
int expect_idx;
};
static int diff_more_cb(const git_tree_diff_data *diff, void *data)
{
git_tree_diff_data *expect = (git_tree_diff_data *) data;
diff_cmp(diff, &expect[expect_idx++]);
struct diff_more_data *more_data = data;
diff_cmp(diff, &more_data->expect[more_data->expect_idx]);
more_data->expect_idx = (more_data->expect_idx + 1) % ARRAY_SIZE(more_data->expect);
return GIT_SUCCESS;
}
......@@ -116,9 +132,10 @@ void test_object_tree_diff__more(void)
{
char *astr = "814889a078c031f61ed08ab5fa863aea9314344d";
char *bstr = "75057dd4114e74cca1d750d0aee1647c903cb60a";
git_tree_diff_data expect[3];
struct diff_more_data more_data;
git_tree_diff_data *expect = more_data.expect;
memset(expect, 0x0, 3 * sizeof(git_tree_diff_data));
memset(&more_data, 0x0, sizeof(struct diff_more_data));
/* M README */
expect[0].old_attr = 0100644;
expect[0].new_attr = 0100644;
......@@ -146,5 +163,5 @@ void test_object_tree_diff__more(void)
cl_must_pass(git_tree_lookup(&atree, repo, &aoid));
cl_must_pass(git_tree_lookup(&btree, repo, &boid));
cl_must_pass(git_tree_diff(atree, btree, diff_more_cb, expect));
test_diff(atree, btree, diff_more_cb, &more_data);
}
#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));
}
#ifndef INCLUDE_testlib_h__
#define INCLUDE_testlib_h__
void file_create(const char *filename, const char *content);
#endif
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