Commit e4ac4000 by Edward Thomson

checkout tests: test symlinks based on support, not platform

When testing whether symlinks are correctly checked out, examine the
`core.symlinks` configuration option to determine if symlinks are
supported in a repository, don't simply assume that Windows means that
symbolic links are not supported.

Further, when testing the expected default behavior of `core.symlinks`,
test the filesystem's support to determine if symlinks are supported.

Finally, ensure that `core.symlinks=true` fails on a system where
symlinks are actually not supported.  This aligns with the behavior of
Git for Windows.
parent 7b6875f4
......@@ -2,6 +2,7 @@
#include "git2/repository.h"
#include "git2/sys/index.h"
#include "fileops.h"
#include "repository.h"
static git_repository *g_repo;
static git_index *g_index;
......@@ -184,11 +185,18 @@ static void ensure_workdir(const char *path, int mode, const char *oid_str)
ensure_workdir_oid(path, oid_str);
}
static void ensure_workdir_link(const char *path, const char *target)
static void ensure_workdir_link(
git_repository *repo,
const char *path,
const char *target)
{
#ifdef GIT_WIN32
int symlinks;
cl_git_pass(git_repository__cvar(&symlinks, repo, GIT_CVAR_SYMLINKS));
if (!symlinks) {
ensure_workdir_contents(path, target);
#else
} else {
git_buf fullpath = GIT_BUF_INIT;
char actual[1024];
struct stat st;
......@@ -205,7 +213,7 @@ static void ensure_workdir_link(const char *path, const char *target)
cl_assert(strcmp(actual, target) == 0);
git_buf_dispose(&fullpath);
#endif
}
}
void test_checkout_conflict__ignored(void)
......@@ -415,8 +423,8 @@ void test_checkout_conflict__links(void)
cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
/* Conflicts with links always keep the ours side (even with -Xtheirs) */
ensure_workdir_link("link-1", LINK_OURS_TARGET);
ensure_workdir_link("link-2", LINK_OURS_TARGET);
ensure_workdir_link(g_repo, "link-1", LINK_OURS_TARGET);
ensure_workdir_link(g_repo, "link-2", LINK_OURS_TARGET);
}
void test_checkout_conflict__add_add(void)
......
......@@ -3,6 +3,7 @@
#include "git2/checkout.h"
#include "refs.h"
#include "path.h"
#include "repository.h"
#ifdef GIT_WIN32
# include <windows.h>
......@@ -91,6 +92,18 @@ static void assert_name_is(const char *expected)
free(actual);
}
static int symlink_or_fake(git_repository *repo, const char *a, const char *b)
{
int symlinks;
cl_git_pass(git_repository__cvar(&symlinks, repo, GIT_CVAR_SYMLINKS));
if (symlinks)
return p_symlink(a, b);
else
return git_futils_fake_symlink(a, b);
}
void test_checkout_icase__refuses_to_overwrite_files_for_files(void)
{
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;
......@@ -117,7 +130,7 @@ void test_checkout_icase__refuses_to_overwrite_links_for_files(void)
{
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;
cl_must_pass(p_symlink("../tmp", "testrepo/BRANCH_FILE.txt"));
cl_must_pass(symlink_or_fake(repo, "../tmp", "testrepo/BRANCH_FILE.txt"));
cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
......@@ -129,7 +142,7 @@ void test_checkout_icase__overwrites_links_for_files_when_forced(void)
{
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
cl_must_pass(p_symlink("../tmp", "testrepo/NEW.txt"));
cl_must_pass(symlink_or_fake(repo, "../tmp", "testrepo/NEW.txt"));
cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
......@@ -205,7 +218,7 @@ void test_checkout_icase__refuses_to_overwrite_links_for_folders(void)
{
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;
cl_must_pass(p_symlink("..", "testrepo/A"));
cl_must_pass(symlink_or_fake(repo, "..", "testrepo/A"));
cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
......@@ -217,7 +230,7 @@ void test_checkout_icase__overwrites_links_for_folders_when_forced(void)
{
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
cl_must_pass(p_symlink("..", "testrepo/A"));
cl_must_pass(symlink_or_fake(repo, "..", "testrepo/A"));
cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
......
......@@ -136,6 +136,25 @@ void test_checkout_index__honor_coreautocrlf_setting_set_to_true(void)
#endif
}
static bool supports_symlinks(const char *dir)
{
git_buf path = GIT_BUF_INIT;
struct stat st;
bool supports_symlinks = 1;
cl_git_pass(git_buf_joinpath(&path, dir, "test"));
/* see if symlinks are supported in the "symlink" directory */
if (p_symlink("target", path.ptr) < 0 ||
p_lstat(path.ptr, &st) < 0 ||
! (S_ISLNK(st.st_mode)))
supports_symlinks = 0;
git_buf_dispose(&path);
return supports_symlinks;
}
void test_checkout_index__honor_coresymlinks_default(void)
{
git_repository *repo;
......@@ -162,10 +181,9 @@ void test_checkout_index__honor_coresymlinks_default(void)
git_object_free(target);
git_repository_free(repo);
#ifdef GIT_WIN32
if (!supports_symlinks("symlink")) {
check_file_contents("./symlink/link_to_new.txt", "new.txt");
#else
{
} else {
char link_data[1024];
size_t link_size = 1024;
......@@ -175,14 +193,33 @@ void test_checkout_index__honor_coresymlinks_default(void)
cl_assert_equal_s(link_data, "new.txt");
check_file_contents("./symlink/link_to_new.txt", "my new file\n");
}
#endif
cl_fixture_cleanup("symlink");
}
void test_checkout_index__coresymlinks_set_to_true_fails_when_unsupported(void)
{
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
if (supports_symlinks("testrepo")) {
cl_skip();
}
cl_repo_set_bool(g_repo, "core.symlinks", true);
opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_RECREATE_MISSING;
cl_git_fail(git_checkout_index(g_repo, NULL, &opts));
}
void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
{
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
char link_data[GIT_PATH_MAX];
size_t link_size = GIT_PATH_MAX;
if (!supports_symlinks("testrepo")) {
cl_skip();
}
cl_repo_set_bool(g_repo, "core.symlinks", true);
......@@ -190,20 +227,11 @@ void test_checkout_index__honor_coresymlinks_setting_set_to_true(void)
cl_git_pass(git_checkout_index(g_repo, NULL, &opts));
#ifdef GIT_WIN32
check_file_contents("./testrepo/link_to_new.txt", "new.txt");
#else
{
char link_data[1024];
size_t link_size = 1024;
link_size = p_readlink("./testrepo/link_to_new.txt", link_data, link_size);
link_data[link_size] = '\0';
cl_assert_equal_i(link_size, strlen("new.txt"));
cl_assert_equal_s(link_data, "new.txt");
check_file_contents("./testrepo/link_to_new.txt", "my new file\n");
}
#endif
}
void test_checkout_index__honor_coresymlinks_setting_set_to_false(void)
......
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