]>
Commit | Line | Data |
---|---|---|
d788499a | 1 | #include "clar_libgit2.h" |
37d91686 RB |
2 | #include "posix.h" |
3 | #include "path.h" | |
7a5ee3dc | 4 | #include "fileops.h" |
d788499a | 5 | |
6 | static git_repository *g_repo = NULL; | |
7 | ||
8 | void test_attr_ignore__initialize(void) | |
9 | { | |
37d91686 | 10 | g_repo = cl_git_sandbox_init("attr"); |
d788499a | 11 | } |
12 | ||
13 | void test_attr_ignore__cleanup(void) | |
14 | { | |
37d91686 RB |
15 | cl_git_sandbox_cleanup(); |
16 | g_repo = NULL; | |
d788499a | 17 | } |
18 | ||
50e46d60 | 19 | static void assert_is_ignored_( |
c8c91433 | 20 | bool expected, const char *filepath, const char *file, int line) |
d788499a | 21 | { |
c8c91433 | 22 | int is_ignored = 0; |
d788499a | 23 | |
c52480fd | 24 | cl_git_expect( |
a1dcc830 | 25 | git_ignore_path_is_ignored(&is_ignored, g_repo, filepath), 0, file, line); |
c8c91433 RB |
26 | |
27 | clar__assert_equal( | |
28 | file, line, "expected != is_ignored", 1, "%d", | |
29 | (int)(expected != 0), (int)(is_ignored != 0)); | |
d788499a | 30 | } |
c8c91433 RB |
31 | #define assert_is_ignored(expected, filepath) \ |
32 | assert_is_ignored_(expected, filepath, __FILE__, __LINE__) | |
d788499a | 33 | |
34 | void test_attr_ignore__honor_temporary_rules(void) | |
35 | { | |
37d91686 | 36 | cl_git_rewritefile("attr/.gitignore", "/NewFolder\n/NewFolder/NewFolder"); |
d788499a | 37 | |
37d91686 RB |
38 | assert_is_ignored(false, "File.txt"); |
39 | assert_is_ignored(true, "NewFolder"); | |
40 | assert_is_ignored(true, "NewFolder/NewFolder"); | |
41 | assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); | |
42 | } | |
43 | ||
2d160ef7 ET |
44 | void test_attr_ignore__allow_root(void) |
45 | { | |
46 | cl_git_rewritefile("attr/.gitignore", "/"); | |
47 | ||
48 | assert_is_ignored(false, "File.txt"); | |
49 | assert_is_ignored(false, "NewFolder"); | |
50 | assert_is_ignored(false, "NewFolder/NewFolder"); | |
51 | assert_is_ignored(false, "NewFolder/NewFolder/File.txt"); | |
52 | } | |
53 | ||
eae0bfdc PP |
54 | void test_attr_ignore__ignore_space(void) |
55 | { | |
56 | cl_git_rewritefile("attr/.gitignore", "/\n\n/NewFolder \n/NewFolder/NewFolder"); | |
57 | ||
58 | assert_is_ignored(false, "File.txt"); | |
59 | assert_is_ignored(true, "NewFolder"); | |
60 | assert_is_ignored(true, "NewFolder/NewFolder"); | |
61 | assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); | |
62 | } | |
63 | ||
4b3ec53c XL |
64 | void test_attr_ignore__ignore_dir(void) |
65 | { | |
66 | cl_git_rewritefile("attr/.gitignore", "dir/\n"); | |
67 | ||
68 | assert_is_ignored(true, "dir"); | |
69 | assert_is_ignored(true, "dir/file"); | |
70 | } | |
71 | ||
72 | void test_attr_ignore__ignore_dir_with_trailing_space(void) | |
73 | { | |
74 | cl_git_rewritefile("attr/.gitignore", "dir/ \n"); | |
75 | ||
76 | assert_is_ignored(true, "dir"); | |
77 | assert_is_ignored(true, "dir/file"); | |
78 | } | |
79 | ||
2d160ef7 ET |
80 | void test_attr_ignore__ignore_root(void) |
81 | { | |
82 | cl_git_rewritefile("attr/.gitignore", "/\n\n/NewFolder\n/NewFolder/NewFolder"); | |
83 | ||
84 | assert_is_ignored(false, "File.txt"); | |
85 | assert_is_ignored(true, "NewFolder"); | |
86 | assert_is_ignored(true, "NewFolder/NewFolder"); | |
87 | assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); | |
88 | } | |
89 | ||
2b6b85f1 RB |
90 | void test_attr_ignore__full_paths(void) |
91 | { | |
92 | cl_git_rewritefile("attr/.gitignore", "Folder/*/Contained"); | |
93 | ||
94 | assert_is_ignored(true, "Folder/Middle/Contained"); | |
95 | assert_is_ignored(false, "Folder/Middle/More/More/Contained"); | |
96 | ||
97 | cl_git_rewritefile("attr/.gitignore", "Folder/**/Contained"); | |
98 | ||
99 | assert_is_ignored(true, "Folder/Middle/Contained"); | |
100 | assert_is_ignored(true, "Folder/Middle/More/More/Contained"); | |
c8c91433 RB |
101 | |
102 | cl_git_rewritefile("attr/.gitignore", "Folder/**/Contained/*/Child"); | |
103 | ||
104 | assert_is_ignored(true, "Folder/Middle/Contained/Happy/Child"); | |
105 | assert_is_ignored(false, "Folder/Middle/Contained/Not/Happy/Child"); | |
106 | assert_is_ignored(true, "Folder/Middle/More/More/Contained/Happy/Child"); | |
107 | assert_is_ignored(false, "Folder/Middle/More/More/Contained/Not/Happy/Child"); | |
2b6b85f1 RB |
108 | } |
109 | ||
d19b2f9f RB |
110 | void test_attr_ignore__more_starstar_cases(void) |
111 | { | |
112 | cl_must_pass(p_unlink("attr/.gitignore")); | |
113 | cl_git_mkfile( | |
114 | "attr/dir/.gitignore", | |
115 | "sub/**/*.html\n"); | |
116 | ||
117 | assert_is_ignored(false, "aaa.html"); | |
118 | assert_is_ignored(false, "dir"); | |
119 | assert_is_ignored(false, "dir/sub"); | |
120 | assert_is_ignored(true, "dir/sub/sub2/aaa.html"); | |
121 | assert_is_ignored(true, "dir/sub/aaa.html"); | |
122 | assert_is_ignored(false, "dir/aaa.html"); | |
123 | assert_is_ignored(false, "sub"); | |
124 | assert_is_ignored(false, "sub/aaa.html"); | |
125 | assert_is_ignored(false, "sub/sub2/aaa.html"); | |
126 | } | |
127 | ||
c8c91433 RB |
128 | void test_attr_ignore__leading_stars(void) |
129 | { | |
130 | cl_git_rewritefile( | |
131 | "attr/.gitignore", | |
132 | "*/onestar\n" | |
133 | "**/twostars\n" | |
134 | "*/parent1/kid1/*\n" | |
135 | "**/parent2/kid2/*\n"); | |
136 | ||
137 | assert_is_ignored(true, "dir1/onestar"); | |
138 | assert_is_ignored(true, "dir1/onestar/child"); /* in ignored dir */ | |
139 | assert_is_ignored(false, "dir1/dir2/onestar"); | |
140 | ||
141 | assert_is_ignored(true, "dir1/twostars"); | |
142 | assert_is_ignored(true, "dir1/twostars/child"); /* in ignored dir */ | |
143 | assert_is_ignored(true, "dir1/dir2/twostars"); | |
144 | assert_is_ignored(true, "dir1/dir2/twostars/child"); /* in ignored dir */ | |
145 | assert_is_ignored(true, "dir1/dir2/dir3/twostars"); | |
146 | ||
147 | assert_is_ignored(true, "dir1/parent1/kid1/file"); | |
148 | assert_is_ignored(true, "dir1/parent1/kid1/file/inside/parent"); | |
149 | assert_is_ignored(false, "dir1/dir2/parent1/kid1/file"); | |
150 | assert_is_ignored(false, "dir1/parent1/file"); | |
151 | assert_is_ignored(false, "dir1/kid1/file"); | |
152 | ||
153 | assert_is_ignored(true, "dir1/parent2/kid2/file"); | |
154 | assert_is_ignored(true, "dir1/parent2/kid2/file/inside/parent"); | |
155 | assert_is_ignored(true, "dir1/dir2/parent2/kid2/file"); | |
156 | assert_is_ignored(true, "dir1/dir2/dir3/parent2/kid2/file"); | |
157 | assert_is_ignored(false, "dir1/parent2/file"); | |
158 | assert_is_ignored(false, "dir1/kid2/file"); | |
159 | } | |
2d160ef7 | 160 | |
0f362716 AS |
161 | void test_attr_ignore__globs_and_path_delimiters(void) |
162 | { | |
1c3018eb CMN |
163 | cl_git_rewritefile("attr/.gitignore", "foo/bar/**"); |
164 | assert_is_ignored(true, "foo/bar/baz"); | |
165 | assert_is_ignored(true, "foo/bar/baz/quux"); | |
166 | ||
167 | cl_git_rewritefile("attr/.gitignore", "_*/"); | |
168 | assert_is_ignored(true, "sub/_test/a/file"); | |
169 | assert_is_ignored(false, "test_folder/file"); | |
170 | assert_is_ignored(true, "_test/file"); | |
171 | assert_is_ignored(true, "_test/a/file"); | |
172 | ||
0f362716 | 173 | cl_git_rewritefile("attr/.gitignore", "**/_*/"); |
1c3018eb | 174 | assert_is_ignored(true, "sub/_test/a/file"); |
0f362716 AS |
175 | assert_is_ignored(false, "test_folder/file"); |
176 | assert_is_ignored(true, "_test/file"); | |
177 | assert_is_ignored(true, "_test/a/file"); | |
178 | ||
179 | cl_git_rewritefile("attr/.gitignore", "**/_*/foo/bar/*ux"); | |
180 | ||
1c3018eb | 181 | assert_is_ignored(true, "sub/_test/foo/bar/qux/file"); |
0f362716 AS |
182 | assert_is_ignored(true, "_test/foo/bar/qux/file"); |
183 | assert_is_ignored(true, "_test/foo/bar/crux/file"); | |
184 | assert_is_ignored(false, "_test/foo/bar/code/file"); | |
185 | } | |
186 | ||
37d91686 RB |
187 | void test_attr_ignore__skip_gitignore_directory(void) |
188 | { | |
189 | cl_git_rewritefile("attr/.git/info/exclude", "/NewFolder\n/NewFolder/NewFolder"); | |
190 | p_unlink("attr/.gitignore"); | |
191 | cl_assert(!git_path_exists("attr/.gitignore")); | |
192 | p_mkdir("attr/.gitignore", 0777); | |
193 | cl_git_mkfile("attr/.gitignore/garbage.txt", "new_file\n"); | |
194 | ||
195 | assert_is_ignored(false, "File.txt"); | |
196 | assert_is_ignored(true, "NewFolder"); | |
197 | assert_is_ignored(true, "NewFolder/NewFolder"); | |
198 | assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); | |
d788499a | 199 | } |
7a5ee3dc | 200 | |
c6bf03b4 MM |
201 | void test_attr_ignore__subdirectory_gitignore(void) |
202 | { | |
203 | p_unlink("attr/.gitignore"); | |
204 | cl_assert(!git_path_exists("attr/.gitignore")); | |
205 | cl_git_mkfile( | |
206 | "attr/.gitignore", | |
207 | "file1\n"); | |
208 | p_mkdir("attr/dir", 0777); | |
209 | cl_git_mkfile( | |
210 | "attr/dir/.gitignore", | |
211 | "file2/\n"); | |
212 | ||
213 | assert_is_ignored(true, "file1"); | |
214 | assert_is_ignored(true, "dir/file1"); | |
9486d203 | 215 | assert_is_ignored(true, "dir/file2/actual_file"); /* in ignored dir */ |
c6bf03b4 MM |
216 | assert_is_ignored(false, "dir/file3"); |
217 | } | |
218 | ||
7a5ee3dc RB |
219 | void test_attr_ignore__expand_tilde_to_homedir(void) |
220 | { | |
7a5ee3dc RB |
221 | git_config *cfg; |
222 | ||
223 | assert_is_ignored(false, "example.global_with_tilde"); | |
224 | ||
0f603132 | 225 | cl_fake_home(); |
7a5ee3dc | 226 | |
a9528b8f RB |
227 | /* construct fake home with fake global excludes */ |
228 | cl_git_mkfile("home/globalexclude", "# found me\n*.global_with_tilde\n"); | |
7a5ee3dc RB |
229 | |
230 | cl_git_pass(git_repository_config(&cfg, g_repo)); | |
a9528b8f | 231 | cl_git_pass(git_config_set_string(cfg, "core.excludesfile", "~/globalexclude")); |
7a5ee3dc RB |
232 | git_config_free(cfg); |
233 | ||
234 | git_attr_cache_flush(g_repo); /* must reset to pick up change */ | |
235 | ||
236 | assert_is_ignored(true, "example.global_with_tilde"); | |
237 | ||
238 | cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES)); | |
239 | ||
0f603132 | 240 | cl_fake_home_cleanup(NULL); |
7a5ee3dc | 241 | |
a9528b8f RB |
242 | git_attr_cache_flush(g_repo); /* must reset to pick up change */ |
243 | ||
244 | assert_is_ignored(false, "example.global_with_tilde"); | |
7a5ee3dc | 245 | } |
adad5181 ET |
246 | |
247 | /* Ensure that the .gitignore in the subdirectory only affects | |
248 | * items in the subdirectory. */ | |
249 | void test_attr_ignore__gitignore_in_subdir(void) | |
250 | { | |
251 | cl_git_rmfile("attr/.gitignore"); | |
252 | ||
253 | cl_must_pass(p_mkdir("attr/dir1", 0777)); | |
254 | cl_must_pass(p_mkdir("attr/dir1/dir2", 0777)); | |
255 | cl_must_pass(p_mkdir("attr/dir1/dir2/dir3", 0777)); | |
256 | ||
257 | cl_git_mkfile("attr/dir1/dir2/dir3/.gitignore", "dir1/\ndir1/subdir/"); | |
258 | ||
259 | assert_is_ignored(false, "dir1/file"); | |
260 | assert_is_ignored(false, "dir1/dir2/file"); | |
261 | assert_is_ignored(false, "dir1/dir2/dir3/file"); | |
adad5181 ET |
262 | assert_is_ignored(true, "dir1/dir2/dir3/dir1/file"); |
263 | assert_is_ignored(true, "dir1/dir2/dir3/dir1/subdir/foo"); | |
264 | ||
265 | if (cl_repo_get_bool(g_repo, "core.ignorecase")) { | |
266 | cl_git_mkfile("attr/dir1/dir2/dir3/.gitignore", "DiR1/\nDiR1/subdir/\n"); | |
267 | ||
268 | assert_is_ignored(false, "dir1/file"); | |
269 | assert_is_ignored(false, "dir1/dir2/file"); | |
270 | assert_is_ignored(false, "dir1/dir2/dir3/file"); | |
adad5181 ET |
271 | assert_is_ignored(true, "dir1/dir2/dir3/dir1/file"); |
272 | assert_is_ignored(true, "dir1/dir2/dir3/dir1/subdir/foo"); | |
273 | } | |
274 | } | |
275 | ||
882cc37f ET |
276 | /* Ensure that files do not match folder cases */ |
277 | void test_attr_ignore__dont_ignore_files_for_folder(void) | |
97fb9ac7 ET |
278 | { |
279 | cl_git_rmfile("attr/.gitignore"); | |
280 | ||
882cc37f | 281 | cl_git_mkfile("attr/dir/.gitignore", "test/\n"); |
97fb9ac7 | 282 | |
882cc37f ET |
283 | /* Create "test" as a file; ensure it is not ignored. */ |
284 | cl_git_mkfile("attr/dir/test", "This is a file."); | |
97fb9ac7 | 285 | |
882cc37f ET |
286 | assert_is_ignored(false, "dir/test"); |
287 | if (cl_repo_get_bool(g_repo, "core.ignorecase")) | |
288 | assert_is_ignored(false, "dir/TeSt"); | |
97fb9ac7 | 289 | |
882cc37f ET |
290 | /* Create "test" as a directory; ensure it is ignored. */ |
291 | cl_git_rmfile("attr/dir/test"); | |
292 | cl_must_pass(p_mkdir("attr/dir/test", 0777)); | |
293 | ||
294 | assert_is_ignored(true, "dir/test"); | |
295 | if (cl_repo_get_bool(g_repo, "core.ignorecase")) | |
296 | assert_is_ignored(true, "dir/TeSt"); | |
97fb9ac7 | 297 | |
882cc37f ET |
298 | /* Remove "test" entirely; ensure it is not ignored. |
299 | * (As it doesn't exist, it is not a directory.) | |
300 | */ | |
301 | cl_must_pass(p_rmdir("attr/dir/test")); | |
302 | ||
303 | assert_is_ignored(false, "dir/test"); | |
304 | if (cl_repo_get_bool(g_repo, "core.ignorecase")) | |
305 | assert_is_ignored(false, "dir/TeSt"); | |
306 | } | |
d364dc8b CMN |
307 | |
308 | void test_attr_ignore__symlink_to_outside(void) | |
309 | { | |
310 | #ifdef GIT_WIN32 | |
311 | cl_skip(); | |
312 | #endif | |
313 | ||
314 | cl_git_rewritefile("attr/.gitignore", "symlink\n"); | |
315 | cl_git_mkfile("target", "target"); | |
316 | cl_git_pass(p_symlink("../target", "attr/symlink")); | |
317 | assert_is_ignored(true, "symlink"); | |
318 | assert_is_ignored(true, "lala/../symlink"); | |
319 | } | |
c3b8e8b3 RG |
320 | |
321 | void test_attr_ignore__test(void) | |
322 | { | |
323 | cl_git_rewritefile("attr/.gitignore", | |
324 | "/*/\n" | |
325 | "!/src\n"); | |
326 | assert_is_ignored(false, "src/foo.c"); | |
327 | assert_is_ignored(false, "src/foo/foo.c"); | |
328 | assert_is_ignored(false, "README.md"); | |
329 | assert_is_ignored(true, "dist/foo.o"); | |
330 | assert_is_ignored(true, "bin/foo"); | |
331 | } | |
eae0bfdc PP |
332 | |
333 | void test_attr_ignore__unignore_dir_succeeds(void) | |
334 | { | |
335 | cl_git_rewritefile("attr/.gitignore", | |
336 | "*.c\n" | |
337 | "!src/*.c\n"); | |
338 | assert_is_ignored(false, "src/foo.c"); | |
339 | assert_is_ignored(true, "src/foo/foo.c"); | |
340 | } | |
341 | ||
342 | void test_attr_ignore__case_insensitive_unignores_previous_rule(void) | |
343 | { | |
344 | git_config *cfg; | |
345 | ||
346 | cl_git_rewritefile("attr/.gitignore", | |
347 | "/case\n" | |
348 | "!/Case/\n"); | |
349 | ||
350 | cl_git_pass(git_repository_config(&cfg, g_repo)); | |
351 | cl_git_pass(git_config_set_bool(cfg, "core.ignorecase", true)); | |
352 | ||
353 | cl_must_pass(p_mkdir("attr/case", 0755)); | |
354 | cl_git_mkfile("attr/case/file", "content"); | |
355 | ||
356 | assert_is_ignored(false, "case/file"); | |
357 | } | |
358 | ||
359 | void test_attr_ignore__case_sensitive_unignore_does_nothing(void) | |
360 | { | |
361 | git_config *cfg; | |
362 | ||
363 | cl_git_rewritefile("attr/.gitignore", | |
364 | "/case\n" | |
365 | "!/Case/\n"); | |
366 | ||
367 | cl_git_pass(git_repository_config(&cfg, g_repo)); | |
368 | cl_git_pass(git_config_set_bool(cfg, "core.ignorecase", false)); | |
369 | ||
370 | cl_must_pass(p_mkdir("attr/case", 0755)); | |
371 | cl_git_mkfile("attr/case/file", "content"); | |
372 | ||
373 | assert_is_ignored(true, "case/file"); | |
374 | } | |
6147f643 PP |
375 | |
376 | void test_attr_ignore__ignored_subdirfiles_with_subdir_rule(void) | |
377 | { | |
378 | cl_git_rewritefile( | |
379 | "attr/.gitignore", | |
380 | "dir/*\n" | |
381 | "!dir/sub1/sub2/**\n"); | |
382 | ||
383 | assert_is_ignored(true, "dir/a.test"); | |
384 | assert_is_ignored(true, "dir/sub1/a.test"); | |
385 | assert_is_ignored(true, "dir/sub1/sub2"); | |
386 | } | |
387 | ||
388 | void test_attr_ignore__ignored_subdirfiles_with_negations(void) | |
389 | { | |
390 | cl_git_rewritefile( | |
391 | "attr/.gitignore", | |
392 | "dir/*\n" | |
393 | "!dir/a.test\n"); | |
394 | ||
395 | assert_is_ignored(false, "dir/a.test"); | |
396 | assert_is_ignored(true, "dir/b.test"); | |
397 | assert_is_ignored(true, "dir/sub1/c.test"); | |
398 | } | |
399 | ||
400 | void test_attr_ignore__negative_directory_rules_only_match_directories(void) | |
401 | { | |
402 | cl_git_rewritefile( | |
403 | "attr/.gitignore", | |
404 | "*\n" | |
405 | "!/**/\n" | |
406 | "!*.keep\n" | |
407 | "!.gitignore\n" | |
408 | ); | |
409 | ||
410 | assert_is_ignored(true, "src"); | |
411 | assert_is_ignored(true, "src/A"); | |
412 | assert_is_ignored(false, "src/"); | |
413 | assert_is_ignored(false, "src/A.keep"); | |
414 | assert_is_ignored(false, ".gitignore"); | |
415 | } |