diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2018-07-02 12:57:56 -0700 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2018-10-20 05:51:46 -0700 |
commit | e4ac40002865b3b8114ef434a97bcaedaafd324a (patch) | |
tree | b1120b6f7853a0708db076c8277b90c87ba1e5db | |
parent | 7b6875f425a0a7acfc776cf213da4b200e9bb6e9 (diff) | |
download | libgit2-e4ac40002865b3b8114ef434a97bcaedaafd324a.tar.gz |
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.
-rw-r--r-- | tests/checkout/conflict.c | 104 | ||||
-rw-r--r-- | tests/checkout/icase.c | 21 | ||||
-rw-r--r-- | tests/checkout/index.c | 68 |
3 files changed, 121 insertions, 72 deletions
diff --git a/tests/checkout/conflict.c b/tests/checkout/conflict.c index 90603d4b7..6670b2ec7 100644 --- a/tests/checkout/conflict.c +++ b/tests/checkout/conflict.c @@ -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,28 +185,35 @@ 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 - ensure_workdir_contents(path, target); -#else - git_buf fullpath = GIT_BUF_INIT; - char actual[1024]; - struct stat st; - int len; + int symlinks; - cl_git_pass( - git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path)); + cl_git_pass(git_repository__cvar(&symlinks, repo, GIT_CVAR_SYMLINKS)); - cl_git_pass(p_lstat(git_buf_cstr(&fullpath), &st)); - cl_assert(S_ISLNK(st.st_mode)); + if (!symlinks) { + ensure_workdir_contents(path, target); + } else { + git_buf fullpath = GIT_BUF_INIT; + char actual[1024]; + struct stat st; + int len; - cl_assert((len = p_readlink(git_buf_cstr(&fullpath), actual, 1024)) > 0); - actual[len] = '\0'; - cl_assert(strcmp(actual, target) == 0); + cl_git_pass( + git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path)); - git_buf_dispose(&fullpath); -#endif + cl_git_pass(p_lstat(git_buf_cstr(&fullpath), &st)); + cl_assert(S_ISLNK(st.st_mode)); + + cl_assert((len = p_readlink(git_buf_cstr(&fullpath), actual, 1024)) > 0); + actual[len] = '\0'; + cl_assert(strcmp(actual, target) == 0); + + git_buf_dispose(&fullpath); + } } 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) @@ -684,7 +692,7 @@ void test_checkout_conflict__renames(void) void test_checkout_conflict__rename_keep_ours(void) { git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; - + struct checkout_index_entry checkout_index_entries[] = { { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, { 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" }, @@ -728,122 +736,122 @@ void test_checkout_conflict__rename_keep_ours(void) { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "7-both-renamed.txt" }, { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" } }; - + struct checkout_name_entry checkout_name_entries[] = { { "3a-renamed-in-ours-deleted-in-theirs.txt", "3a-newname-in-ours-deleted-in-theirs.txt", "" }, - + { "3b-renamed-in-theirs-deleted-in-ours.txt", "", "3b-newname-in-theirs-deleted-in-ours.txt" }, - + { "4a-renamed-in-ours-added-in-theirs.txt", "4a-newname-in-ours-added-in-theirs.txt", "" }, - + { "4b-renamed-in-theirs-added-in-ours.txt", "", "4b-newname-in-theirs-added-in-ours.txt" }, - + { "5a-renamed-in-ours-added-in-theirs.txt", "5a-newname-in-ours-added-in-theirs.txt", "5a-renamed-in-ours-added-in-theirs.txt" }, - + { "5b-renamed-in-theirs-added-in-ours.txt", "5b-renamed-in-theirs-added-in-ours.txt", "5b-newname-in-theirs-added-in-ours.txt" }, - + { "6-both-renamed-1-to-2.txt", "6-both-renamed-1-to-2-ours.txt", "6-both-renamed-1-to-2-theirs.txt" }, - + { "7-both-renamed-side-1.txt", "7-both-renamed.txt", "7-both-renamed-side-1.txt" }, - + { "7-both-renamed-side-2.txt", "7-both-renamed-side-2.txt", "7-both-renamed.txt" } }; - + opts.checkout_strategy |= GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS; - + create_index(checkout_index_entries, 41); create_index_names(checkout_name_entries, 9); cl_git_pass(git_index_write(g_index)); - + cl_git_pass(git_checkout_index(g_repo, g_index, &opts)); - + ensure_workdir("0a-no-change.txt", 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e"); - + ensure_workdir("0b-duplicated-in-ours.txt", 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6"); - + ensure_workdir("0b-rewritten-in-ours.txt", 0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e"); - + ensure_workdir("0c-duplicated-in-theirs.txt", 0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31"); - + ensure_workdir("0c-rewritten-in-theirs.txt", 0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09"); - + ensure_workdir("1a-newname-in-ours-edited-in-theirs.txt", 0100644, "0d872f8e871a30208305978ecbf9e66d864f1638"); - + ensure_workdir("1a-newname-in-ours.txt", 0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb"); - + ensure_workdir("1b-newname-in-theirs-edited-in-ours.txt", 0100644, "ed9523e62e453e50dd9be1606af19399b96e397a"); - + ensure_workdir("1b-newname-in-theirs.txt", 0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136"); - + ensure_workdir("2-newname-in-both.txt", 0100644, "178940b450f238a56c0d75b7955cb57b38191982"); ensure_workdir("3a-newname-in-ours-deleted-in-theirs.txt", 0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9"); - + ensure_workdir("3b-newname-in-theirs-deleted-in-ours.txt", 0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495"); - + ensure_workdir("4a-newname-in-ours-added-in-theirs.txt", 0100644, "227792b52aaa0b238bea00ec7e509b02623f168c"); - + ensure_workdir("4b-newname-in-theirs-added-in-ours.txt", 0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9"); - + ensure_workdir("5a-newname-in-ours-added-in-theirs.txt", 0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436"); - + ensure_workdir("5b-newname-in-theirs-added-in-ours.txt", 0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced"); ensure_workdir("6-both-renamed-1-to-2-ours.txt", 0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450"); - + ensure_workdir("7-both-renamed.txt", 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11"); } diff --git a/tests/checkout/icase.c b/tests/checkout/icase.c index d804d086e..4aa78a869 100644 --- a/tests/checkout/icase.c +++ b/tests/checkout/icase.c @@ -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)); diff --git a/tests/checkout/index.c b/tests/checkout/index.c index 69252e3d9..452362662 100644 --- a/tests/checkout/index.c +++ b/tests/checkout/index.c @@ -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 - check_file_contents("./symlink/link_to_new.txt", "new.txt"); -#else - { + if (!supports_symlinks("symlink")) { + check_file_contents("./symlink/link_to_new.txt", "new.txt"); + } 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 + 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"); } void test_checkout_index__honor_coresymlinks_setting_set_to_false(void) @@ -474,7 +502,7 @@ void test_checkout_index__can_overcome_name_clashes(void) cl_assert(git_path_isfile("./testrepo/path0/file0")); opts.checkout_strategy = - GIT_CHECKOUT_SAFE | + GIT_CHECKOUT_SAFE | GIT_CHECKOUT_RECREATE_MISSING | GIT_CHECKOUT_ALLOW_CONFLICTS; cl_git_pass(git_checkout_index(g_repo, index, &opts)); |