diff --git a/SPEC.md b/SPEC.md index d456540..9c3ffe1 100644 --- a/SPEC.md +++ b/SPEC.md @@ -337,10 +337,7 @@ changed between the tree of the commit's parent and the commit's tree. Matching is performed on the paths of the changed files, relative to the repo root. A files changed filter can have one or multiple patterns defined. The filter -will match if at least one defined pattern matches for every file changed. - -(TODO this may change to be: `The filter will match if any of the changed files -matches at least one defined pattern.`) +will match if any of the changed files matches at least one defined pattern. A files changed filter with only one pattern can be defined like this: diff --git a/accessctl/filter_pattern.go b/accessctl/filter_pattern.go index 26ca1cd..648f804 100644 --- a/accessctl/filter_pattern.go +++ b/accessctl/filter_pattern.go @@ -84,9 +84,13 @@ 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); err != nil { + if err := f.StringMatcher.Match(path); errors.As(err, new(ErrFilterNoMatch)) { + continue + } else if err != nil { return err } + return nil } - return nil + + return ErrFilterNoMatch{Err: errors.New("no paths matched")} } diff --git a/accessctl/filter_pattern_test.go b/accessctl/filter_pattern_test.go index 700508f..96f0878 100644 --- a/accessctl/filter_pattern_test.go +++ b/accessctl/filter_pattern_test.go @@ -132,3 +132,68 @@ func TestStringMatcher(t *testing.T) { }) } } + +func TestFilterFilesChanged(t *testing.T) { + mkReq := func(paths ...string) CommitRequest { + return CommitRequest{FilesChanged: paths} + } + + runCommitMatchTests(t, []filterCommitMatchTest{ + { + descr: "no paths", + filter: FilterFilesChanged{ + StringMatcher: StringMatcher{Pattern: "foo"}, + }, + req: mkReq(), + match: false, + }, + { + descr: "all paths against one pattern", + filter: FilterFilesChanged{ + StringMatcher: StringMatcher{Pattern: "foo/*"}, + }, + req: mkReq("foo/bar", "foo/baz"), + match: true, + }, + { + descr: "all paths against multiple patterns", + filter: FilterFilesChanged{ + StringMatcher: StringMatcher{Patterns: []string{"foo", "bar"}}, + }, + req: mkReq("foo", "bar"), + match: true, + }, + { + descr: "some paths against one pattern", + filter: FilterFilesChanged{ + StringMatcher: StringMatcher{Pattern: "foo"}, + }, + req: mkReq("foo", "bar"), + match: true, + }, + { + descr: "some paths against many patterns", + filter: FilterFilesChanged{ + StringMatcher: StringMatcher{Patterns: []string{"foo", "bar"}}, + }, + req: mkReq("foo", "baz"), + match: true, + }, + { + descr: "no paths against one pattern", + filter: FilterFilesChanged{ + StringMatcher: StringMatcher{Pattern: "foo"}, + }, + req: mkReq("baz", "buz"), + match: false, + }, + { + descr: "no paths against many patterns", + filter: FilterFilesChanged{ + StringMatcher: StringMatcher{Patterns: []string{"foo", "bar"}}, + }, + req: mkReq("baz", "buz"), + match: false, + }, + }) +} diff --git a/accessctl/filter_test.go b/accessctl/filter_test.go index f6edcfa..6e3606e 100644 --- a/accessctl/filter_test.go +++ b/accessctl/filter_test.go @@ -12,8 +12,8 @@ type filterCommitMatchTest struct { req CommitRequest match bool - // assumes match == true, and will ensure that the returned wrapped error is - // this one. + // assumes match == false, and will ensure that the returned wrapped error + // is this one. matchErr error } @@ -29,7 +29,7 @@ func runCommitMatchTests(t *testing.T, tests []filterCommitMatchTest) { return } else if fErr := new(ErrFilterNoMatch); !errors.As(err, fErr) { - t.Fatalf("expected ErrFilterNoMatch, got %#v", err) + t.Fatalf("expected ErrFilterNoMatch, got: %#v", err) } else if test.matchErr != nil && !reflect.DeepEqual(fErr.Err, test.matchErr) { t.Fatalf("expected err %#v, not %#v", test.matchErr, fErr.Err)