summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2015-09-12 22:49:23 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2015-09-12 22:49:23 +0200
commitdc5b678fda918386f01630d2bc928edb546ac4f2 (patch)
treed06b61174453c1167615a2c12ac1254d6e90b0c4
parent049dbf42f50a7d04db5ab99577455b8933e3d532 (diff)
parent8ab4d0e1e16bf42e4617a40a13d67385fc8fa40c (diff)
downloadlibgit2-dc5b678fda918386f01630d2bc928edb546ac4f2.tar.gz
Merge pull request #3422 from ethomson/workdir_diff
diff: examine pathlist on non-files
-rw-r--r--src/diff.c25
-rw-r--r--tests/diff/workdir.c43
2 files changed, 60 insertions, 8 deletions
diff --git a/src/diff.c b/src/diff.c
index 32c1d4aa5..d97dcd9d2 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -75,18 +75,27 @@ static int diff_insert_delta(
}
static bool diff_pathspec_match(
- const char **matched_pathspec, git_diff *diff, const char *path)
+ const char **matched_pathspec,
+ git_diff *diff,
+ const git_index_entry *entry)
{
- /* The iterator has filtered out paths for us, so the fact that we're
- * seeing this patch means that it must match the given path list.
+ bool disable_pathspec_match =
+ DIFF_FLAG_IS_SET(diff, GIT_DIFF_DISABLE_PATHSPEC_MATCH);
+
+ /* If we're disabling fnmatch, then the iterator has already applied
+ * the filters to the files for us and we don't have to do anything.
+ * However, this only applies to *files* - the iterator will include
+ * directories that we need to recurse into when not autoexpanding,
+ * so we still need to apply the pathspec match to directories.
*/
- if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_DISABLE_PATHSPEC_MATCH)) {
- *matched_pathspec = path;
+ if ((S_ISLNK(entry->mode) || S_ISREG(entry->mode)) &&
+ disable_pathspec_match) {
+ *matched_pathspec = entry->path;
return true;
}
return git_pathspec__match(
- &diff->pathspec, path, false,
+ &diff->pathspec, entry->path, disable_pathspec_match,
DIFF_FLAG_IS_SET(diff, GIT_DIFF_IGNORE_CASE),
matched_pathspec, NULL);
}
@@ -127,7 +136,7 @@ static int diff_delta__from_one(
DIFF_FLAG_ISNT_SET(diff, GIT_DIFF_INCLUDE_UNREADABLE))
return 0;
- if (!diff_pathspec_match(&matched_pathspec, diff, entry->path))
+ if (!diff_pathspec_match(&matched_pathspec, diff, entry))
return 0;
delta = diff_delta__alloc(diff, status, entry->path);
@@ -768,7 +777,7 @@ static int maybe_modified(
const char *matched_pathspec;
int error = 0;
- if (!diff_pathspec_match(&matched_pathspec, diff, oitem->path))
+ if (!diff_pathspec_match(&matched_pathspec, diff, oitem))
return 0;
memset(&noid, 0, sizeof(noid));
diff --git a/tests/diff/workdir.c b/tests/diff/workdir.c
index e87769170..89f9483a6 100644
--- a/tests/diff/workdir.c
+++ b/tests/diff/workdir.c
@@ -2054,3 +2054,46 @@ void test_diff_workdir__only_writes_index_when_necessary(void)
git_index_free(index);
}
+void test_diff_workdir__to_index_pathlist(void)
+{
+ git_index *index;
+ git_diff *diff;
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+ git_vector pathlist = GIT_VECTOR_INIT;
+
+ git_vector_insert(&pathlist, "foobar/asdf");
+ git_vector_insert(&pathlist, "subdir/asdf");
+ git_vector_insert(&pathlist, "ignored/asdf");
+
+ g_repo = cl_git_sandbox_init("status");
+
+ cl_git_mkfile("status/.gitignore", ".gitignore\n" "ignored/\n");
+
+ cl_must_pass(p_mkdir("status/foobar", 0777));
+ cl_git_mkfile("status/foobar/one", "one\n");
+
+ cl_must_pass(p_mkdir("status/ignored", 0777));
+ cl_git_mkfile("status/ignored/one", "one\n");
+ cl_git_mkfile("status/ignored/two", "two\n");
+ cl_git_mkfile("status/ignored/three", "three\n");
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+
+ opts.flags = GIT_DIFF_INCLUDE_IGNORED;
+ opts.pathspec.strings = pathlist.contents;
+ opts.pathspec.count = pathlist.length;
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &opts));
+ cl_assert_equal_i(0, git_diff_num_deltas(diff));
+ git_diff_free(diff);
+
+ opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &opts));
+ cl_assert_equal_i(0, git_diff_num_deltas(diff));
+ git_diff_free(diff);
+
+ git_index_free(index);
+ git_vector_free(&pathlist);
+}
+