filepathfilter: teach AllowsPattern, to return the pattern that matched

This commit is contained in:
Taylor Blau 2017-06-20 17:34:44 -06:00
parent f7ab3c3ef3
commit f465ae4f83
2 changed files with 92 additions and 55 deletions

@ -28,12 +28,24 @@ func New(include, exclude []string) *Filter {
}
func (f *Filter) Allows(filename string) bool {
_, allowed := f.AllowsPattern(filename)
return allowed
}
// AllowsPattern returns whether the given filename is permitted by the
// inclusion/exclusion rules of this filter, as well as the pattern that either
// allowed or disallowed that filename.
//
// In special cases, such as a nil `*Filter` receiver, the absence of any
// patterns, or the given filename not being matched by any pattern, the empty
// string "" will be returned in place of the pattern.
func (f *Filter) AllowsPattern(filename string) (pattern string, allowed bool) {
if f == nil {
return true
return "", true
}
if len(f.include)+len(f.exclude) == 0 {
return true
return "", true
}
cleanedName := filepath.Clean(filename)
@ -43,23 +55,24 @@ func (f *Filter) Allows(filename string) bool {
for _, inc := range f.include {
matched = inc.Match(cleanedName)
if matched {
pattern = inc.String()
break
}
}
if !matched {
return false
return "", false
}
}
if len(f.exclude) > 0 {
for _, ex := range f.exclude {
if ex.Match(cleanedName) {
return false
return ex.String(), false
}
}
}
return true
return pattern, true
}
func NewPattern(rawpattern string) Pattern {

@ -105,66 +105,78 @@ func patternMatch(pattern, filename string) bool {
}
type filterTest struct {
expectedResult bool
includes []string
excludes []string
expectedResult bool
expectedPattern string
includes []string
excludes []string
}
func TestFilterAllows(t *testing.T) {
cases := []filterTest{
// Null case
filterTest{true, nil, nil},
filterTest{true, "", nil, nil},
// Inclusion
filterTest{true, []string{"*.dat"}, nil},
filterTest{true, []string{"file*.dat"}, nil},
filterTest{true, []string{"file*"}, nil},
filterTest{true, []string{"*name.dat"}, nil},
filterTest{false, []string{"/*.dat"}, nil},
filterTest{false, []string{"otherfolder/*.dat"}, nil},
filterTest{false, []string{"*.nam"}, nil},
filterTest{true, []string{"test/filename.dat"}, nil},
filterTest{true, []string{"test/filename.dat"}, nil},
filterTest{false, []string{"blank", "something", "foo"}, nil},
filterTest{false, []string{"test/notfilename.dat"}, nil},
filterTest{true, []string{"test"}, nil},
filterTest{true, []string{"test/*"}, nil},
filterTest{false, []string{"nottest"}, nil},
filterTest{false, []string{"nottest/*"}, nil},
filterTest{true, []string{"test/fil*"}, nil},
filterTest{false, []string{"test/g*"}, nil},
filterTest{true, []string{"tes*/*"}, nil},
filterTest{true, []string{"[Tt]est/[Ff]ilename.dat"}, nil},
filterTest{true, "*.dat", []string{"*.dat"}, nil},
filterTest{true, "file*.dat", []string{"file*.dat"}, nil},
filterTest{true, "file*", []string{"file*"}, nil},
filterTest{true, "*name.dat", []string{"*name.dat"}, nil},
filterTest{false, "", []string{"/*.dat"}, nil},
filterTest{false, "", []string{"otherfolder/*.dat"}, nil},
filterTest{false, "", []string{"*.nam"}, nil},
filterTest{true, "test/filename.dat", []string{"test/filename.dat"}, nil},
filterTest{true, "test/filename.dat", []string{"test/filename.dat"}, nil},
filterTest{false, "", []string{"blank", "something", "foo"}, nil},
filterTest{false, "", []string{"test/notfilename.dat"}, nil},
filterTest{true, "test", []string{"test"}, nil},
filterTest{true, "test/*", []string{"test/*"}, nil},
filterTest{false, "", []string{"nottest"}, nil},
filterTest{false, "", []string{"nottest/*"}, nil},
filterTest{true, "test/fil*", []string{"test/fil*"}, nil},
filterTest{false, "", []string{"test/g*"}, nil},
filterTest{true, "tes*/*", []string{"tes*/*"}, nil},
filterTest{true, "[Tt]est/[Ff]ilename.dat", []string{"[Tt]est/[Ff]ilename.dat"}, nil},
// Exclusion
filterTest{false, nil, []string{"*.dat"}},
filterTest{false, nil, []string{"file*.dat"}},
filterTest{false, nil, []string{"file*"}},
filterTest{false, nil, []string{"*name.dat"}},
filterTest{true, nil, []string{"/*.dat"}},
filterTest{true, nil, []string{"otherfolder/*.dat"}},
filterTest{false, nil, []string{"test/filename.dat"}},
filterTest{false, nil, []string{"blank", "something", "test/filename.dat", "foo"}},
filterTest{true, nil, []string{"blank", "something", "foo"}},
filterTest{true, nil, []string{"test/notfilename.dat"}},
filterTest{false, nil, []string{"test"}},
filterTest{false, nil, []string{"test/*"}},
filterTest{true, nil, []string{"nottest"}},
filterTest{true, nil, []string{"nottest/*"}},
filterTest{false, nil, []string{"test/fil*"}},
filterTest{true, nil, []string{"test/g*"}},
filterTest{false, nil, []string{"tes*/*"}},
filterTest{false, nil, []string{"[Tt]est/[Ff]ilename.dat"}},
filterTest{false, "*.dat", nil, []string{"*.dat"}},
filterTest{false, "file*.dat", nil, []string{"file*.dat"}},
filterTest{false, "file*", nil, []string{"file*"}},
filterTest{false, "*name.dat", nil, []string{"*name.dat"}},
filterTest{true, "", nil, []string{"/*.dat"}},
filterTest{true, "", nil, []string{"otherfolder/*.dat"}},
filterTest{false, "test/filename.dat", nil, []string{"test/filename.dat"}},
filterTest{false, "test/filename.dat", nil, []string{"blank", "something", "test/filename.dat", "foo"}},
filterTest{true, "", nil, []string{"blank", "something", "foo"}},
filterTest{true, "", nil, []string{"test/notfilename.dat"}},
filterTest{false, "test", nil, []string{"test"}},
filterTest{false, "test/*", nil, []string{"test/*"}},
filterTest{true, "", nil, []string{"nottest"}},
filterTest{true, "", nil, []string{"nottest/*"}},
filterTest{false, "test/fil*", nil, []string{"test/fil*"}},
filterTest{true, "", nil, []string{"test/g*"}},
filterTest{false, "tes*/*", nil, []string{"tes*/*"}},
filterTest{false, "[Tt]est/[Ff]ilename.dat", nil, []string{"[Tt]est/[Ff]ilename.dat"}},
// Both
filterTest{true, []string{"test/filename.dat"}, []string{"test/notfilename.dat"}},
filterTest{false, []string{"test"}, []string{"test/filename.dat"}},
filterTest{true, []string{"test/*"}, []string{"test/notfile*"}},
filterTest{false, []string{"test/*"}, []string{"test/file*"}},
filterTest{false, []string{"another/*", "test/*"}, []string{"test/notfilename.dat", "test/filename.dat"}},
// // Both
filterTest{true, "test/filename.dat", []string{"test/filename.dat"}, []string{"test/notfilename.dat"}},
filterTest{false, "test/filename.dat", []string{"test"}, []string{"test/filename.dat"}},
filterTest{true, "test/*", []string{"test/*"}, []string{"test/notfile*"}},
filterTest{false, "test/file*", []string{"test/*"}, []string{"test/file*"}},
filterTest{false, "test/filename.dat", []string{"another/*", "test/*"}, []string{"test/notfilename.dat", "test/filename.dat"}},
}
for _, c := range cases {
result := New(c.includes, c.excludes).Allows("test/filename.dat")
assert.Equal(t, c.expectedResult, result, "includes: %v excludes: %v", c.includes, c.excludes)
filter := New(c.includes, c.excludes)
r1 := filter.Allows("test/filename.dat")
pattern, r2 := filter.AllowsPattern("test/filename.dat")
assert.Equal(t, r1, r2,
"filepathfilter: expected Allows() and AllowsPattern() to return identical result")
assert.Equal(t, c.expectedResult, r2, "includes: %v excludes: %v", c.includes, c.excludes)
assert.Equal(t, c.expectedPattern, pattern,
"filepathfilter: expected pattern match of: %q, got: %q",
c.expectedPattern, pattern)
if runtime.GOOS == "windows" {
// also test with \ path separators, tolerate mixed separators
for i, inc := range c.includes {
@ -173,7 +185,19 @@ func TestFilterAllows(t *testing.T) {
for i, ex := range c.excludes {
c.excludes[i] = strings.Replace(ex, "/", "\\", -1)
}
assert.Equal(t, c.expectedResult, New(c.includes, c.excludes).Allows("test/filename.dat"), c)
filter = New(c.includes, c.excludes)
r1 = filter.Allows("test/filename.dat")
pattern, r2 = filter.AllowsPattern("test/filename.dat")
assert.Equal(t, r1, r2,
"filepathfilter: expected Allows() and AllowsPattern() to return identical result")
assert.Equal(t, c.expectedResult, r1, c)
assert.Equal(t, c.expectedPattern, pattern,
"filepathfilter: expected pattern match of: %q, got: %q",
c.expectedPattern, pattern)
}
}
}