libgit2/tests/index/tests.c
Edward Thomson ac2fba0ecd git_futils_mkdir_*: make a relative-to-base mkdir
Untangle git_futils_mkdir from git_futils_mkdir_ext - the latter
assumes that we own everything beneath the base, as if it were
being called with a base of the repository or working directory,
and is tailored towards checkout and ensuring that there is no
bogosity beneath the base that must be cleaned up.

This is (at best) slow and (at worst) unsafe in the larger context
of a filesystem where we do not own things and cannot do things like
unlink symlinks that are in our way.
2015-09-17 10:00:35 -04:00

877 lines
24 KiB
C

#include "clar_libgit2.h"
#include "index.h"
static const size_t index_entry_count = 109;
static const size_t index_entry_count_2 = 1437;
#define TEST_INDEX_PATH cl_fixture("testrepo.git/index")
#define TEST_INDEX2_PATH cl_fixture("gitgit.index")
#define TEST_INDEXBIG_PATH cl_fixture("big.index")
#define TEST_INDEXBAD_PATH cl_fixture("bad.index")
/* Suite data */
struct test_entry {
size_t index;
char path[128];
git_off_t file_size;
git_time_t mtime;
};
static struct test_entry test_entries[] = {
{4, "Makefile", 5064, 0x4C3F7F33},
{62, "tests/Makefile", 2631, 0x4C3F7F33},
{36, "src/index.c", 10014, 0x4C43368D},
{6, "git.git-authors", 2709, 0x4C3F7F33},
{48, "src/revobject.h", 1448, 0x4C3F7FE2}
};
/* Helpers */
static void copy_file(const char *src, const char *dst)
{
git_buf source_buf = GIT_BUF_INIT;
git_file dst_fd;
cl_git_pass(git_futils_readbuffer(&source_buf, src));
dst_fd = git_futils_creat_withpath(dst, 0777, 0666); /* -V536 */
if (dst_fd < 0)
goto cleanup;
cl_git_pass(p_write(dst_fd, source_buf.ptr, source_buf.size));
cleanup:
git_buf_free(&source_buf);
p_close(dst_fd);
}
static void files_are_equal(const char *a, const char *b)
{
git_buf buf_a = GIT_BUF_INIT;
git_buf buf_b = GIT_BUF_INIT;
int pass;
if (git_futils_readbuffer(&buf_a, a) < 0)
cl_assert(0);
if (git_futils_readbuffer(&buf_b, b) < 0) {
git_buf_free(&buf_a);
cl_assert(0);
}
pass = (buf_a.size == buf_b.size && !memcmp(buf_a.ptr, buf_b.ptr, buf_a.size));
git_buf_free(&buf_a);
git_buf_free(&buf_b);
cl_assert(pass);
}
/* Fixture setup and teardown */
void test_index_tests__initialize(void)
{
}
void test_index_tests__empty_index(void)
{
git_index *index;
cl_git_pass(git_index_open(&index, "in-memory-index"));
cl_assert(index->on_disk == 0);
cl_assert(git_index_entrycount(index) == 0);
cl_assert(git_vector_is_sorted(&index->entries));
git_index_free(index);
}
void test_index_tests__default_test_index(void)
{
git_index *index;
unsigned int i;
git_index_entry **entries;
cl_git_pass(git_index_open(&index, TEST_INDEX_PATH));
cl_assert(index->on_disk);
cl_assert(git_index_entrycount(index) == index_entry_count);
cl_assert(git_vector_is_sorted(&index->entries));
entries = (git_index_entry **)index->entries.contents;
for (i = 0; i < ARRAY_SIZE(test_entries); ++i) {
git_index_entry *e = entries[test_entries[i].index];
cl_assert_equal_s(e->path, test_entries[i].path);
cl_assert_equal_i(e->mtime.seconds, test_entries[i].mtime);
cl_assert_equal_i(e->file_size, test_entries[i].file_size);
}
git_index_free(index);
}
void test_index_tests__gitgit_index(void)
{
git_index *index;
cl_git_pass(git_index_open(&index, TEST_INDEX2_PATH));
cl_assert(index->on_disk);
cl_assert(git_index_entrycount(index) == index_entry_count_2);
cl_assert(git_vector_is_sorted(&index->entries));
cl_assert(index->tree != NULL);
git_index_free(index);
}
void test_index_tests__find_in_existing(void)
{
git_index *index;
unsigned int i;
cl_git_pass(git_index_open(&index, TEST_INDEX_PATH));
for (i = 0; i < ARRAY_SIZE(test_entries); ++i) {
size_t idx;
cl_assert(!git_index_find(&idx, index, test_entries[i].path));
cl_assert(idx == test_entries[i].index);
}
git_index_free(index);
}
void test_index_tests__find_in_empty(void)
{
git_index *index;
unsigned int i;
cl_git_pass(git_index_open(&index, "fake-index"));
for (i = 0; i < ARRAY_SIZE(test_entries); ++i) {
cl_assert(GIT_ENOTFOUND == git_index_find(NULL, index, test_entries[i].path));
}
git_index_free(index);
}
void test_index_tests__find_prefix(void)
{
git_index *index;
const git_index_entry *entry;
size_t pos;
cl_git_pass(git_index_open(&index, TEST_INDEX_PATH));
cl_git_pass(git_index_find_prefix(&pos, index, "src"));
entry = git_index_get_byindex(index, pos);
cl_assert(git__strcmp(entry->path, "src/block-sha1/sha1.c") == 0);
cl_git_pass(git_index_find_prefix(&pos, index, "src/co"));
entry = git_index_get_byindex(index, pos);
cl_assert(git__strcmp(entry->path, "src/commit.c") == 0);
cl_assert(GIT_ENOTFOUND == git_index_find_prefix(NULL, index, "blah"));
git_index_free(index);
}
void test_index_tests__write(void)
{
git_index *index;
copy_file(TEST_INDEXBIG_PATH, "index_rewrite");
cl_git_pass(git_index_open(&index, "index_rewrite"));
cl_assert(index->on_disk);
cl_git_pass(git_index_write(index));
files_are_equal(TEST_INDEXBIG_PATH, "index_rewrite");
git_index_free(index);
p_unlink("index_rewrite");
}
void test_index_tests__sort0(void)
{
/* sort the entires in an index */
/*
* TODO: This no longer applies:
* index sorting in Git uses some specific changes to the way
* directories are sorted.
*
* We need to specificially check for this by creating a new
* index, adding entries in random order and then
* checking for consistency
*/
}
void test_index_tests__sort1(void)
{
/* sort the entires in an empty index */
git_index *index;
cl_git_pass(git_index_open(&index, "fake-index"));
/* FIXME: this test is slightly dumb */
cl_assert(git_vector_is_sorted(&index->entries));
git_index_free(index);
}
static void cleanup_myrepo(void *opaque)
{
GIT_UNUSED(opaque);
cl_fixture_cleanup("myrepo");
}
void test_index_tests__add(void)
{
git_index *index;
git_filebuf file = GIT_FILEBUF_INIT;
git_repository *repo;
const git_index_entry *entry;
git_oid id1;
cl_set_cleanup(&cleanup_myrepo, NULL);
/* Intialize a new repository */
cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
/* Ensure we're the only guy in the room */
cl_git_pass(git_repository_index(&index, repo));
cl_assert(git_index_entrycount(index) == 0);
/* Create a new file in the working directory */
cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777));
cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0, 0666));
cl_git_pass(git_filebuf_write(&file, "hey there\n", 10));
cl_git_pass(git_filebuf_commit(&file));
/* Store the expected hash of the file/blob
* This has been generated by executing the following
* $ echo "hey there" | git hash-object --stdin
*/
cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6"));
/* Add the new file to the index */
cl_git_pass(git_index_add_bypath(index, "test.txt"));
/* Wow... it worked! */
cl_assert(git_index_entrycount(index) == 1);
entry = git_index_get_byindex(index, 0);
/* And the built-in hashing mechanism worked as expected */
cl_assert_equal_oid(&id1, &entry->id);
/* Test access by path instead of index */
cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL);
cl_assert_equal_oid(&id1, &entry->id);
git_index_free(index);
git_repository_free(repo);
}
void test_index_tests__add_frombuffer(void)
{
git_index *index;
git_repository *repo;
git_index_entry entry;
const git_index_entry *returned_entry;
git_oid id1;
git_blob *blob;
const char *content = "hey there\n";
cl_set_cleanup(&cleanup_myrepo, NULL);
/* Intialize a new repository */
cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
/* Ensure we're the only guy in the room */
cl_git_pass(git_repository_index(&index, repo));
cl_assert(git_index_entrycount(index) == 0);
/* Store the expected hash of the file/blob
* This has been generated by executing the following
* $ echo "hey there" | git hash-object --stdin
*/
cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6"));
/* Add the new file to the index */
memset(&entry, 0x0, sizeof(git_index_entry));
entry.mode = GIT_FILEMODE_BLOB;
entry.path = "test.txt";
cl_git_pass(git_index_add_frombuffer(index, &entry,
content, strlen(content)));
/* Wow... it worked! */
cl_assert(git_index_entrycount(index) == 1);
returned_entry = git_index_get_byindex(index, 0);
/* And the built-in hashing mechanism worked as expected */
cl_assert_equal_oid(&id1, &returned_entry->id);
/* And mode is the one asked */
cl_assert_equal_i(GIT_FILEMODE_BLOB, returned_entry->mode);
/* Test access by path instead of index */
cl_assert((returned_entry = git_index_get_bypath(index, "test.txt", 0)) != NULL);
cl_assert_equal_oid(&id1, &returned_entry->id);
/* Test the blob is in the repository */
cl_git_pass(git_blob_lookup(&blob, repo, &id1));
cl_assert_equal_s(
content, git_blob_rawcontent(blob));
git_blob_free(blob);
git_index_free(index);
git_repository_free(repo);
}
void test_index_tests__add_frombuffer_reset_entry(void)
{
git_index *index;
git_repository *repo;
git_index_entry entry;
const git_index_entry *returned_entry;
git_filebuf file = GIT_FILEBUF_INIT;
git_oid id1;
git_blob *blob;
const char *old_content = "here\n";
const char *content = "hey there\n";
cl_set_cleanup(&cleanup_myrepo, NULL);
/* Intialize a new repository */
cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
cl_git_pass(git_repository_index(&index, repo));
cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777));
cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0, 0666));
cl_git_pass(git_filebuf_write(&file, old_content, strlen(old_content)));
cl_git_pass(git_filebuf_commit(&file));
/* Store the expected hash of the file/blob
* This has been generated by executing the following
* $ echo "hey there" | git hash-object --stdin
*/
cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6"));
cl_git_pass(git_index_add_bypath(index, "test.txt"));
/* Add the new file to the index */
memset(&entry, 0x0, sizeof(git_index_entry));
entry.mode = GIT_FILEMODE_BLOB;
entry.path = "test.txt";
cl_git_pass(git_index_add_frombuffer(index, &entry,
content, strlen(content)));
/* Wow... it worked! */
cl_assert(git_index_entrycount(index) == 1);
returned_entry = git_index_get_byindex(index, 0);
/* And the built-in hashing mechanism worked as expected */
cl_assert_equal_oid(&id1, &returned_entry->id);
/* And mode is the one asked */
cl_assert_equal_i(GIT_FILEMODE_BLOB, returned_entry->mode);
/* Test access by path instead of index */
cl_assert((returned_entry = git_index_get_bypath(index, "test.txt", 0)) != NULL);
cl_assert_equal_oid(&id1, &returned_entry->id);
cl_assert_equal_i(0, returned_entry->dev);
cl_assert_equal_i(0, returned_entry->ino);
cl_assert_equal_i(0, returned_entry->uid);
cl_assert_equal_i(0, returned_entry->uid);
cl_assert_equal_i(10, returned_entry->file_size);
/* Test the blob is in the repository */
cl_git_pass(git_blob_lookup(&blob, repo, &id1));
cl_assert_equal_s(content, git_blob_rawcontent(blob));
git_blob_free(blob);
git_index_free(index);
git_repository_free(repo);
}
static void cleanup_1397(void *opaque)
{
GIT_UNUSED(opaque);
cl_git_sandbox_cleanup();
}
void test_index_tests__add_issue_1397(void)
{
git_index *index;
git_repository *repo;
const git_index_entry *entry;
git_oid id1;
cl_set_cleanup(&cleanup_1397, NULL);
repo = cl_git_sandbox_init("issue_1397");
cl_repo_set_bool(repo, "core.autocrlf", true);
/* Ensure we're the only guy in the room */
cl_git_pass(git_repository_index(&index, repo));
/* Store the expected hash of the file/blob
* This has been generated by executing the following
* $ git hash-object crlf_file.txt
*/
cl_git_pass(git_oid_fromstr(&id1, "8312e0889a9cbab77c732b6bc39b51a683e3a318"));
/* Make sure the initial SHA-1 is correct */
cl_assert((entry = git_index_get_bypath(index, "crlf_file.txt", 0)) != NULL);
cl_assert_equal_oid(&id1, &entry->id);
/* Update the index */
cl_git_pass(git_index_add_bypath(index, "crlf_file.txt"));
/* Check the new SHA-1 */
cl_assert((entry = git_index_get_bypath(index, "crlf_file.txt", 0)) != NULL);
cl_assert_equal_oid(&id1, &entry->id);
git_index_free(index);
}
void test_index_tests__add_bypath_to_a_bare_repository_returns_EBAREPO(void)
{
git_repository *bare_repo;
git_index *index;
cl_git_pass(git_repository_open(&bare_repo, cl_fixture("testrepo.git")));
cl_git_pass(git_repository_index(&index, bare_repo));
cl_assert_equal_i(GIT_EBAREREPO, git_index_add_bypath(index, "test.txt"));
git_index_free(index);
git_repository_free(bare_repo);
}
static void add_invalid_filename(git_repository *repo, const char *fn)
{
git_index *index;
git_buf path = GIT_BUF_INIT;
cl_git_pass(git_repository_index(&index, repo));
cl_assert(git_index_entrycount(index) == 0);
git_buf_joinpath(&path, "./invalid", fn);
cl_git_mkfile(path.ptr, NULL);
cl_git_fail(git_index_add_bypath(index, fn));
cl_must_pass(p_unlink(path.ptr));
cl_assert(git_index_entrycount(index) == 0);
git_buf_free(&path);
git_index_free(index);
}
/* Test that writing an invalid filename fails */
void test_index_tests__add_invalid_filename(void)
{
git_repository *repo;
p_mkdir("invalid", 0700);
cl_git_pass(git_repository_init(&repo, "./invalid", 0));
cl_must_pass(p_mkdir("./invalid/subdir", 0777));
/* cl_git_mkfile() needs the dir to exist */
if (!git_path_exists("./invalid/.GIT"))
cl_must_pass(p_mkdir("./invalid/.GIT", 0777));
if (!git_path_exists("./invalid/.GiT"))
cl_must_pass(p_mkdir("./invalid/.GiT", 0777));
add_invalid_filename(repo, ".git/hello");
add_invalid_filename(repo, ".GIT/hello");
add_invalid_filename(repo, ".GiT/hello");
add_invalid_filename(repo, "./.git/hello");
add_invalid_filename(repo, "./foo");
add_invalid_filename(repo, "./bar");
add_invalid_filename(repo, "subdir/../bar");
git_repository_free(repo);
cl_fixture_cleanup("invalid");
}
static void replace_char(char *str, char in, char out)
{
char *c = str;
while (*c++)
if (*c == in)
*c = out;
}
static void write_invalid_filename(git_repository *repo, const char *fn_orig)
{
git_index *index;
git_oid expected;
const git_index_entry *entry;
git_buf path = GIT_BUF_INIT;
char *fn;
cl_git_pass(git_repository_index(&index, repo));
cl_assert(git_index_entrycount(index) == 0);
/*
* Sneak a valid path into the index, we'll update it
* to an invalid path when we try to write the index.
*/
fn = git__strdup(fn_orig);
replace_char(fn, '/', '_');
git_buf_joinpath(&path, "./invalid", fn);
cl_git_mkfile(path.ptr, NULL);
cl_git_pass(git_index_add_bypath(index, fn));
cl_assert(entry = git_index_get_bypath(index, fn, 0));
/* kids, don't try this at home */
replace_char((char *)entry->path, '_', '/');
/* write-tree */
cl_git_fail(git_index_write_tree(&expected, index));
p_unlink(path.ptr);
cl_git_pass(git_index_remove_all(index, NULL, NULL, NULL));
git_buf_free(&path);
git_index_free(index);
git__free(fn);
}
/* Test that writing an invalid filename fails */
void test_index_tests__write_invalid_filename(void)
{
git_repository *repo;
p_mkdir("invalid", 0700);
cl_git_pass(git_repository_init(&repo, "./invalid", 0));
write_invalid_filename(repo, ".git/hello");
write_invalid_filename(repo, ".GIT/hello");
write_invalid_filename(repo, ".GiT/hello");
write_invalid_filename(repo, "./.git/hello");
write_invalid_filename(repo, "./foo");
write_invalid_filename(repo, "./bar");
write_invalid_filename(repo, "foo/../bar");
git_repository_free(repo);
cl_fixture_cleanup("invalid");
}
void test_index_tests__honors_protect_filesystems(void)
{
git_repository *repo;
p_mkdir("invalid", 0700);
cl_git_pass(git_repository_init(&repo, "./invalid", 0));
cl_repo_set_bool(repo, "core.protectHFS", true);
cl_repo_set_bool(repo, "core.protectNTFS", true);
write_invalid_filename(repo, ".git./hello");
write_invalid_filename(repo, ".git\xe2\x80\xad/hello");
write_invalid_filename(repo, "git~1/hello");
write_invalid_filename(repo, ".git\xe2\x81\xaf/hello");
git_repository_free(repo);
cl_fixture_cleanup("invalid");
}
void test_index_tests__remove_entry(void)
{
git_repository *repo;
git_index *index;
p_mkdir("index_test", 0770);
cl_git_pass(git_repository_init(&repo, "index_test", 0));
cl_git_pass(git_repository_index(&index, repo));
cl_assert(git_index_entrycount(index) == 0);
cl_git_mkfile("index_test/hello", NULL);
cl_git_pass(git_index_add_bypath(index, "hello"));
cl_git_pass(git_index_write(index));
cl_git_pass(git_index_read(index, true)); /* reload */
cl_assert(git_index_entrycount(index) == 1);
cl_assert(git_index_get_bypath(index, "hello", 0) != NULL);
cl_git_pass(git_index_remove(index, "hello", 0));
cl_git_pass(git_index_write(index));
cl_git_pass(git_index_read(index, true)); /* reload */
cl_assert(git_index_entrycount(index) == 0);
cl_assert(git_index_get_bypath(index, "hello", 0) == NULL);
git_index_free(index);
git_repository_free(repo);
cl_fixture_cleanup("index_test");
}
void test_index_tests__remove_directory(void)
{
git_repository *repo;
git_index *index;
p_mkdir("index_test", 0770);
cl_git_pass(git_repository_init(&repo, "index_test", 0));
cl_git_pass(git_repository_index(&index, repo));
cl_assert_equal_i(0, (int)git_index_entrycount(index));
p_mkdir("index_test/a", 0770);
cl_git_mkfile("index_test/a/1.txt", NULL);
cl_git_mkfile("index_test/a/2.txt", NULL);
cl_git_mkfile("index_test/a/3.txt", NULL);
cl_git_mkfile("index_test/b.txt", NULL);
cl_git_pass(git_index_add_bypath(index, "a/1.txt"));
cl_git_pass(git_index_add_bypath(index, "a/2.txt"));
cl_git_pass(git_index_add_bypath(index, "a/3.txt"));
cl_git_pass(git_index_add_bypath(index, "b.txt"));
cl_git_pass(git_index_write(index));
cl_git_pass(git_index_read(index, true)); /* reload */
cl_assert_equal_i(4, (int)git_index_entrycount(index));
cl_assert(git_index_get_bypath(index, "a/1.txt", 0) != NULL);
cl_assert(git_index_get_bypath(index, "a/2.txt", 0) != NULL);
cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL);
cl_git_pass(git_index_remove(index, "a/1.txt", 0));
cl_git_pass(git_index_write(index));
cl_git_pass(git_index_read(index, true)); /* reload */
cl_assert_equal_i(3, (int)git_index_entrycount(index));
cl_assert(git_index_get_bypath(index, "a/1.txt", 0) == NULL);
cl_assert(git_index_get_bypath(index, "a/2.txt", 0) != NULL);
cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL);
cl_git_pass(git_index_remove_directory(index, "a", 0));
cl_git_pass(git_index_write(index));
cl_git_pass(git_index_read(index, true)); /* reload */
cl_assert_equal_i(1, (int)git_index_entrycount(index));
cl_assert(git_index_get_bypath(index, "a/1.txt", 0) == NULL);
cl_assert(git_index_get_bypath(index, "a/2.txt", 0) == NULL);
cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL);
git_index_free(index);
git_repository_free(repo);
cl_fixture_cleanup("index_test");
}
void test_index_tests__preserves_case(void)
{
git_repository *repo;
git_index *index;
const git_index_entry *entry;
int index_caps;
cl_set_cleanup(&cleanup_myrepo, NULL);
cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
cl_git_pass(git_repository_index(&index, repo));
index_caps = git_index_caps(index);
cl_git_rewritefile("myrepo/test.txt", "hey there\n");
cl_git_pass(git_index_add_bypath(index, "test.txt"));
cl_git_pass(p_rename("myrepo/test.txt", "myrepo/TEST.txt"));
cl_git_rewritefile("myrepo/TEST.txt", "hello again\n");
cl_git_pass(git_index_add_bypath(index, "TEST.txt"));
if (index_caps & GIT_INDEXCAP_IGNORE_CASE)
cl_assert_equal_i(1, (int)git_index_entrycount(index));
else
cl_assert_equal_i(2, (int)git_index_entrycount(index));
/* Test access by path instead of index */
cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL);
/* The path should *not* have changed without an explicit remove */
cl_assert(git__strcmp(entry->path, "test.txt") == 0);
cl_assert((entry = git_index_get_bypath(index, "TEST.txt", 0)) != NULL);
if (index_caps & GIT_INDEXCAP_IGNORE_CASE)
/* The path should *not* have changed without an explicit remove */
cl_assert(git__strcmp(entry->path, "test.txt") == 0);
else
cl_assert(git__strcmp(entry->path, "TEST.txt") == 0);
git_index_free(index);
git_repository_free(repo);
}
void test_index_tests__elocked(void)
{
git_repository *repo;
git_index *index;
git_filebuf file = GIT_FILEBUF_INIT;
const git_error *err;
int error;
cl_set_cleanup(&cleanup_myrepo, NULL);
cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
cl_git_pass(git_repository_index(&index, repo));
/* Lock the index file so we fail to lock it */
cl_git_pass(git_filebuf_open(&file, index->index_file_path, 0, 0666));
error = git_index_write(index);
cl_assert_equal_i(GIT_ELOCKED, error);
err = giterr_last();
cl_assert_equal_i(err->klass, GITERR_INDEX);
git_filebuf_cleanup(&file);
git_index_free(index);
git_repository_free(repo);
}
void test_index_tests__reload_from_disk(void)
{
git_repository *repo;
git_index *read_index;
git_index *write_index;
cl_set_cleanup(&cleanup_myrepo, NULL);
cl_git_pass(git_futils_mkdir("./myrepo", 0777, GIT_MKDIR_PATH));
cl_git_mkfile("./myrepo/a.txt", "a\n");
cl_git_mkfile("./myrepo/b.txt", "b\n");
cl_git_pass(git_repository_init(&repo, "./myrepo", 0));
cl_git_pass(git_repository_index(&write_index, repo));
cl_assert_equal_i(false, write_index->on_disk);
cl_git_pass(git_index_open(&read_index, write_index->index_file_path));
cl_assert_equal_i(false, read_index->on_disk);
/* Stage two new files against the write_index */
cl_git_pass(git_index_add_bypath(write_index, "a.txt"));
cl_git_pass(git_index_add_bypath(write_index, "b.txt"));
cl_assert_equal_sz(2, git_index_entrycount(write_index));
/* Persist the index changes to disk */
cl_git_pass(git_index_write(write_index));
cl_assert_equal_i(true, write_index->on_disk);
/* Sync the changes back into the read_index */
cl_assert_equal_sz(0, git_index_entrycount(read_index));
cl_git_pass(git_index_read(read_index, true));
cl_assert_equal_i(true, read_index->on_disk);
cl_assert_equal_sz(2, git_index_entrycount(read_index));
/* Remove the index file from the filesystem */
cl_git_pass(p_unlink(write_index->index_file_path));
/* Sync the changes back into the read_index */
cl_git_pass(git_index_read(read_index, true));
cl_assert_equal_i(false, read_index->on_disk);
cl_assert_equal_sz(0, git_index_entrycount(read_index));
git_index_free(read_index);
git_index_free(write_index);
git_repository_free(repo);
}
void test_index_tests__corrupted_extension(void)
{
git_index *index;
cl_git_fail_with(git_index_open(&index, TEST_INDEXBAD_PATH), GIT_ERROR);
}
void test_index_tests__reload_while_ignoring_case(void)
{
git_index *index;
unsigned int caps;
cl_git_pass(git_index_open(&index, TEST_INDEX_PATH));
cl_git_pass(git_vector_verify_sorted(&index->entries));
caps = git_index_caps(index);
cl_git_pass(git_index_set_caps(index, caps &= ~GIT_INDEXCAP_IGNORE_CASE));
cl_git_pass(git_index_read(index, true));
cl_git_pass(git_vector_verify_sorted(&index->entries));
cl_assert(git_index_get_bypath(index, ".HEADER", 0));
cl_assert_equal_p(NULL, git_index_get_bypath(index, ".header", 0));
cl_git_pass(git_index_set_caps(index, caps | GIT_INDEXCAP_IGNORE_CASE));
cl_git_pass(git_index_read(index, true));
cl_git_pass(git_vector_verify_sorted(&index->entries));
cl_assert(git_index_get_bypath(index, ".HEADER", 0));
cl_assert(git_index_get_bypath(index, ".header", 0));
git_index_free(index);
}
void test_index_tests__change_icase_on_instance(void)
{
git_index *index;
unsigned int caps;
const git_index_entry *e;
cl_git_pass(git_index_open(&index, TEST_INDEX_PATH));
cl_git_pass(git_vector_verify_sorted(&index->entries));
caps = git_index_caps(index);
cl_git_pass(git_index_set_caps(index, caps &= ~GIT_INDEXCAP_IGNORE_CASE));
cl_assert_equal_i(false, index->ignore_case);
cl_git_pass(git_vector_verify_sorted(&index->entries));
cl_assert(e = git_index_get_bypath(index, "src/common.h", 0));
cl_assert_equal_p(NULL, e = git_index_get_bypath(index, "SRC/Common.h", 0));
cl_assert(e = git_index_get_bypath(index, "COPYING", 0));
cl_assert_equal_p(NULL, e = git_index_get_bypath(index, "copying", 0));
cl_git_pass(git_index_set_caps(index, caps | GIT_INDEXCAP_IGNORE_CASE));
cl_assert_equal_i(true, index->ignore_case);
cl_git_pass(git_vector_verify_sorted(&index->entries));
cl_assert(e = git_index_get_bypath(index, "COPYING", 0));
cl_assert_equal_s("COPYING", e->path);
cl_assert(e = git_index_get_bypath(index, "copying", 0));
cl_assert_equal_s("COPYING", e->path);
git_index_free(index);
}
void test_index_tests__can_lock_index(void)
{
git_index *index;
git_indexwriter one = GIT_INDEXWRITER_INIT,
two = GIT_INDEXWRITER_INIT;
cl_git_pass(git_index_open(&index, TEST_INDEX_PATH));
cl_git_pass(git_indexwriter_init(&one, index));
cl_git_fail_with(GIT_ELOCKED, git_indexwriter_init(&two, index));
cl_git_fail_with(GIT_ELOCKED, git_index_write(index));
cl_git_pass(git_indexwriter_commit(&one));
cl_git_pass(git_index_write(index));
git_indexwriter_cleanup(&one);
git_indexwriter_cleanup(&two);
git_index_free(index);
}