From 067bd83d36ff1ea86d29f422417fc1a96b8c3dcd Mon Sep 17 00:00:00 2001 From: Luke Massa Date: Thu, 23 Jan 2025 17:50:31 -0500 Subject: [PATCH 1/3] Add ability to compile a pattern --- doublestar_test.go | 23 +++++++++++++++++++++++ match.go | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/doublestar_test.go b/doublestar_test.go index 3962ab5..693e824 100644 --- a/doublestar_test.go +++ b/doublestar_test.go @@ -236,6 +236,29 @@ func TestMatch(t *testing.T) { } } +func TestCompile(t *testing.T) { + for idx, tt := range matchTests { + testCompileWith(t, idx, tt) + } +} + +func testCompileWith(t *testing.T, idx int, tt MatchTest) { + defer func() { + if r := recover(); r != nil { + t.Errorf("#%v. Match(%#q, %#q) panicked: %#v", idx, tt.pattern, tt.testPath, r) + } + }() + + ok := false + pat, err := Compile(tt.pattern) + if err == nil { + ok = pat.Match(tt.testPath) + } + if ok != tt.shouldMatch || err != tt.expectedErr { + t.Errorf("#%v. Match(%#q, %#q) = %v, %v want %v, %v", idx, tt.pattern, tt.testPath, ok, err, tt.shouldMatch, tt.expectedErr) + } +} + func testMatchWith(t *testing.T, idx int, tt MatchTest) { defer func() { if r := recover(); r != nil { diff --git a/match.go b/match.go index a21259d..66d5a0f 100644 --- a/match.go +++ b/match.go @@ -89,6 +89,46 @@ func PathMatchUnvalidated(pattern, name string) bool { return matched } +// Pattern is a representation of a compiled glob pattern. +type Pattern struct { + // initial implementation doesn't actually "compile", just saves the pattern to use when matching + // Obviously long term we'll want to store some kind of tree or something + pattern string +} + +// Compile parses a pattern and returns, if successful, a [Pattern] object +// that can be used to match against text. +func Compile(pattern string) (*Pattern, error) { + if !ValidatePattern(pattern) { + return nil, ErrBadPattern + } + return &Pattern{ + pattern: pattern, + }, nil +} + +// MustCompile is like Compile but panics if the expression cannot be parsed. +func MustCompile(pattern string) *Pattern { + + p, err := Compile(pattern) + if err != nil { + panic(err) + } + return p +} + +// Match reports whether the name matches this pattern +func (p *Pattern) Match(name string) bool { + matches, err := Match(p.pattern, name) + // This shouldn't be able to happen, since we validated the pattern already + // When this function is converted to actually doing a match instead of calling Match() + // on the initial pattern, this can go away + if err != nil { + panic(err) + } + return matches +} + func matchWithSeparator(pattern, name string, separator rune, validate bool) (matched bool, err error) { return doMatchWithSeparator(pattern, name, separator, validate, -1, -1, -1, -1, 0, 0) } From 3cf2709dfe604fae7295bc902d48f7e0bf47d15a Mon Sep 17 00:00:00 2001 From: Luke Massa Date: Fri, 24 Jan 2025 14:17:54 -0500 Subject: [PATCH 2/3] Use unvalidated matcher --- match.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/match.go b/match.go index 66d5a0f..045388c 100644 --- a/match.go +++ b/match.go @@ -119,14 +119,7 @@ func MustCompile(pattern string) *Pattern { // Match reports whether the name matches this pattern func (p *Pattern) Match(name string) bool { - matches, err := Match(p.pattern, name) - // This shouldn't be able to happen, since we validated the pattern already - // When this function is converted to actually doing a match instead of calling Match() - // on the initial pattern, this can go away - if err != nil { - panic(err) - } - return matches + return MatchUnvalidated(p.pattern, name) } func matchWithSeparator(pattern, name string, separator rune, validate bool) (matched bool, err error) { From 15cbf42f5675c4d8f22bd0386ef1802bebf47178 Mon Sep 17 00:00:00 2001 From: Luke Massa Date: Fri, 24 Jan 2025 14:30:51 -0500 Subject: [PATCH 3/3] Add standard tests to compiled pattern --- doublestar_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doublestar_test.go b/doublestar_test.go index 693e824..503d4a7 100644 --- a/doublestar_test.go +++ b/doublestar_test.go @@ -257,6 +257,13 @@ func testCompileWith(t *testing.T, idx int, tt MatchTest) { if ok != tt.shouldMatch || err != tt.expectedErr { t.Errorf("#%v. Match(%#q, %#q) = %v, %v want %v, %v", idx, tt.pattern, tt.testPath, ok, err, tt.shouldMatch, tt.expectedErr) } + + if tt.isStandard { + stdOk, stdErr := path.Match(tt.pattern, tt.testPath) + if ok != stdOk || !compareErrors(err, stdErr) { + t.Errorf("#%v. Match(%#q, %#q) != path.Match(...). Got %v, %v want %v, %v", idx, tt.pattern, tt.testPath, ok, err, stdOk, stdErr) + } + } } func testMatchWith(t *testing.T, idx int, tt MatchTest) {