]>
Commit | Line | Data |
---|---|---|
e74340b0 ET |
1 | #include "clar_libgit2.h" |
2 | ||
3 | #include "git2/checkout.h" | |
64842d87 | 4 | #include "refs.h" |
e74340b0 | 5 | #include "path.h" |
ac3d33df | 6 | #include "repository.h" |
e74340b0 | 7 | |
53eb139d | 8 | #ifdef GIT_WIN32 |
118e6fdc | 9 | # include <windows.h> |
cd79d99a ET |
10 | #else |
11 | # include <dirent.h> | |
53eb139d ET |
12 | #endif |
13 | ||
e74340b0 ET |
14 | static git_repository *repo; |
15 | static git_object *obj; | |
16 | static git_checkout_options checkout_opts; | |
17 | ||
18 | void test_checkout_icase__initialize(void) | |
19 | { | |
20 | git_oid id; | |
64842d87 ET |
21 | git_config *cfg; |
22 | int icase = 0; | |
e74340b0 ET |
23 | |
24 | repo = cl_git_sandbox_init("testrepo"); | |
25 | ||
64842d87 ET |
26 | cl_git_pass(git_repository_config_snapshot(&cfg, repo)); |
27 | git_config_get_bool(&icase, cfg, "core.ignorecase"); | |
28 | git_config_free(cfg); | |
29 | ||
30 | if (!icase) | |
31 | cl_skip(); | |
32 | ||
e74340b0 | 33 | cl_git_pass(git_reference_name_to_id(&id, repo, "refs/heads/dir")); |
ac3d33df | 34 | cl_git_pass(git_object_lookup(&obj, repo, &id, GIT_OBJECT_ANY)); |
e74340b0 | 35 | |
22a2d3d5 | 36 | git_checkout_options_init(&checkout_opts, GIT_CHECKOUT_OPTIONS_VERSION); |
05f69012 | 37 | checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE; |
e74340b0 ET |
38 | } |
39 | ||
40 | void test_checkout_icase__cleanup(void) | |
41 | { | |
42 | git_object_free(obj); | |
43 | cl_git_sandbox_cleanup(); | |
44 | } | |
45 | ||
cd79d99a | 46 | static char *get_filename(const char *in) |
53eb139d | 47 | { |
cd79d99a ET |
48 | char *search_dirname, *search_filename, *filename = NULL; |
49 | git_buf out = GIT_BUF_INIT; | |
50 | DIR *dir; | |
51 | struct dirent *de; | |
52 | ||
53 | cl_assert(search_dirname = git_path_dirname(in)); | |
54 | cl_assert(search_filename = git_path_basename(in)); | |
55 | ||
56 | cl_assert(dir = opendir(search_dirname)); | |
57 | ||
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); | |
62 | break; | |
63 | } | |
64 | } | |
65 | ||
66 | closedir(dir); | |
67 | ||
68 | git__free(search_dirname); | |
69 | git__free(search_filename); | |
ac3d33df | 70 | git_buf_dispose(&out); |
cd79d99a ET |
71 | |
72 | return filename; | |
53eb139d ET |
73 | } |
74 | ||
e74340b0 ET |
75 | static void assert_name_is(const char *expected) |
76 | { | |
77 | char *actual; | |
78 | size_t actual_len, expected_len, start; | |
79 | ||
cd79d99a | 80 | cl_assert(actual = get_filename(expected)); |
e74340b0 ET |
81 | |
82 | expected_len = strlen(expected); | |
83 | actual_len = strlen(actual); | |
84 | cl_assert(actual_len >= expected_len); | |
85 | ||
86 | start = actual_len - expected_len; | |
87 | cl_assert_equal_s(expected, actual + start); | |
88 | ||
89 | if (start) | |
90 | cl_assert_equal_strn("/", actual + (start - 1), 1); | |
91 | ||
92 | free(actual); | |
93 | } | |
94 | ||
ac3d33df JK |
95 | static int symlink_or_fake(git_repository *repo, const char *a, const char *b) |
96 | { | |
97 | int symlinks; | |
98 | ||
22a2d3d5 | 99 | cl_git_pass(git_repository__configmap_lookup(&symlinks, repo, GIT_CONFIGMAP_SYMLINKS)); |
ac3d33df JK |
100 | |
101 | if (symlinks) | |
102 | return p_symlink(a, b); | |
103 | else | |
104 | return git_futils_fake_symlink(a, b); | |
105 | } | |
106 | ||
05f69012 ET |
107 | void test_checkout_icase__refuses_to_overwrite_files_for_files(void) |
108 | { | |
109 | checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING; | |
110 | ||
111 | cl_git_write2file("testrepo/BRANCH_FILE.txt", "neue file\n", 10, \ | |
112 | O_WRONLY | O_CREAT | O_TRUNC, 0644); | |
113 | ||
114 | cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts)); | |
115 | assert_name_is("testrepo/BRANCH_FILE.txt"); | |
116 | } | |
117 | ||
118 | void test_checkout_icase__overwrites_files_for_files_when_forced(void) | |
e74340b0 | 119 | { |
05f69012 ET |
120 | checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; |
121 | ||
e74340b0 ET |
122 | cl_git_write2file("testrepo/NEW.txt", "neue file\n", 10, \ |
123 | O_WRONLY | O_CREAT | O_TRUNC, 0644); | |
124 | ||
125 | cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts)); | |
126 | assert_name_is("testrepo/new.txt"); | |
127 | } | |
128 | ||
05f69012 | 129 | void test_checkout_icase__refuses_to_overwrite_links_for_files(void) |
e74340b0 | 130 | { |
05f69012 ET |
131 | checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING; |
132 | ||
ac3d33df | 133 | cl_must_pass(symlink_or_fake(repo, "../tmp", "testrepo/BRANCH_FILE.txt")); |
05f69012 ET |
134 | |
135 | cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts)); | |
136 | ||
137 | cl_assert(!git_path_exists("tmp")); | |
138 | assert_name_is("testrepo/BRANCH_FILE.txt"); | |
139 | } | |
140 | ||
141 | void test_checkout_icase__overwrites_links_for_files_when_forced(void) | |
142 | { | |
143 | checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; | |
144 | ||
ac3d33df | 145 | cl_must_pass(symlink_or_fake(repo, "../tmp", "testrepo/NEW.txt")); |
e74340b0 ET |
146 | |
147 | cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts)); | |
148 | ||
149 | cl_assert(!git_path_exists("tmp")); | |
150 | assert_name_is("testrepo/new.txt"); | |
151 | } | |
152 | ||
05f69012 ET |
153 | void test_checkout_icase__overwrites_empty_folders_for_files(void) |
154 | { | |
155 | checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING; | |
156 | ||
157 | cl_must_pass(p_mkdir("testrepo/NEW.txt", 0777)); | |
158 | ||
159 | cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts)); | |
160 | ||
161 | assert_name_is("testrepo/new.txt"); | |
162 | cl_assert(!git_path_isdir("testrepo/new.txt")); | |
163 | } | |
164 | ||
165 | void test_checkout_icase__refuses_to_overwrite_populated_folders_for_files(void) | |
166 | { | |
167 | checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING; | |
168 | ||
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); | |
172 | ||
173 | cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts)); | |
174 | ||
175 | assert_name_is("testrepo/BRANCH_FILE.txt"); | |
176 | cl_assert(git_path_isdir("testrepo/BRANCH_FILE.txt")); | |
177 | } | |
178 | ||
179 | void test_checkout_icase__overwrites_folders_for_files_when_forced(void) | |
e74340b0 | 180 | { |
05f69012 ET |
181 | checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; |
182 | ||
e74340b0 | 183 | cl_must_pass(p_mkdir("testrepo/NEW.txt", 0777)); |
05f69012 ET |
184 | cl_git_write2file("testrepo/NEW.txt/foobar", "neue file\n", 10, \ |
185 | O_WRONLY | O_CREAT | O_TRUNC, 0644); | |
e74340b0 ET |
186 | |
187 | cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts)); | |
188 | ||
189 | assert_name_is("testrepo/new.txt"); | |
190 | cl_assert(!git_path_isdir("testrepo/new.txt")); | |
191 | } | |
192 | ||
05f69012 | 193 | void test_checkout_icase__refuses_to_overwrite_files_for_folders(void) |
e74340b0 | 194 | { |
05f69012 ET |
195 | checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING; |
196 | ||
197 | cl_git_write2file("testrepo/A", "neue file\n", 10, \ | |
198 | O_WRONLY | O_CREAT | O_TRUNC, 0644); | |
199 | ||
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")); | |
203 | } | |
204 | ||
205 | void test_checkout_icase__overwrites_files_for_folders_when_forced(void) | |
206 | { | |
207 | checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; | |
208 | ||
e74340b0 ET |
209 | cl_git_write2file("testrepo/A", "neue file\n", 10, \ |
210 | O_WRONLY | O_CREAT | O_TRUNC, 0644); | |
211 | ||
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")); | |
215 | } | |
216 | ||
05f69012 ET |
217 | void test_checkout_icase__refuses_to_overwrite_links_for_folders(void) |
218 | { | |
219 | checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING; | |
220 | ||
ac3d33df | 221 | cl_must_pass(symlink_or_fake(repo, "..", "testrepo/A")); |
05f69012 ET |
222 | |
223 | cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts)); | |
224 | ||
225 | cl_assert(!git_path_exists("b.txt")); | |
226 | assert_name_is("testrepo/A"); | |
227 | } | |
228 | ||
229 | void test_checkout_icase__overwrites_links_for_folders_when_forced(void) | |
e74340b0 | 230 | { |
05f69012 ET |
231 | checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; |
232 | ||
ac3d33df | 233 | cl_must_pass(symlink_or_fake(repo, "..", "testrepo/A")); |
e74340b0 ET |
234 | |
235 | cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts)); | |
236 | ||
237 | cl_assert(!git_path_exists("b.txt")); | |
238 | assert_name_is("testrepo/a"); | |
239 | } | |
64842d87 ET |
240 | |
241 | void test_checkout_icase__ignores_unstaged_casechange(void) | |
242 | { | |
243 | git_reference *orig_ref, *br2_ref; | |
244 | git_commit *orig, *br2; | |
245 | git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; | |
246 | ||
247 | checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; | |
248 | ||
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)); | |
252 | ||
253 | cl_rename("testrepo/branch_file.txt", "testrepo/Branch_File.txt"); | |
254 | ||
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))); | |
257 | ||
258 | cl_git_pass(git_checkout_tree(repo, (const git_object *)br2, &checkout_opts)); | |
259 | ||
260 | git_commit_free(orig); | |
26d5c0b8 | 261 | git_commit_free(br2); |
64842d87 | 262 | git_reference_free(orig_ref); |
26d5c0b8 | 263 | git_reference_free(br2_ref); |
64842d87 ET |
264 | } |
265 | ||
266 | void test_checkout_icase__conflicts_with_casechanged_subtrees(void) | |
267 | { | |
268 | git_reference *orig_ref; | |
269 | git_object *orig, *subtrees; | |
270 | git_oid oid; | |
271 | git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; | |
272 | ||
273 | checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; | |
274 | ||
275 | cl_git_pass(git_reference_lookup_resolved(&orig_ref, repo, "HEAD", 100)); | |
ac3d33df | 276 | cl_git_pass(git_object_lookup(&orig, repo, git_reference_target(orig_ref), GIT_OBJECT_COMMIT)); |
64842d87 ET |
277 | cl_git_pass(git_reset(repo, (git_object *)orig, GIT_RESET_HARD, NULL)); |
278 | ||
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); | |
282 | ||
283 | cl_git_pass(git_reference_name_to_id(&oid, repo, "refs/heads/subtrees")); | |
ac3d33df | 284 | cl_git_pass(git_object_lookup(&subtrees, repo, &oid, GIT_OBJECT_ANY)); |
64842d87 ET |
285 | |
286 | cl_git_fail(git_checkout_tree(repo, subtrees, &checkout_opts)); | |
287 | ||
288 | git_object_free(orig); | |
289 | git_object_free(subtrees); | |
290 | git_reference_free(orig_ref); | |
291 | } | |
292 |