Skip to content

Commit e4ac400

Browse files
committed
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.
1 parent 7b6875f commit e4ac400

File tree

3 files changed

+121
-72
lines changed

3 files changed

+121
-72
lines changed

tests/checkout/conflict.c

Lines changed: 56 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "git2/repository.h"
33
#include "git2/sys/index.h"
44
#include "fileops.h"
5+
#include "repository.h"
56

67
static git_repository *g_repo;
78
static git_index *g_index;
@@ -184,28 +185,35 @@ static void ensure_workdir(const char *path, int mode, const char *oid_str)
184185
ensure_workdir_oid(path, oid_str);
185186
}
186187

187-
static void ensure_workdir_link(const char *path, const char *target)
188+
static void ensure_workdir_link(
189+
git_repository *repo,
190+
const char *path,
191+
const char *target)
188192
{
189-
#ifdef GIT_WIN32
190-
ensure_workdir_contents(path, target);
191-
#else
192-
git_buf fullpath = GIT_BUF_INIT;
193-
char actual[1024];
194-
struct stat st;
195-
int len;
193+
int symlinks;
196194

197-
cl_git_pass(
198-
git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path));
195+
cl_git_pass(git_repository__cvar(&symlinks, repo, GIT_CVAR_SYMLINKS));
199196

200-
cl_git_pass(p_lstat(git_buf_cstr(&fullpath), &st));
201-
cl_assert(S_ISLNK(st.st_mode));
197+
if (!symlinks) {
198+
ensure_workdir_contents(path, target);
199+
} else {
200+
git_buf fullpath = GIT_BUF_INIT;
201+
char actual[1024];
202+
struct stat st;
203+
int len;
202204

203-
cl_assert((len = p_readlink(git_buf_cstr(&fullpath), actual, 1024)) > 0);
204-
actual[len] = '\0';
205-
cl_assert(strcmp(actual, target) == 0);
205+
cl_git_pass(
206+
git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path));
206207

207-
git_buf_dispose(&fullpath);
208-
#endif
208+
cl_git_pass(p_lstat(git_buf_cstr(&fullpath), &st));
209+
cl_assert(S_ISLNK(st.st_mode));
210+
211+
cl_assert((len = p_readlink(git_buf_cstr(&fullpath), actual, 1024)) > 0);
212+
actual[len] = '\0';
213+
cl_assert(strcmp(actual, target) == 0);
214+
215+
git_buf_dispose(&fullpath);
216+
}
209217
}
210218

211219
void test_checkout_conflict__ignored(void)
@@ -415,8 +423,8 @@ void test_checkout_conflict__links(void)
415423
cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
416424

417425
/* Conflicts with links always keep the ours side (even with -Xtheirs) */
418-
ensure_workdir_link("link-1", LINK_OURS_TARGET);
419-
ensure_workdir_link("link-2", LINK_OURS_TARGET);
426+
ensure_workdir_link(g_repo, "link-1", LINK_OURS_TARGET);
427+
ensure_workdir_link(g_repo, "link-2", LINK_OURS_TARGET);
420428
}
421429

422430
void test_checkout_conflict__add_add(void)
@@ -684,7 +692,7 @@ void test_checkout_conflict__renames(void)
684692
void test_checkout_conflict__rename_keep_ours(void)
685693
{
686694
git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT;
687-
695+
688696
struct checkout_index_entry checkout_index_entries[] = {
689697
{ 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" },
690698
{ 0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6", 0, "0b-duplicated-in-ours.txt" },
@@ -728,122 +736,122 @@ void test_checkout_conflict__rename_keep_ours(void)
728736
{ 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 2, "7-both-renamed.txt" },
729737
{ 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" }
730738
};
731-
739+
732740
struct checkout_name_entry checkout_name_entries[] = {
733741
{
734742
"3a-renamed-in-ours-deleted-in-theirs.txt",
735743
"3a-newname-in-ours-deleted-in-theirs.txt",
736744
""
737745
},
738-
746+
739747
{
740748
"3b-renamed-in-theirs-deleted-in-ours.txt",
741749
"",
742750
"3b-newname-in-theirs-deleted-in-ours.txt"
743751
},
744-
752+
745753
{
746754
"4a-renamed-in-ours-added-in-theirs.txt",
747755
"4a-newname-in-ours-added-in-theirs.txt",
748756
""
749757
},
750-
758+
751759
{
752760
"4b-renamed-in-theirs-added-in-ours.txt",
753761
"",
754762
"4b-newname-in-theirs-added-in-ours.txt"
755763
},
756-
764+
757765
{
758766
"5a-renamed-in-ours-added-in-theirs.txt",
759767
"5a-newname-in-ours-added-in-theirs.txt",
760768
"5a-renamed-in-ours-added-in-theirs.txt"
761769
},
762-
770+
763771
{
764772
"5b-renamed-in-theirs-added-in-ours.txt",
765773
"5b-renamed-in-theirs-added-in-ours.txt",
766774
"5b-newname-in-theirs-added-in-ours.txt"
767775
},
768-
776+
769777
{
770778
"6-both-renamed-1-to-2.txt",
771779
"6-both-renamed-1-to-2-ours.txt",
772780
"6-both-renamed-1-to-2-theirs.txt"
773781
},
774-
782+
775783
{
776784
"7-both-renamed-side-1.txt",
777785
"7-both-renamed.txt",
778786
"7-both-renamed-side-1.txt"
779787
},
780-
788+
781789
{
782790
"7-both-renamed-side-2.txt",
783791
"7-both-renamed-side-2.txt",
784792
"7-both-renamed.txt"
785793
}
786794
};
787-
795+
788796
opts.checkout_strategy |= GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS;
789-
797+
790798
create_index(checkout_index_entries, 41);
791799
create_index_names(checkout_name_entries, 9);
792800
cl_git_pass(git_index_write(g_index));
793-
801+
794802
cl_git_pass(git_checkout_index(g_repo, g_index, &opts));
795-
803+
796804
ensure_workdir("0a-no-change.txt",
797805
0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e");
798-
806+
799807
ensure_workdir("0b-duplicated-in-ours.txt",
800808
0100644, "f0ce2b8e4986084d9b308fb72709e414c23eb5e6");
801-
809+
802810
ensure_workdir("0b-rewritten-in-ours.txt",
803811
0100644, "e376fbdd06ebf021c92724da9f26f44212734e3e");
804-
812+
805813
ensure_workdir("0c-duplicated-in-theirs.txt",
806814
0100644, "2f56120107d680129a5d9791b521cb1e73a2ed31");
807-
815+
808816
ensure_workdir("0c-rewritten-in-theirs.txt",
809817
0100644, "efc9121fdedaf08ba180b53ebfbcf71bd488ed09");
810-
818+
811819
ensure_workdir("1a-newname-in-ours-edited-in-theirs.txt",
812820
0100644, "0d872f8e871a30208305978ecbf9e66d864f1638");
813-
821+
814822
ensure_workdir("1a-newname-in-ours.txt",
815823
0100644, "d0d4594e16f2e19107e3fa7ea63e7aaaff305ffb");
816-
824+
817825
ensure_workdir("1b-newname-in-theirs-edited-in-ours.txt",
818826
0100644, "ed9523e62e453e50dd9be1606af19399b96e397a");
819-
827+
820828
ensure_workdir("1b-newname-in-theirs.txt",
821829
0100644, "2b5f1f181ee3b58ea751f5dd5d8f9b445520a136");
822-
830+
823831
ensure_workdir("2-newname-in-both.txt",
824832
0100644, "178940b450f238a56c0d75b7955cb57b38191982");
825833

826834
ensure_workdir("3a-newname-in-ours-deleted-in-theirs.txt",
827835
0100644, "18cb316b1cefa0f8a6946f0e201a8e1a6f845ab9");
828-
836+
829837
ensure_workdir("3b-newname-in-theirs-deleted-in-ours.txt",
830838
0100644, "36219b49367146cb2e6a1555b5a9ebd4d0328495");
831-
839+
832840
ensure_workdir("4a-newname-in-ours-added-in-theirs.txt",
833841
0100644, "227792b52aaa0b238bea00ec7e509b02623f168c");
834-
842+
835843
ensure_workdir("4b-newname-in-theirs-added-in-ours.txt",
836844
0100644, "de872ee3618b894992e9d1e18ba2ebe256a112f9");
837-
845+
838846
ensure_workdir("5a-newname-in-ours-added-in-theirs.txt",
839847
0100644, "d3719a5ae8e4d92276b5313ce976f6ee5af2b436");
840-
848+
841849
ensure_workdir("5b-newname-in-theirs-added-in-ours.txt",
842850
0100644, "385c8a0f26ddf79e9041e15e17dc352ed2c4cced");
843851

844852
ensure_workdir("6-both-renamed-1-to-2-ours.txt",
845853
0100644, "d8fa77b6833082c1ea36b7828a582d4c43882450");
846-
854+
847855
ensure_workdir("7-both-renamed.txt",
848856
0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11");
849857
}

tests/checkout/icase.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "git2/checkout.h"
44
#include "refs.h"
55
#include "path.h"
6+
#include "repository.h"
67

78
#ifdef GIT_WIN32
89
# include <windows.h>
@@ -91,6 +92,18 @@ static void assert_name_is(const char *expected)
9192
free(actual);
9293
}
9394

95+
static int symlink_or_fake(git_repository *repo, const char *a, const char *b)
96+
{
97+
int symlinks;
98+
99+
cl_git_pass(git_repository__cvar(&symlinks, repo, GIT_CVAR_SYMLINKS));
100+
101+
if (symlinks)
102+
return p_symlink(a, b);
103+
else
104+
return git_futils_fake_symlink(a, b);
105+
}
106+
94107
void test_checkout_icase__refuses_to_overwrite_files_for_files(void)
95108
{
96109
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)
117130
{
118131
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;
119132

120-
cl_must_pass(p_symlink("../tmp", "testrepo/BRANCH_FILE.txt"));
133+
cl_must_pass(symlink_or_fake(repo, "../tmp", "testrepo/BRANCH_FILE.txt"));
121134

122135
cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
123136

@@ -129,7 +142,7 @@ void test_checkout_icase__overwrites_links_for_files_when_forced(void)
129142
{
130143
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
131144

132-
cl_must_pass(p_symlink("../tmp", "testrepo/NEW.txt"));
145+
cl_must_pass(symlink_or_fake(repo, "../tmp", "testrepo/NEW.txt"));
133146

134147
cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
135148

@@ -205,7 +218,7 @@ void test_checkout_icase__refuses_to_overwrite_links_for_folders(void)
205218
{
206219
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;
207220

208-
cl_must_pass(p_symlink("..", "testrepo/A"));
221+
cl_must_pass(symlink_or_fake(repo, "..", "testrepo/A"));
209222

210223
cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts));
211224

@@ -217,7 +230,7 @@ void test_checkout_icase__overwrites_links_for_folders_when_forced(void)
217230
{
218231
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
219232

220-
cl_must_pass(p_symlink("..", "testrepo/A"));
233+
cl_must_pass(symlink_or_fake(repo, "..", "testrepo/A"));
221234

222235
cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts));
223236

0 commit comments

Comments
 (0)