f52ea2a708
--- type: change description: |- Rework how FilterFilesChanged works Previously the filter would only match if _all_ files changed matched a pattern within it. This ends up not being very useful, as usually the filter is being used to guard a specific set of content within the project, and so it's a lot more useful to have the filter match if _any_ files changed matched a pattern. fingerprint: AFSaaPVOBsFYc0D3JQd0M7yJKDiS8/VjAsppPXTngGPb credentials: - type: pgp_signature pub_key_id: 95C46FA6A41148AC body: iQIzBAABAgAdFiEEJ6tQKp6olvZKJ0lwlcRvpqQRSKwFAl63Q/oACgkQlcRvpqQRSKxHew//QO74joMfwg+mCiSKjXRbTidYW/ILr3mspFSLMYS5RKcf2YQNpYOP24a7BINe5LQYXGAOEH7PxEWOTTJTzwv90/T/jmYwJJMuNRa3NHXfCRS63i7L2b4nWSEATPQlGZRaMLOOsYdg2m/mcEQuHgf+fmfd4iRGFJHDzxj4etcfD/cHi9fg8Assr7E8K9xoYp3vs/8cPWGP16p94LHmsu5m8pt990Bn4XzxUzHAseyjPgs3OElH67SqW9D9F2PHZvdmCo58bvt13otzn137jwf/EZQOkcOWXxaOxNG8bqZFWgFGUEQajgXYLwfPULC4J3c1Rj+umAT0R1QPzj0h2MIoE/gM1wbw5fwtIfCpM9pA526TFJfdujvYY4x8oPMve9hTQ0FZ9Vv1cTCrOWo5vVNjum0jY58GGr9/I+PXupstDmGnKHnwivz459YNq0Uuyir3KgyM8fY7rTf+FQslrv7Hafnrju3KqCvCoHT0nNj0dWVen5RFK6dee4fsYvGK8ujKYCJpwm+3/0ggJOCC3XsMOCCh/F/YMvq4Xtwo7AbNIrVPOSIAnu2khkybInmZGmIVEP4E6MWfVzjb4wVVocqYhhuHg09IDeBv9WS5s3KBUVL4RNYadrUXMOs4W7wXvHILSYx87j0UJfy9bUfALwclXaFuhBYzghbBQVN3L00ASaw= account: mediocregopher
97 lines
2.6 KiB
Go
97 lines
2.6 KiB
Go
package accessctl
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/bmatcuk/doublestar"
|
|
)
|
|
|
|
// StringMatcher is used to match against a string. It can use one of several
|
|
// methods to match. Only one field should be filled at a time.
|
|
type StringMatcher struct {
|
|
// Pattern, if set, indicates that the Match method should succeed if this
|
|
// doublestar pattern matches against the string.
|
|
Pattern string `yaml:"pattern,omitempty"`
|
|
|
|
// Patterns, if set, indicates that the Match method should succeed if at
|
|
// least one of these doublestar patterns matches against the string.
|
|
Patterns []string `yaml:"patterns,omitempty"`
|
|
}
|
|
|
|
func doublestarMatch(pattern, str string) (bool, error) {
|
|
ok, err := doublestar.Match(pattern, str)
|
|
if err != nil {
|
|
return false, fmt.Errorf("matching %q on pattern %q: %w",
|
|
str, pattern, err)
|
|
}
|
|
return ok, nil
|
|
}
|
|
|
|
// Match operates similarly to the Match method of the FilterInterface, except
|
|
// it only takes in strings.
|
|
func (m StringMatcher) Match(str string) error {
|
|
switch {
|
|
case m.Pattern != "":
|
|
if ok, err := doublestarMatch(m.Pattern, str); err != nil {
|
|
return err
|
|
} else if !ok {
|
|
return ErrFilterNoMatch{
|
|
Err: fmt.Errorf("pattern %q does not match %q", m.Pattern, str),
|
|
}
|
|
}
|
|
return nil
|
|
|
|
case len(m.Patterns) > 0:
|
|
for _, pattern := range m.Patterns {
|
|
if ok, err := doublestarMatch(pattern, str); err != nil {
|
|
return err
|
|
} else if ok {
|
|
return nil
|
|
}
|
|
}
|
|
return ErrFilterNoMatch{
|
|
Err: fmt.Errorf("no patterns in %+v match %q", m.Patterns, str),
|
|
}
|
|
|
|
default:
|
|
return errors.New(`one of the following fields must be set: "pattern", "patterns"`)
|
|
}
|
|
}
|
|
|
|
// FilterBranch matches a CommitRequest's Branch field using a double-star
|
|
// pattern.
|
|
type FilterBranch struct {
|
|
StringMatcher StringMatcher `yaml:",inline"`
|
|
}
|
|
|
|
var _ Filter = FilterBranch{}
|
|
|
|
// MatchCommit implements the method for FilterInterface.
|
|
func (f FilterBranch) MatchCommit(req CommitRequest) error {
|
|
return f.StringMatcher.Match(req.Branch)
|
|
}
|
|
|
|
// FilterFilesChanged matches a CommitRequest's FilesChanged field using a
|
|
// double-star pattern. It only matches if all of the CommitRequest's
|
|
// FilesChanged match.
|
|
type FilterFilesChanged struct {
|
|
StringMatcher StringMatcher `yaml:",inline"`
|
|
}
|
|
|
|
var _ Filter = FilterFilesChanged{}
|
|
|
|
// MatchCommit implements the method for FilterInterface.
|
|
func (f FilterFilesChanged) MatchCommit(req CommitRequest) error {
|
|
for _, path := range req.FilesChanged {
|
|
if err := f.StringMatcher.Match(path); errors.As(err, new(ErrFilterNoMatch)) {
|
|
continue
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
return ErrFilterNoMatch{Err: errors.New("no paths matched")}
|
|
}
|