summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2015-08-28 20:06:18 -0400
committerEdward Thomson <ethomson@edwardthomson.com>2015-08-28 20:45:08 -0400
commit3273ab3f0b04d673b9515b149674d5716939d9a5 (patch)
tree622aaadacda093f686442c03f3898447dbd5a72f
parent6c9352bf30e97af5d646d92ceab1c7b0f4c7a1c4 (diff)
downloadlibgit2-3273ab3f0b04d673b9515b149674d5716939d9a5.tar.gz
diff: better document GIT_DIFF_PATHSPEC_DISABLE
Document that `GIT_DIFF_PATHSPEC_DISABLE` is not necessarily about explicit path matching, but also includes matching of directory names. Enforce this in a test.
-rw-r--r--include/git2/diff.h4
-rw-r--r--tests/diff/workdir.c210
2 files changed, 213 insertions, 1 deletions
diff --git a/include/git2/diff.h b/include/git2/diff.h
index c3589bb13..d3adf9f01 100644
--- a/include/git2/diff.h
+++ b/include/git2/diff.h
@@ -130,7 +130,9 @@ typedef enum {
GIT_DIFF_INCLUDE_CASECHANGE = (1u << 11),
/** If the pathspec is set in the diff options, this flags means to
- * apply it as an exact match instead of as an fnmatch pattern.
+ * use exact prefix matches instead of an fnmatch pattern. Each
+ * path in the list must either be a full filename or a subdirectory
+ * prefix.
*/
GIT_DIFF_DISABLE_PATHSPEC_MATCH = (1u << 12),
diff --git a/tests/diff/workdir.c b/tests/diff/workdir.c
index 8a23f53ae..503d67450 100644
--- a/tests/diff/workdir.c
+++ b/tests/diff/workdir.c
@@ -444,6 +444,216 @@ void test_diff_workdir__to_index_with_pathspec(void)
git_diff_free(diff);
}
+void test_diff_workdir__to_index_with_pathlist_disabling_fnmatch(void)
+{
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+ git_diff *diff = NULL;
+ diff_expects exp;
+ char *pathspec = NULL;
+ int use_iterator;
+
+ g_repo = cl_git_sandbox_init("status");
+
+ opts.context_lines = 3;
+ opts.interhunk_lines = 1;
+ opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED |
+ GIT_DIFF_DISABLE_PATHSPEC_MATCH;
+ opts.pathspec.strings = &pathspec;
+ opts.pathspec.count = 0;
+
+ /* ensure that an empty pathspec list is ignored */
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+
+ for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
+ memset(&exp, 0, sizeof(exp));
+
+ if (use_iterator)
+ cl_git_pass(diff_foreach_via_iterator(
+ diff, diff_file_cb, NULL, NULL, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
+
+ cl_assert_equal_i(13, exp.files);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
+ cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]);
+ cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]);
+ cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
+ cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]);
+ }
+
+ git_diff_free(diff);
+
+ /* ensure that a single NULL pathspec is filtered out (like when using
+ * fnmatch filtering)
+ */
+ opts.pathspec.strings = &pathspec;
+ opts.pathspec.count = 1;
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+
+ for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
+ memset(&exp, 0, sizeof(exp));
+
+ if (use_iterator)
+ cl_git_pass(diff_foreach_via_iterator(
+ diff, diff_file_cb, NULL, NULL, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
+
+ cl_assert_equal_i(13, exp.files);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
+ cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]);
+ cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]);
+ cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
+ cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]);
+ }
+
+ git_diff_free(diff);
+
+ pathspec = "modified_file";
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+
+ for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
+ memset(&exp, 0, sizeof(exp));
+
+ if (use_iterator)
+ cl_git_pass(diff_foreach_via_iterator(
+ diff, diff_file_cb, NULL, NULL, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
+
+ cl_assert_equal_i(1, exp.files);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
+ cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]);
+ }
+
+ git_diff_free(diff);
+
+ /* ensure that subdirs can be specified */
+ pathspec = "subdir";
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+
+ for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
+ memset(&exp, 0, sizeof(exp));
+
+ if (use_iterator)
+ cl_git_pass(diff_foreach_via_iterator(
+ diff, diff_file_cb, NULL, NULL, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
+
+ cl_assert_equal_i(3, exp.files);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
+ cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
+ cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
+ cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]);
+ }
+
+ git_diff_free(diff);
+
+ /* ensure that subdirs can be specified with a trailing slash */
+ pathspec = "subdir/";
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+
+ for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
+ memset(&exp, 0, sizeof(exp));
+
+ if (use_iterator)
+ cl_git_pass(diff_foreach_via_iterator(
+ diff, diff_file_cb, NULL, NULL, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
+
+ cl_assert_equal_i(3, exp.files);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
+ cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
+ cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
+ cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]);
+ }
+
+ git_diff_free(diff);
+
+ /* ensure that fnmatching is completely disabled */
+ pathspec = "subdir/*";
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+
+ for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
+ memset(&exp, 0, sizeof(exp));
+
+ if (use_iterator)
+ cl_git_pass(diff_foreach_via_iterator(
+ diff, diff_file_cb, NULL, NULL, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
+
+ cl_assert_equal_i(0, exp.files);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]);
+ }
+
+ git_diff_free(diff);
+
+ /* ensure that the prefix matching isn't completely braindead */
+ pathspec = "subdi";
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+
+ for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
+ memset(&exp, 0, sizeof(exp));
+
+ if (use_iterator)
+ cl_git_pass(diff_foreach_via_iterator(
+ diff, diff_file_cb, NULL, NULL, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
+
+ cl_assert_equal_i(0, exp.files);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]);
+ }
+
+ git_diff_free(diff);
+
+ /* ensure that fnmatching isn't working at all */
+ pathspec = "*_deleted";
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+
+ for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
+ memset(&exp, 0, sizeof(exp));
+
+ if (use_iterator)
+ cl_git_pass(diff_foreach_via_iterator(
+ diff, diff_file_cb, NULL, NULL, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
+
+ cl_assert_equal_i(0, exp.files);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]);
+ }
+
+ git_diff_free(diff);
+}
+
void test_diff_workdir__filemode_changes(void)
{
git_diff *diff = NULL;