@@ -164,9 +164,18 @@ func (pm *PatternMatcher) Patterns() []*Pattern {
164164 return pm .patterns
165165}
166166
167- // Pattern defines a single regexp used to filter file paths.
167+ type matchType int
168+
169+ const (
170+ unknownMatch matchType = iota
171+ regexpMatch
172+ suffixMatch
173+ )
174+
175+ // Pattern defines a single pattern used to filter file paths.
168176type Pattern struct {
169177 cleanedPattern string
178+ matchType matchType
170179 regexp * regexp.Regexp
171180 exclusion bool
172181}
@@ -181,18 +190,26 @@ func (p *Pattern) Exclusion() bool {
181190}
182191
183192func (p * Pattern ) match (path string ) (bool , error ) {
184- if p .regexp == nil {
193+ if p .matchType == unknownMatch {
185194 if err := p .compile (); err != nil {
186195 return false , filepath .ErrBadPattern
187196 }
188197 }
189198
190- b := p .regexp .MatchString (path )
191-
192- return b , nil
199+ switch p .matchType {
200+ case regexpMatch :
201+ return p .regexp .MatchString (path ), nil
202+ case suffixMatch :
203+ suffix := p .cleanedPattern [2 :]
204+ return strings .HasSuffix (path , suffix ), nil
205+ default :
206+ return false , fmt .Errorf ("unknown match type: %d" , p .matchType )
207+ }
193208}
194209
195210func (p * Pattern ) compile () error {
211+ p .matchType = regexpMatch
212+
196213 var regStrBuilder strings.Builder
197214 regStrBuilder .WriteString ("^" )
198215
@@ -209,17 +226,21 @@ func (p *Pattern) compile() error {
209226 escSL += bs
210227 }
211228
212- for scan .Peek () != scanner .EOF {
229+ for i := 0 ; scan .Peek () != scanner .EOF ; i ++ {
213230 ch := scan .Next ()
214231
215232 if ch == '*' {
233+ p .matchType = regexpMatch
234+
216235 if scan .Peek () == '*' {
217236 // is some flavor of "**"
218237 scan .Next ()
219238
239+ slashEaten := false
220240 // Treat **/ as ** so eat the "/"
221241 if string (scan .Peek ()) == sl {
222242 scan .Next ()
243+ slashEaten = true
223244 }
224245
225246 if scan .Peek () == scanner .EOF {
@@ -233,13 +254,19 @@ func (p *Pattern) compile() error {
233254 regStrBuilder .WriteString (escSL )
234255 regStrBuilder .WriteString (")?" )
235256 }
257+
258+ if i == 0 && ! slashEaten {
259+ p .matchType = suffixMatch
260+ }
236261 } else {
237262 // is "*" so map it to anything but "/"
238263 regStrBuilder .WriteString ("[^" )
239264 regStrBuilder .WriteString (escSL )
240265 regStrBuilder .WriteString ("]*" )
241266 }
242267 } else if ch == '?' {
268+ p .matchType = regexpMatch
269+
243270 // "?" is any char except "/"
244271 regStrBuilder .WriteString ("[^" )
245272 regStrBuilder .WriteString (escSL )
@@ -259,12 +286,18 @@ func (p *Pattern) compile() error {
259286 continue
260287 }
261288 if scan .Peek () != scanner .EOF {
289+ p .matchType = regexpMatch
290+
262291 regStrBuilder .WriteString (bs )
263292 regStrBuilder .WriteRune (scan .Next ())
264293 } else {
265294 return filepath .ErrBadPattern
266295 }
267296 } else {
297+ if ch == '[' || ch == ']' {
298+ p .matchType = regexpMatch
299+ }
300+
268301 regStrBuilder .WriteRune (ch )
269302 }
270303 }
0 commit comments