93 lines
2.1 KiB
Go
93 lines
2.1 KiB
Go
package fileglob
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/gobwas/glob/syntax/ast"
|
|
"github.com/gobwas/glob/syntax/lexer"
|
|
)
|
|
|
|
// ValidPattern determines whether a pattern is valid. It returns the parser
|
|
// error if the pattern is invalid and nil otherwise.
|
|
func ValidPattern(pattern string) error {
|
|
_, err := ast.Parse(lexer.NewLexer(pattern))
|
|
return err // nolint:wrapcheck
|
|
}
|
|
|
|
// ContainsMatchers determines whether the pattern contains any type of glob
|
|
// matcher. It will also return false if the pattern is an invalid expression.
|
|
func ContainsMatchers(pattern string) bool {
|
|
rootNode, err := ast.Parse(lexer.NewLexer(pattern))
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
_, isStatic := staticText(rootNode)
|
|
return !isStatic
|
|
}
|
|
|
|
// staticText returns the static string matcher represented by the AST unless
|
|
// it contains dynamic matchers (wildcards, etc.). In this case the ok return
|
|
// value is false.
|
|
func staticText(node *ast.Node) (text string, ok bool) {
|
|
// nolint:exhaustive
|
|
switch node.Kind {
|
|
case ast.KindPattern:
|
|
text := ""
|
|
|
|
for _, child := range node.Children {
|
|
childText, ok := staticText(child)
|
|
if !ok {
|
|
return "", false
|
|
}
|
|
|
|
text += childText
|
|
}
|
|
|
|
return text, true
|
|
case ast.KindText:
|
|
return node.Value.(ast.Text).Text, true
|
|
case ast.KindNothing:
|
|
return "", true
|
|
default:
|
|
return "", false
|
|
}
|
|
}
|
|
|
|
// staticPrefix returns the file path inside the pattern up
|
|
// to the first path element that contains a wildcard.
|
|
func staticPrefix(pattern string) (string, error) {
|
|
parts := strings.Split(pattern, separatorString)
|
|
|
|
// nolint:prealloc
|
|
var prefixPath []string
|
|
for _, part := range parts {
|
|
if part == "" {
|
|
continue
|
|
}
|
|
|
|
rootNode, err := ast.Parse(lexer.NewLexer(part))
|
|
if err != nil {
|
|
return "", fmt.Errorf("parse glob pattern: %w", err)
|
|
}
|
|
|
|
staticPart, ok := staticText(rootNode)
|
|
if !ok {
|
|
break
|
|
}
|
|
|
|
prefixPath = append(prefixPath, staticPart)
|
|
}
|
|
prefix := strings.Join(prefixPath, separatorString)
|
|
if len(pattern) > 0 && rune(pattern[0]) == separatorRune && !strings.HasPrefix(prefix, separatorString) {
|
|
prefix = separatorString + prefix
|
|
}
|
|
|
|
if prefix == "" {
|
|
prefix = "."
|
|
}
|
|
|
|
return prefix, nil
|
|
}
|