@@ -36,7 +36,7 @@ var matchTests = []MatchTest{
3636 {"/*" , "/debug/" , false , false , false , nil , false , false , true , false , 0 , 0 },
3737 {"/*" , "//" , false , false , false , nil , false , false , true , false , 0 , 0 },
3838 {"abc" , "abc" , true , true , false , nil , false , false , true , true , 1 , 1 },
39- {"*" , "abc" , true , true , false , nil , false , false , true , true , 25 , 20 },
39+ {"*" , "abc" , true , true , false , nil , false , false , true , true , 29 , 24 },
4040 {"*c" , "abc" , true , true , false , nil , false , false , true , true , 2 , 2 },
4141 {"*/" , "a/" , true , true , false , nil , false , false , true , false , 0 , 0 },
4242 {"a*" , "a" , true , true , false , nil , false , false , true , true , 9 , 9 },
@@ -64,8 +64,8 @@ var matchTests = []MatchTest{
6464 {"a[!a]b" , "a☺b" , true , true , false , nil , false , false , false , true , 1 , 1 },
6565 {"a???b" , "a☺b" , false , false , false , nil , false , false , true , true , 0 , 0 },
6666 {"a[^a][^a][^a]b" , "a☺b" , false , false , false , nil , false , false , true , true , 0 , 0 },
67- {"[a-ζ]*" , "α" , true , true , false , nil , false , false , true , true , 22 , 19 },
68- {"*[a-ζ]" , "A" , false , false , false , nil , false , false , true , true , 22 , 19 },
67+ {"[a-ζ]*" , "α" , true , true , false , nil , false , false , true , true , 23 , 20 },
68+ {"*[a-ζ]" , "A" , false , false , false , nil , false , false , true , true , 26 , 23 },
6969 {"a?b" , "a/b" , false , false , false , nil , false , false , true , true , 1 , 1 },
7070 {"a*b" , "a/b" , false , false , false , nil , false , false , true , true , 1 , 1 },
7171 {"[\\ ]a]" , "]" , true , true , false , nil , false , false , true , ! onWindows , 2 , 2 },
@@ -203,6 +203,11 @@ var matchTests = []MatchTest{
203203 {"nopermission/*" , "nopermission/file" , true , false , false , nil , true , false , true , ! onWindows , 0 , 0 },
204204 {"nopermission/dir/" , "nopermission/dir" , false , false , false , nil , true , false , true , ! onWindows , 0 , 0 },
205205 {"nopermission/file" , "nopermission/file" , true , false , false , nil , true , false , true , ! onWindows , 0 , 0 },
206+ {".*" , ".hidden_file" , true , true , false , nil , false , false , false , true , 3 , 3 },
207+ {".hidden_dir/**" , ".hidden_dir" , true , true , false , nil , false , false , false , true , 2 , 2 },
208+ {".hidden_dir/*" , ".hidden_dir/.nested_hidden" , true , true , false , nil , false , false , false , true , 1 , 1 },
209+ {".another_hidden/file" , ".another_hidden/file" , true , true , false , nil , false , false , false , true , 1 , 1 },
210+ {"foo/**/bar" , "foo/visible/bar" , true , true , false , nil , false , false , false , true , 4 , 4 },
206211}
207212
208213// True if the file system supports case-sensitive filenames
@@ -220,6 +225,10 @@ var numResultsNoFollow []int
220225// of the options enabled at runtime and memoize them here
221226var numResultsAllOpts []int
222227
228+ // Calculate the number of results that we expect
229+ // WithNoHidden at runtime and memoize them here
230+ var numResultsNoHidden []int
231+
223232func TestValidatePattern (t * testing.T ) {
224233 for idx , tt := range matchTests {
225234 testValidatePatternWith (t , idx , tt )
@@ -462,6 +471,10 @@ func TestGlobWithNoFollow(t *testing.T) {
462471 doGlobTest (t , WithNoFollow ())
463472}
464473
474+ func TestGlobWithNoHidden (t * testing.T ) {
475+ doGlobTest (t , WithNoHidden ())
476+ }
477+
465478func TestGlobWithAllOptions (t * testing.T ) {
466479 doGlobTest (t , WithCaseInsensitive (), WithFailOnIOErrors (), WithFailOnPatternNotExist (), WithFilesOnly (), WithNoFollow ())
467480}
@@ -510,6 +523,10 @@ func TestGlobWalkWithNoFollow(t *testing.T) {
510523 doGlobWalkTest (t , WithNoFollow ())
511524}
512525
526+ func TestGlobWalkWithNoHidden (t * testing.T ) {
527+ doGlobWalkTest (t , WithNoHidden ())
528+ }
529+
513530func TestGlobWalkWithAllOptions (t * testing.T ) {
514531 doGlobWalkTest (t , WithFailOnIOErrors (), WithFailOnPatternNotExist (), WithFilesOnly (), WithNoFollow ())
515532}
@@ -571,6 +588,10 @@ func TestFilepathGlobWithNoFollow(t *testing.T) {
571588 doFilepathGlobTest (t , WithNoFollow ())
572589}
573590
591+ func TestFilepathGlobWithNoHidden (t * testing.T ) {
592+ doFilepathGlobTest (t , WithNoHidden ())
593+ }
594+
574595func doFilepathGlobTest (t * testing.T , opts ... GlobOption ) {
575596 glob := newGlob (opts ... )
576597 fsys := os .DirFS ("test" )
@@ -635,7 +656,9 @@ func verifyGlobResults(t *testing.T, idx int, fn string, tt MatchTest, g *glob,
635656 if onWindows {
636657 numResults = tt .winNumResults
637658 }
638- if g .filesOnly {
659+ if g .noHidden {
660+ numResults = numResultsNoHidden [idx ]
661+ } else if g .filesOnly {
639662 if g .noFollow {
640663 numResults = numResultsAllOpts [idx ]
641664 } else {
@@ -651,7 +674,8 @@ func verifyGlobResults(t *testing.T, idx int, fn string, tt MatchTest, g *glob,
651674 if len (matches ) != numResults {
652675 t .Errorf ("#%v. %v(%#q, %#v) = %#v - should have %#v results, got %#v" , idx , fn , tt .pattern , g , matches , numResults , len (matches ))
653676 }
654- if ! g .filesOnly && ! g .noFollow && inSlice (tt .testPath , matches ) != tt .shouldMatchGlob {
677+ // Skip testPath check for noHidden since the match semantics are different
678+ if ! g .filesOnly && ! g .noFollow && ! g .noHidden && inSlice (tt .testPath , matches ) != tt .shouldMatchGlob {
655679 if tt .shouldMatchGlob {
656680 t .Errorf ("#%v. %v(%#q, %#v) = %#v - doesn't contain %v, but should" , idx , fn , tt .pattern , g , matches , tt .testPath )
657681 } else {
@@ -769,6 +793,7 @@ func buildNumResults() {
769793 numResultsFilesOnly = make ([]int , testLen , testLen )
770794 numResultsNoFollow = make ([]int , testLen , testLen )
771795 numResultsAllOpts = make ([]int , testLen , testLen )
796+ numResultsNoHidden = make ([]int , testLen , testLen )
772797
773798 fsys := os .DirFS ("test" )
774799 g := newGlob ()
@@ -798,6 +823,14 @@ func buildNumResults() {
798823 numResultsFilesOnly [idx ] = filesOnly
799824 numResultsNoFollow [idx ] = noFollow
800825 numResultsAllOpts [idx ] = allOpts
826+
827+ // Compute noHidden results by actually running with WithNoHidden
828+ noHidden := 0
829+ GlobWalk (fsys , tt .pattern , func (p string , d fs.DirEntry ) error {
830+ noHidden ++
831+ return nil
832+ }, WithNoHidden ())
833+ numResultsNoHidden [idx ] = noHidden
801834 }
802835 }
803836}
@@ -882,6 +915,18 @@ func TestMain(m *testing.M) {
882915
883916 touch ("test" , "}" )
884917
918+ mkdirp ("test" , ".hidden_dir" )
919+ mkdirp ("test" , ".another_hidden" )
920+ mkdirp ("test" , "foo" , ".hidden" , "deep" )
921+ mkdirp ("test" , "foo" , "visible" )
922+ touch ("test" , ".hidden_file" )
923+ touch ("test" , ".hidden_dir" , ".nested_hidden" )
924+ touch ("test" , ".another_hidden" , "file" )
925+ touch ("test" , "foo" , ".hidden" , "bar" )
926+ touch ("test" , "foo" , ".hidden" , "deep" , "bar" )
927+ touch ("test" , "foo" , "visible" , "bar" )
928+ touch ("test" , "foo" , "bar" )
929+
885930 if ! onWindows {
886931 // these files/symlinks won't work on Windows
887932 touch ("test" , "-" )
0 commit comments