forked from bmatcuk/doublestar
-
Notifications
You must be signed in to change notification settings - Fork 1
/
globoptions.go
151 lines (137 loc) · 4.41 KB
/
globoptions.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
140
141
142
143
144
145
146
147
148
149
150
151
package doublestar
import (
"strings"
"time"
)
// glob is an internal type to store options during globbing.
type glob struct {
failOnIOErrors bool
failOnPatternNotExist bool
filesOnly bool
noFollow bool
maxAge time.Duration
}
// GlobOption represents a setting that can be passed to Glob, GlobWalk, and
// FilepathGlob.
type GlobOption func(*glob)
// Construct a new glob object with the given options
func newGlob(opts ...GlobOption) *glob {
g := &glob{}
for _, opt := range opts {
opt(g)
}
return g
}
// WithFailOnIOErrors is an option that can be passed to Glob, GlobWalk, or
// FilepathGlob. If passed, doublestar will abort and return IO errors when
// encountered. Note that if the glob pattern references a path that does not
// exist (such as `nonexistent/path/*`), this is _not_ considered an IO error:
// it is considered a pattern with no matches.
func WithFailOnIOErrors() GlobOption {
return func(g *glob) {
g.failOnIOErrors = true
}
}
// WithFailOnPatternNotExist is an option that can be passed to Glob, GlobWalk,
// or FilepathGlob. If passed, doublestar will abort and return
// ErrPatternNotExist if the pattern references a path that does not exist
// before any meta charcters such as `nonexistent/path/*`. Note that alts (ie,
// `{...}`) are expanded before this check. In other words, a pattern such as
// `{a,b}/*` may fail if either `a` or `b` do not exist but `*/{a,b}` will
// never fail because the star may match nothing.
func WithFailOnPatternNotExist() GlobOption {
return func(g *glob) {
g.failOnPatternNotExist = true
}
}
// WithFilesOnly is an option that can be passed to Glob, GlobWalk, or
// FilepathGlob. If passed, doublestar will only return files that match the
// pattern, not directories.
//
// Note: if combined with the WithNoFollow option, symlinks to directories
// _will_ be included in the result since no attempt is made to follow the
// symlink.
func WithFilesOnly() GlobOption {
return func(g *glob) {
g.filesOnly = true
}
}
// WithNoFollow is an option that can be passed to Glob, GlobWalk, or
// FilepathGlob. If passed, doublestar will not follow symlinks while
// traversing the filesystem. However, due to io/fs's _very_ poor support for
// querying the filesystem about symlinks, there's a caveat here: if part of
// the pattern before any meta characters contains a reference to a symlink, it
// will be followed. For example, a pattern such as `path/to/symlink/*` will be
// followed assuming it is a valid symlink to a directory. However, from this
// same example, a pattern such as `path/to/**` will not traverse the
// `symlink`, nor would `path/*/symlink/*`
//
// Note: if combined with the WithFilesOnly option, symlinks to directories
// _will_ be included in the result since no attempt is made to follow the
// symlink.
func WithNoFollow() GlobOption {
return func(g *glob) {
g.noFollow = true
}
}
// WithMaxAge is an option that can be passed to Glob, GlobWalk, or
// FilepathGlob. If passed, doublestar will exclude all file which
// have modified time older than the age specified.
func WithMaxAge(age time.Duration) GlobOption {
return func(g *glob) {
g.maxAge = age
}
}
// forwardErrIfFailOnIOErrors is used to wrap the return values of I/O
// functions. When failOnIOErrors is enabled, it will return err; otherwise, it
// always returns nil.
func (g *glob) forwardErrIfFailOnIOErrors(err error) error {
if g.failOnIOErrors {
return err
}
return nil
}
// handleErrNotExist handles fs.ErrNotExist errors. If
// WithFailOnPatternNotExist has been enabled and canFail is true, this will
// return ErrPatternNotExist. Otherwise, it will return nil.
func (g *glob) handlePatternNotExist(canFail bool) error {
if canFail && g.failOnPatternNotExist {
return ErrPatternNotExist
}
return nil
}
// Format options for debugging/testing purposes
func (g *glob) GoString() string {
var b strings.Builder
b.WriteString("opts: ")
hasOpts := false
if g.failOnIOErrors {
b.WriteString("WithFailOnIOErrors")
hasOpts = true
}
if g.failOnPatternNotExist {
if hasOpts {
b.WriteString(", ")
}
b.WriteString("WithFailOnPatternNotExist")
hasOpts = true
}
if g.filesOnly {
if hasOpts {
b.WriteString(", ")
}
b.WriteString("WithFilesOnly")
hasOpts = true
}
if g.noFollow {
if hasOpts {
b.WriteString(", ")
}
b.WriteString("WithNoFollow")
hasOpts = true
}
if !hasOpts {
b.WriteString("nil")
}
return b.String()
}