@@ -10,6 +10,50 @@ func AllReferencesFilter(_ Reference) bool {
1010 return true
1111}
1212
13+ type Polarity uint8
14+
15+ const (
16+ Include Polarity = iota
17+ Exclude
18+ )
19+
20+ // polarizedFilter is a filter that might match, in which case it
21+ // includes or excludes the reference (according to its polarity). If
22+ // it doesn't match, then it doesn't say anything about the reference.
23+ type polarizedFilter struct {
24+ polarity Polarity
25+ filter ReferenceFilter
26+ }
27+
28+ // IncludeExcludeFilter is a filter based on a bunch of
29+ // `polarizedFilter`s. The last one that matches a reference wins. If
30+ // none match, then the result is based on the polarity of the first
31+ // polarizedFilter: if it is `Include`, then return `false`; if it is
32+ // `Exclude`, then return `true`.
33+ type IncludeExcludeFilter struct {
34+ filters []polarizedFilter
35+ }
36+
37+ func (ief * IncludeExcludeFilter ) Include (f ReferenceFilter ) {
38+ ief .filters = append (ief .filters , polarizedFilter {Include , f })
39+ }
40+
41+ func (ief * IncludeExcludeFilter ) Exclude (f ReferenceFilter ) {
42+ ief .filters = append (ief .filters , polarizedFilter {Exclude , f })
43+ }
44+
45+ func (ief * IncludeExcludeFilter ) Filter (r Reference ) bool {
46+ for i := len (ief .filters ); i > 0 ; i -- {
47+ f := ief .filters [i - 1 ]
48+ if ! f .filter (r ) {
49+ continue
50+ }
51+ return f .polarity == Include
52+ }
53+
54+ return len (ief .filters ) == 0 || ief .filters [0 ].polarity == Exclude
55+ }
56+
1357// PrefixFilter returns a `ReferenceFilter` that matches references
1458// whose names start with the specified `prefix`, which must match at
1559// a component boundary. For example,
@@ -33,59 +77,7 @@ func PrefixFilter(prefix string) ReferenceFilter {
3377}
3478
3579var (
36- BranchesFilter ReferenceFilter = PrefixFilter ("refs/heads/" )
37- TagsFilter ReferenceFilter = PrefixFilter ("refs/tags/" )
38- RemotesFilter ReferenceFilter = PrefixFilter ("refs/remotes/" )
80+ BranchesFilter = PrefixFilter ("refs/heads/" )
81+ TagsFilter = PrefixFilter ("refs/tags/" )
82+ RemotesFilter = PrefixFilter ("refs/remotes/" )
3983)
40-
41- func notNilFilters (filters ... ReferenceFilter ) []ReferenceFilter {
42- var ret []ReferenceFilter
43- for _ , filter := range filters {
44- if filter != nil {
45- ret = append (ret , filter )
46- }
47- }
48- return ret
49- }
50-
51- func OrFilter (filters ... ReferenceFilter ) ReferenceFilter {
52- filters = notNilFilters (filters ... )
53- if len (filters ) == 0 {
54- return AllReferencesFilter
55- } else if len (filters ) == 1 {
56- return filters [0 ]
57- } else {
58- return func (r Reference ) bool {
59- for _ , filter := range filters {
60- if filter (r ) {
61- return true
62- }
63- }
64- return false
65- }
66- }
67- }
68-
69- func AndFilter (filters ... ReferenceFilter ) ReferenceFilter {
70- filters = notNilFilters (filters ... )
71- if len (filters ) == 0 {
72- return AllReferencesFilter
73- } else if len (filters ) == 1 {
74- return filters [0 ]
75- } else {
76- return func (r Reference ) bool {
77- for _ , filter := range filters {
78- if ! filter (r ) {
79- return false
80- }
81- }
82- return true
83- }
84- }
85- }
86-
87- func NotFilter (filter ReferenceFilter ) ReferenceFilter {
88- return func (r Reference ) bool {
89- return ! filter (r )
90- }
91- }
0 commit comments