1 #include "clar_libgit2.h"
2 #include "iterator.h"
3 #include "repository.h"
4 #include "futils.h"
5 #include "iterator_helpers.h"
6 #include "../submodule/submodule_helpers.h"
7 #include <stdarg.h>
8 
9 static git_repository *g_repo;
10 
test_iterator_index__initialize(void)11 void test_iterator_index__initialize(void)
12 {
13 }
14 
test_iterator_index__cleanup(void)15 void test_iterator_index__cleanup(void)
16 {
17 	cl_git_sandbox_cleanup();
18 	g_repo = NULL;
19 }
20 
index_iterator_test(const char * sandbox,const char * start,const char * end,git_iterator_flag_t flags,int expected_count,const char ** expected_names,const char ** expected_oids)21 static void index_iterator_test(
22 	const char *sandbox,
23 	const char *start,
24 	const char *end,
25 	git_iterator_flag_t flags,
26 	int expected_count,
27 	const char **expected_names,
28 	const char **expected_oids)
29 {
30 	git_index *index;
31 	git_iterator *i;
32 	const git_index_entry *entry;
33 	int error, count = 0, caps;
34 	git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
35 
36 	g_repo = cl_git_sandbox_init(sandbox);
37 
38 	cl_git_pass(git_repository_index(&index, g_repo));
39 	caps = git_index_caps(index);
40 
41 	iter_opts.flags = flags;
42 	iter_opts.start = start;
43 	iter_opts.end = end;
44 
45 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &iter_opts));
46 
47 	while (!(error = git_iterator_advance(&entry, i))) {
48 		cl_assert(entry);
49 
50 		if (expected_names != NULL)
51 			cl_assert_equal_s(expected_names[count], entry->path);
52 
53 		if (expected_oids != NULL) {
54 			git_oid oid;
55 			cl_git_pass(git_oid_fromstr(&oid, expected_oids[count]));
56 			cl_assert_equal_oid(&oid, &entry->id);
57 		}
58 
59 		count++;
60 	}
61 
62 	cl_assert_equal_i(GIT_ITEROVER, error);
63 	cl_assert(!entry);
64 	cl_assert_equal_i(expected_count, count);
65 
66 	git_iterator_free(i);
67 
68 	cl_assert(caps == git_index_caps(index));
69 	git_index_free(index);
70 }
71 
72 static const char *expected_index_0[] = {
73 	"attr0",
74 	"attr1",
75 	"attr2",
76 	"attr3",
77 	"binfile",
78 	"gitattributes",
79 	"macro_bad",
80 	"macro_test",
81 	"root_test1",
82 	"root_test2",
83 	"root_test3",
84 	"root_test4.txt",
85 	"sub/abc",
86 	"sub/file",
87 	"sub/sub/file",
88 	"sub/sub/subsub.txt",
89 	"sub/subdir_test1",
90 	"sub/subdir_test2.txt",
91 	"subdir/.gitattributes",
92 	"subdir/abc",
93 	"subdir/subdir_test1",
94 	"subdir/subdir_test2.txt",
95 	"subdir2/subdir2_test1",
96 };
97 
98 static const char *expected_index_oids_0[] = {
99 	"556f8c827b8e4a02ad5cab77dca2bcb3e226b0b3",
100 	"3b74db7ab381105dc0d28f8295a77f6a82989292",
101 	"2c66e14f77196ea763fb1e41612c1aa2bc2d8ed2",
102 	"c485abe35abd4aa6fd83b076a78bbea9e2e7e06c",
103 	"d800886d9c86731ae5c4a62b0b77c437015e00d2",
104 	"2b40c5aca159b04ea8d20ffe36cdf8b09369b14a",
105 	"5819a185d77b03325aaf87cafc771db36f6ddca7",
106 	"ff69f8639ce2e6010b3f33a74160aad98b48da2b",
107 	"45141a79a77842c59a63229403220a4e4be74e3d",
108 	"4d713dc48e6b1bd75b0d61ad078ba9ca3a56745d",
109 	"108bb4e7fd7b16490dc33ff7d972151e73d7166e",
110 	"a0f7217ae99f5ac3e88534f5cea267febc5fa85b",
111 	"3e42ffc54a663f9401cc25843d6c0e71a33e4249",
112 	"45b983be36b73c0788dc9cbcb76cbb80fc7bb057",
113 	"45b983be36b73c0788dc9cbcb76cbb80fc7bb057",
114 	"9e5bdc47d6a80f2be0ea3049ad74231b94609242",
115 	"e563cf4758f0d646f1b14b76016aa17fa9e549a4",
116 	"fb5067b1aef3ac1ada4b379dbcb7d17255df7d78",
117 	"99eae476896f4907224978b88e5ecaa6c5bb67a9",
118 	"3e42ffc54a663f9401cc25843d6c0e71a33e4249",
119 	"e563cf4758f0d646f1b14b76016aa17fa9e549a4",
120 	"fb5067b1aef3ac1ada4b379dbcb7d17255df7d78",
121 	"dccada462d3df8ac6de596fb8c896aba9344f941"
122 };
123 
test_iterator_index__0(void)124 void test_iterator_index__0(void)
125 {
126 	index_iterator_test(
127 		"attr", NULL, NULL, 0, ARRAY_SIZE(expected_index_0),
128 		expected_index_0, expected_index_oids_0);
129 }
130 
131 static const char *expected_index_1[] = {
132 	"current_file",
133 	"file_deleted",
134 	"modified_file",
135 	"staged_changes",
136 	"staged_changes_file_deleted",
137 	"staged_changes_modified_file",
138 	"staged_new_file",
139 	"staged_new_file_deleted_file",
140 	"staged_new_file_modified_file",
141 	"subdir.txt",
142 	"subdir/current_file",
143 	"subdir/deleted_file",
144 	"subdir/modified_file",
145 };
146 
147 static const char* expected_index_oids_1[] = {
148 	"a0de7e0ac200c489c41c59dfa910154a70264e6e",
149 	"5452d32f1dd538eb0405e8a83cc185f79e25e80f",
150 	"452e4244b5d083ddf0460acf1ecc74db9dcfa11a",
151 	"55d316c9ba708999f1918e9677d01dfcae69c6b9",
152 	"a6be623522ce87a1d862128ac42672604f7b468b",
153 	"906ee7711f4f4928ddcb2a5f8fbc500deba0d2a8",
154 	"529a16e8e762d4acb7b9636ff540a00831f9155a",
155 	"90b8c29d8ba39434d1c63e1b093daaa26e5bd972",
156 	"ed062903b8f6f3dccb2fa81117ba6590944ef9bd",
157 	"e8ee89e15bbe9b20137715232387b3de5b28972e",
158 	"53ace0d1cc1145a5f4fe4f78a186a60263190733",
159 	"1888c805345ba265b0ee9449b8877b6064592058",
160 	"a6191982709b746d5650e93c2acf34ef74e11504"
161 };
162 
test_iterator_index__1(void)163 void test_iterator_index__1(void)
164 {
165 	index_iterator_test(
166 		"status", NULL, NULL, 0, ARRAY_SIZE(expected_index_1),
167 		expected_index_1, expected_index_oids_1);
168 }
169 
170 static const char *expected_index_range[] = {
171 	"root_test1",
172 	"root_test2",
173 	"root_test3",
174 	"root_test4.txt",
175 };
176 
177 static const char *expected_index_oids_range[] = {
178 	"45141a79a77842c59a63229403220a4e4be74e3d",
179 	"4d713dc48e6b1bd75b0d61ad078ba9ca3a56745d",
180 	"108bb4e7fd7b16490dc33ff7d972151e73d7166e",
181 	"a0f7217ae99f5ac3e88534f5cea267febc5fa85b",
182 };
183 
test_iterator_index__range(void)184 void test_iterator_index__range(void)
185 {
186 	index_iterator_test(
187 		"attr", "root", "root", 0, ARRAY_SIZE(expected_index_range),
188 		expected_index_range, expected_index_oids_range);
189 }
190 
test_iterator_index__range_empty_0(void)191 void test_iterator_index__range_empty_0(void)
192 {
193 	index_iterator_test(
194 		"attr", "empty", "empty", 0, 0, NULL, NULL);
195 }
196 
test_iterator_index__range_empty_1(void)197 void test_iterator_index__range_empty_1(void)
198 {
199 	index_iterator_test(
200 		"attr", "z_empty_after", NULL, 0, 0, NULL, NULL);
201 }
202 
test_iterator_index__range_empty_2(void)203 void test_iterator_index__range_empty_2(void)
204 {
205 	index_iterator_test(
206 		"attr", NULL, ".aaa_empty_before", 0, 0, NULL, NULL);
207 }
208 
check_index_range(git_repository * repo,const char * start,const char * end,bool ignore_case,int expected_count)209 static void check_index_range(
210 	git_repository *repo,
211 	const char *start,
212 	const char *end,
213 	bool ignore_case,
214 	int expected_count)
215 {
216 	git_index *index;
217 	git_iterator *i;
218 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
219 	int error, count, caps;
220 	bool is_ignoring_case;
221 
222 	cl_git_pass(git_repository_index(&index, repo));
223 
224 	caps = git_index_caps(index);
225 	is_ignoring_case = ((caps & GIT_INDEX_CAPABILITY_IGNORE_CASE) != 0);
226 
227 	if (ignore_case != is_ignoring_case)
228 		cl_git_pass(git_index_set_caps(index, caps ^ GIT_INDEX_CAPABILITY_IGNORE_CASE));
229 
230 	i_opts.flags = 0;
231 	i_opts.start = start;
232 	i_opts.end = end;
233 
234 	cl_git_pass(git_iterator_for_index(&i, repo, index, &i_opts));
235 
236 	cl_assert(git_iterator_ignore_case(i) == ignore_case);
237 
238 	for (count = 0; !(error = git_iterator_advance(NULL, i)); ++count)
239 		/* count em up */;
240 
241 	cl_assert_equal_i(GIT_ITEROVER, error);
242 	cl_assert_equal_i(expected_count, count);
243 
244 	git_iterator_free(i);
245 	git_index_free(index);
246 }
247 
test_iterator_index__range_icase(void)248 void test_iterator_index__range_icase(void)
249 {
250 	git_index *index;
251 	git_tree *head;
252 
253 	g_repo = cl_git_sandbox_init("testrepo");
254 
255 	/* reset index to match HEAD */
256 	cl_git_pass(git_repository_head_tree(&head, g_repo));
257 	cl_git_pass(git_repository_index(&index, g_repo));
258 	cl_git_pass(git_index_read_tree(index, head));
259 	cl_git_pass(git_index_write(index));
260 	git_tree_free(head);
261 	git_index_free(index);
262 
263 	/* do some ranged iterator checks toggling case sensitivity */
264 	check_index_range(g_repo, "B", "C", false, 0);
265 	check_index_range(g_repo, "B", "C", true, 1);
266 	check_index_range(g_repo, "a", "z", false, 3);
267 	check_index_range(g_repo, "a", "z", true, 4);
268 }
269 
270 static const char *expected_index_cs[] = {
271 	"B", "D", "F", "H", "J", "L/1", "L/B", "L/D", "L/a", "L/c",
272 	"a", "c", "e", "g", "i", "k/1", "k/B", "k/D", "k/a", "k/c",
273 };
274 
275 static const char *expected_index_ci[] = {
276 	"a", "B", "c", "D", "e", "F", "g", "H", "i", "J",
277 	"k/1", "k/a", "k/B", "k/c", "k/D", "L/1", "L/a", "L/B", "L/c", "L/D",
278 };
279 
test_iterator_index__case_folding(void)280 void test_iterator_index__case_folding(void)
281 {
282 	git_buf path = GIT_BUF_INIT;
283 	int fs_is_ci = 0;
284 
285 	cl_git_pass(git_buf_joinpath(&path, cl_fixture("icase"), ".gitted/CoNfIg"));
286 	fs_is_ci = git_path_exists(path.ptr);
287 	git_buf_dispose(&path);
288 
289 	index_iterator_test(
290 		"icase", NULL, NULL, 0, ARRAY_SIZE(expected_index_cs),
291 		fs_is_ci ? expected_index_ci : expected_index_cs, NULL);
292 
293 	cl_git_sandbox_cleanup();
294 
295 	index_iterator_test(
296 		"icase", NULL, NULL, GIT_ITERATOR_IGNORE_CASE,
297 		ARRAY_SIZE(expected_index_ci), expected_index_ci, NULL);
298 
299 	cl_git_sandbox_cleanup();
300 
301 	index_iterator_test(
302 		"icase", NULL, NULL, GIT_ITERATOR_DONT_IGNORE_CASE,
303 		ARRAY_SIZE(expected_index_cs), expected_index_cs, NULL);
304 }
305 
306 /* Index contents (including pseudotrees):
307  *
308  * 0: a     5: F     10: k/      16: L/
309  * 1: B     6: g     11: k/1     17: L/1
310  * 2: c     7: H     12: k/a     18: L/a
311  * 3: D     8: i     13: k/B     19: L/B
312  * 4: e     9: J     14: k/c     20: L/c
313  *                   15: k/D     21: L/D
314  *
315  * 0: B     5: L/    11: a       16: k/
316  * 1: D     6: L/1   12: c       17: k/1
317  * 2: F     7: L/B   13: e       18: k/B
318  * 3: H     8: L/D   14: g       19: k/D
319  * 4: J     9: L/a   15: i       20: k/a
320  *         10: L/c               21: k/c
321  */
322 
test_iterator_index__icase_0(void)323 void test_iterator_index__icase_0(void)
324 {
325 	git_iterator *i;
326 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
327 	git_index *index;
328 
329 	g_repo = cl_git_sandbox_init("icase");
330 
331 	cl_git_pass(git_repository_index(&index, g_repo));
332 
333 	/* autoexpand with no tree entries for index */
334 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, NULL));
335 	expect_iterator_items(i, 20, NULL, 20, NULL);
336 	git_iterator_free(i);
337 
338 	/* auto expand with tree entries */
339 	i_opts.flags = GIT_ITERATOR_INCLUDE_TREES;
340 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
341 	expect_iterator_items(i, 22, NULL, 22, NULL);
342 	git_iterator_free(i);
343 
344 	/* no auto expand (implies trees included) */
345 	i_opts.flags = GIT_ITERATOR_DONT_AUTOEXPAND;
346 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
347 	expect_iterator_items(i, 12, NULL, 22, NULL);
348 	git_iterator_free(i);
349 
350 	git_index_free(index);
351 }
352 
test_iterator_index__icase_1(void)353 void test_iterator_index__icase_1(void)
354 {
355 	git_iterator *i;
356 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
357 	git_index *index;
358 	int caps;
359 
360 	g_repo = cl_git_sandbox_init("icase");
361 
362 	cl_git_pass(git_repository_index(&index, g_repo));
363 	caps = git_index_caps(index);
364 
365 	/* force case sensitivity */
366 	cl_git_pass(git_index_set_caps(index, caps & ~GIT_INDEX_CAPABILITY_IGNORE_CASE));
367 
368 	/* autoexpand with no tree entries over range */
369 	i_opts.start = "c";
370 	i_opts.end = "k/D";
371 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
372 	expect_iterator_items(i, 7, NULL, 7, NULL);
373 	git_iterator_free(i);
374 
375 	i_opts.start = "k";
376 	i_opts.end = "k/Z";
377 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
378 	expect_iterator_items(i, 3, NULL, 3, NULL);
379 	git_iterator_free(i);
380 
381 	/* auto expand with tree entries */
382 	i_opts.flags = GIT_ITERATOR_INCLUDE_TREES;
383 
384 	i_opts.start = "c";
385 	i_opts.end = "k/D";
386 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
387 	expect_iterator_items(i, 8, NULL, 8, NULL);
388 	git_iterator_free(i);
389 
390 	i_opts.start = "k";
391 	i_opts.end = "k/Z";
392 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
393 	expect_iterator_items(i, 4, NULL, 4, NULL);
394 	git_iterator_free(i);
395 
396 	/* no auto expand (implies trees included) */
397 	i_opts.flags = GIT_ITERATOR_DONT_AUTOEXPAND;
398 
399 	i_opts.start = "c";
400 	i_opts.end = "k/D";
401 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
402 	expect_iterator_items(i, 5, NULL, 8, NULL);
403 	git_iterator_free(i);
404 
405 	i_opts.start = "k";
406 	i_opts.end = "k/Z";
407 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
408 	expect_iterator_items(i, 1, NULL, 4, NULL);
409 	git_iterator_free(i);
410 
411 	/* force case insensitivity */
412 	cl_git_pass(git_index_set_caps(index, caps | GIT_INDEX_CAPABILITY_IGNORE_CASE));
413 
414 	/* autoexpand with no tree entries over range */
415 	i_opts.flags = 0;
416 
417 	i_opts.start = "c";
418 	i_opts.end = "k/D";
419 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
420 	expect_iterator_items(i, 13, NULL, 13, NULL);
421 	git_iterator_free(i);
422 
423 	i_opts.start = "k";
424 	i_opts.end = "k/Z";
425 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
426 	expect_iterator_items(i, 5, NULL, 5, NULL);
427 	git_iterator_free(i);
428 
429 	/* auto expand with tree entries */
430 	i_opts.flags = GIT_ITERATOR_INCLUDE_TREES;
431 
432 	i_opts.start = "c";
433 	i_opts.end = "k/D";
434 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
435 	expect_iterator_items(i, 14, NULL, 14, NULL);
436 	git_iterator_free(i);
437 
438 	i_opts.start = "k";
439 	i_opts.end = "k/Z";
440 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
441 	expect_iterator_items(i, 6, NULL, 6, NULL);
442 	git_iterator_free(i);
443 
444 	/* no auto expand (implies trees included) */
445 	i_opts.flags = GIT_ITERATOR_DONT_AUTOEXPAND;
446 
447 	i_opts.start = "c";
448 	i_opts.end = "k/D";
449 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
450 	expect_iterator_items(i, 9, NULL, 14, NULL);
451 	git_iterator_free(i);
452 
453 	i_opts.start = "k";
454 	i_opts.end = "k/Z";
455 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
456 	expect_iterator_items(i, 1, NULL, 6, NULL);
457 	git_iterator_free(i);
458 
459 	cl_git_pass(git_index_set_caps(index, caps));
460 	git_index_free(index);
461 }
462 
test_iterator_index__pathlist(void)463 void test_iterator_index__pathlist(void)
464 {
465 	git_iterator *i;
466 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
467 	git_index *index;
468 	git_vector filelist;
469 
470 	cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb));
471 	cl_git_pass(git_vector_insert(&filelist, "a"));
472 	cl_git_pass(git_vector_insert(&filelist, "B"));
473 	cl_git_pass(git_vector_insert(&filelist, "c"));
474 	cl_git_pass(git_vector_insert(&filelist, "D"));
475 	cl_git_pass(git_vector_insert(&filelist, "e"));
476 	cl_git_pass(git_vector_insert(&filelist, "k/1"));
477 	cl_git_pass(git_vector_insert(&filelist, "k/a"));
478 	cl_git_pass(git_vector_insert(&filelist, "L/1"));
479 
480 	g_repo = cl_git_sandbox_init("icase");
481 
482 	cl_git_pass(git_repository_index(&index, g_repo));
483 
484 	i_opts.pathlist.strings = (char **)filelist.contents;
485 	i_opts.pathlist.count = filelist.length;
486 
487 	/* Case sensitive */
488 	{
489 		const char *expected[] = {
490 			"B", "D", "L/1", "a", "c", "e", "k/1", "k/a" };
491 		size_t expected_len = 8;
492 
493 		i_opts.start = NULL;
494 		i_opts.end = NULL;
495 		i_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
496 
497 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
498 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
499 		git_iterator_free(i);
500 	}
501 
502 	/* Case INsensitive */
503 	{
504 		const char *expected[] = {
505 			"a", "B", "c", "D", "e", "k/1", "k/a", "L/1" };
506 		size_t expected_len = 8;
507 
508 		i_opts.start = NULL;
509 		i_opts.end = NULL;
510 		i_opts.flags = GIT_ITERATOR_IGNORE_CASE;
511 
512 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
513 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
514 		git_iterator_free(i);
515 	}
516 
517 	/* Set a start, but no end.  Case sensitive. */
518 	{
519 		const char *expected[] = { "c", "e", "k/1", "k/a" };
520 		size_t expected_len = 4;
521 
522 		i_opts.start = "c";
523 		i_opts.end = NULL;
524 		i_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
525 
526 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
527 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
528 		git_iterator_free(i);
529 	}
530 
531 	/* Set a start, but no end.  Case INsensitive. */
532 	{
533 		const char *expected[] = { "c", "D", "e", "k/1", "k/a", "L/1" };
534 		size_t expected_len = 6;
535 
536 		i_opts.start = "c";
537 		i_opts.end = NULL;
538 		i_opts.flags = GIT_ITERATOR_IGNORE_CASE;
539 
540 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
541 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
542 		git_iterator_free(i);
543 	}
544 
545 	/* Set no start, but an end.  Case sensitive. */
546 	{
547 		const char *expected[] = { "B", "D", "L/1", "a", "c", "e" };
548 		size_t expected_len = 6;
549 
550 		i_opts.start = NULL;
551 		i_opts.end = "e";
552 		i_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
553 
554 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
555 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
556 		git_iterator_free(i);
557 	}
558 
559 	/* Set no start, but an end.  Case INsensitive. */
560 	{
561 		const char *expected[] = { "a", "B", "c", "D", "e" };
562 		size_t expected_len = 5;
563 
564 		i_opts.start = NULL;
565 		i_opts.end = "e";
566 		i_opts.flags = GIT_ITERATOR_IGNORE_CASE;
567 
568 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
569 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
570 		git_iterator_free(i);
571 	}
572 
573 	/* Start and an end, case sensitive */
574 	{
575 		const char *expected[] = { "c", "e", "k/1" };
576 		size_t expected_len = 3;
577 
578 		i_opts.start = "c";
579 		i_opts.end = "k/D";
580 		i_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
581 
582 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
583 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
584 		git_iterator_free(i);
585 	}
586 
587 	/* Start and an end, case sensitive */
588 	{
589 		const char *expected[] = { "k/1" };
590 		size_t expected_len = 1;
591 
592 		i_opts.start = "k";
593 		i_opts.end = "k/D";
594 		i_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
595 
596 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
597 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
598 		git_iterator_free(i);
599 	}
600 
601 	/* Start and an end, case INsensitive */
602 	{
603 		const char *expected[] = { "c", "D", "e", "k/1", "k/a" };
604 		size_t expected_len = 5;
605 
606 		i_opts.start = "c";
607 		i_opts.end = "k/D";
608 		i_opts.flags = GIT_ITERATOR_IGNORE_CASE;
609 
610 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
611 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
612 		git_iterator_free(i);
613 	}
614 
615 	/* Start and an end, case INsensitive */
616 	{
617 		const char *expected[] = { "k/1", "k/a" };
618 		size_t expected_len = 2;
619 
620 		i_opts.start = "k";
621 		i_opts.end = "k/D";
622 		i_opts.flags = GIT_ITERATOR_IGNORE_CASE;
623 
624 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
625 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
626 		git_iterator_free(i);
627 	}
628 
629 	git_index_free(index);
630 	git_vector_free(&filelist);
631 }
632 
test_iterator_index__pathlist_with_dirs(void)633 void test_iterator_index__pathlist_with_dirs(void)
634 {
635 	git_iterator *i;
636 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
637 	git_index *index;
638 	git_vector filelist;
639 
640 	cl_git_pass(git_vector_init(&filelist, 5, NULL));
641 
642 	g_repo = cl_git_sandbox_init("icase");
643 
644 	cl_git_pass(git_repository_index(&index, g_repo));
645 
646 	/* Test that a prefix `k` matches folders, even without trailing slash */
647 	{
648 		const char *expected[] = { "k/1", "k/B", "k/D", "k/a", "k/c" };
649 		size_t expected_len = 5;
650 
651 		git_vector_clear(&filelist);
652 		cl_git_pass(git_vector_insert(&filelist, "k"));
653 
654 		i_opts.pathlist.strings = (char **)filelist.contents;
655 		i_opts.pathlist.count = filelist.length;
656 		i_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
657 
658 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
659 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
660 		git_iterator_free(i);
661 	}
662 
663 	/* Test that a `k/` matches a folder */
664 	{
665 		const char *expected[] = { "k/1", "k/B", "k/D", "k/a", "k/c" };
666 		size_t expected_len = 5;
667 
668 		git_vector_clear(&filelist);
669 		cl_git_pass(git_vector_insert(&filelist, "k/"));
670 
671 		i_opts.pathlist.strings = (char **)filelist.contents;
672 		i_opts.pathlist.count = filelist.length;
673 		i_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
674 
675 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
676 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
677 		git_iterator_free(i);
678 	}
679 
680 	/* When the iterator is case sensitive, ensure we can't lookup the
681 	 * directory with the wrong case.
682 	 */
683 	{
684 		git_vector_clear(&filelist);
685 		cl_git_pass(git_vector_insert(&filelist, "K/"));
686 
687 		i_opts.pathlist.strings = (char **)filelist.contents;
688 		i_opts.pathlist.count = filelist.length;
689 		i_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
690 
691 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
692 		cl_git_fail_with(GIT_ITEROVER, git_iterator_advance(NULL, i));
693 		git_iterator_free(i);
694 	}
695 
696 	/* Test that case insensitive matching works. */
697 	{
698 		const char *expected[] = { "k/1", "k/a", "k/B", "k/c", "k/D" };
699 		size_t expected_len = 5;
700 
701 		git_vector_clear(&filelist);
702 		cl_git_pass(git_vector_insert(&filelist, "K/"));
703 
704 		i_opts.pathlist.strings = (char **)filelist.contents;
705 		i_opts.pathlist.count = filelist.length;
706 		i_opts.flags = GIT_ITERATOR_IGNORE_CASE;
707 
708 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
709 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
710 		git_iterator_free(i);
711 	}
712 
713 	/* Test that case insensitive matching works without trailing slash. */
714 	{
715 		const char *expected[] = { "k/1", "k/a", "k/B", "k/c", "k/D" };
716 		size_t expected_len = 5;
717 
718 		git_vector_clear(&filelist);
719 		cl_git_pass(git_vector_insert(&filelist, "K"));
720 
721 		i_opts.pathlist.strings = (char **)filelist.contents;
722 		i_opts.pathlist.count = filelist.length;
723 		i_opts.flags = GIT_ITERATOR_IGNORE_CASE;
724 
725 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
726 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
727 		git_iterator_free(i);
728 	}
729 
730 	git_index_free(index);
731 	git_vector_free(&filelist);
732 }
733 
test_iterator_index__pathlist_with_dirs_include_trees(void)734 void test_iterator_index__pathlist_with_dirs_include_trees(void)
735 {
736 	git_iterator *i;
737 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
738 	git_index *index;
739 	git_vector filelist;
740 
741 	const char *expected[] = { "k/", "k/1", "k/B", "k/D", "k/a", "k/c" };
742 	size_t expected_len = 6;
743 
744 	cl_git_pass(git_vector_init(&filelist, 5, NULL));
745 
746 	g_repo = cl_git_sandbox_init("icase");
747 
748 	cl_git_pass(git_repository_index(&index, g_repo));
749 
750 	git_vector_clear(&filelist);
751 	cl_git_pass(git_vector_insert(&filelist, "k"));
752 
753 	i_opts.pathlist.strings = (char **)filelist.contents;
754 	i_opts.pathlist.count = filelist.length;
755 	i_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE | GIT_ITERATOR_INCLUDE_TREES;
756 
757 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
758 	expect_iterator_items(i, expected_len, expected, expected_len, expected);
759 	git_iterator_free(i);
760 
761 	git_index_free(index);
762 	git_vector_free(&filelist);
763 }
764 
test_iterator_index__pathlist_1(void)765 void test_iterator_index__pathlist_1(void)
766 {
767 	git_iterator *i;
768 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
769 	git_index *index;
770 	git_vector filelist = GIT_VECTOR_INIT;
771 	int default_icase, expect;
772 
773 	g_repo = cl_git_sandbox_init("icase");
774 
775 	cl_git_pass(git_repository_index(&index, g_repo));
776 
777 	cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb));
778 	cl_git_pass(git_vector_insert(&filelist, "0"));
779 	cl_git_pass(git_vector_insert(&filelist, "c"));
780 	cl_git_pass(git_vector_insert(&filelist, "D"));
781 	cl_git_pass(git_vector_insert(&filelist, "e"));
782 	cl_git_pass(git_vector_insert(&filelist, "k/1"));
783 	cl_git_pass(git_vector_insert(&filelist, "k/a"));
784 
785 	/* In this test we DO NOT force a case setting on the index. */
786 	default_icase = ((git_index_caps(index) & GIT_INDEX_CAPABILITY_IGNORE_CASE) != 0);
787 
788 	i_opts.pathlist.strings = (char **)filelist.contents;
789 	i_opts.pathlist.count = filelist.length;
790 
791 	i_opts.start = "b";
792 	i_opts.end = "k/D";
793 
794 	/* (c D e k/1 k/a ==> 5) vs (c e k/1 ==> 3) */
795 	expect = default_icase ? 5 : 3;
796 
797 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
798 	expect_iterator_items(i, expect, NULL, expect, NULL);
799 	git_iterator_free(i);
800 
801 	git_index_free(index);
802 	git_vector_free(&filelist);
803 }
804 
test_iterator_index__pathlist_2(void)805 void test_iterator_index__pathlist_2(void)
806 {
807 	git_iterator *i;
808 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
809 	git_index *index;
810 	git_vector filelist = GIT_VECTOR_INIT;
811 	int default_icase, expect;
812 
813 	g_repo = cl_git_sandbox_init("icase");
814 
815 	cl_git_pass(git_repository_index(&index, g_repo));
816 
817 	cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb));
818 	cl_git_pass(git_vector_insert(&filelist, "0"));
819 	cl_git_pass(git_vector_insert(&filelist, "c"));
820 	cl_git_pass(git_vector_insert(&filelist, "D"));
821 	cl_git_pass(git_vector_insert(&filelist, "e"));
822 	cl_git_pass(git_vector_insert(&filelist, "k/"));
823 	cl_git_pass(git_vector_insert(&filelist, "k.a"));
824 	cl_git_pass(git_vector_insert(&filelist, "k.b"));
825 	cl_git_pass(git_vector_insert(&filelist, "kZZZZZZZ"));
826 
827 	/* In this test we DO NOT force a case setting on the index. */
828 	default_icase = ((git_index_caps(index) & GIT_INDEX_CAPABILITY_IGNORE_CASE) != 0);
829 
830 	i_opts.pathlist.strings = (char **)filelist.contents;
831 	i_opts.pathlist.count = filelist.length;
832 
833 	i_opts.start = "b";
834 	i_opts.end = "k/D";
835 
836 	/* (c D e k/1 k/a k/B k/c k/D) vs (c e k/1 k/B k/D) */
837 	expect = default_icase ? 8 : 5;
838 
839 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
840 	expect_iterator_items(i, expect, NULL, expect, NULL);
841 	git_iterator_free(i);
842 
843 	git_index_free(index);
844 	git_vector_free(&filelist);
845 }
846 
test_iterator_index__pathlist_four(void)847 void test_iterator_index__pathlist_four(void)
848 {
849 	git_iterator *i;
850 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
851 	git_index *index;
852 	git_vector filelist = GIT_VECTOR_INIT;
853 	int default_icase, expect;
854 
855 	g_repo = cl_git_sandbox_init("icase");
856 
857 	cl_git_pass(git_repository_index(&index, g_repo));
858 
859 	cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb));
860 	cl_git_pass(git_vector_insert(&filelist, "0"));
861 	cl_git_pass(git_vector_insert(&filelist, "c"));
862 	cl_git_pass(git_vector_insert(&filelist, "D"));
863 	cl_git_pass(git_vector_insert(&filelist, "e"));
864 	cl_git_pass(git_vector_insert(&filelist, "k"));
865 	cl_git_pass(git_vector_insert(&filelist, "k.a"));
866 	cl_git_pass(git_vector_insert(&filelist, "k.b"));
867 	cl_git_pass(git_vector_insert(&filelist, "kZZZZZZZ"));
868 
869 	/* In this test we DO NOT force a case setting on the index. */
870 	default_icase = ((git_index_caps(index) & GIT_INDEX_CAPABILITY_IGNORE_CASE) != 0);
871 
872 	i_opts.pathlist.strings = (char **)filelist.contents;
873 	i_opts.pathlist.count = filelist.length;
874 
875 	i_opts.start = "b";
876 	i_opts.end = "k/D";
877 
878 	/* (c D e k/1 k/a k/B k/c k/D) vs (c e k/1 k/B k/D) */
879 	expect = default_icase ? 8 : 5;
880 
881 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
882 	expect_iterator_items(i, expect, NULL, expect, NULL);
883 	git_iterator_free(i);
884 
885 	git_index_free(index);
886 	git_vector_free(&filelist);
887 }
888 
test_iterator_index__pathlist_icase(void)889 void test_iterator_index__pathlist_icase(void)
890 {
891 	git_iterator *i;
892 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
893 	git_index *index;
894 	int caps;
895 	git_vector filelist;
896 
897 	cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb));
898 	cl_git_pass(git_vector_insert(&filelist, "a"));
899 	cl_git_pass(git_vector_insert(&filelist, "B"));
900 	cl_git_pass(git_vector_insert(&filelist, "c"));
901 	cl_git_pass(git_vector_insert(&filelist, "D"));
902 	cl_git_pass(git_vector_insert(&filelist, "e"));
903 	cl_git_pass(git_vector_insert(&filelist, "k/1"));
904 	cl_git_pass(git_vector_insert(&filelist, "k/a"));
905 	cl_git_pass(git_vector_insert(&filelist, "L/1"));
906 
907 	g_repo = cl_git_sandbox_init("icase");
908 
909 	cl_git_pass(git_repository_index(&index, g_repo));
910 	caps = git_index_caps(index);
911 
912 	/* force case sensitivity */
913 	cl_git_pass(git_index_set_caps(index, caps & ~GIT_INDEX_CAPABILITY_IGNORE_CASE));
914 
915 	/* All indexfilelist iterator tests are "autoexpand with no tree entries" */
916 
917 	i_opts.pathlist.strings = (char **)filelist.contents;
918 	i_opts.pathlist.count = filelist.length;
919 
920 	i_opts.start = "c";
921 	i_opts.end = "k/D";
922 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
923 	expect_iterator_items(i, 3, NULL, 3, NULL);
924 	git_iterator_free(i);
925 
926 	i_opts.start = "k";
927 	i_opts.end = "k/Z";
928 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
929 	expect_iterator_items(i, 1, NULL, 1, NULL);
930 	git_iterator_free(i);
931 
932 	/* force case insensitivity */
933 	cl_git_pass(git_index_set_caps(index, caps | GIT_INDEX_CAPABILITY_IGNORE_CASE));
934 
935 	i_opts.start = "c";
936 	i_opts.end = "k/D";
937 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
938 	expect_iterator_items(i, 5, NULL, 5, NULL);
939 	git_iterator_free(i);
940 
941 	i_opts.start = "k";
942 	i_opts.end = "k/Z";
943 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
944 	expect_iterator_items(i, 2, NULL, 2, NULL);
945 	git_iterator_free(i);
946 
947 	cl_git_pass(git_index_set_caps(index, caps));
948 	git_index_free(index);
949 	git_vector_free(&filelist);
950 }
951 
test_iterator_index__pathlist_with_directory(void)952 void test_iterator_index__pathlist_with_directory(void)
953 {
954 	git_iterator *i;
955 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
956 	git_vector filelist;
957 	git_tree *tree;
958 	git_index *index;
959 
960 	g_repo = cl_git_sandbox_init("testrepo2");
961 	git_repository_head_tree(&tree, g_repo);
962 
963 	cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb));
964 	cl_git_pass(git_vector_insert(&filelist, "subdir"));
965 
966 	i_opts.pathlist.strings = (char **)filelist.contents;
967 	i_opts.pathlist.count = filelist.length;
968 
969 	cl_git_pass(git_repository_index(&index, g_repo));
970 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
971 	expect_iterator_items(i, 4, NULL, 4, NULL);
972 	git_iterator_free(i);
973 
974 	git_index_free(index);
975 	git_tree_free(tree);
976 	git_vector_free(&filelist);
977 }
978 
create_paths(git_index * index,const char * root,int depth)979 static void create_paths(git_index *index, const char *root, int depth)
980 {
981 	git_buf fullpath = GIT_BUF_INIT;
982 	git_index_entry entry;
983 	size_t root_len;
984 	int i;
985 
986 	if (root) {
987 		cl_git_pass(git_buf_puts(&fullpath, root));
988 		cl_git_pass(git_buf_putc(&fullpath, '/'));
989 	}
990 
991 	root_len = fullpath.size;
992 
993 	for (i = 0; i < 8; i++) {
994 		bool file = (depth == 0 || (i % 2) == 0);
995 		git_buf_truncate(&fullpath, root_len);
996 		cl_git_pass(git_buf_printf(&fullpath, "item%d", i));
997 
998 		if (file) {
999 			memset(&entry, 0, sizeof(git_index_entry));
1000 			entry.path = fullpath.ptr;
1001 			entry.mode = GIT_FILEMODE_BLOB;
1002 			git_oid_fromstr(&entry.id, "d44e18fb93b7107b5cd1b95d601591d77869a1b6");
1003 
1004 			cl_git_pass(git_index_add(index, &entry));
1005 		} else if (depth > 0) {
1006 			create_paths(index, fullpath.ptr, (depth - 1));
1007 		}
1008 	}
1009 
1010 	git_buf_dispose(&fullpath);
1011 }
1012 
test_iterator_index__pathlist_for_deeply_nested_item(void)1013 void test_iterator_index__pathlist_for_deeply_nested_item(void)
1014 {
1015 	git_iterator *i;
1016 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
1017 	git_index *index;
1018 	git_vector filelist;
1019 
1020 	cl_git_pass(git_vector_init(&filelist, 5, NULL));
1021 
1022 	g_repo = cl_git_sandbox_init("icase");
1023 	cl_git_pass(git_repository_index(&index, g_repo));
1024 
1025 	create_paths(index, NULL, 3);
1026 
1027 	/* Ensure that we find the single path we're interested in */
1028 	{
1029 		const char *expected[] = { "item1/item3/item5/item7" };
1030 		size_t expected_len = 1;
1031 
1032 		git_vector_clear(&filelist);
1033 		cl_git_pass(git_vector_insert(&filelist, "item1/item3/item5/item7"));
1034 
1035 		i_opts.pathlist.strings = (char **)filelist.contents;
1036 		i_opts.pathlist.count = filelist.length;
1037 		i_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
1038 
1039 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
1040 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
1041 		git_iterator_free(i);
1042 	}
1043 
1044 	{
1045 		const char *expected[] = {
1046 			"item1/item3/item5/item0", "item1/item3/item5/item1",
1047 			"item1/item3/item5/item2", "item1/item3/item5/item3",
1048 			"item1/item3/item5/item4", "item1/item3/item5/item5",
1049 			"item1/item3/item5/item6", "item1/item3/item5/item7",
1050 		};
1051 		size_t expected_len = 8;
1052 
1053 		git_vector_clear(&filelist);
1054 		cl_git_pass(git_vector_insert(&filelist, "item1/item3/item5/"));
1055 
1056 		i_opts.pathlist.strings = (char **)filelist.contents;
1057 		i_opts.pathlist.count = filelist.length;
1058 		i_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
1059 
1060 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
1061 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
1062 		git_iterator_free(i);
1063 	}
1064 
1065 	{
1066 		const char *expected[] = {
1067 			"item1/item3/item0",
1068 			"item1/item3/item1/item0", "item1/item3/item1/item1",
1069 			"item1/item3/item1/item2", "item1/item3/item1/item3",
1070 			"item1/item3/item1/item4", "item1/item3/item1/item5",
1071 			"item1/item3/item1/item6", "item1/item3/item1/item7",
1072 			"item1/item3/item2",
1073 			"item1/item3/item3/item0", "item1/item3/item3/item1",
1074 			"item1/item3/item3/item2", "item1/item3/item3/item3",
1075 			"item1/item3/item3/item4", "item1/item3/item3/item5",
1076 			"item1/item3/item3/item6", "item1/item3/item3/item7",
1077 			"item1/item3/item4",
1078 			"item1/item3/item5/item0", "item1/item3/item5/item1",
1079 			"item1/item3/item5/item2", "item1/item3/item5/item3",
1080 			"item1/item3/item5/item4", "item1/item3/item5/item5",
1081 			"item1/item3/item5/item6", "item1/item3/item5/item7",
1082 			"item1/item3/item6",
1083 			"item1/item3/item7/item0", "item1/item3/item7/item1",
1084 			"item1/item3/item7/item2", "item1/item3/item7/item3",
1085 			"item1/item3/item7/item4", "item1/item3/item7/item5",
1086 			"item1/item3/item7/item6", "item1/item3/item7/item7",
1087 		};
1088 		size_t expected_len = 36;
1089 
1090 		git_vector_clear(&filelist);
1091 		cl_git_pass(git_vector_insert(&filelist, "item1/item3/"));
1092 
1093 		i_opts.pathlist.strings = (char **)filelist.contents;
1094 		i_opts.pathlist.count = filelist.length;
1095 		i_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
1096 
1097 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
1098 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
1099 		git_iterator_free(i);
1100 	}
1101 
1102 	/* Ensure that we find the single path we're interested in, and we find
1103 	 * it efficiently, and don't stat the entire world to get there.
1104 	 */
1105 	{
1106 		const char *expected[] = {
1107 			"item0", "item1/item2", "item5/item7/item4", "item6",
1108 			"item7/item3/item1/item6" };
1109 		size_t expected_len = 5;
1110 
1111 		git_vector_clear(&filelist);
1112 		cl_git_pass(git_vector_insert(&filelist, "item7/item3/item1/item6"));
1113 		cl_git_pass(git_vector_insert(&filelist, "item6"));
1114 		cl_git_pass(git_vector_insert(&filelist, "item5/item7/item4"));
1115 		cl_git_pass(git_vector_insert(&filelist, "item1/item2"));
1116 		cl_git_pass(git_vector_insert(&filelist, "item0"));
1117 
1118 		/* also add some things that don't exist or don't match the right type */
1119 		cl_git_pass(git_vector_insert(&filelist, "item2/"));
1120 		cl_git_pass(git_vector_insert(&filelist, "itemN"));
1121 		cl_git_pass(git_vector_insert(&filelist, "item1/itemA"));
1122 		cl_git_pass(git_vector_insert(&filelist, "item5/item3/item4/"));
1123 
1124 		i_opts.pathlist.strings = (char **)filelist.contents;
1125 		i_opts.pathlist.count = filelist.length;
1126 		i_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
1127 
1128 		cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
1129 		expect_iterator_items(i, expected_len, expected, expected_len, expected);
1130 		git_iterator_free(i);
1131 	}
1132 
1133 	git_index_free(index);
1134 	git_vector_free(&filelist);
1135 }
1136 
test_iterator_index__advance_over(void)1137 void test_iterator_index__advance_over(void)
1138 {
1139 	git_iterator *i;
1140 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
1141 	git_index *index;
1142 
1143 	i_opts.flags |= GIT_ITERATOR_DONT_IGNORE_CASE |
1144 		GIT_ITERATOR_DONT_AUTOEXPAND;
1145 
1146 	g_repo = cl_git_sandbox_init("icase");
1147 	cl_git_pass(git_repository_index(&index, g_repo));
1148 
1149 	create_paths(index, NULL, 1);
1150 
1151 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
1152 
1153 	expect_advance_over(i, "B", GIT_ITERATOR_STATUS_NORMAL);
1154 	expect_advance_over(i, "D", GIT_ITERATOR_STATUS_NORMAL);
1155 	expect_advance_over(i, "F", GIT_ITERATOR_STATUS_NORMAL);
1156 	expect_advance_over(i, "H", GIT_ITERATOR_STATUS_NORMAL);
1157 	expect_advance_over(i, "J", GIT_ITERATOR_STATUS_NORMAL);
1158 	expect_advance_over(i, "L/", GIT_ITERATOR_STATUS_NORMAL);
1159 	expect_advance_over(i, "a", GIT_ITERATOR_STATUS_NORMAL);
1160 	expect_advance_over(i, "c", GIT_ITERATOR_STATUS_NORMAL);
1161 	expect_advance_over(i, "e", GIT_ITERATOR_STATUS_NORMAL);
1162 	expect_advance_over(i, "g", GIT_ITERATOR_STATUS_NORMAL);
1163 	expect_advance_over(i, "i", GIT_ITERATOR_STATUS_NORMAL);
1164 	expect_advance_over(i, "item0", GIT_ITERATOR_STATUS_NORMAL);
1165 	expect_advance_over(i, "item1/", GIT_ITERATOR_STATUS_NORMAL);
1166 	expect_advance_over(i, "item2", GIT_ITERATOR_STATUS_NORMAL);
1167 	expect_advance_over(i, "item3/", GIT_ITERATOR_STATUS_NORMAL);
1168 	expect_advance_over(i, "item4", GIT_ITERATOR_STATUS_NORMAL);
1169 	expect_advance_over(i, "item5/", GIT_ITERATOR_STATUS_NORMAL);
1170 	expect_advance_over(i, "item6", GIT_ITERATOR_STATUS_NORMAL);
1171 	expect_advance_over(i, "item7/", GIT_ITERATOR_STATUS_NORMAL);
1172 	expect_advance_over(i, "k/", GIT_ITERATOR_STATUS_NORMAL);
1173 
1174 	cl_git_fail_with(GIT_ITEROVER, git_iterator_advance(NULL, i));
1175 	git_iterator_free(i);
1176 	git_index_free(index);
1177 }
1178 
test_iterator_index__advance_into(void)1179 void test_iterator_index__advance_into(void)
1180 {
1181 	git_iterator *i;
1182 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
1183 	git_index *index;
1184 
1185 	g_repo = cl_git_sandbox_init("icase");
1186 
1187 	i_opts.flags |= GIT_ITERATOR_DONT_IGNORE_CASE |
1188 		GIT_ITERATOR_DONT_AUTOEXPAND;
1189 
1190 	cl_git_pass(git_repository_index(&index, g_repo));
1191 
1192 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
1193 	expect_advance_into(i, "B");
1194 	expect_advance_into(i, "D");
1195 	expect_advance_into(i, "F");
1196 	expect_advance_into(i, "H");
1197 	expect_advance_into(i, "J");
1198 	expect_advance_into(i, "L/");
1199 	expect_advance_into(i, "L/1");
1200 	expect_advance_into(i, "L/B");
1201 	expect_advance_into(i, "L/D");
1202 	expect_advance_into(i, "L/a");
1203 	expect_advance_into(i, "L/c");
1204 	expect_advance_into(i, "a");
1205 	expect_advance_into(i, "c");
1206 	expect_advance_into(i, "e");
1207 	expect_advance_into(i, "g");
1208 	expect_advance_into(i, "i");
1209 	expect_advance_into(i, "k/");
1210 	expect_advance_into(i, "k/1");
1211 	expect_advance_into(i, "k/B");
1212 	expect_advance_into(i, "k/D");
1213 	expect_advance_into(i, "k/a");
1214 	expect_advance_into(i, "k/c");
1215 
1216 	cl_git_fail_with(GIT_ITEROVER, git_iterator_advance(NULL, i));
1217 	git_iterator_free(i);
1218 	git_index_free(index);
1219 }
1220 
test_iterator_index__advance_into_and_over(void)1221 void test_iterator_index__advance_into_and_over(void)
1222 {
1223 	git_iterator *i;
1224 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
1225 	git_index *index;
1226 
1227 	g_repo = cl_git_sandbox_init("icase");
1228 
1229 	i_opts.flags |= GIT_ITERATOR_DONT_IGNORE_CASE |
1230 	GIT_ITERATOR_DONT_AUTOEXPAND;
1231 
1232 	cl_git_pass(git_repository_index(&index, g_repo));
1233 
1234 	create_paths(index, NULL, 2);
1235 
1236 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
1237 	expect_advance_into(i, "B");
1238 	expect_advance_into(i, "D");
1239 	expect_advance_into(i, "F");
1240 	expect_advance_into(i, "H");
1241 	expect_advance_into(i, "J");
1242 	expect_advance_into(i, "L/");
1243 	expect_advance_into(i, "L/1");
1244 	expect_advance_into(i, "L/B");
1245 	expect_advance_into(i, "L/D");
1246 	expect_advance_into(i, "L/a");
1247 	expect_advance_into(i, "L/c");
1248 	expect_advance_into(i, "a");
1249 	expect_advance_into(i, "c");
1250 	expect_advance_into(i, "e");
1251 	expect_advance_into(i, "g");
1252 	expect_advance_into(i, "i");
1253 	expect_advance_into(i, "item0");
1254 	expect_advance_into(i, "item1/");
1255 	expect_advance_into(i, "item1/item0");
1256 	expect_advance_into(i, "item1/item1/");
1257 	expect_advance_into(i, "item1/item1/item0");
1258 	expect_advance_into(i, "item1/item1/item1");
1259 	expect_advance_into(i, "item1/item1/item2");
1260 	expect_advance_into(i, "item1/item1/item3");
1261 	expect_advance_into(i, "item1/item1/item4");
1262 	expect_advance_into(i, "item1/item1/item5");
1263 	expect_advance_into(i, "item1/item1/item6");
1264 	expect_advance_into(i, "item1/item1/item7");
1265 	expect_advance_into(i, "item1/item2");
1266 	expect_advance_over(i, "item1/item3/", GIT_ITERATOR_STATUS_NORMAL);
1267 	expect_advance_over(i, "item1/item4", GIT_ITERATOR_STATUS_NORMAL);
1268 	expect_advance_over(i, "item1/item5/", GIT_ITERATOR_STATUS_NORMAL);
1269 	expect_advance_over(i, "item1/item6", GIT_ITERATOR_STATUS_NORMAL);
1270 	expect_advance_over(i, "item1/item7/", GIT_ITERATOR_STATUS_NORMAL);
1271 	expect_advance_into(i, "item2");
1272 	expect_advance_over(i, "item3/", GIT_ITERATOR_STATUS_NORMAL);
1273 	expect_advance_over(i, "item4", GIT_ITERATOR_STATUS_NORMAL);
1274 	expect_advance_over(i, "item5/", GIT_ITERATOR_STATUS_NORMAL);
1275 	expect_advance_over(i, "item6", GIT_ITERATOR_STATUS_NORMAL);
1276 	expect_advance_over(i, "item7/", GIT_ITERATOR_STATUS_NORMAL);
1277 	expect_advance_into(i, "k/");
1278 	expect_advance_into(i, "k/1");
1279 	expect_advance_into(i, "k/B");
1280 	expect_advance_into(i, "k/D");
1281 	expect_advance_into(i, "k/a");
1282 	expect_advance_into(i, "k/c");
1283 
1284 	cl_git_fail_with(GIT_ITEROVER, git_iterator_advance(NULL, i));
1285 	git_iterator_free(i);
1286 	git_index_free(index);
1287 }
1288 
add_conflict(git_index * index,const char * ancestor_path,const char * our_path,const char * their_path)1289 static void add_conflict(
1290 	git_index *index,
1291 	const char *ancestor_path,
1292 	const char *our_path,
1293 	const char *their_path)
1294 {
1295 	git_index_entry ancestor = {{0}}, ours = {{0}}, theirs = {{0}};
1296 
1297 	ancestor.path = ancestor_path;
1298 	ancestor.mode = GIT_FILEMODE_BLOB;
1299 	git_oid_fromstr(&ancestor.id, "d44e18fb93b7107b5cd1b95d601591d77869a1b6");
1300 	GIT_INDEX_ENTRY_STAGE_SET(&ancestor, 1);
1301 
1302 	ours.path = our_path;
1303 	ours.mode = GIT_FILEMODE_BLOB;
1304 	git_oid_fromstr(&ours.id, "d44e18fb93b7107b5cd1b95d601591d77869a1b6");
1305 	GIT_INDEX_ENTRY_STAGE_SET(&ours, 2);
1306 
1307 	theirs.path = their_path;
1308 	theirs.mode = GIT_FILEMODE_BLOB;
1309 	git_oid_fromstr(&theirs.id, "d44e18fb93b7107b5cd1b95d601591d77869a1b6");
1310 	GIT_INDEX_ENTRY_STAGE_SET(&theirs, 3);
1311 
1312 	cl_git_pass(git_index_conflict_add(index, &ancestor, &ours, &theirs));
1313 }
1314 
test_iterator_index__include_conflicts(void)1315 void test_iterator_index__include_conflicts(void)
1316 {
1317 	git_iterator *i;
1318 	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
1319 	git_index *index;
1320 
1321 	i_opts.flags |= GIT_ITERATOR_DONT_IGNORE_CASE |
1322 		GIT_ITERATOR_DONT_AUTOEXPAND;
1323 
1324 	g_repo = cl_git_sandbox_init("icase");
1325 	cl_git_pass(git_repository_index(&index, g_repo));
1326 
1327 	add_conflict(index, "CONFLICT1", "CONFLICT1" ,"CONFLICT1");
1328 	add_conflict(index, "ZZZ-CONFLICT2.ancestor", "ZZZ-CONFLICT2.ours", "ZZZ-CONFLICT2.theirs");
1329 	add_conflict(index, "ancestor.conflict3", "ours.conflict3", "theirs.conflict3");
1330 	add_conflict(index, "zzz-conflict4", "zzz-conflict4", "zzz-conflict4");
1331 
1332 	/* Iterate the index, ensuring that conflicts are not included */
1333 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
1334 
1335 	expect_advance_over(i, "B", GIT_ITERATOR_STATUS_NORMAL);
1336 	expect_advance_over(i, "D", GIT_ITERATOR_STATUS_NORMAL);
1337 	expect_advance_over(i, "F", GIT_ITERATOR_STATUS_NORMAL);
1338 	expect_advance_over(i, "H", GIT_ITERATOR_STATUS_NORMAL);
1339 	expect_advance_over(i, "J", GIT_ITERATOR_STATUS_NORMAL);
1340 	expect_advance_over(i, "L/", GIT_ITERATOR_STATUS_NORMAL);
1341 	expect_advance_over(i, "a", GIT_ITERATOR_STATUS_NORMAL);
1342 	expect_advance_over(i, "c", GIT_ITERATOR_STATUS_NORMAL);
1343 	expect_advance_over(i, "e", GIT_ITERATOR_STATUS_NORMAL);
1344 	expect_advance_over(i, "g", GIT_ITERATOR_STATUS_NORMAL);
1345 	expect_advance_over(i, "i", GIT_ITERATOR_STATUS_NORMAL);
1346 	expect_advance_over(i, "k/", GIT_ITERATOR_STATUS_NORMAL);
1347 
1348 	cl_git_fail_with(GIT_ITEROVER, git_iterator_advance(NULL, i));
1349 	git_iterator_free(i);
1350 
1351 	/* Try again, returning conflicts */
1352 	i_opts.flags |= GIT_ITERATOR_INCLUDE_CONFLICTS;
1353 
1354 	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
1355 
1356 	expect_advance_over(i, "B", GIT_ITERATOR_STATUS_NORMAL);
1357 	expect_advance_over(i, "CONFLICT1", GIT_ITERATOR_STATUS_NORMAL);
1358 	expect_advance_over(i, "CONFLICT1", GIT_ITERATOR_STATUS_NORMAL);
1359 	expect_advance_over(i, "CONFLICT1", GIT_ITERATOR_STATUS_NORMAL);
1360 	expect_advance_over(i, "D", GIT_ITERATOR_STATUS_NORMAL);
1361 	expect_advance_over(i, "F", GIT_ITERATOR_STATUS_NORMAL);
1362 	expect_advance_over(i, "H", GIT_ITERATOR_STATUS_NORMAL);
1363 	expect_advance_over(i, "J", GIT_ITERATOR_STATUS_NORMAL);
1364 	expect_advance_over(i, "L/", GIT_ITERATOR_STATUS_NORMAL);
1365 	expect_advance_over(i, "ZZZ-CONFLICT2.ancestor", GIT_ITERATOR_STATUS_NORMAL);
1366 	expect_advance_over(i, "ZZZ-CONFLICT2.ours", GIT_ITERATOR_STATUS_NORMAL);
1367 	expect_advance_over(i, "ZZZ-CONFLICT2.theirs", GIT_ITERATOR_STATUS_NORMAL);
1368 	expect_advance_over(i, "a", GIT_ITERATOR_STATUS_NORMAL);
1369 	expect_advance_over(i, "ancestor.conflict3", GIT_ITERATOR_STATUS_NORMAL);
1370 	expect_advance_over(i, "c", GIT_ITERATOR_STATUS_NORMAL);
1371 	expect_advance_over(i, "e", GIT_ITERATOR_STATUS_NORMAL);
1372 	expect_advance_over(i, "g", GIT_ITERATOR_STATUS_NORMAL);
1373 	expect_advance_over(i, "i", GIT_ITERATOR_STATUS_NORMAL);
1374 	expect_advance_over(i, "k/", GIT_ITERATOR_STATUS_NORMAL);
1375 	expect_advance_over(i, "ours.conflict3", GIT_ITERATOR_STATUS_NORMAL);
1376 	expect_advance_over(i, "theirs.conflict3", GIT_ITERATOR_STATUS_NORMAL);
1377 	expect_advance_over(i, "zzz-conflict4", GIT_ITERATOR_STATUS_NORMAL);
1378 	expect_advance_over(i, "zzz-conflict4", GIT_ITERATOR_STATUS_NORMAL);
1379 	expect_advance_over(i, "zzz-conflict4", GIT_ITERATOR_STATUS_NORMAL);
1380 
1381 	cl_git_fail_with(GIT_ITEROVER, git_iterator_advance(NULL, i));
1382 	git_iterator_free(i);
1383 
1384 	git_index_free(index);
1385 }
1386