Skip to content

Commit

Permalink
Merge branch 'simplesurance-fail_on_io_errors'
Browse files Browse the repository at this point in the history
  • Loading branch information
bmatcuk committed Oct 31, 2022
2 parents 80d72e7 + caa3af3 commit cd84160
Show file tree
Hide file tree
Showing 7 changed files with 326 additions and 278 deletions.
42 changes: 33 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,19 +105,35 @@ that both `pattern` and `name` are using the system's path separator. If you
can't be sure of that, use `filepath.ToSlash()` on both `pattern` and `name`,
and then use the `Match()` function instead.

### GlobOption

Options that may be passed to `Glob`, `GlobWalk`, or `FilepathGlob`. Any number
of options may be passed to these functions, and in any order, as the last
argument(s).

```go
WithFailOnIOErrors()
```

If passed, it enables aborting and returning the error when an IO error is
encountered.

### Glob

```go
func Glob(fsys fs.FS, pattern string) ([]string, error)
func Glob(fsys fs.FS, pattern string, opts ...GlobOption) ([]string, error)
```

Glob returns the names of all files matching pattern or nil if there is no
matching file. The syntax of patterns is the same as in `Match()`. The pattern
may describe hierarchical names such as `usr/*/bin/ed`.
Glob ignores file system errors such as I/O errors reading directories. The
only possible returned error is `ErrBadPattern`, reporting that the pattern is
malformed.
Glob ignores file system errors such as I/O errors reading directories by
default. The only possible returned error is `ErrBadPattern`, reporting that
the pattern is malformed.
To enable aborting on I/O errors, the `WithFailOnIOErrors` option can be
passed.
Note: this is meant as a drop-in replacement for `io/fs.Glob()`. Like
`io/fs.Glob()`, this function assumes that your pattern uses `/` as the path
Expand Down Expand Up @@ -157,8 +173,13 @@ will skip the current directory. This means that if the current path _is_ a
directory, GlobWalk will not recurse into it. If the current path is not a
directory, the rest of the parent directory will be skipped.

GlobWalk ignores file system errors such as I/O errors reading directories.
GlobWalk may return `ErrBadPattern`, reporting that the pattern is malformed.
GlobWalk ignores file system errors such as I/O errors reading directories by
default. GlobWalk may return `ErrBadPattern`, reporting that the pattern is
malformed.

To enable aborting on I/O errors, the `WithFailOnIOErrors` option can be
passed.

Additionally, if the callback function `fn` returns an error, GlobWalk will
exit immediately and return that error.

Expand All @@ -180,9 +201,12 @@ FilepathGlob returns the names of all files matching pattern or nil if there is
no matching file. The syntax of pattern is the same as in Match(). The pattern
may describe hierarchical names such as usr/*/bin/ed.
FilepathGlob ignores file system errors such as I/O errors reading directories.
The only possible returned error is `ErrBadPattern`, reporting that the pattern
is malformed.
FilepathGlob ignores file system errors such as I/O errors reading directories
by default. The only possible returned error is `ErrBadPattern`, reporting that
the pattern is malformed.
To enable aborting on I/O errors, the `WithFailOnIOErrors` option can be
passed.
Note: FilepathGlob is a convenience function that is meant as a drop-in
replacement for `path/filepath.Glob()` for users who don't need the
Expand Down
415 changes: 211 additions & 204 deletions doublestar_test.go

Large diffs are not rendered by default.

16 changes: 10 additions & 6 deletions glob.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
// Glob ignores file system errors such as I/O errors reading directories by
// default. The only possible returned error is ErrBadPattern, reporting that
// the pattern is malformed.
//
// To enable aborting on I/O errors, the WithFailOnIOErrors option can be
// passed.
//
Expand All @@ -27,7 +28,8 @@ import (
//
// Note: users should _not_ count on the returned error,
// doublestar.ErrBadPattern, being equal to path.ErrBadPattern.
func Glob(fsys fs.FS, pattern string, opts ...Opt) ([]string, error) {
//
func Glob(fsys fs.FS, pattern string, opts ...GlobOption) ([]string, error) {
if !ValidatePattern(pattern) {
return nil, ErrBadPattern
}
Expand Down Expand Up @@ -65,7 +67,6 @@ func (g *glob) doGlob(fsys fs.FS, pattern string, m []string, firstSegment bool)

if pathExists {
matches = append(matches, path)
return
}

return
Expand Down Expand Up @@ -209,11 +210,14 @@ func (g *glob) globDir(fsys fs.FS, dir, pattern string, matches []string, canMat
var matched bool
for _, info := range dirs {
name := info.Name()
isDir, err := g.isDir(fsys, dir, name, info)
if err != nil {
return nil, err
matched = canMatchFiles
if !matched {
matched, e = g.isDir(fsys, dir, name, info)
if e != nil {
return
}
}
if canMatchFiles || isDir {
if matched {
matched, e = matchWithSeparator(pattern, name, '/', false)
if e != nil {
return
Expand Down
46 changes: 46 additions & 0 deletions globoptions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package doublestar

// glob is an internal type to store options during globbing.
type glob struct {
failOnIOErrors bool
}

// 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, it enables aborting and returning the error when an
// IO error is encountered.
//
func WithFailOnIOErrors() GlobOption {
return func(g *glob) {
g.failOnIOErrors = true
}
}

// 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
}

func (g *glob) GoString() string {
if g.failOnIOErrors {
return "opts: WithFailOnIOErrors"
}
return "opts: nil"
}
43 changes: 0 additions & 43 deletions globopts.go

This file was deleted.

27 changes: 17 additions & 10 deletions globwalk.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ type GlobWalkFunc func(path string, d fs.DirEntry) error
// path _is_ a directory, GlobWalk will not recurse into it. If the current
// path is not a directory, the rest of the parent directory will be skipped.
//
// GlobWalk ignores file system errors such as I/O errors reading directories by
// default. GlobWalk may return ErrBadPattern, reporting that the pattern is
// malformed. To enable aborting on I/O errors, the WithFailOnIOErrors option
// can be passed.
// GlobWalk ignores file system errors such as I/O errors reading directories
// by default. GlobWalk may return ErrBadPattern, reporting that the pattern is
// malformed.
//
// To enable aborting on I/O errors, the WithFailOnIOErrors option can be
// passed.
//
// Additionally, if the callback function `fn` returns an error, GlobWalk will
// exit immediately and return that error.
//
Expand All @@ -46,12 +49,13 @@ type GlobWalkFunc func(path string, d fs.DirEntry) error
//
// Note: users should _not_ count on the returned error,
// doublestar.ErrBadPattern, being equal to path.ErrBadPattern.
func GlobWalk(fsys fs.FS, pattern string, fn GlobWalkFunc, opts ...Opt) error {
//
func GlobWalk(fsys fs.FS, pattern string, fn GlobWalkFunc, opts ...GlobOption) error {
if !ValidatePattern(pattern) {
return ErrBadPattern
}
g := newGlob(opts...)

g := newGlob(opts...)
return g.doGlobWalk(fsys, pattern, true, fn)
}

Expand Down Expand Up @@ -270,11 +274,14 @@ func (g *glob) globDirWalk(fsys fs.FS, dir, pattern string, canMatchFiles bool,
var matched bool
for _, info := range dirs {
name := info.Name()
isDir, err := g.isDir(fsys, dir, name, info)
if err != nil {
return err
matched = canMatchFiles
if !matched {
matched, e = g.isDir(fsys, dir, name, info)
if e != nil {
return e
}
}
if canMatchFiles || isDir {
if matched {
matched, e = matchWithSeparator(pattern, name, '/', false)
if e != nil {
return
Expand Down
15 changes: 9 additions & 6 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ import (
// The second string is everything after that slash. For example, given the
// pattern:
//
// ../../path/to/meta*/**
// ^----------- split here
// ../../path/to/meta*/**
// ^----------- split here
//
// SplitPattern returns "../../path/to" and "meta*/**". This is useful for
// initializing os.DirFS() to call Glob() because Glob() will silently fail if
// your pattern includes `/./` or `/../`. For example:
//
// base, pattern := SplitPattern("../../path/to/meta*/**")
// fsys := os.DirFS(base)
// matches, err := Glob(fsys, pattern)
// base, pattern := SplitPattern("../../path/to/meta*/**")
// fsys := os.DirFS(base)
// matches, err := Glob(fsys, pattern)
//
// If SplitPattern cannot find somewhere to split the pattern (for example,
// `meta*/**`), it will return "." and the unaltered pattern (`meta*/**` in
Expand All @@ -31,6 +31,7 @@ import (
// Of course, it is your responsibility to decide if the returned base path is
// "safe" in the context of your application. Perhaps you could use Match() to
// validate against a list of approved base directories?
//
func SplitPattern(p string) (base, pattern string) {
base = "."
pattern = p
Expand Down Expand Up @@ -63,6 +64,7 @@ func SplitPattern(p string) (base, pattern string) {
// FilepathGlob ignores file system errors such as I/O errors reading
// directories by default. The only possible returned error is ErrBadPattern,
// reporting that the pattern is malformed.
//
// To enable aborting on I/O errors, the WithFailOnIOErrors option can be
// passed.
//
Expand All @@ -79,7 +81,8 @@ func SplitPattern(p string) (base, pattern string) {
//
// Note: the returned error doublestar.ErrBadPattern is not equal to
// filepath.ErrBadPattern.
func FilepathGlob(pattern string, opts ...Opt) (matches []string, err error) {
//
func FilepathGlob(pattern string, opts ...GlobOption) (matches []string, err error) {
pattern = filepath.Clean(pattern)
pattern = filepath.ToSlash(pattern)
base, f := SplitPattern(pattern)
Expand Down

0 comments on commit cd84160

Please sign in to comment.