1 #include "clar_libgit2.h"
3 #include "git2/checkout.h"
6 #include "repository.h"
14 static git_repository
*repo
;
15 static git_object
*obj
;
16 static git_checkout_options checkout_opts
;
18 void test_checkout_icase__initialize(void)
24 repo
= cl_git_sandbox_init("testrepo");
26 cl_git_pass(git_repository_config_snapshot(&cfg
, repo
));
27 git_config_get_bool(&icase
, cfg
, "core.ignorecase");
33 cl_git_pass(git_reference_name_to_id(&id
, repo
, "refs/heads/dir"));
34 cl_git_pass(git_object_lookup(&obj
, repo
, &id
, GIT_OBJECT_ANY
));
36 git_checkout_init_options(&checkout_opts
, GIT_CHECKOUT_OPTIONS_VERSION
);
37 checkout_opts
.checkout_strategy
= GIT_CHECKOUT_NONE
;
40 void test_checkout_icase__cleanup(void)
43 cl_git_sandbox_cleanup();
46 static char *get_filename(const char *in
)
48 char *search_dirname
, *search_filename
, *filename
= NULL
;
49 git_buf out
= GIT_BUF_INIT
;
53 cl_assert(search_dirname
= git_path_dirname(in
));
54 cl_assert(search_filename
= git_path_basename(in
));
56 cl_assert(dir
= opendir(search_dirname
));
58 while ((de
= readdir(dir
))) {
59 if (strcasecmp(de
->d_name
, search_filename
) == 0) {
60 git_buf_join(&out
, '/', search_dirname
, de
->d_name
);
61 filename
= git_buf_detach(&out
);
68 git__free(search_dirname
);
69 git__free(search_filename
);
70 git_buf_dispose(&out
);
75 static void assert_name_is(const char *expected
)
78 size_t actual_len
, expected_len
, start
;
80 cl_assert(actual
= get_filename(expected
));
82 expected_len
= strlen(expected
);
83 actual_len
= strlen(actual
);
84 cl_assert(actual_len
>= expected_len
);
86 start
= actual_len
- expected_len
;
87 cl_assert_equal_s(expected
, actual
+ start
);
90 cl_assert_equal_strn("/", actual
+ (start
- 1), 1);
95 static int symlink_or_fake(git_repository
*repo
, const char *a
, const char *b
)
99 cl_git_pass(git_repository__cvar(&symlinks
, repo
, GIT_CVAR_SYMLINKS
));
102 return p_symlink(a
, b
);
104 return git_futils_fake_symlink(a
, b
);
107 void test_checkout_icase__refuses_to_overwrite_files_for_files(void)
109 checkout_opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
|GIT_CHECKOUT_RECREATE_MISSING
;
111 cl_git_write2file("testrepo/BRANCH_FILE.txt", "neue file\n", 10, \
112 O_WRONLY
| O_CREAT
| O_TRUNC
, 0644);
114 cl_git_fail(git_checkout_tree(repo
, obj
, &checkout_opts
));
115 assert_name_is("testrepo/BRANCH_FILE.txt");
118 void test_checkout_icase__overwrites_files_for_files_when_forced(void)
120 checkout_opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
122 cl_git_write2file("testrepo/NEW.txt", "neue file\n", 10, \
123 O_WRONLY
| O_CREAT
| O_TRUNC
, 0644);
125 cl_git_pass(git_checkout_tree(repo
, obj
, &checkout_opts
));
126 assert_name_is("testrepo/new.txt");
129 void test_checkout_icase__refuses_to_overwrite_links_for_files(void)
131 checkout_opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
|GIT_CHECKOUT_RECREATE_MISSING
;
133 cl_must_pass(symlink_or_fake(repo
, "../tmp", "testrepo/BRANCH_FILE.txt"));
135 cl_git_fail(git_checkout_tree(repo
, obj
, &checkout_opts
));
137 cl_assert(!git_path_exists("tmp"));
138 assert_name_is("testrepo/BRANCH_FILE.txt");
141 void test_checkout_icase__overwrites_links_for_files_when_forced(void)
143 checkout_opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
145 cl_must_pass(symlink_or_fake(repo
, "../tmp", "testrepo/NEW.txt"));
147 cl_git_pass(git_checkout_tree(repo
, obj
, &checkout_opts
));
149 cl_assert(!git_path_exists("tmp"));
150 assert_name_is("testrepo/new.txt");
153 void test_checkout_icase__overwrites_empty_folders_for_files(void)
155 checkout_opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
|GIT_CHECKOUT_RECREATE_MISSING
;
157 cl_must_pass(p_mkdir("testrepo/NEW.txt", 0777));
159 cl_git_pass(git_checkout_tree(repo
, obj
, &checkout_opts
));
161 assert_name_is("testrepo/new.txt");
162 cl_assert(!git_path_isdir("testrepo/new.txt"));
165 void test_checkout_icase__refuses_to_overwrite_populated_folders_for_files(void)
167 checkout_opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
|GIT_CHECKOUT_RECREATE_MISSING
;
169 cl_must_pass(p_mkdir("testrepo/BRANCH_FILE.txt", 0777));
170 cl_git_write2file("testrepo/BRANCH_FILE.txt/foobar", "neue file\n", 10, \
171 O_WRONLY
| O_CREAT
| O_TRUNC
, 0644);
173 cl_git_fail(git_checkout_tree(repo
, obj
, &checkout_opts
));
175 assert_name_is("testrepo/BRANCH_FILE.txt");
176 cl_assert(git_path_isdir("testrepo/BRANCH_FILE.txt"));
179 void test_checkout_icase__overwrites_folders_for_files_when_forced(void)
181 checkout_opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
183 cl_must_pass(p_mkdir("testrepo/NEW.txt", 0777));
184 cl_git_write2file("testrepo/NEW.txt/foobar", "neue file\n", 10, \
185 O_WRONLY
| O_CREAT
| O_TRUNC
, 0644);
187 cl_git_pass(git_checkout_tree(repo
, obj
, &checkout_opts
));
189 assert_name_is("testrepo/new.txt");
190 cl_assert(!git_path_isdir("testrepo/new.txt"));
193 void test_checkout_icase__refuses_to_overwrite_files_for_folders(void)
195 checkout_opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
|GIT_CHECKOUT_RECREATE_MISSING
;
197 cl_git_write2file("testrepo/A", "neue file\n", 10, \
198 O_WRONLY
| O_CREAT
| O_TRUNC
, 0644);
200 cl_git_fail(git_checkout_tree(repo
, obj
, &checkout_opts
));
201 assert_name_is("testrepo/A");
202 cl_assert(!git_path_isdir("testrepo/A"));
205 void test_checkout_icase__overwrites_files_for_folders_when_forced(void)
207 checkout_opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
209 cl_git_write2file("testrepo/A", "neue file\n", 10, \
210 O_WRONLY
| O_CREAT
| O_TRUNC
, 0644);
212 cl_git_pass(git_checkout_tree(repo
, obj
, &checkout_opts
));
213 assert_name_is("testrepo/a");
214 cl_assert(git_path_isdir("testrepo/a"));
217 void test_checkout_icase__refuses_to_overwrite_links_for_folders(void)
219 checkout_opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
|GIT_CHECKOUT_RECREATE_MISSING
;
221 cl_must_pass(symlink_or_fake(repo
, "..", "testrepo/A"));
223 cl_git_fail(git_checkout_tree(repo
, obj
, &checkout_opts
));
225 cl_assert(!git_path_exists("b.txt"));
226 assert_name_is("testrepo/A");
229 void test_checkout_icase__overwrites_links_for_folders_when_forced(void)
231 checkout_opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
233 cl_must_pass(symlink_or_fake(repo
, "..", "testrepo/A"));
235 cl_git_pass(git_checkout_tree(repo
, obj
, &checkout_opts
));
237 cl_assert(!git_path_exists("b.txt"));
238 assert_name_is("testrepo/a");
241 void test_checkout_icase__ignores_unstaged_casechange(void)
243 git_reference
*orig_ref
, *br2_ref
;
244 git_commit
*orig
, *br2
;
245 git_checkout_options checkout_opts
= GIT_CHECKOUT_OPTIONS_INIT
;
247 checkout_opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
;
249 cl_git_pass(git_reference_lookup_resolved(&orig_ref
, repo
, "HEAD", 100));
250 cl_git_pass(git_commit_lookup(&orig
, repo
, git_reference_target(orig_ref
)));
251 cl_git_pass(git_reset(repo
, (git_object
*)orig
, GIT_RESET_HARD
, NULL
));
253 cl_rename("testrepo/branch_file.txt", "testrepo/Branch_File.txt");
255 cl_git_pass(git_reference_lookup_resolved(&br2_ref
, repo
, "refs/heads/br2", 100));
256 cl_git_pass(git_commit_lookup(&br2
, repo
, git_reference_target(br2_ref
)));
258 cl_git_pass(git_checkout_tree(repo
, (const git_object
*)br2
, &checkout_opts
));
260 git_commit_free(orig
);
261 git_commit_free(br2
);
262 git_reference_free(orig_ref
);
263 git_reference_free(br2_ref
);
266 void test_checkout_icase__conflicts_with_casechanged_subtrees(void)
268 git_reference
*orig_ref
;
269 git_object
*orig
, *subtrees
;
271 git_checkout_options checkout_opts
= GIT_CHECKOUT_OPTIONS_INIT
;
273 checkout_opts
.checkout_strategy
= GIT_CHECKOUT_SAFE
;
275 cl_git_pass(git_reference_lookup_resolved(&orig_ref
, repo
, "HEAD", 100));
276 cl_git_pass(git_object_lookup(&orig
, repo
, git_reference_target(orig_ref
), GIT_OBJECT_COMMIT
));
277 cl_git_pass(git_reset(repo
, (git_object
*)orig
, GIT_RESET_HARD
, NULL
));
279 cl_must_pass(p_mkdir("testrepo/AB", 0777));
280 cl_must_pass(p_mkdir("testrepo/AB/C", 0777));
281 cl_git_write2file("testrepo/AB/C/3.txt", "Foobar!\n", 8, O_RDWR
|O_CREAT
, 0666);
283 cl_git_pass(git_reference_name_to_id(&oid
, repo
, "refs/heads/subtrees"));
284 cl_git_pass(git_object_lookup(&subtrees
, repo
, &oid
, GIT_OBJECT_ANY
));
286 cl_git_fail(git_checkout_tree(repo
, subtrees
, &checkout_opts
));
288 git_object_free(orig
);
289 git_object_free(subtrees
);
290 git_reference_free(orig_ref
);