Commit ae86aa5a68d584a6db0da320fd9b00c96cdaed47

Marc Strapetz 2016-03-16T11:38:02

iterator: test pathlist handling for directories tree_iterator was only working properly for a pathlist containing file paths. In case of directory paths, it didn't match children which contradicts GIT_DIFF_DISABLE_PATHSPEC_MATCH and is different from index_iterator and fs_iterator. As a consequence head-to-index status reporting for a specific directory did not work properly -- all files have been reported as added. Include additional tests.

diff --git a/tests/repo/iterator.c b/tests/repo/iterator.c
index df31386..158a6e4 100644
--- a/tests/repo/iterator.c
+++ b/tests/repo/iterator.c
@@ -1371,6 +1371,31 @@ void test_repo_iterator__indexfilelist_icase(void)
 	git_vector_free(&filelist);
 }
 
+void test_repo_iterator__indexfilelist_with_directory(void)
+{
+	git_iterator *i;
+	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
+	git_vector filelist;
+	git_tree *tree;
+	git_index *index;
+
+	g_repo = cl_git_sandbox_init("testrepo2");
+	git_repository_head_tree(&tree, g_repo);
+
+	cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb));
+	cl_git_pass(git_vector_insert(&filelist, "subdir"));
+
+	i_opts.pathlist.strings = (char **)filelist.contents;
+	i_opts.pathlist.count = filelist.length;
+
+	cl_git_pass(git_repository_index(&index, g_repo));
+	cl_git_pass(git_iterator_for_index(&i, g_repo, index, &i_opts));
+	expect_iterator_items(i, 4, NULL, 4, NULL);
+	git_iterator_free(i);
+	git_index_free(index);
+	git_vector_free(&filelist);
+}
+
 void test_repo_iterator__workdir_pathlist(void)
 {
 	git_iterator *i;
@@ -2016,6 +2041,27 @@ void test_repo_iterator__workdir_advance_over_with_pathlist(void)
 	git_vector_free(&pathlist);
 }
 
+void test_repo_iterator__workdir_filelist_with_directory(void)
+{
+	git_iterator *i;
+	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
+	git_vector filelist;
+
+	cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb));
+	cl_git_pass(git_vector_insert(&filelist, "subdir/"));
+
+	g_repo = cl_git_sandbox_init("testrepo2");
+
+	i_opts.pathlist.strings = (char **)filelist.contents;
+	i_opts.pathlist.count = filelist.length;
+
+	cl_git_pass(git_iterator_for_workdir(&i, g_repo, NULL, NULL, &i_opts));
+	expect_iterator_items(i, 4, NULL, 4, NULL);
+	git_iterator_free(i);
+
+	git_vector_free(&filelist);
+}
+
 void test_repo_iterator__treefilelist(void)
 {
 	git_iterator *i;
@@ -2129,3 +2175,94 @@ void test_repo_iterator__treefilelist_icase(void)
 	git_vector_free(&filelist);
 	git_tree_free(tree);
 }
+
+void test_repo_iterator__tree_filelist_with_directory(void)
+{
+	git_iterator *i;
+	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
+	git_vector filelist;
+	git_tree *tree;
+
+	g_repo = cl_git_sandbox_init("testrepo2");
+	git_repository_head_tree(&tree, g_repo);
+
+	cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb));
+	cl_git_pass(git_vector_insert(&filelist, "subdir"));
+
+	i_opts.pathlist.strings = (char **)filelist.contents;
+	i_opts.pathlist.count = filelist.length;
+
+	cl_git_pass(git_iterator_for_tree(&i, tree, &i_opts));
+	expect_iterator_items(i, 4, NULL, 4, NULL);
+	git_iterator_free(i);
+
+	git_vector_clear(&filelist);
+	cl_git_pass(git_vector_insert(&filelist, "subdir/"));
+
+	i_opts.pathlist.strings = (char **)filelist.contents;
+	i_opts.pathlist.count = filelist.length;
+
+	cl_git_pass(git_iterator_for_tree(&i, tree, &i_opts));
+	expect_iterator_items(i, 4, NULL, 4, NULL);
+	git_iterator_free(i);
+
+	git_vector_clear(&filelist);
+	cl_git_pass(git_vector_insert(&filelist, "subdir/subdir2"));
+
+	i_opts.pathlist.strings = (char **)filelist.contents;
+	i_opts.pathlist.count = filelist.length;
+
+	cl_git_pass(git_iterator_for_tree(&i, tree, &i_opts));
+	expect_iterator_items(i, 2, NULL, 2, NULL);
+	git_iterator_free(i);
+
+	git_vector_free(&filelist);
+}
+
+void test_repo_iterator__tree_filelist_with_directory_include_tree_nodes(void)
+{
+	git_iterator *i;
+	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
+	git_vector filelist;
+	git_tree *tree;
+
+	g_repo = cl_git_sandbox_init("testrepo2");
+	git_repository_head_tree(&tree, g_repo);
+
+	cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb));
+	cl_git_pass(git_vector_insert(&filelist, "subdir"));
+
+	i_opts.flags |= GIT_ITERATOR_INCLUDE_TREES;
+	i_opts.pathlist.strings = (char **)filelist.contents;
+	i_opts.pathlist.count = filelist.length;
+
+	cl_git_pass(git_iterator_for_tree(&i, tree, &i_opts));
+	expect_iterator_items(i, 6, NULL, 6, NULL);
+	git_iterator_free(i);
+
+	git_vector_free(&filelist);
+}
+
+void test_repo_iterator__tree_filelist_no_match(void)
+{
+	git_iterator *i;
+	git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT;
+	git_vector filelist;
+	git_tree *tree;
+	const git_index_entry *entry;
+
+	g_repo = cl_git_sandbox_init("testrepo2");
+	git_repository_head_tree(&tree, g_repo);
+
+	cl_git_pass(git_vector_init(&filelist, 100, &git__strcmp_cb));
+	cl_git_pass(git_vector_insert(&filelist, "nonexistent/"));
+
+	i_opts.pathlist.strings = (char **)filelist.contents;
+	i_opts.pathlist.count = filelist.length;
+
+	cl_git_pass(git_iterator_for_tree(&i, tree, &i_opts));
+	cl_assert_equal_i(GIT_ITEROVER, git_iterator_current(&entry, i));
+
+	git_vector_free(&filelist);
+}
+
diff --git a/tests/status/worktree.c b/tests/status/worktree.c
index 6b82378..d1117f4 100644
--- a/tests/status/worktree.c
+++ b/tests/status/worktree.c
@@ -1146,3 +1146,85 @@ void test_status_worktree__update_index_with_symlink_doesnt_change_mode(void)
 	git_reference_free(head);
 }
 
+static const char *testrepo2_subdir_paths[] = {
+		"subdir/README",
+		"subdir/new.txt",
+		"subdir/subdir2/README",
+		"subdir/subdir2/new.txt",
+};
+
+static const char *testrepo2_subdir_paths_icase[] = {
+		"subdir/new.txt",
+		"subdir/README",
+		"subdir/subdir2/new.txt",
+		"subdir/subdir2/README"
+};
+
+void test_status_worktree__with_directory_in_pathlist(void)
+{
+	git_repository *repo = cl_git_sandbox_init("testrepo2");
+	git_index *index;
+	git_status_options opts = GIT_STATUS_OPTIONS_INIT;
+	git_status_list *statuslist;
+	const git_status_entry *status;
+	size_t i, entrycount;
+	bool native_ignore_case;
+
+	cl_git_pass(git_repository_index(&index, repo));
+	native_ignore_case =
+			(git_index_caps(index) & GIT_INDEXCAP_IGNORE_CASE) != 0;
+	git_index_free(index);
+
+	opts.pathspec.count = 1;
+	opts.pathspec.strings = malloc(opts.pathspec.count * sizeof(char *));
+	opts.pathspec.strings[0] = "subdir";
+	opts.flags =
+			GIT_STATUS_OPT_DEFAULTS |
+			GIT_STATUS_OPT_INCLUDE_UNMODIFIED |
+			GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH;
+
+	opts.show = GIT_STATUS_SHOW_WORKDIR_ONLY;
+	git_status_list_new(&statuslist, repo, &opts);
+
+	entrycount = git_status_list_entrycount(statuslist);
+	cl_assert_equal_i(4, entrycount);
+
+	for (i = 0; i < entrycount; i++) {
+		status = git_status_byindex(statuslist, i);
+		cl_assert_equal_i(0, status->status);
+		cl_assert_equal_s(native_ignore_case ?
+			testrepo2_subdir_paths_icase[i] :
+			testrepo2_subdir_paths[i],
+			status->index_to_workdir->old_file.path);
+	}
+
+	opts.show = GIT_STATUS_SHOW_INDEX_ONLY;
+	git_status_list_new(&statuslist, repo, &opts);
+
+	entrycount = git_status_list_entrycount(statuslist);
+	cl_assert_equal_i(4, entrycount);
+
+	for (i = 0; i < entrycount; i++) {
+		status = git_status_byindex(statuslist, i);
+		cl_assert_equal_i(0, status->status);
+		cl_assert_equal_s(native_ignore_case ?
+			testrepo2_subdir_paths_icase[i] :
+			testrepo2_subdir_paths[i],
+			status->head_to_index->old_file.path);
+	}
+
+	opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
+	git_status_list_new(&statuslist, repo, &opts);
+
+	entrycount = git_status_list_entrycount(statuslist);
+	cl_assert_equal_i(4, entrycount);
+
+	for (i = 0; i < entrycount; i++) {
+		status = git_status_byindex(statuslist, i);
+		cl_assert_equal_i(0, status->status);
+		cl_assert_equal_s(native_ignore_case ?
+			testrepo2_subdir_paths_icase[i] :
+			testrepo2_subdir_paths[i],
+			status->index_to_workdir->old_file.path);
+	}
+}