Skip to content

Commit 237ec6e

Browse files
pcloudsgitster
authored andcommitted
Support "**" wildcard in .gitignore and .gitattributes
Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4c251e5 commit 237ec6e

File tree

4 files changed

+77
-1
lines changed

4 files changed

+77
-1
lines changed

Documentation/gitignore.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,25 @@ PATTERN FORMAT
9696
For example, "/{asterisk}.c" matches "cat-file.c" but not
9797
"mozilla-sha1/sha1.c".
9898

99+
Two consecutive asterisks ("`**`") in patterns matched against
100+
full pathname may have special meaning:
101+
102+
- A leading "`**`" followed by a slash means match in all
103+
directories. For example, "`**/foo`" matches file or directory
104+
"`foo`" anywhere, the same as pattern "`foo`". "**/foo/bar"
105+
matches file or directory "`bar`" anywhere that is directly
106+
under directory "`foo`".
107+
108+
- A trailing "/**" matches everything inside. For example,
109+
"abc/**" matches all files inside directory "abc", relative
110+
to the location of the `.gitignore` file, with infinite depth.
111+
112+
- A slash followed by two consecutive asterisks then a slash
113+
matches zero or more directories. For example, "`a/**/b`"
114+
matches "`a/b`", "`a/x/b`", "`a/x/y/b`" and so on.
115+
116+
- Other consecutive asterisks are considered invalid.
117+
99118
NOTES
100119
-----
101120

dir.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "cache.h"
99
#include "dir.h"
1010
#include "refs.h"
11+
#include "wildmatch.h"
1112

1213
struct path_simplify {
1314
int len;
@@ -593,7 +594,8 @@ int match_pathname(const char *pathname, int pathlen,
593594
namelen -= prefix;
594595
}
595596

596-
return fnmatch_icase(pattern, name, FNM_PATHNAME) == 0;
597+
return wildmatch(pattern, name,
598+
ignore_case ? FNM_CASEFOLD : 0) == 0;
597599
}
598600

599601
/* Scan the list and let the last match determine the fate.

t/t0003-attributes.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,43 @@ test_expect_success 'patterns starting with exclamation' '
216216
attr_check "!f" foo
217217
'
218218

219+
test_expect_success '"**" test' '
220+
echo "**/f foo=bar" >.gitattributes &&
221+
cat <<\EOF >expect &&
222+
f: foo: bar
223+
a/f: foo: bar
224+
a/b/f: foo: bar
225+
a/b/c/f: foo: bar
226+
EOF
227+
git check-attr foo -- "f" >actual 2>err &&
228+
git check-attr foo -- "a/f" >>actual 2>>err &&
229+
git check-attr foo -- "a/b/f" >>actual 2>>err &&
230+
git check-attr foo -- "a/b/c/f" >>actual 2>>err &&
231+
test_cmp expect actual &&
232+
test_line_count = 0 err
233+
'
234+
235+
test_expect_success '"**" with no slashes test' '
236+
echo "a**f foo=bar" >.gitattributes &&
237+
git check-attr foo -- "f" >actual &&
238+
cat <<\EOF >expect &&
239+
f: foo: unspecified
240+
af: foo: bar
241+
axf: foo: bar
242+
a/f: foo: unspecified
243+
a/b/f: foo: unspecified
244+
a/b/c/f: foo: unspecified
245+
EOF
246+
git check-attr foo -- "f" >actual 2>err &&
247+
git check-attr foo -- "af" >>actual 2>err &&
248+
git check-attr foo -- "axf" >>actual 2>err &&
249+
git check-attr foo -- "a/f" >>actual 2>>err &&
250+
git check-attr foo -- "a/b/f" >>actual 2>>err &&
251+
git check-attr foo -- "a/b/c/f" >>actual 2>>err &&
252+
test_cmp expect actual &&
253+
test_line_count = 0 err
254+
'
255+
219256
test_expect_success 'setup bare' '
220257
git clone --bare . bare.git &&
221258
cd bare.git

t/t3001-ls-files-others-exclude.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,22 @@ test_expect_success 'pattern matches prefix completely' '
220220
test_cmp expect actual
221221
'
222222

223+
test_expect_success 'ls-files with "**" patterns' '
224+
cat <<\EOF >expect &&
225+
a.1
226+
one/a.1
227+
one/two/a.1
228+
three/a.1
229+
EOF
230+
git ls-files -o -i --exclude "**/a.1" >actual
231+
test_cmp expect actual
232+
'
233+
234+
235+
test_expect_success 'ls-files with "**" patterns and no slashes' '
236+
: >expect &&
237+
git ls-files -o -i --exclude "one**a.1" >actual &&
238+
test_cmp expect actual
239+
'
240+
223241
test_done

0 commit comments

Comments
 (0)