]> git.proxmox.com Git - libgit2.git/blob - tests/core/dirent.c
08e0b11cf16368be6551a7a6f63ac3d4b706cfc4
[libgit2.git] / tests / core / dirent.c
1 #include "clar_libgit2.h"
2 #include "futils.h"
3
4 typedef struct name_data {
5 int count; /* return count */
6 char *name; /* filename */
7 } name_data;
8
9 typedef struct walk_data {
10 char *sub; /* sub-directory name */
11 name_data *names; /* name state data */
12 git_buf path;
13 } walk_data;
14
15
16 static char *top_dir = "dir-walk";
17 static walk_data *state_loc;
18
19 static void setup(walk_data *d)
20 {
21 name_data *n;
22
23 cl_must_pass(p_mkdir(top_dir, 0777));
24
25 cl_must_pass(p_chdir(top_dir));
26
27 if (strcmp(d->sub, ".") != 0)
28 cl_must_pass(p_mkdir(d->sub, 0777));
29
30 cl_git_pass(git_buf_sets(&d->path, d->sub));
31
32 state_loc = d;
33
34 for (n = d->names; n->name; n++) {
35 git_file fd = p_creat(n->name, 0666);
36 cl_assert(fd >= 0);
37 p_close(fd);
38 n->count = 0;
39 }
40 }
41
42 static void dirent_cleanup__cb(void *_d)
43 {
44 walk_data *d = _d;
45 name_data *n;
46
47 for (n = d->names; n->name; n++) {
48 cl_must_pass(p_unlink(n->name));
49 }
50
51 if (strcmp(d->sub, ".") != 0)
52 cl_must_pass(p_rmdir(d->sub));
53
54 cl_must_pass(p_chdir(".."));
55
56 cl_must_pass(p_rmdir(top_dir));
57
58 git_buf_dispose(&d->path);
59 }
60
61 static void check_counts(walk_data *d)
62 {
63 name_data *n;
64
65 for (n = d->names; n->name; n++) {
66 cl_assert(n->count == 1);
67 }
68 }
69
70 static int update_count(name_data *data, const char *name)
71 {
72 name_data *n;
73
74 for (n = data; n->name; n++) {
75 if (!strcmp(n->name, name)) {
76 n->count++;
77 return 0;
78 }
79 }
80
81 return GIT_ERROR;
82 }
83
84 static int one_entry(void *state, git_buf *path)
85 {
86 walk_data *d = (walk_data *) state;
87
88 if (state != state_loc)
89 return GIT_ERROR;
90
91 if (path != &d->path)
92 return GIT_ERROR;
93
94 return update_count(d->names, path->ptr);
95 }
96
97
98 static name_data dot_names[] = {
99 { 0, "./a" },
100 { 0, "./asdf" },
101 { 0, "./pack-foo.pack" },
102 { 0, NULL }
103 };
104 static walk_data dot = {
105 ".",
106 dot_names,
107 GIT_BUF_INIT
108 };
109
110 /* make sure that the '.' folder is not traversed */
111 void test_core_dirent__dont_traverse_dot(void)
112 {
113 cl_set_cleanup(&dirent_cleanup__cb, &dot);
114 setup(&dot);
115
116 cl_git_pass(git_path_direach(&dot.path, 0, one_entry, &dot));
117
118 check_counts(&dot);
119 }
120
121
122 static name_data sub_names[] = {
123 { 0, "sub/a" },
124 { 0, "sub/asdf" },
125 { 0, "sub/pack-foo.pack" },
126 { 0, NULL }
127 };
128 static walk_data sub = {
129 "sub",
130 sub_names,
131 GIT_BUF_INIT
132 };
133
134 /* traverse a subfolder */
135 void test_core_dirent__traverse_subfolder(void)
136 {
137 cl_set_cleanup(&dirent_cleanup__cb, &sub);
138 setup(&sub);
139
140 cl_git_pass(git_path_direach(&sub.path, 0, one_entry, &sub));
141
142 check_counts(&sub);
143 }
144
145
146 static walk_data sub_slash = {
147 "sub/",
148 sub_names,
149 GIT_BUF_INIT
150 };
151
152 /* traverse a slash-terminated subfolder */
153 void test_core_dirent__traverse_slash_terminated_folder(void)
154 {
155 cl_set_cleanup(&dirent_cleanup__cb, &sub_slash);
156 setup(&sub_slash);
157
158 cl_git_pass(git_path_direach(&sub_slash.path, 0, one_entry, &sub_slash));
159
160 check_counts(&sub_slash);
161 }
162
163
164 static name_data empty_names[] = {
165 { 0, NULL }
166 };
167 static walk_data empty = {
168 "empty",
169 empty_names,
170 GIT_BUF_INIT
171 };
172
173 /* make sure that empty folders are not traversed */
174 void test_core_dirent__dont_traverse_empty_folders(void)
175 {
176 cl_set_cleanup(&dirent_cleanup__cb, &empty);
177 setup(&empty);
178
179 cl_git_pass(git_path_direach(&empty.path, 0, one_entry, &empty));
180
181 check_counts(&empty);
182
183 /* make sure callback not called */
184 cl_assert(git_path_is_empty_dir(empty.path.ptr));
185 }
186
187 static name_data odd_names[] = {
188 { 0, "odd/.a" },
189 { 0, "odd/..c" },
190 /* the following don't work on cygwin/win32 */
191 /* { 0, "odd/.b." }, */
192 /* { 0, "odd/..d.." }, */
193 { 0, NULL }
194 };
195 static walk_data odd = {
196 "odd",
197 odd_names,
198 GIT_BUF_INIT
199 };
200
201 /* make sure that strange looking filenames ('..c') are traversed */
202 void test_core_dirent__traverse_weird_filenames(void)
203 {
204 cl_set_cleanup(&dirent_cleanup__cb, &odd);
205 setup(&odd);
206
207 cl_git_pass(git_path_direach(&odd.path, 0, one_entry, &odd));
208
209 check_counts(&odd);
210 }
211
212 /* test filename length limits */
213 void test_core_dirent__length_limits(void)
214 {
215 char *big_filename = (char *)git__malloc(FILENAME_MAX + 1);
216 memset(big_filename, 'a', FILENAME_MAX + 1);
217 big_filename[FILENAME_MAX] = 0;
218
219 cl_must_fail(p_creat(big_filename, 0666));
220
221 git__free(big_filename);
222 }
223
224 void test_core_dirent__empty_dir(void)
225 {
226 cl_must_pass(p_mkdir("empty_dir", 0777));
227 cl_assert(git_path_is_empty_dir("empty_dir"));
228
229 cl_git_mkfile("empty_dir/content", "whatever\n");
230 cl_assert(!git_path_is_empty_dir("empty_dir"));
231 cl_assert(!git_path_is_empty_dir("empty_dir/content"));
232
233 cl_must_pass(p_unlink("empty_dir/content"));
234
235 cl_must_pass(p_mkdir("empty_dir/content", 0777));
236 cl_assert(!git_path_is_empty_dir("empty_dir"));
237 cl_assert(git_path_is_empty_dir("empty_dir/content"));
238
239 cl_must_pass(p_rmdir("empty_dir/content"));
240
241 cl_must_pass(p_rmdir("empty_dir"));
242 }
243
244 static void handle_next(git_path_diriter *diriter, walk_data *walk)
245 {
246 const char *fullpath, *filename;
247 size_t fullpath_len, filename_len;
248
249 cl_git_pass(git_path_diriter_fullpath(&fullpath, &fullpath_len, diriter));
250 cl_git_pass(git_path_diriter_filename(&filename, &filename_len, diriter));
251
252 cl_assert_equal_strn(fullpath, "sub/", 4);
253 cl_assert_equal_s(fullpath+4, filename);
254
255 update_count(walk->names, fullpath);
256 }
257
258 /* test directory iterator */
259 void test_core_dirent__diriter_with_fullname(void)
260 {
261 git_path_diriter diriter = GIT_PATH_DIRITER_INIT;
262 int error;
263
264 cl_set_cleanup(&dirent_cleanup__cb, &sub);
265 setup(&sub);
266
267 cl_git_pass(git_path_diriter_init(&diriter, sub.path.ptr, 0));
268
269 while ((error = git_path_diriter_next(&diriter)) == 0)
270 handle_next(&diriter, &sub);
271
272 cl_assert_equal_i(error, GIT_ITEROVER);
273
274 git_path_diriter_free(&diriter);
275
276 check_counts(&sub);
277 }
278
279 void test_core_dirent__diriter_at_directory_root(void)
280 {
281 git_path_diriter diriter = GIT_PATH_DIRITER_INIT;
282 const char *sandbox_path, *path;
283 char *root_path;
284 size_t path_len;
285 int root_offset, error;
286
287 sandbox_path = clar_sandbox_path();
288 cl_assert((root_offset = git_path_root(sandbox_path)) >= 0);
289
290 cl_assert(root_path = git__calloc(1, root_offset + 2));
291 strncpy(root_path, sandbox_path, root_offset + 1);
292
293 cl_git_pass(git_path_diriter_init(&diriter, root_path, 0));
294
295 while ((error = git_path_diriter_next(&diriter)) == 0) {
296 cl_git_pass(git_path_diriter_fullpath(&path, &path_len, &diriter));
297
298 cl_assert(path_len > (size_t)(root_offset + 1));
299 cl_assert(path[root_offset+1] != '/');
300 }
301
302 cl_assert_equal_i(error, GIT_ITEROVER);
303
304 git_path_diriter_free(&diriter);
305 git__free(root_path);
306 }