-
Notifications
You must be signed in to change notification settings - Fork 190
/
matcher.go
139 lines (116 loc) · 2.83 KB
/
matcher.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package finder
import (
"bytes"
"github.com/gookit/goutil/fsutil"
)
// Matcher for match file path.
type Matcher interface {
// Apply check find elem. return False will skip this file.
Apply(elem Elem) bool
}
// MatcherFunc for match file info, return False will skip this file
type MatcherFunc func(elem Elem) bool
// Apply check file path. return False will skip this file.
func (fn MatcherFunc) Apply(elem Elem) bool {
return fn(elem)
}
// ------------------ Multi matcher wrapper ------------------
// MultiMatcher wrapper for multi matchers
type MultiMatcher struct {
Before Matcher
Matchers []Matcher
}
// Add matchers
func (mf *MultiMatcher) Add(fls ...Matcher) {
mf.Matchers = append(mf.Matchers, fls...)
}
// Apply check file path is match.
func (mf *MultiMatcher) Apply(el Elem) bool {
if mf.Before != nil && !mf.Before.Apply(el) {
return false
}
for _, fl := range mf.Matchers {
if !fl.Apply(el) {
return false
}
}
return true
}
// NewDirMatchers create a new dir matchers
func NewDirMatchers(fls ...Matcher) *MultiMatcher {
return &MultiMatcher{
Before: MatchDir,
Matchers: fls,
}
}
// NewFileMatchers create a new dir matchers
func NewFileMatchers(fls ...Matcher) *MultiMatcher {
return &MultiMatcher{
Before: MatchFile,
Matchers: fls,
}
}
// ------------------ Body Matcher ------------------
// BodyMatcher for match file contents.
type BodyMatcher interface {
Apply(filePath string, body *bytes.Buffer) bool
}
// BodyMatcherFunc for match file contents.
type BodyMatcherFunc func(filePath string, body *bytes.Buffer) bool
// Apply for match file contents.
func (fn BodyMatcherFunc) Apply(filePath string, body *bytes.Buffer) bool {
return fn(filePath, body)
}
// BodyMatchers multi body matchers as Matcher
type BodyMatchers struct {
Matchers []BodyMatcher
}
// NewBodyMatchers create a new body matchers
//
// Usage:
//
// bf := finder.NewBodyMatchers(
// finder.BodyMatcherFunc(func(filePath string, buf *bytes.Buffer) bool {
// // match file contents
// return true
// }),
// )
//
// es := finder.NewFinder('path/to/dir').Add(bf).Elems()
// for el := range es {
// fmt.Println(el.Path())
// }
func NewBodyMatchers(fls ...BodyMatcher) *BodyMatchers {
return &BodyMatchers{
Matchers: fls,
}
}
// AddMatcher add matchers
func (mf *BodyMatchers) AddMatcher(fls ...BodyMatcher) {
mf.Matchers = append(mf.Matchers, fls...)
}
// Apply check file contents is match.
func (mf *BodyMatchers) Apply(el Elem) bool {
if el.IsDir() {
return false
}
// read file contents
buf := bytes.NewBuffer(nil)
file, err := fsutil.OpenReadFile(el.Path())
if err != nil {
return false
}
_, err = buf.ReadFrom(file)
if err != nil {
file.Close()
return false
}
file.Close()
// apply matchers
for _, fl := range mf.Matchers {
if !fl.Apply(el.Path(), buf) {
return false
}
}
return true
}