]> git.proxmox.com Git - libgit2.git/blob - tests/checkout/icase.c
e6c640ef50f26cc313a76f2b6c0555fac09edf7a
[libgit2.git] / tests / checkout / icase.c
1 #include "clar_libgit2.h"
2
3 #include "git2/checkout.h"
4 #include "refs.h"
5 #include "path.h"
6 #include "repository.h"
7
8 #ifdef GIT_WIN32
9 # include <windows.h>
10 #else
11 # include <dirent.h>
12 #endif
13
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;
21 git_config *cfg;
22 int icase = 0;
23
24 repo = cl_git_sandbox_init("testrepo");
25
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
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));
35
36 git_checkout_init_options(&checkout_opts, GIT_CHECKOUT_OPTIONS_VERSION);
37 checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE;
38 }
39
40 void test_checkout_icase__cleanup(void)
41 {
42 git_object_free(obj);
43 cl_git_sandbox_cleanup();
44 }
45
46 static char *get_filename(const char *in)
47 {
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);
70 git_buf_dispose(&out);
71
72 return filename;
73 }
74
75 static void assert_name_is(const char *expected)
76 {
77 char *actual;
78 size_t actual_len, expected_len, start;
79
80 cl_assert(actual = get_filename(expected));
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
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
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)
119 {
120 checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
121
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
129 void test_checkout_icase__refuses_to_overwrite_links_for_files(void)
130 {
131 checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING;
132
133 cl_must_pass(symlink_or_fake(repo, "../tmp", "testrepo/BRANCH_FILE.txt"));
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
145 cl_must_pass(symlink_or_fake(repo, "../tmp", "testrepo/NEW.txt"));
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
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)
180 {
181 checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
182
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);
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
193 void test_checkout_icase__refuses_to_overwrite_files_for_folders(void)
194 {
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
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
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
221 cl_must_pass(symlink_or_fake(repo, "..", "testrepo/A"));
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)
230 {
231 checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
232
233 cl_must_pass(symlink_or_fake(repo, "..", "testrepo/A"));
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 }
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);
261 git_commit_free(br2);
262 git_reference_free(orig_ref);
263 git_reference_free(br2_ref);
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));
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));
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"));
284 cl_git_pass(git_object_lookup(&subtrees, repo, &oid, GIT_OBJECT_ANY));
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