diff --git a/match.go b/match.go index 4c34638..69fcd05 100644 --- a/match.go +++ b/match.go @@ -157,6 +157,9 @@ func buildPatternRegex(pattern string) (*regexp.Regexp, error) { case '?': // Single-character wildcard re.WriteString(`[^` + sep + `]`) + case '[', ']': + // Escape square brackets to treat them as literal characters + re.WriteString(`\` + string(ch)) default: // Regular character re.WriteString(regexp.QuoteMeta(string(ch))) diff --git a/parse.go b/parse.go index 8c95a57..7969c6e 100644 --- a/parse.go +++ b/parse.go @@ -257,7 +257,7 @@ func isAlphanumeric(ch rune) bool { // isPatternChar matches characters that are allowed in patterns func isPatternChar(ch rune) bool { switch ch { - case '*', '?', '.', '/', '@', '_', '+', '-', ':', '\\', '(', ')', '|', '{', '}', '~': + case '*', '?', '.', '/', '@', '_', '+', '-', ':', '\\', '(', ')', '|', '{', '}', '[', ']', '~': return true } return isAlphanumeric(ch) diff --git a/parse_test.go b/parse_test.go index 2ea1a31..9d9d751 100644 --- a/parse_test.go +++ b/parse_test.go @@ -304,11 +304,6 @@ func TestParseRule(t *testing.T) { rule: "", err: "unexpected end of rule", }, - { - name: "patterns with brackets", - rule: "file.[cC] @user", - err: "unexpected character '[' at position 6", - }, { name: "malformed owners", rule: "file.txt missing-at-sign", diff --git a/testdata/patterns.json b/testdata/patterns.json index 13846b1..9dd2be0 100644 --- a/testdata/patterns.json +++ b/testdata/patterns.json @@ -306,6 +306,16 @@ "foo/qux/bar/qux": false } }, + { + "name": "pattern with square brackets", + "pattern": "/apps/[param]/file.ts", + "paths": { + "apps/[param]/file.ts": true, + "apps/other/file.ts": false, + "apps/[other]/file.ts": false, + "apps/param/file.ts": false + } + }, { "name": "pattern with colon", "pattern": "services/foo:bar/**/*",