Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 Documentation/gitignore.txt        | 19 +++++++++++++++++++
 dir.c                              |  4 +++-
 t/t0003-attributes.sh              | 37 +++++++++++++++++++++++++++++++++++++
 t/t3001-ls-files-others-exclude.sh | 18 ++++++++++++++++++
 4 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt
index 2e7328b..d4747ce 100644
--- a/Documentation/gitignore.txt
+++ b/Documentation/gitignore.txt
@@ -96,6 +96,25 @@ PATTERN FORMAT
    For example, "/{asterisk}.c" matches "cat-file.c" but not
    "mozilla-sha1/sha1.c".
 
+Two consecutive asterisks ("`**`") in patterns matched against
+full pathname may have special meaning:
+
+ - A leading "`**`" followed by a slash means match in all
+   directories. For example, "`**/foo`" matches file or directory
+   "`foo`" anywhere, the same as pattern "`foo`". "**/foo/bar"
+   matches file or directory "`bar`" anywhere that is directly
+   under directory "`foo`".
+
+ - A trailing "/**" matches everything inside. For example,
+   "abc/**" matches all files inside directory "abc", relative
+   to the location of the `.gitignore` file, with infinite depth.
+
+ - A slash followed by two consecutive asterisks then a slash
+   matches zero or more directories. For example, "`a/**/b`"
+   matches "`a/b`", "`a/x/b`", "`a/x/y/b`" and so on.
+
+ - Other consecutive asterisks are considered invalid.
+
 NOTES
 -----
 
diff --git a/dir.c b/dir.c
index ee8e711..cb7328b 100644
--- a/dir.c
+++ b/dir.c
@@ -8,6 +8,7 @@
 #include "cache.h"
 #include "dir.h"
 #include "refs.h"
+#include "wildmatch.h"
 
 struct path_simplify {
        int len;
@@ -593,7 +594,8 @@ int match_pathname(const char *pathname, int pathlen,
                namelen -= prefix;
        }
 
-       return fnmatch_icase(pattern, name, FNM_PATHNAME) == 0;
+       return wildmatch(pattern, name,
+                        ignore_case ? FNM_CASEFOLD : 0) == 0;
 }
 
 /* Scan the list and let the last match determine the fate.
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index f6c21ea..c962403 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -216,6 +216,43 @@ test_expect_success 'patterns starting with exclamation' '
        attr_check "!f" foo
 '
 
+test_expect_success '"**" test' '
+       echo "**/f foo=bar" >.gitattributes &&
+       cat <<\EOF >expect &&
+f: foo: bar
+a/f: foo: bar
+a/b/f: foo: bar
+a/b/c/f: foo: bar
+EOF
+       git check-attr foo -- "f" >actual 2>err &&
+       git check-attr foo -- "a/f" >>actual 2>>err &&
+       git check-attr foo -- "a/b/f" >>actual 2>>err &&
+       git check-attr foo -- "a/b/c/f" >>actual 2>>err &&
+       test_cmp expect actual &&
+       test_line_count = 0 err
+'
+
+test_expect_success '"**" with no slashes test' '
+       echo "a**f foo=bar" >.gitattributes &&
+       git check-attr foo -- "f" >actual &&
+       cat <<\EOF >expect &&
+f: foo: unspecified
+af: foo: bar
+axf: foo: bar
+a/f: foo: unspecified
+a/b/f: foo: unspecified
+a/b/c/f: foo: unspecified
+EOF
+       git check-attr foo -- "f" >actual 2>err &&
+       git check-attr foo -- "af" >>actual 2>err &&
+       git check-attr foo -- "axf" >>actual 2>err &&
+       git check-attr foo -- "a/f" >>actual 2>>err &&
+       git check-attr foo -- "a/b/f" >>actual 2>>err &&
+       git check-attr foo -- "a/b/c/f" >>actual 2>>err &&
+       test_cmp expect actual &&
+       test_line_count = 0 err
+'
+
 test_expect_success 'setup bare' '
        git clone --bare . bare.git &&
        cd bare.git
diff --git a/t/t3001-ls-files-others-exclude.sh 
b/t/t3001-ls-files-others-exclude.sh
index dc2f045..efb7ebc 100755
--- a/t/t3001-ls-files-others-exclude.sh
+++ b/t/t3001-ls-files-others-exclude.sh
@@ -220,4 +220,22 @@ test_expect_success 'pattern matches prefix completely' '
        test_cmp expect actual
 '
 
+test_expect_success 'ls-files with "**" patterns' '
+       cat <<\EOF >expect &&
+a.1
+one/a.1
+one/two/a.1
+three/a.1
+EOF
+       git ls-files -o -i --exclude "**/a.1" >actual
+       test_cmp expect actual
+'
+
+
+test_expect_success 'ls-files with "**" patterns and no slashes' '
+       : >expect &&
+       git ls-files -o -i --exclude "one**a.1" >actual &&
+       test_cmp expect actual
+'
+
 test_done
-- 
1.8.0.rc0.29.g1fdd78f

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to