@@ -617,3 +617,147 @@ func TestMatchesAmount(t *testing.T) {
617617 assert .Equal (t , testCase .isMatch , isMatch , desc )
618618 }
619619}
620+
621+ func TestShouldDescendExcludedDir (t * testing.T ) {
622+ tests := []struct {
623+ name string
624+ dir string
625+ patterns []string
626+ expected bool
627+ }{
628+ {
629+ name : "nil PatternMatcher" ,
630+ dir : "cmd" ,
631+ patterns : nil ,
632+ expected : false ,
633+ },
634+ {
635+ name : "no exclusions" ,
636+ dir : "cmd" ,
637+ patterns : []string {"*.go" },
638+ expected : false ,
639+ },
640+ {
641+ name : "literal prefix match" ,
642+ dir : "cmd" ,
643+ patterns : []string {"*.go" , "!cmd/main.go" },
644+ expected : true ,
645+ },
646+ {
647+ name : "literal prefix nested" ,
648+ dir : "cmd/sub" ,
649+ patterns : []string {"*.go" , "!cmd/sub/main.go" },
650+ expected : true ,
651+ },
652+ {
653+ name : "literal prefix partial non-match" ,
654+ dir : "cmds" ,
655+ patterns : []string {"*.go" , "!cmd/main.go" },
656+ expected : false ,
657+ },
658+ {
659+ name : "double-star wildcard at root" ,
660+ dir : "cmd" ,
661+ patterns : []string {"*.go" , "!**/*.go" },
662+ expected : true ,
663+ },
664+ {
665+ name : "double-star wildcard deeply nested" ,
666+ dir : "a/b/c" ,
667+ patterns : []string {"*" , "!**/*.txt" },
668+ expected : true ,
669+ },
670+ {
671+ name : "single-star wildcard" ,
672+ dir : "cmd" ,
673+ patterns : []string {"*" , "!*/*.go" },
674+ expected : true ,
675+ },
676+ {
677+ name : "question-mark wildcard" ,
678+ dir : "cmd" ,
679+ patterns : []string {"*" , "!cm?/main.go" },
680+ expected : true ,
681+ },
682+ {
683+ name : "bracket expression wildcard" ,
684+ dir : "cmd" ,
685+ patterns : []string {"*" , "!cm[d]/main.go" },
686+ expected : true ,
687+ },
688+ {
689+ name : "mid-segment wildcard" ,
690+ dir : "cmd" ,
691+ patterns : []string {"*" , "!cmd/image*/main.go" },
692+ expected : true ,
693+ },
694+ {
695+ name : "mid-segment wildcard nested dir" ,
696+ dir : "cmd/imager" ,
697+ patterns : []string {"*" , "!cmd/image*/main.go" },
698+ expected : true ,
699+ },
700+ {
701+ name : "leading slash stripped" ,
702+ dir : "cmd" ,
703+ patterns : []string {"*" , "!/cmd/main.go" },
704+ expected : true ,
705+ },
706+ {
707+ name : "dir matches literal prefix exactly" ,
708+ dir : "vendor" ,
709+ patterns : []string {"*" , "!vendor/github.com/foo" },
710+ expected : true ,
711+ },
712+ {
713+ name : "dir is child of literal prefix" ,
714+ dir : "vendor/github.com" ,
715+ patterns : []string {"*" , "!vendor/github.com/foo" },
716+ expected : true ,
717+ },
718+ {
719+ name : "dir is parent of literal prefix" ,
720+ dir : "vendor" ,
721+ patterns : []string {"*" , "!vendor/github.com/foo" },
722+ expected : true ,
723+ },
724+ {
725+ name : "no matching exclusion pattern" ,
726+ dir : "docs" ,
727+ patterns : []string {"*" , "!cmd/main.go" },
728+ expected : false ,
729+ },
730+ {
731+ name : "unrelated wildcard pattern" ,
732+ dir : "docs" ,
733+ patterns : []string {"*" , "!cmd/*/*.go" },
734+ expected : false ,
735+ },
736+ {
737+ name : "root-level glob matches any dir" ,
738+ dir : "anything" ,
739+ patterns : []string {"*" , "!*.go" },
740+ expected : true ,
741+ },
742+ {
743+ name : "trailing slash on dir path" ,
744+ dir : "cmd/" ,
745+ patterns : []string {"*" , "!cmd/main.go" },
746+ expected : true ,
747+ },
748+ }
749+
750+ for _ , tc := range tests {
751+ t .Run (tc .name , func (t * testing.T ) {
752+ if tc .patterns == nil {
753+ result := ShouldDescendExcludedDir (tc .dir , nil )
754+ assert .Equal (t , tc .expected , result )
755+ return
756+ }
757+ pm , err := NewPatternMatcher (tc .patterns )
758+ require .NoError (t , err )
759+ result := ShouldDescendExcludedDir (tc .dir , pm )
760+ assert .Equal (t , tc .expected , result , "dir=%q patterns=%v" , tc .dir , tc .patterns )
761+ })
762+ }
763+ }
0 commit comments