Skip to content

Commit eb17cc5

Browse files
committed
refactor(pattern-matcher): add CanSkipDir method in patternMatcher
1. Remove deprecated method: `Matches` in `PatternMatcher` 2. Add `CanSkipDir` to `MatchesResult` 3. Improve `MatchesResult` 1. Remove the `matches` and `excludes` fields (no one is using these two fields) Signed-off-by: Black-Hole1 <[email protected]>
1 parent fab5175 commit eb17cc5

File tree

2 files changed

+54
-25
lines changed

2 files changed

+54
-25
lines changed

pkg/fileutils/fileutils.go

+35-9
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func NewPatternMatcher(patterns []string) (*PatternMatcher, error) {
4242
pm.exclusions = true
4343
}
4444
// Do some syntax checking on the pattern.
45-
// filepath's Match() has some really weird rules that are inconsistent
45+
// filepath.Match() has some really weird rules that are inconsistent
4646
// so instead of trying to dup their logic, just call Match() for its
4747
// error state and if there is an error in the pattern return it.
4848
// If this becomes an issue we can remove this since its really only
@@ -89,11 +89,11 @@ func (pm *PatternMatcher) Matches(file string) (bool, error) {
8989
}
9090

9191
type MatchResult struct {
92-
isMatched bool
93-
matches, excludes uint
92+
isMatched, canSkipDir bool
93+
matches, excludes uint
9494
}
9595

96-
// Excludes returns true if the overall result is matched
96+
// IsMatched returns true if the overall result is matched
9797
func (m *MatchResult) IsMatched() bool {
9898
return m.isMatched
9999
}
@@ -108,12 +108,20 @@ func (m *MatchResult) Excludes() uint {
108108
return m.excludes
109109
}
110110

111+
// CanSkipDir returns true if it is possible to use filepath.SkipDir
112+
// Only when the pattern is very simple (does not start with ! and does not contain ? and *)
113+
// and is not influenced by other patterns, will it return true.
114+
func (m *MatchResult) CanSkipDir() bool {
115+
return m.canSkipDir
116+
}
117+
111118
// MatchesResult verifies the provided filepath against all patterns.
112119
// It returns the `*MatchResult` result for the patterns on success, otherwise
113120
// an error. This method is not safe to be called concurrently.
114121
func (pm *PatternMatcher) MatchesResult(file string) (res *MatchResult, err error) {
115122
file = filepath.FromSlash(file)
116-
res = &MatchResult{false, 0, 0}
123+
res = &MatchResult{false, false, 0, 0}
124+
matchPatterns := make([]*Pattern, 0, len(pm.patterns))
117125

118126
for _, pattern := range pm.patterns {
119127
negative := false
@@ -129,16 +137,34 @@ func (pm *PatternMatcher) MatchesResult(file string) (res *MatchResult, err erro
129137

130138
if match {
131139
res.isMatched = !negative
132-
if negative {
133-
res.excludes++
134-
} else {
140+
if res.isMatched {
135141
res.matches++
142+
matchPatterns = append(matchPatterns, pattern)
143+
} else {
144+
res.excludes++
136145
}
137146
}
138147
}
139148

140-
if res.matches > 0 {
149+
if res.isMatched {
141150
logrus.Debugf("Skipping excluded path: %s", file)
151+
152+
isPatternsEqual := true
153+
first := matchPatterns[0].String()
154+
if len(matchPatterns) != 1 {
155+
for _, pattern := range matchPatterns[1:] {
156+
if first != pattern.String() {
157+
isPatternsEqual = false
158+
break
159+
}
160+
}
161+
}
162+
163+
if isPatternsEqual {
164+
if !strings.Contains(first, "*") && !strings.Contains(first, "?") {
165+
res.canSkipDir = true
166+
}
167+
}
142168
}
143169

144170
return res, nil

pkg/fileutils/fileutils_test.go

+19-16
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ func TestMatches(t *testing.T) {
390390
assert.Equal(t, err, filepath.ErrBadPattern)
391391
} else {
392392
assert.Nil(t, err)
393-
assert.Equal(t, test.match, res.isMatched, desc)
393+
assert.Equal(t, test.match, res.IsMatched(), desc)
394394
}
395395
}
396396
})
@@ -591,22 +591,24 @@ func TestMatch(t *testing.T) {
591591

592592
func TestMatchesAmount(t *testing.T) {
593593
testData := []struct {
594-
patterns []string
595-
input string
596-
matches uint
597-
excludes uint
598-
isMatch bool
594+
patterns []string
595+
input string
596+
matches uint
597+
excludes uint
598+
isMatch bool
599+
canSkipDir bool
599600
}{
600-
{[]string{"1", "2", "3"}, "2", 1, 0, true},
601-
{[]string{"2", "!2", "!2"}, "2", 1, 2, false},
602-
{[]string{"1", "2", "2"}, "2", 2, 0, true},
603-
{[]string{"1", "2", "2", "2"}, "2", 3, 0, true},
604-
{[]string{"/prefix/path", "/prefix/other"}, "/prefix/path", 1, 0, true},
605-
{[]string{"/prefix*", "!/prefix/path"}, "/prefix/match", 1, 0, true},
606-
{[]string{"/prefix*", "!/prefix/path"}, "/prefix/path", 1, 0, true},
607-
{[]string{"/prefix*", "!/prefix/path"}, "prefix/path", 0, 1, false},
608-
{[]string{"/prefix*", "!./prefix/path"}, "prefix/path", 0, 1, false},
609-
{[]string{"/prefix*", "!prefix/path"}, "prefix/path", 0, 1, false},
601+
{[]string{"1", "2", "3"}, "2", 1, 0, true, true},
602+
{[]string{"!1", "1"}, "1", 1, 1, true, true},
603+
{[]string{"2", "!2", "!2"}, "2", 1, 2, false, false},
604+
{[]string{"1", "2", "2"}, "2", 2, 0, true, true},
605+
{[]string{"1", "2", "2", "2"}, "2", 3, 0, true, true},
606+
{[]string{"/prefix/path", "/prefix/other"}, "/prefix/path", 1, 0, true, true},
607+
{[]string{"/prefix*", "!/prefix/path"}, "/prefix/match", 1, 0, true, false},
608+
{[]string{"/prefix*", "!/prefix/path"}, "/prefix/path", 1, 0, true, false},
609+
{[]string{"/prefix*", "!/prefix/path"}, "prefix/path", 0, 1, false, false},
610+
{[]string{"/prefix*", "!./prefix/path"}, "prefix/path", 0, 1, false, false},
611+
{[]string{"/prefix*", "!prefix/path"}, "prefix/path", 0, 1, false, false},
610612
}
611613

612614
for _, testCase := range testData {
@@ -618,6 +620,7 @@ func TestMatchesAmount(t *testing.T) {
618620
assert.Equal(t, testCase.excludes, res.Excludes(), desc)
619621
assert.Equal(t, testCase.matches, res.Matches(), desc)
620622
assert.Equal(t, testCase.isMatch, res.IsMatched(), desc)
623+
assert.Equal(t, testCase.canSkipDir, res.CanSkipDir(), desc)
621624

622625
isMatch, err := pm.IsMatch(testCase.input)
623626
require.NoError(t, err)

0 commit comments

Comments
 (0)