summaryrefslogtreecommitdiff
path: root/tests-clar
diff options
context:
space:
mode:
authorVicent Martí <vicent@github.com>2013-01-04 16:14:49 -0800
committerVicent Martí <vicent@github.com>2013-01-04 16:14:49 -0800
commitcfc7b835d6702049968cb0a6899d9741e6e0ebf4 (patch)
tree8a0c00a4048b371635b95324928bf70a867ed97b /tests-clar
parent6040616214c69a53d2155c2378b31a0d65e37567 (diff)
parent817d625161f212b86c22733f7dde2f2155a65ac5 (diff)
downloadlibgit2-cfc7b835d6702049968cb0a6899d9741e6e0ebf4.tar.gz
Merge pull request #1118 from arrbee/fix-reset-hard
Fix checkout corner cases, index handling, and reset hard behavior
Diffstat (limited to 'tests-clar')
-rw-r--r--tests-clar/checkout/head.c43
-rw-r--r--tests-clar/checkout/index.c229
-rw-r--r--tests-clar/checkout/tree.c222
-rw-r--r--tests-clar/checkout/typechange.c181
-rw-r--r--tests-clar/clar_libgit2.c10
-rw-r--r--tests-clar/clar_libgit2.h18
-rw-r--r--tests-clar/index/tests.c83
-rw-r--r--tests-clar/object/raw/convert.c4
-rw-r--r--tests-clar/online/clone.c2
-rw-r--r--tests-clar/reset/hard.c4
-rw-r--r--tests-clar/stash/drop.c7
-rw-r--r--tests-clar/stash/foreach.c8
12 files changed, 707 insertions, 104 deletions
diff --git a/tests-clar/checkout/head.c b/tests-clar/checkout/head.c
index 103b9999e..8b3099303 100644
--- a/tests-clar/checkout/head.c
+++ b/tests-clar/checkout/head.c
@@ -1,6 +1,8 @@
#include "clar_libgit2.h"
#include "refs.h"
#include "repo/repo_helpers.h"
+#include "path.h"
+#include "fileops.h"
static git_repository *g_repo;
@@ -14,9 +16,48 @@ void test_checkout_head__cleanup(void)
cl_git_sandbox_cleanup();
}
-void test_checkout_head__checking_out_an_orphaned_head_returns_GIT_EORPHANEDHEAD(void)
+void test_checkout_head__orphaned_head_returns_GIT_EORPHANEDHEAD(void)
{
make_head_orphaned(g_repo, NON_EXISTING_HEAD);
cl_assert_equal_i(GIT_EORPHANEDHEAD, git_checkout_head(g_repo, NULL));
}
+
+void test_checkout_head__with_index_only_tree(void)
+{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+ git_index *index;
+
+ /* let's start by getting things into a known state */
+
+ opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+ cl_git_pass(git_checkout_head(g_repo, &opts));
+
+ /* now let's stage some new stuff including a new directory */
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+
+ p_mkdir("testrepo/newdir", 0777);
+ cl_git_mkfile("testrepo/newdir/newfile.txt", "new file\n");
+
+ cl_git_pass(git_index_add_from_workdir(index, "newdir/newfile.txt"));
+ cl_git_pass(git_index_write(index));
+
+ cl_assert(git_path_isfile("testrepo/newdir/newfile.txt"));
+ cl_assert(git_index_get_bypath(index, "newdir/newfile.txt", 0) != NULL);
+
+ git_index_free(index);
+
+ /* okay, so now we have staged this new file; let's see if we can remove */
+
+ opts.checkout_strategy = GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED;
+ cl_git_pass(git_checkout_head(g_repo, &opts));
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+ cl_git_pass(git_index_read(index)); /* reload if needed */
+
+ cl_assert(!git_path_isfile("testrepo/newdir/newfile.txt"));
+ cl_assert(git_index_get_bypath(index, "newdir/newfile.txt", 0) == NULL);
+
+ git_index_free(index);
+}
diff --git a/tests-clar/checkout/index.c b/tests-clar/checkout/index.c
index a67765b26..fe1f6874f 100644
--- a/tests-clar/checkout/index.c
+++ b/tests-clar/checkout/index.c
@@ -4,7 +4,6 @@
#include "repository.h"
static git_repository *g_repo;
-static git_checkout_opts g_opts;
static void reset_index_to_treeish(git_object *treeish)
{
@@ -25,9 +24,6 @@ void test_checkout_index__initialize(void)
{
git_tree *tree;
- GIT_INIT_STRUCTURE(&g_opts, GIT_CHECKOUT_OPTS_VERSION);
- g_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
-
g_repo = cl_git_sandbox_init("testrepo");
cl_git_pass(git_repository_head_tree(&tree, g_repo));
@@ -66,7 +62,6 @@ void test_checkout_index__cannot_checkout_a_bare_repository(void)
{
test_checkout_index__cleanup();
- GIT_INIT_STRUCTURE(&g_opts, GIT_CHECKOUT_OPTS_VERSION);
g_repo = cl_git_sandbox_init("testrepo.git");
cl_git_fail(git_checkout_index(g_repo, NULL, NULL));
@@ -74,11 +69,15 @@ void test_checkout_index__cannot_checkout_a_bare_repository(void)
void test_checkout_index__can_create_missing_files(void)
{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt"));
cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt"));
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
test_file_contents("./testrepo/README", "hey there\n");
test_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n");
@@ -87,30 +86,37 @@ void test_checkout_index__can_create_missing_files(void)
void test_checkout_index__can_remove_untracked_files(void)
{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
git_futils_mkdir("./testrepo/dir/subdir/subsubdir", NULL, 0755, GIT_MKDIR_PATH);
cl_git_mkfile("./testrepo/dir/one", "one\n");
cl_git_mkfile("./testrepo/dir/subdir/two", "two\n");
cl_assert_equal_i(true, git_path_isdir("./testrepo/dir/subdir/subsubdir"));
- g_opts.checkout_strategy |= GIT_CHECKOUT_REMOVE_UNTRACKED;
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ opts.checkout_strategy =
+ GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_REMOVE_UNTRACKED;
+
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
cl_assert_equal_i(false, git_path_isdir("./testrepo/dir"));
}
void test_checkout_index__honor_the_specified_pathspecs(void)
{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
char *entries[] = { "*.txt" };
- g_opts.paths.strings = entries;
- g_opts.paths.count = 1;
+ opts.paths.strings = entries;
+ opts.paths.count = 1;
cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt"));
cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt"));
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
cl_assert_equal_i(false, git_path_isfile("./testrepo/README"));
test_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n");
@@ -134,6 +140,7 @@ static void set_core_autocrlf_to(bool value)
void test_checkout_index__honor_the_gitattributes_directives(void)
{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
const char *attributes =
"branch_file.txt text eol=crlf\n"
"new.txt text eol=lf\n";
@@ -141,7 +148,9 @@ void test_checkout_index__honor_the_gitattributes_directives(void)
cl_git_mkfile("./testrepo/.gitattributes", attributes);
set_core_autocrlf_to(false);
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
test_file_contents("./testrepo/README", "hey there\n");
test_file_contents("./testrepo/new.txt", "my new file\n");
@@ -151,12 +160,15 @@ void test_checkout_index__honor_the_gitattributes_directives(void)
void test_checkout_index__honor_coreautocrlf_setting_set_to_true(void)
{
#ifdef GIT_WIN32
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
const char *expected_readme_text = "hey there\r\n";
cl_git_pass(p_unlink("./testrepo/.gitattributes"));
set_core_autocrlf_to(true);
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
test_file_contents("./testrepo/README", expected_readme_text);
#endif
@@ -169,9 +181,13 @@ static void set_repo_symlink_handling_cap_to(bool value)
void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
set_repo_symlink_handling_cap_to(true);
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
#ifdef GIT_WIN32
test_file_contents("./testrepo/link_to_new.txt", "new.txt");
@@ -191,51 +207,63 @@ void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
void test_checkout_index__honor_coresymlinks_setting_set_to_false(void)
{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
set_repo_symlink_handling_cap_to(false);
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
test_file_contents("./testrepo/link_to_new.txt", "new.txt");
}
void test_checkout_index__donot_overwrite_modified_file_by_default(void)
{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!");
/* set this up to not return an error code on conflicts, but it
* still will not have permission to overwrite anything...
*/
- g_opts.checkout_strategy = GIT_CHECKOUT_ALLOW_CONFLICTS;
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_ALLOW_CONFLICTS;
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
test_file_contents("./testrepo/new.txt", "This isn't what's stored!");
}
void test_checkout_index__can_overwrite_modified_file(void)
{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!");
- g_opts.checkout_strategy |= GIT_CHECKOUT_UPDATE_MODIFIED;
+ opts.checkout_strategy = GIT_CHECKOUT_FORCE;
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
test_file_contents("./testrepo/new.txt", "my new file\n");
}
void test_checkout_index__options_disable_filters(void)
{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
cl_git_mkfile("./testrepo/.gitattributes", "*.txt text eol=crlf\n");
- g_opts.disable_filters = false;
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+ opts.disable_filters = false;
+
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
test_file_contents("./testrepo/new.txt", "my new file\r\n");
p_unlink("./testrepo/new.txt");
- g_opts.disable_filters = true;
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ opts.disable_filters = true;
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
test_file_contents("./testrepo/new.txt", "my new file\n");
}
@@ -243,6 +271,7 @@ void test_checkout_index__options_disable_filters(void)
void test_checkout_index__options_dir_modes(void)
{
#ifndef GIT_WIN32
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
struct stat st;
git_oid oid;
git_commit *commit;
@@ -252,8 +281,10 @@ void test_checkout_index__options_dir_modes(void)
reset_index_to_treeish((git_object *)commit);
- g_opts.dir_mode = 0701;
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+ opts.dir_mode = 0701;
+
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
cl_git_pass(p_stat("./testrepo/a", &st));
cl_assert_equal_i(st.st_mode & 0777, 0701);
@@ -269,11 +300,13 @@ void test_checkout_index__options_dir_modes(void)
void test_checkout_index__options_override_file_modes(void)
{
#ifndef GIT_WIN32
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
struct stat st;
- g_opts.file_mode = 0700;
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+ opts.file_mode = 0700;
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
cl_git_pass(p_stat("./testrepo/new.txt", &st));
cl_assert_equal_i(st.st_mode & 0777, 0700);
@@ -282,42 +315,48 @@ void test_checkout_index__options_override_file_modes(void)
void test_checkout_index__options_open_flags(void)
{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
cl_git_mkfile("./testrepo/new.txt", "hi\n");
- g_opts.file_open_flags = O_CREAT | O_RDWR | O_APPEND;
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+ opts.file_open_flags = O_CREAT | O_RDWR | O_APPEND;
- g_opts.checkout_strategy |= GIT_CHECKOUT_UPDATE_MODIFIED;
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
test_file_contents("./testrepo/new.txt", "hi\nmy new file\n");
}
-struct conflict_data {
+struct notify_data {
const char *file;
const char *sha;
};
-static int conflict_cb(
- const char *conflict_file,
- const git_oid *blob_oid,
- unsigned int index_mode,
- unsigned int wd_mode,
+static int test_checkout_notify_cb(
+ git_checkout_notify_t why,
+ const char *path,
+ const git_diff_file *baseline,
+ const git_diff_file *target,
+ const git_diff_file *workdir,
void *payload)
{
- struct conflict_data *expectations = (struct conflict_data *)payload;
+ struct notify_data *expectations = (struct notify_data *)payload;
- GIT_UNUSED(index_mode);
- GIT_UNUSED(wd_mode);
+ GIT_UNUSED(workdir);
- cl_assert_equal_s(expectations->file, conflict_file);
- cl_assert_equal_i(0, git_oid_streq(blob_oid, expectations->sha));
+ cl_assert_equal_i(GIT_CHECKOUT_NOTIFY_CONFLICT, why);
+ cl_assert_equal_s(expectations->file, path);
+ cl_assert_equal_i(0, git_oid_streq(&baseline->oid, expectations->sha));
+ cl_assert_equal_i(0, git_oid_streq(&target->oid, expectations->sha));
return 0;
}
void test_checkout_index__can_notify_of_skipped_files(void)
{
- struct conflict_data data;
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+ struct notify_data data;
cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!");
@@ -330,24 +369,28 @@ void test_checkout_index__can_notify_of_skipped_files(void)
data.file = "new.txt";
data.sha = "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd";
- g_opts.checkout_strategy |= GIT_CHECKOUT_ALLOW_CONFLICTS;
- g_opts.conflict_cb = conflict_cb;
- g_opts.conflict_payload = &data;
+ opts.checkout_strategy =
+ GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS;
+ opts.notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICT;
+ opts.notify_cb = test_checkout_notify_cb;
+ opts.notify_payload = &data;
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
}
-static int dont_conflict_cb(
- const char *conflict_file,
- const git_oid *blob_oid,
- unsigned int index_mode,
- unsigned int wd_mode,
+static int dont_notify_cb(
+ git_checkout_notify_t why,
+ const char *path,
+ const git_diff_file *baseline,
+ const git_diff_file *target,
+ const git_diff_file *workdir,
void *payload)
{
- GIT_UNUSED(conflict_file);
- GIT_UNUSED(blob_oid);
- GIT_UNUSED(index_mode);
- GIT_UNUSED(wd_mode);
+ GIT_UNUSED(why);
+ GIT_UNUSED(path);
+ GIT_UNUSED(baseline);
+ GIT_UNUSED(target);
+ GIT_UNUSED(workdir);
GIT_UNUSED(payload);
cl_assert(false);
@@ -357,37 +400,45 @@ static int dont_conflict_cb(
void test_checkout_index__wont_notify_of_expected_line_ending_changes(void)
{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
cl_git_pass(p_unlink("./testrepo/.gitattributes"));
set_core_autocrlf_to(true);
cl_git_mkfile("./testrepo/new.txt", "my new file\r\n");
- g_opts.checkout_strategy |= GIT_CHECKOUT_ALLOW_CONFLICTS;
- g_opts.conflict_cb = dont_conflict_cb;
- g_opts.conflict_payload = NULL;
+ opts.checkout_strategy =
+ GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS;
+ opts.notify_flags = GIT_CHECKOUT_NOTIFY_CONFLICT;
+ opts.notify_cb = dont_notify_cb;
+ opts.notify_payload = NULL;
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
}
-static void progress(const char *path, size_t cur, size_t tot, void *payload)
+static void checkout_progress_counter(
+ const char *path, size_t cur, size_t tot, void *payload)
{
- bool *was_called = (bool*)payload;
GIT_UNUSED(path); GIT_UNUSED(cur); GIT_UNUSED(tot);
- *was_called = true;
+ (*(int *)payload)++;
}
void test_checkout_index__calls_progress_callback(void)
{
- bool was_called = 0;
- g_opts.progress_cb = progress;
- g_opts.progress_payload = &was_called;
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+ int calls = 0;
+
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+ opts.progress_cb = checkout_progress_counter;
+ opts.progress_payload = &calls;
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
- cl_assert_equal_i(was_called, true);
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
+ cl_assert(calls > 0);
}
void test_checkout_index__can_overcome_name_clashes(void)
{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
git_index *index;
cl_git_pass(git_repository_index(&index, g_repo));
@@ -400,7 +451,6 @@ void test_checkout_index__can_overcome_name_clashes(void)
cl_git_pass(git_index_add_from_workdir(index, "path0"));
cl_git_pass(git_index_add_from_workdir(index, "path1/file1"));
-
cl_git_pass(p_unlink("./testrepo/path0"));
cl_git_pass(git_futils_rmdir_r(
"./testrepo/path1", NULL, GIT_RMDIR_REMOVE_FILES));
@@ -412,14 +462,15 @@ void test_checkout_index__can_overcome_name_clashes(void)
cl_assert(git_path_isfile("./testrepo/path1"));
cl_assert(git_path_isfile("./testrepo/path0/file0"));
- g_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_ALLOW_CONFLICTS;
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ opts.checkout_strategy =
+ GIT_CHECKOUT_SAFE_CREATE | GIT_CHECKOUT_ALLOW_CONFLICTS;
+ cl_git_pass(git_checkout_index(g_repo, index, &opts));
cl_assert(git_path_isfile("./testrepo/path1"));
cl_assert(git_path_isfile("./testrepo/path0/file0"));
- g_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
- cl_git_pass(git_checkout_index(g_repo, NULL, &g_opts));
+ opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+ cl_git_pass(git_checkout_index(g_repo, index, &opts));
cl_assert(git_path_isfile("./testrepo/path0"));
cl_assert(git_path_isfile("./testrepo/path1/file1"));
@@ -429,18 +480,44 @@ void test_checkout_index__can_overcome_name_clashes(void)
void test_checkout_index__validates_struct_version(void)
{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
const git_error *err;
- g_opts.version = 1024;
- cl_git_fail(git_checkout_index(g_repo, NULL, &g_opts));
+ opts.version = 1024;
+ cl_git_fail(git_checkout_index(g_repo, NULL, &opts));
err = giterr_last();
cl_assert_equal_i(err->klass, GITERR_INVALID);
- g_opts.version = 0;
+ opts.version = 0;
giterr_clear();
- cl_git_fail(git_checkout_index(g_repo, NULL, &g_opts));
+ cl_git_fail(git_checkout_index(g_repo, NULL, &opts));
err = giterr_last();
cl_assert_equal_i(err->klass, GITERR_INVALID);
}
+
+void test_checkout_index__can_update_prefixed_files(void)
+{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
+ cl_git_mkfile("./testrepo/READ", "content\n");
+ cl_git_mkfile("./testrepo/README.after", "content\n");
+ cl_git_pass(p_mkdir("./testrepo/branch_file", 0777));
+ cl_git_pass(p_mkdir("./testrepo/branch_file/contained_dir", 0777));
+ cl_git_mkfile("./testrepo/branch_file/contained_file", "content\n");
+ cl_git_pass(p_mkdir("./testrepo/branch_file.txt.after", 0777));
+
+ opts.checkout_strategy = GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED;
+
+ cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
+
+ test_file_contents("./testrepo/README", "hey there\n");
+ test_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n");
+ test_file_contents("./testrepo/new.txt", "my new file\n");
+
+ cl_assert(!git_path_exists("testrepo/READ"));
+ cl_assert(!git_path_exists("testrepo/README.after"));
+ cl_assert(!git_path_exists("testrepo/branch_file"));
+ cl_assert(!git_path_exists("testrepo/branch_file.txt.after"));
+}
diff --git a/tests-clar/checkout/tree.c b/tests-clar/checkout/tree.c
index 88dbe4ffc..ff5c43aef 100644
--- a/tests-clar/checkout/tree.c
+++ b/tests-clar/checkout/tree.c
@@ -2,6 +2,8 @@
#include "git2/checkout.h"
#include "repository.h"
+#include "buffer.h"
+#include "fileops.h"
static git_repository *g_repo;
static git_checkout_opts g_opts;
@@ -12,7 +14,7 @@ void test_checkout_tree__initialize(void)
g_repo = cl_git_sandbox_init("testrepo");
GIT_INIT_STRUCTURE(&g_opts, GIT_CHECKOUT_OPTS_VERSION);
- g_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
+ g_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
}
void test_checkout_tree__cleanup(void)
@@ -48,6 +50,34 @@ void test_checkout_tree__can_checkout_a_subdirectory_from_a_commit(void)
cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/fgh/1.txt"));
}
+void test_checkout_tree__can_checkout_and_remove_directory(void)
+{
+ cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/"));
+
+ /* Checkout brach "subtrees" and update HEAD, so that HEAD matches the
+ * current working tree
+ */
+ cl_git_pass(git_revparse_single(&g_object, g_repo, "subtrees"));
+ cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
+
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
+
+ cl_assert_equal_i(true, git_path_isdir("./testrepo/ab/"));
+ cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/2.txt"));
+ cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/fgh/1.txt"));
+
+ /* Checkout brach "master" and update HEAD, so that HEAD matches the
+ * current working tree
+ */
+ cl_git_pass(git_revparse_single(&g_object, g_repo, "master"));
+ cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts));
+
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master"));
+
+ /* This directory should no longer exist */
+ cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/"));
+}
+
void test_checkout_tree__can_checkout_a_subdirectory_from_a_subtree(void)
{
char *entries[] = { "de/" };
@@ -85,3 +115,193 @@ void test_checkout_tree__calls_progress_callback(void)
cl_assert_equal_i(was_called, true);
}
+
+void test_checkout_tree__doesnt_write_unrequested_files_to_worktree(void)
+{
+ git_oid master_oid;
+ git_oid chomped_oid;
+ git_commit* p_master_commit;
+ git_commit* p_chomped_commit;
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
+ git_oid_fromstr(&master_oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
+ git_oid_fromstr(&chomped_oid, "e90810b8df3e80c413d903f631643c716887138d");
+ cl_git_pass(git_commit_lookup(&p_master_commit, g_repo, &master_oid));
+ cl_git_pass(git_commit_lookup(&p_chomped_commit, g_repo, &chomped_oid));
+
+ /* GIT_CHECKOUT_NONE should not add any file to the working tree from the
+ * index as it is supposed to be a dry run.
+ */
+ opts.checkout_strategy = GIT_CHECKOUT_NONE;
+ git_checkout_tree(g_repo, (git_object*)p_chomped_commit, &opts);
+ cl_assert_equal_i(false, git_path_isfile("testrepo/readme.txt"));
+}
+
+static void assert_on_branch(git_repository *repo, const char *branch)
+{
+ git_reference *head;
+ git_buf bname = GIT_BUF_INIT;
+
+ cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE));
+ cl_assert_(git_reference_type(head) == GIT_REF_SYMBOLIC, branch);
+
+ cl_git_pass(git_buf_joinpath(&bname, "refs/heads", branch));
+ cl_assert_equal_s(bname.ptr, git_reference_symbolic_target(head));
+
+ git_reference_free(head);
+ git_buf_free(&bname);
+}
+
+void test_checkout_tree__can_switch_branches(void)
+{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+ git_oid oid;
+ git_object *obj = NULL;
+
+ assert_on_branch(g_repo, "master");
+
+ /* do first checkout with FORCE because we don't know if testrepo
+ * base data is clean for a checkout or not
+ */
+ opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+
+ cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir"));
+ cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY));
+
+ cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir"));
+
+ cl_assert(git_path_isfile("testrepo/README"));
+ cl_assert(git_path_isfile("testrepo/branch_file.txt"));
+ cl_assert(git_path_isfile("testrepo/new.txt"));
+ cl_assert(git_path_isfile("testrepo/a/b.txt"));
+
+ cl_assert(!git_path_isdir("testrepo/ab"));
+
+ assert_on_branch(g_repo, "dir");
+
+ git_object_free(obj);
+
+ /* do second checkout safe because we should be clean after first */
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE;
+
+ cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/subtrees"));
+ cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY));
+
+ cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/subtrees"));
+
+ cl_assert(git_path_isfile("testrepo/README"));
+ cl_assert(git_path_isfile("testrepo/branch_file.txt"));
+ cl_assert(git_path_isfile("testrepo/new.txt"));
+ cl_assert(git_path_isfile("testrepo/ab/4.txt"));
+ cl_assert(git_path_isfile("testrepo/ab/c/3.txt"));
+ cl_assert(git_path_isfile("testrepo/ab/de/2.txt"));
+ cl_assert(git_path_isfile("testrepo/ab/de/fgh/1.txt"));
+
+ cl_assert(!git_path_isdir("testrepo/a"));
+
+ assert_on_branch(g_repo, "subtrees");
+
+ git_object_free(obj);
+}
+
+void test_checkout_tree__can_remove_untracked(void)
+{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_REMOVE_UNTRACKED;
+
+ cl_git_mkfile("testrepo/untracked_file", "as you wish");
+ cl_assert(git_path_isfile("testrepo/untracked_file"));
+
+ cl_git_pass(git_checkout_head(g_repo, &opts));
+
+ cl_assert(!git_path_isfile("testrepo/untracked_file"));
+}
+
+void test_checkout_tree__can_remove_ignored(void)
+{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+ int ignored = 0;
+
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_REMOVE_IGNORED;
+
+ cl_git_mkfile("testrepo/ignored_file", "as you wish");
+
+ cl_git_pass(git_ignore_add_rule(g_repo, "ignored_file\n"));
+
+ cl_git_pass(git_ignore_path_is_ignored(&ignored, g_repo, "ignored_file"));
+ cl_assert_equal_i(1, ignored);
+
+ cl_assert(git_path_isfile("testrepo/ignored_file"));
+
+ cl_git_pass(git_checkout_head(g_repo, &opts));
+
+ cl_assert(!git_path_isfile("testrepo/ignored_file"));
+}
+
+/* this is essentially the code from git__unescape modified slightly */
+static void strip_cr_from_buf(git_buf *buf)
+{
+ char *scan, *pos = buf->ptr;
+
+ for (scan = pos; *scan; pos++, scan++) {
+ if (*scan == '\r')
+ scan++; /* skip '\r' */
+ if (pos != scan)
+ *pos = *scan;
+ }
+
+ *pos = '\0';
+ buf->size = (pos - buf->ptr);
+}
+
+void test_checkout_tree__can_update_only(void)
+{
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+ git_oid oid;
+ git_object *obj = NULL;
+ git_buf buf = GIT_BUF_INIT;
+
+ /* first let's get things into a known state - by checkout out the HEAD */
+
+ assert_on_branch(g_repo, "master");
+
+ opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+ cl_git_pass(git_checkout_head(g_repo, &opts));
+
+ cl_assert(!git_path_isdir("testrepo/a"));
+
+ cl_git_pass(git_futils_readbuffer(&buf, "testrepo/branch_file.txt"));
+ strip_cr_from_buf(&buf);
+ cl_assert_equal_s("hi\nbye!\n", buf.ptr);
+ git_buf_free(&buf);
+
+ /* now checkout branch but with update only */
+
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_UPDATE_ONLY;
+
+ cl_git_pass(git_reference_name_to_id(&oid, g_repo, "refs/heads/dir"));
+ cl_git_pass(git_object_lookup(&obj, g_repo, &oid, GIT_OBJ_ANY));
+
+ cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
+ cl_git_pass(git_repository_set_head(g_repo, "refs/heads/dir"));
+
+ assert_on_branch(g_repo, "dir");
+
+ /* this normally would have been created (which was tested separately in
+ * the test_checkout_tree__can_switch_branches test), but with
+ * UPDATE_ONLY it will not have been created.
+ */
+ cl_assert(!git_path_isdir("testrepo/a"));
+
+ /* but this file still should have been updated */
+ cl_git_pass(git_futils_readbuffer(&buf, "testrepo/branch_file.txt"));
+ strip_cr_from_buf(&buf);
+ cl_assert_equal_s("hi\n", buf.ptr);
+
+ git_buf_free(&buf);
+
+ git_object_free(obj);
+}
diff --git a/tests-clar/checkout/typechange.c b/tests-clar/checkout/typechange.c
index 98c15bcb7..b92cc23fa 100644
--- a/tests-clar/checkout/typechange.c
+++ b/tests-clar/checkout/typechange.c
@@ -2,6 +2,7 @@
#include "git2/checkout.h"
#include "path.h"
#include "posix.h"
+#include "fileops.h"
static git_repository *g_repo = NULL;
@@ -34,28 +35,97 @@ void test_checkout_typechange__cleanup(void)
cl_fixture_cleanup("submod2_target");
}
-void test_checkout_typechange__checkout_typechanges(void)
+static void assert_file_exists(const char *path)
+{
+ cl_assert_(git_path_isfile(path), path);
+}
+
+static void assert_dir_exists(const char *path)
+{
+ cl_assert_(git_path_isdir(path), path);
+}
+
+static void assert_workdir_matches_tree(
+ git_repository *repo, const git_oid *id, const char *root, bool recurse)
{
- int i;
git_object *obj;
- git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+ git_tree *tree;
+ size_t i, max_i;
+ git_buf path = GIT_BUF_INIT;
+
+ if (!root)
+ root = git_repository_workdir(repo);
+ cl_assert(root);
+
+ cl_git_pass(git_object_lookup(&obj, repo, id, GIT_OBJ_ANY));
+ cl_git_pass(git_object_peel((git_object **)&tree, obj, GIT_OBJ_TREE));
+ git_object_free(obj);
+
+ max_i = git_tree_entrycount(tree);
+
+ for (i = 0; i < max_i; ++i) {
+ const git_tree_entry *te = git_tree_entry_byindex(tree, i);
+ cl_assert(te);
+
+ cl_git_pass(git_buf_joinpath(&path, root, git_tree_entry_name(te)));
+
+ switch (git_tree_entry_type(te)) {
+ case GIT_OBJ_COMMIT:
+ assert_dir_exists(path.ptr);
+ break;
+ case GIT_OBJ_TREE:
+ assert_dir_exists(path.ptr);
+ if (recurse)
+ assert_workdir_matches_tree(
+ repo, git_tree_entry_id(te), path.ptr, true);
+ break;
+ case GIT_OBJ_BLOB:
+ switch (git_tree_entry_filemode(te)) {
+ case GIT_FILEMODE_BLOB:
+ case GIT_FILEMODE_BLOB_EXECUTABLE:
+ assert_file_exists(path.ptr);
+ /* because of cross-platform, don't confirm exec bit yet */
+ break;
+ case GIT_FILEMODE_LINK:
+ cl_assert_(git_path_exists(path.ptr), path.ptr);
+ /* because of cross-platform, don't confirm link yet */
+ break;
+ default:
+ cl_assert(false); /* really?! */
+ }
+ break;
+ default:
+ cl_assert(false); /* really?!! */
+ }
+ }
- opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+ git_tree_free(tree);
+ git_buf_free(&path);
+}
- /* if you don't include GIT_CHECKOUT_REMOVE_UNTRACKED then on the final
- * checkout which is supposed to remove all the files, we will not
- * actually remove them!
- */
+void test_checkout_typechange__checkout_typechanges_safe(void)
+{
+ int i;
+ git_object *obj;
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
for (i = 0; g_typechange_oids[i] != NULL; ++i) {
cl_git_pass(git_revparse_single(&obj, g_repo, g_typechange_oids[i]));
- /* fprintf(stderr, "checking out '%s'\n", g_typechange_oids[i]); */
+
+ opts.checkout_strategy = GIT_CHECKOUT_FORCE;
+
+ /* There are bugs in some submodule->tree changes that prevent
+ * SAFE from passing here, even though the following should work:
+ */
+ /* !i ? GIT_CHECKOUT_FORCE : GIT_CHECKOUT_SAFE; */
cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
cl_git_pass(
git_repository_set_head_detached(g_repo, git_object_id(obj)));
+ assert_workdir_matches_tree(g_repo, git_object_id(obj), NULL, true);
+
git_object_free(obj);
if (!g_typechange_empty[i]) {
@@ -75,3 +145,96 @@ void test_checkout_typechange__checkout_typechanges(void)
}
}
}
+
+typedef struct {
+ int conflicts;
+ int dirty;
+ int updates;
+ int untracked;
+ int ignored;
+} notify_counts;
+
+static int notify_counter(
+ git_checkout_notify_t why,
+ const char *path,
+ const git_diff_file *baseline,
+ const git_diff_file *target,
+ const git_diff_file *workdir,
+ void *payload)
+{
+ notify_counts *cts = payload;
+
+ GIT_UNUSED(path);
+ GIT_UNUSED(baseline);
+ GIT_UNUSED(target);
+ GIT_UNUSED(workdir);
+
+ switch (why) {
+ case GIT_CHECKOUT_NOTIFY_CONFLICT: cts->conflicts++; break;
+ case GIT_CHECKOUT_NOTIFY_DIRTY: cts->dirty++; break;
+ case GIT_CHECKOUT_NOTIFY_UPDATED: cts->updates++; break;
+ case GIT_CHECKOUT_NOTIFY_UNTRACKED: cts->untracked++; break;
+ case GIT_CHECKOUT_NOTIFY_IGNORED: cts->ignored++; break;
+ default: break;
+ }
+
+ return 0;
+}
+
+static void force_create_file(const char *file)
+{
+ int error = git_futils_rmdir_r(file, NULL,
+ GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_REMOVE_BLOCKERS);
+ cl_assert(!error || error == GIT_ENOTFOUND);
+ cl_git_pass(git_futils_mkpath2file(file, 0777));
+ cl_git_rewritefile(file, "yowza!");
+}
+
+void test_checkout_typechange__checkout_with_conflicts(void)
+{
+ int i;
+ git_object *obj;
+ git_checkout_opts opts = GIT_CHECKOUT_OPTS_INIT;
+ notify_counts cts = {0};
+
+ opts.notify_flags =
+ GIT_CHECKOUT_NOTIFY_CONFLICT | GIT_CHECKOUT_NOTIFY_UNTRACKED;
+ opts.notify_cb = notify_counter;
+ opts.notify_payload = &cts;
+
+ for (i = 0; g_typechange_oids[i] != NULL; ++i) {
+ cl_git_pass(git_revparse_single(&obj, g_repo, g_typechange_oids[i]));
+
+ force_create_file("typechanges/a/blocker");
+ force_create_file("typechanges/b");
+ force_create_file("typechanges/c/sub/sub/file");
+ git_futils_rmdir_r("typechanges/d", NULL, GIT_RMDIR_REMOVE_FILES);
+ p_mkdir("typechanges/d", 0777); /* intentionally empty dir */
+ force_create_file("typechanges/untracked");
+
+ opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+ memset(&cts, 0, sizeof(cts));
+
+ cl_git_fail(git_checkout_tree(g_repo, obj, &opts));
+ cl_assert(cts.conflicts > 0);
+ cl_assert(cts.untracked > 0);
+
+ opts.checkout_strategy =
+ GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED;
+ memset(&cts, 0, sizeof(cts));
+
+ cl_assert(git_path_exists("typechanges/untracked"));
+
+ cl_git_pass(git_checkout_tree(g_repo, obj, &opts));
+ cl_assert_equal_i(0, cts.conflicts);
+
+ cl_assert(!git_path_exists("typechanges/untracked"));
+
+ cl_git_pass(
+ git_repository_set_head_detached(g_repo, git_object_id(obj)));
+
+ assert_workdir_matches_tree(g_repo, git_object_id(obj), NULL, true);
+
+ git_object_free(obj);
+ }
+}
diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c
index ce3ec4af4..88ffb2bca 100644
--- a/tests-clar/clar_libgit2.c
+++ b/tests-clar/clar_libgit2.c
@@ -2,6 +2,16 @@
#include "posix.h"
#include "path.h"
+void cl_git_report_failure(
+ int error, const char *file, int line, const char *fncall)
+{
+ char msg[4096];
+ const git_error *last = giterr_last();
+ p_snprintf(msg, 4096, "error %d - %s",
+ error, last ? last->message : "<no message>");
+ clar__assert(0, file, line, fncall, msg, 1);
+}
+
void cl_git_mkfile(const char *filename, const char *content)
{
int fd;
diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h
index 91a542654..321ec5f2f 100644
--- a/tests-clar/clar_libgit2.h
+++ b/tests-clar/clar_libgit2.h
@@ -6,17 +6,17 @@
#include "common.h"
/**
- * Special wrapper for `clar_must_pass` that passes
- * the last library error as the test failure message.
+ * Replace for `clar_must_pass` that passes the last library error as the
+ * test failure message.
*
- * Use this wrapper around all `git_` library calls that
- * return error codes!
+ * Use this wrapper around all `git_` library calls that return error codes!
*/
#define cl_git_pass(expr) do { \
+ int _lg2_error; \
giterr_clear(); \
- if ((expr) != 0) \
- clar__assert(0, __FILE__, __LINE__, "Function call failed: " #expr, giterr_last() ? giterr_last()->message : NULL, 1); \
- } while(0)
+ if ((_lg2_error = (expr)) != 0) \
+ cl_git_report_failure(_lg2_error, __FILE__, __LINE__, "Function call failed: " #expr); \
+ } while (0)
/**
* Wrapper for `clar_must_fail` -- this one is
@@ -25,6 +25,10 @@
*/
#define cl_git_fail(expr) cl_must_fail(expr)
+#define cl_git_fail_with(expr, error) cl_assert_equal_i(error,expr)
+
+void cl_git_report_failure(int, const char *, int, const char *);
+
#define cl_assert_equal_sz(sz1,sz2) cl_assert((sz1) == (sz2))
/*
diff --git a/tests-clar/index/tests.c b/tests-clar/index/tests.c
index 989734c1b..5c3d4cf41 100644
--- a/tests-clar/index/tests.c
+++ b/tests-clar/index/tests.c
@@ -290,3 +290,86 @@ void test_index_tests__write_invalid_filename(void)
cl_fixture_cleanup("read_tree");
}
+
+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_from_workdir(index, "hello"));
+ cl_git_pass(git_index_write(index));
+
+ cl_git_pass(git_index_read(index)); /* 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)); /* 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_from_workdir(index, "a/1.txt"));
+ cl_git_pass(git_index_add_from_workdir(index, "a/2.txt"));
+ cl_git_pass(git_index_add_from_workdir(index, "a/3.txt"));
+ cl_git_pass(git_index_add_from_workdir(index, "b.txt"));
+ cl_git_pass(git_index_write(index));
+
+ cl_git_pass(git_index_read(index)); /* 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)); /* 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)); /* 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");
+}
diff --git a/tests-clar/object/raw/convert.c b/tests-clar/object/raw/convert.c
index 7f310ddf0..74442c153 100644
--- a/tests-clar/object/raw/convert.c
+++ b/tests-clar/object/raw/convert.c
@@ -21,9 +21,9 @@ void test_object_raw_convert__succeed_on_oid_to_string_conversion(void)
str = git_oid_tostr(out, 0, &in);
cl_assert(str && *str == '\0' && str != out);
- /* NULL oid pointer, returns static empty string */
+ /* NULL oid pointer, sets existing buffer to empty string */
str = git_oid_tostr(out, sizeof(out), NULL);
- cl_assert(str && *str == '\0' && str != out);
+ cl_assert(str && *str == '\0' && str == out);
/* n == 1, returns out as an empty string */
str = git_oid_tostr(out, 1, &in);
diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c
index c216a1ea7..082ed52b3 100644
--- a/tests-clar/online/clone.c
+++ b/tests-clar/online/clone.c
@@ -91,7 +91,7 @@ void test_online_clone__can_checkout_a_cloned_repo(void)
bool checkout_progress_cb_was_called = false,
fetch_progress_cb_was_called = false;
- g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
+ g_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
g_options.checkout_opts.progress_cb = &checkout_progress;
g_options.checkout_opts.progress_payload = &checkout_progress_cb_was_called;
g_options.fetch_progress_cb = &fetch_progress;
diff --git a/tests-clar/reset/hard.c b/tests-clar/reset/hard.c
index 9381007db..6d2123e87 100644
--- a/tests-clar/reset/hard.c
+++ b/tests-clar/reset/hard.c
@@ -54,9 +54,7 @@ void test_reset_hard__resetting_reverts_modified_files(void)
static const char *after[4] = {
"current_file\n",
"modified_file\n",
- /* wrong value because reset is still slightly incorrect */
- "staged_new_file\n",
- /* right value: NULL, */
+ NULL,
"staged_changes_modified_file\n"
};
const char *wd = git_repository_workdir(repo);
diff --git a/tests-clar/stash/drop.c b/tests-clar/stash/drop.c
index c146e90ec..2af95c737 100644
--- a/tests-clar/stash/drop.c
+++ b/tests-clar/stash/drop.c
@@ -36,15 +36,22 @@ static void push_three_states(void)
cl_git_pass(git_repository_index(&index, repo));
cl_git_pass(git_index_add_from_workdir(index, "zero.txt"));
commit_staged_files(&oid, index, signature);
+ cl_assert(git_path_exists("stash/zero.txt"));
cl_git_mkfile("stash/one.txt", "content\n");
cl_git_pass(git_stash_save(&oid, repo, signature, "First", GIT_STASH_INCLUDE_UNTRACKED));
+ cl_assert(!git_path_exists("stash/one.txt"));
+ cl_assert(git_path_exists("stash/zero.txt"));
cl_git_mkfile("stash/two.txt", "content\n");
cl_git_pass(git_stash_save(&oid, repo, signature, "Second", GIT_STASH_INCLUDE_UNTRACKED));
+ cl_assert(!git_path_exists("stash/two.txt"));
+ cl_assert(git_path_exists("stash/zero.txt"));
cl_git_mkfile("stash/three.txt", "content\n");
cl_git_pass(git_stash_save(&oid, repo, signature, "Third", GIT_STASH_INCLUDE_UNTRACKED));
+ cl_assert(!git_path_exists("stash/three.txt"));
+ cl_assert(git_path_exists("stash/zero.txt"));
git_index_free(index);
}
diff --git a/tests-clar/stash/foreach.c b/tests-clar/stash/foreach.c
index c7d59a3a1..f1983625f 100644
--- a/tests-clar/stash/foreach.c
+++ b/tests-clar/stash/foreach.c
@@ -38,10 +38,10 @@ void test_stash_foreach__cleanup(void)
}
static int callback_cb(
- size_t index,
- const char* message,
- const git_oid *stash_oid,
- void *payload)
+ size_t index,
+ const char* message,
+ const git_oid *stash_oid,
+ void *payload)
{
struct callback_data *data = (struct callback_data *)payload;