@@ -10,6 +10,24 @@ import (
10
10
"strings"
11
11
)
12
12
13
+ type parseOption func (* parseOptions )
14
+
15
+ type parseOptions struct {
16
+ ownerMatchers []OwnerMatcher
17
+ }
18
+
19
+ func WithOwnerMatchers (mm []OwnerMatcher ) parseOption {
20
+ return func (opts * parseOptions ) {
21
+ opts .ownerMatchers = mm
22
+ }
23
+ }
24
+
25
+ type OwnerMatcher interface {
26
+ // Matches give string agains a pattern e.g. a regexp.
27
+ // Should return ErrNoMatch if the pattern doesn't match.
28
+ Match (s string ) (Owner , error )
29
+ }
30
+
13
31
type ErrInvalidOwnerFormat struct {
14
32
Owner string
15
33
}
@@ -26,30 +44,19 @@ var (
26
44
usernameRegexp = regexp .MustCompile (`\A@([a-zA-Z0-9\-]+)\z` )
27
45
)
28
46
29
- const (
30
- statePattern = iota + 1
31
- stateOwners
32
- )
33
-
34
- var DefaultMatchers = []Matcher {
35
- MatcherFunc (MatchEmail ),
36
- MatcherFunc (MatchTeam ),
37
- MatcherFunc (MatchUsername ),
38
- }
39
-
40
- type Matcher interface {
41
- // Matches give string agains a pattern e.g. a regexp.
42
- // Should return ErrNoMatch if the pattern doesn't match.
43
- Match (s string ) (Owner , error )
47
+ var DefaultOwnerMatchers = []OwnerMatcher {
48
+ OwnerMatchFunc (MatchEmailOwner ),
49
+ OwnerMatchFunc (MatchTeamOwner ),
50
+ OwnerMatchFunc (MatchUsernameOwner ),
44
51
}
45
52
46
- type MatcherFunc func (s string ) (Owner , error )
53
+ type OwnerMatchFunc func (s string ) (Owner , error )
47
54
48
- func (f MatcherFunc ) Match (s string ) (Owner , error ) {
55
+ func (f OwnerMatchFunc ) Match (s string ) (Owner , error ) {
49
56
return f (s )
50
57
}
51
58
52
- func MatchEmail (s string ) (Owner , error ) {
59
+ func MatchEmailOwner (s string ) (Owner , error ) {
53
60
match := emailRegexp .FindStringSubmatch (s )
54
61
if match == nil {
55
62
return Owner {}, ErrNoMatch
@@ -58,7 +65,7 @@ func MatchEmail(s string) (Owner, error) {
58
65
return Owner {Value : match [0 ], Type : EmailOwner }, nil
59
66
}
60
67
61
- func MatchTeam (s string ) (Owner , error ) {
68
+ func MatchTeamOwner (s string ) (Owner , error ) {
62
69
match := teamRegexp .FindStringSubmatch (s )
63
70
if match == nil {
64
71
return Owner {}, ErrNoMatch
@@ -67,7 +74,7 @@ func MatchTeam(s string) (Owner, error) {
67
74
return Owner {Value : match [1 ], Type : TeamOwner }, nil
68
75
}
69
76
70
- func MatchUsername (s string ) (Owner , error ) {
77
+ func MatchUsernameOwner (s string ) (Owner , error ) {
71
78
match := usernameRegexp .FindStringSubmatch (s )
72
79
if match == nil {
73
80
return Owner {}, ErrNoMatch
@@ -76,9 +83,14 @@ func MatchUsername(s string) (Owner, error) {
76
83
return Owner {Value : match [1 ], Type : UsernameOwner }, nil
77
84
}
78
85
79
- // ParseFile parses a CODEOWNERS file and Matcher, returning a set of rules.
80
- // If no Matchers are passed explicitly the DefaultMatchers are used.
81
- func ParseFile (f io.Reader , mm ... Matcher ) (Ruleset , error ) {
86
+ // ParseFile parses a CODEOWNERS file, returning a set of rules.
87
+ // To override the default owner matchers, pass WithOwnerMatchers() as an option.
88
+ func ParseFile (f io.Reader , options ... parseOption ) (Ruleset , error ) {
89
+ opts := parseOptions {ownerMatchers : DefaultOwnerMatchers }
90
+ for _ , opt := range options {
91
+ opt (& opts )
92
+ }
93
+
82
94
rules := Ruleset {}
83
95
scanner := bufio .NewScanner (f )
84
96
lineNo := 0
@@ -91,7 +103,7 @@ func ParseFile(f io.Reader, mm ...Matcher) (Ruleset, error) {
91
103
continue
92
104
}
93
105
94
- rule , err := parseRule (line , mm )
106
+ rule , err := parseRule (line , opts )
95
107
if err != nil {
96
108
return nil , fmt .Errorf ("line %d: %w" , lineNo , err )
97
109
}
@@ -101,8 +113,13 @@ func ParseFile(f io.Reader, mm ...Matcher) (Ruleset, error) {
101
113
return rules , nil
102
114
}
103
115
116
+ const (
117
+ statePattern = iota + 1
118
+ stateOwners
119
+ )
120
+
104
121
// parseRule parses a single line of a CODEOWNERS file, returning a Rule struct
105
- func parseRule (ruleStr string , mm [] Matcher ) (Rule , error ) {
122
+ func parseRule (ruleStr string , opts parseOptions ) (Rule , error ) {
106
123
r := Rule {}
107
124
108
125
state := statePattern
@@ -152,7 +169,7 @@ func parseRule(ruleStr string, mm []Matcher) (Rule, error) {
152
169
// through whitespace before or after owner declarations
153
170
if buf .Len () > 0 {
154
171
ownerStr := buf .String ()
155
- owner , err := newOwner (ownerStr , mm )
172
+ owner , err := newOwner (ownerStr , opts . ownerMatchers )
156
173
if err != nil {
157
174
return r , fmt .Errorf ("%w at position %d" , err , i + 1 - len (ownerStr ))
158
175
}
@@ -188,7 +205,7 @@ func parseRule(ruleStr string, mm []Matcher) (Rule, error) {
188
205
// If there's an owner left in the buffer, don't leave it behind
189
206
if buf .Len () > 0 {
190
207
ownerStr := buf .String ()
191
- owner , err := newOwner (ownerStr , mm )
208
+ owner , err := newOwner (ownerStr , opts . ownerMatchers )
192
209
if err != nil {
193
210
return r , fmt .Errorf ("%s at position %d" , err .Error (), len (ruleStr )+ 1 - len (ownerStr ))
194
211
}
@@ -200,11 +217,7 @@ func parseRule(ruleStr string, mm []Matcher) (Rule, error) {
200
217
}
201
218
202
219
// newOwner figures out which kind of owner this is and returns an Owner struct
203
- func newOwner (s string , mm []Matcher ) (Owner , error ) {
204
- if len (mm ) == 0 {
205
- mm = DefaultMatchers
206
- }
207
-
220
+ func newOwner (s string , mm []OwnerMatcher ) (Owner , error ) {
208
221
for _ , m := range mm {
209
222
o , err := m .Match (s )
210
223
if errors .Is (err , ErrNoMatch ) {
0 commit comments