The function excluded_from_list (or its public API excluded) is currently used to mark what entry is included in sparse checkout. Because index does not have directories, the pattern "foo", while would match directory "foo" on working directory, would not match against index. To overcome this, if a pattern does not match, check if it matches parent directories too before moving on to the next pattern. This behavior only applies to index matching. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- There is subtle difference, which might break things. When working with file system, it checks top-down, parent directories first. I do bottom-up. If/you/have/deep/directories sparse checkout may become slow. And my test broke :( dir.c | 24 ++++++++++++++++++++++-- t/t1009-read-tree-sparse-checkout.sh | 4 ++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/dir.c b/dir.c index 3a8d3e6..82227e5 100644 --- a/dir.c +++ b/dir.c @@ -334,13 +334,15 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen) } /* Scan the list and let the last match determine the fate. + * dtype == NULL means matching against index, not working directory. * Return 1 for exclude, 0 for include and -1 for undecided. */ -int excluded_from_list(const char *pathname, - int pathlen, const char *basename, int *dtype, +int excluded_from_list(const char *pathname_, + int pathlen_, const char *basename_, int *dtype, struct exclude_list *el) { int i; + char buf[PATH_MAX]; if (el->nr) { for (i = el->nr - 1; 0 <= i; i--) { @@ -348,6 +350,11 @@ int excluded_from_list(const char *pathname, const char *exclude = x->pattern; int to_exclude = x->to_exclude; + const char *pathname = pathname_; + const char *basename = basename_; + int pathlen = pathlen_; + +recheck: if (x->flags & EXC_FLAG_MUSTBEDIR) { if (!dtype) { if (!prefixcmp(pathname, exclude)) @@ -398,6 +405,19 @@ int excluded_from_list(const char *pathname, return to_exclude; } } + + if (!dtype) { /* matching against index */ + basename = strrchr(pathname, '/'); + if (basename) { + pathlen = basename-pathname; + memcpy(buf, pathname, pathlen); + buf[pathlen] = '\0'; + pathname = buf; + basename = strrchr(pathname, '/'); + basename = (basename) ? basename+1 : pathname; + goto recheck; + } + } } } return -1; /* undecided */ diff --git a/t/t1009-read-tree-sparse-checkout.sh b/t/t1009-read-tree-sparse-checkout.sh index 62246db..b57d237 100755 --- a/t/t1009-read-tree-sparse-checkout.sh +++ b/t/t1009-read-tree-sparse-checkout.sh @@ -84,13 +84,13 @@ cat >expected.swt <<EOF H init.t H sub/added EOF -test_expect_failure 'match directories without trailing slash' ' +test_expect_success 'match directories without trailing slash' ' echo init.t > .git/info/sparse-checkout && echo sub >> .git/info/sparse-checkout && git read-tree -m -u HEAD && git ls-files -t > result && test_cmp expected.swt result && - test ! -f init.t && + test -f init.t && test -f sub/added ' -- 1.6.5.2.216.g9c1ec -- 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