Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- t/t9999-test.sh | 44 ++++++++++++++++++++++++++++++++++++++++++++ tree-walk.c | 36 +++++++++++++++++++++++++++++++----- 2 files changed, 75 insertions(+), 5 deletions(-) create mode 100755 t/t9999-test.sh diff --git a/t/t9999-test.sh b/t/t9999-test.sh new file mode 100755 index 0000000..535386e --- /dev/null +++ b/t/t9999-test.sh @@ -0,0 +1,44 @@ +#!/bin/sh +test_description=f + +. ./test-lib.sh + +test_expect_success setup ' + mkdir one one/two && + touch file one/file one/two/file one/zoo && + git add . && + git commit -m 1 && + for i in file one/file one/two/file one/zoo; do echo 1 >>$i;done && + git add . && git commit -m 2 +' + +test_expect_success 'diff' ' + cat >expected <<-\EOF && +:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 d00491fd7e5bb6fa28c517a0bb32b8b506539d4d M one/file +:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 d00491fd7e5bb6fa28c517a0bb32b8b506539d4d M one/two/file +:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 d00491fd7e5bb6fa28c517a0bb32b8b506539d4d M one/zoo +EOF + git diff-tree -r HEAD^ HEAD -- one >result && + test_cmp expected result +' + +test_expect_success 'diff one ^one/two' ' + cat >expected <<-\EOF && +:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 d00491fd7e5bb6fa28c517a0bb32b8b506539d4d M one/file +:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 d00491fd7e5bb6fa28c517a0bb32b8b506539d4d M one/zoo +EOF + git diff-tree -r HEAD^ HEAD -- one ^one/two >result && + test_cmp expected result +' + +test_expect_success 'diff ^one/two' ' + cat >expected <<-\EOF && +:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 d00491fd7e5bb6fa28c517a0bb32b8b506539d4d M file +:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 d00491fd7e5bb6fa28c517a0bb32b8b506539d4d M one/file +:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 d00491fd7e5bb6fa28c517a0bb32b8b506539d4d M one/zoo +EOF + git diff-tree -r HEAD^ HEAD -- ^one/two >result && + test_cmp expected result +' + +test_done diff --git a/tree-walk.c b/tree-walk.c index a2f4a00..fd19681 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -532,7 +532,7 @@ int tree_entry_interesting(const struct name_entry *entry, const char *base, int pathlen = tree_entry_len(entry->path, entry->sha1); - for (i = 0; i < ps->nr; i++) { + for (i = ps->nr-1; i >= 0; i--) { const char *match = ps->info[i].path; int matchlen = ps->info[i].pathlen; int m = -1; /* signals that we haven't called strncmp() */ @@ -548,8 +548,18 @@ int tree_entry_interesting(const struct name_entry *entry, const char *base, int */ if (!matchlen || base[matchlen] == '/' || - match[matchlen - 1] == '/') - return 2; + match[matchlen - 1] == '/') { + if (!ps->info[i].has_sub_pathspec && + ps->info[i].to_exclude) + return -1; + /* + * If has_sub_pathspec is 1, there is + * another sub pathspec that will + * negate the result. Don't return "2" + * in that case. + */ + return ps->info[i].has_sub_pathspec ? 1 : 2; + } /* Just a random prefix match */ continue; @@ -615,8 +625,24 @@ int tree_entry_interesting(const struct name_entry *entry, const char *base, int * because we rejected the case where path is not a * leading directory and is shorter than match. */ - if (!m) + if (!m) { + /* + * If this is negative pathspec, we exclude + * the path only if it's a perfect + * match. Otherwise assume it's in, because + * there could be a positive subpathspec, + * which includes some trees again. + */ + if (ps->info[i].to_exclude) + return matchlen == pathlen ? 0 : 1; return 1; + } } - return never_interesting; /* No matches */ + + /* + * if include_by_default is 1, all items should be included by + * default, because some of them will be excluded later on by + * negative pathspecs. + */ + return ps->include_by_default ? 1 : never_interesting; /* No matches */ } -- 1.7.1.rc1.70.g13aff -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html