Skip to content

Commit

Permalink
replace gobwas/glob with bmatcuk/doublestar
Browse files Browse the repository at this point in the history
because

- `**` in gobwas/glob does not match to zero directories (`globstar`)
- gobwas/glob looks unmaintained
  • Loading branch information
rhysd committed Oct 30, 2024
1 parent 8f6800f commit ff10b3b
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 248 deletions.
113 changes: 37 additions & 76 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,97 +7,49 @@ import (
"regexp"
"strings"

"github.com/gobwas/glob"
"github.com/bmatcuk/doublestar/v4"
"gopkg.in/yaml.v3"
)

// PathConfig is a configuration for specific file path pattern. This is for values of the "paths" mapping
// in the configuration file.
type PathConfig struct {
glob glob.Glob
// Ignore is a list of patterns. They are used for ignoring errors by matching to the error messages.
// These are similar to the "-ignore" command line option.
Ignore []*regexp.Regexp
}

// UnmarshalYAML impelements yaml.Unmarshaler. This function partially initializes the PathConfig object
// and is for internal implementation purpose.
func (cfg *PathConfig) UnmarshalYAML(n *yaml.Node) error {
for i := 0; i < len(n.Content); i += 2 {
k, v := n.Content[i], n.Content[i+1]
switch k.Value {
case "ignore":
if v.Kind != yaml.SequenceNode {
return fmt.Errorf("yaml: \"ignore\" must be a sequence node at line:%d,col:%d", v.Line, v.Column)
}
cfg.Ignore = make([]*regexp.Regexp, 0, len(v.Content))
for _, p := range v.Content {
r, err := regexp.Compile(p.Value)
if err != nil {
return fmt.Errorf("invalid regular expression %q in \"ignore\" at line%d,col:%d: %w", p.Value, v.Line, v.Column, err)
}
cfg.Ignore = append(cfg.Ignore, r)
}
default:
return fmt.Errorf("invalid key %q at line:%d,col:%d", k.Value, k.Line, k.Column)
}
}
return nil
}

// Matches returns whether this config is for the given path.
func (cfg *PathConfig) Matches(path string) bool {
return cfg.glob.Match(path)
}
// IgnorePatterns is a list of regular expressions. They are used for ignoring errors by matching
// to the error messages.
type IgnorePatterns []*regexp.Regexp

// Ignores returns whether the given error should be ignored due to the "ignore" configuration.

Check failure on line 18 in config.go

View workflow job for this annotation

GitHub Actions / Lint

comment on exported method Match should be of the form "Match ..." (ST1020)
func (cfg *PathConfig) Ignores(err *Error) bool {
for _, r := range cfg.Ignore {
func (pats IgnorePatterns) Match(err *Error) bool {
for _, r := range pats {
if r.MatchString(err.Message) {
return true
}
}
return false
}

// PathConfigs is a "paths" mapping in the configuration file. The keys are glob patterns matching to
// file paths relative to the repository root. And the values are the corresponding configurations.
type PathConfigs map[string]*PathConfig

// UnmarshalYAML impelements yaml.Unmarshaler.
//
// https://pkg.go.dev/gopkg.in/yaml.v3?utm_source=godoc#Unmarshaler
func (cfgs *PathConfigs) UnmarshalYAML(n *yaml.Node) error {
if n.Kind != yaml.MappingNode {
return expectedMapping("paths", n)
// UnmarshalYAML implements yaml.Unmarshaler.
func (pats *IgnorePatterns) UnmarshalYAML(n *yaml.Node) error {
if n.Kind != yaml.SequenceNode {
return fmt.Errorf("yaml: \"ignore\" must be a sequence node at line:%d,col:%d", n.Line, n.Column)
}

ret := make(PathConfigs, len(n.Content)/2)
for i := 0; i < len(n.Content); i += 2 {
pat, child := n.Content[i].Value, n.Content[i+1]

var cfg PathConfig

g, err := glob.Compile(pat)
rs := make([]*regexp.Regexp, 0, len(n.Content))
for _, p := range n.Content {
r, err := regexp.Compile(p.Value)
if err != nil {
return fmt.Errorf("error while processing glob pattern %q in \"paths\" config: %w", pat, err)
}
cfg.glob = g

if err := cfg.UnmarshalYAML(child); err != nil {
return fmt.Errorf("error while processing \"paths\" config: %w", err)
return fmt.Errorf("invalid regular expression %q in \"ignore\" at line%d,col:%d: %w", p.Value, n.Line, n.Column, err)
}

if _, ok := ret[pat]; ok {
return fmt.Errorf("key duplicates within \"paths\" config: %q", pat)
}
ret[pat] = &cfg
rs = append(rs, r)
}
*cfgs = ret

*pats = rs
return nil
}

// PathConfig is a configuration for specific file path pattern. This is for values of the "paths" mapping
// in the configuration file.
type PathConfig struct {
// Ignore is a list of patterns. They are used for ignoring errors by matching to the error messages.
// It is similar to the "-ignore" command line option.
Ignore IgnorePatterns `yaml:"ignore"`
}

// Config is configuration of actionlint. This struct instance is parsed from "actionlint.yaml"
// file usually put in ".github" directory.
type Config struct {
Expand All @@ -111,8 +63,9 @@ type Config struct {
// listed here as undefined config variables.
// https://docs.github.com/en/actions/learn-github-actions/variables
ConfigVariables []string `yaml:"config-variables"`
// Paths is a "paths" mapping in the configuration file. See the document for PathConfigs for more details.
Paths PathConfigs `yaml:"paths"`
// Paths is a "paths" mapping in the configuration file. The keys are glob patterns to match file paths.
// And the values are corresponding configurations applied to the file paths.
Paths map[string]*PathConfig `yaml:"paths"`
}

// PathConfigsFor returns a list of all PathConfig values matching to the given file path. The path must
Expand All @@ -122,8 +75,11 @@ func (cfg *Config) PathConfigsFor(path string) []*PathConfig {

var ret []*PathConfig
if cfg != nil {
for _, c := range cfg.Paths {
if c.Matches(path) {
for p, c := range cfg.Paths {
if c == nil {
continue
}
if doublestar.MatchUnvalidated(p, path) {
ret = append(ret, c)
}
}
Expand All @@ -137,6 +93,11 @@ func parseConfig(b []byte, path string) (*Config, error) {
msg := strings.ReplaceAll(err.Error(), "\n", " ")
return nil, fmt.Errorf("could not parse config file %q: %s", path, msg)
}
for pat := range c.Paths {
if !doublestar.ValidatePattern(pat) {
return nil, fmt.Errorf("could not parse config file %q: invalid glob pattern %q in \"paths\"", path, pat)
}
}
return &c, nil
}

Expand Down
Loading

0 comments on commit ff10b3b

Please sign in to comment.