diff --git a/vendor/github.com/radovskyb/watcher/README.md b/vendor/github.com/radovskyb/watcher/README.md index c0ef08bc..b457080c 100644 --- a/vendor/github.com/radovskyb/watcher/README.md +++ b/vendor/github.com/radovskyb/watcher/README.md @@ -15,7 +15,8 @@ Events contain the `os.FileInfo` of the file or directory that the event is base [Watcher Command](#command) # Update -Event.Path for Rename and Move events is now returned in the format of `fromPath -> toPath` +- Added new file filter hooks (Including a built in regexp filtering hook) [Dec 12, 2018] +- Event.Path for Rename and Move events is now returned in the format of `fromPath -> toPath` #### Chmod event is not supported under windows. @@ -68,6 +69,11 @@ func main() { // Only notify rename and move events. w.FilterOps(watcher.Rename, watcher.Move) + // Only files that match the regular expression during file listings + // will be watched. + r := regexp.MustCompile("^abc$") + w.AddFilterHook(watcher.RegexFilterHook(r, false)) + go func() { for { select { @@ -128,6 +134,8 @@ Usage of watcher: command to run when an event occurs -dotfiles watch dot files (default true) + -ignore string + comma separated list of paths to ignore -interval string watcher poll interval (default "100ms") -keepalive diff --git a/vendor/github.com/radovskyb/watcher/ishidden.go b/vendor/github.com/radovskyb/watcher/ishidden.go new file mode 100644 index 00000000..0f242e8a --- /dev/null +++ b/vendor/github.com/radovskyb/watcher/ishidden.go @@ -0,0 +1,12 @@ +// +build !windows + +package watcher + +import ( + "path/filepath" + "strings" +) + +func isHiddenFile(path string) (bool, error) { + return strings.HasPrefix(filepath.Base(path), "."), nil +} diff --git a/vendor/github.com/radovskyb/watcher/ishidden_windows.go b/vendor/github.com/radovskyb/watcher/ishidden_windows.go new file mode 100644 index 00000000..306c6b71 --- /dev/null +++ b/vendor/github.com/radovskyb/watcher/ishidden_windows.go @@ -0,0 +1,21 @@ +// +build windows + +package watcher + +import ( + "syscall" +) + +func isHiddenFile(path string) (bool, error) { + pointer, err := syscall.UTF16PtrFromString(path) + if err != nil { + return false, err + } + + attributes, err := syscall.GetFileAttributes(pointer) + if err != nil { + return false, err + } + + return attributes&syscall.FILE_ATTRIBUTE_HIDDEN != 0, nil +} diff --git a/vendor/github.com/radovskyb/watcher/samefile.go b/vendor/github.com/radovskyb/watcher/samefile.go index 8c9cb325..5968bb6f 100644 --- a/vendor/github.com/radovskyb/watcher/samefile.go +++ b/vendor/github.com/radovskyb/watcher/samefile.go @@ -4,6 +4,6 @@ package watcher import "os" -func SameFile(fi1, fi2 os.FileInfo) bool { +func sameFile(fi1, fi2 os.FileInfo) bool { return os.SameFile(fi1, fi2) } diff --git a/vendor/github.com/radovskyb/watcher/samefile_windows.go b/vendor/github.com/radovskyb/watcher/samefile_windows.go index 1ea95120..7785a129 100644 --- a/vendor/github.com/radovskyb/watcher/samefile_windows.go +++ b/vendor/github.com/radovskyb/watcher/samefile_windows.go @@ -4,7 +4,7 @@ package watcher import "os" -func SameFile(fi1, fi2 os.FileInfo) bool { +func sameFile(fi1, fi2 os.FileInfo) bool { return fi1.ModTime() == fi2.ModTime() && fi1.Size() == fi2.Size() && fi1.Mode() == fi2.Mode() && diff --git a/vendor/github.com/radovskyb/watcher/watcher.go b/vendor/github.com/radovskyb/watcher/watcher.go index e486ea0a..e3532969 100644 --- a/vendor/github.com/radovskyb/watcher/watcher.go +++ b/vendor/github.com/radovskyb/watcher/watcher.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "os" "path/filepath" + "regexp" "strings" "sync" "time" @@ -24,6 +25,10 @@ var ( // ErrWatchedFileDeleted is an error that occurs when a file or folder that was // being watched has been deleted. ErrWatchedFileDeleted = errors.New("error: watched file or folder deleted") + + // ErrSkip is less of an error, but more of a way for path hooks to skip a file or + // directory. + ErrSkip = errors.New("error: skipping file") ) // An Op is a type that is used to describe what type @@ -69,16 +74,43 @@ type Event struct { // String returns a string depending on what type of event occurred and the // file name associated with the event. func (e Event) String() string { - if e.FileInfo != nil { - pathType := "FILE" - if e.IsDir() { - pathType = "DIRECTORY" - } - return fmt.Sprintf("%s %q %s [%s]", pathType, e.Name(), e.Op, e.Path) + if e.FileInfo == nil { + return "???" } - return "???" + + pathType := "FILE" + if e.IsDir() { + pathType = "DIRECTORY" + } + return fmt.Sprintf("%s %q %s [%s]", pathType, e.Name(), e.Op, e.Path) } +// FilterFileHookFunc is a function that is called to filter files during listings. +// If a file is ok to be listed, nil is returned otherwise ErrSkip is returned. +type FilterFileHookFunc func(info os.FileInfo, fullPath string) error + +// RegexFilterHook is a function that accepts or rejects a file +// for listing based on whether it's filename or full path matches +// a regular expression. +func RegexFilterHook(r *regexp.Regexp, useFullPath bool) FilterFileHookFunc { + return func(info os.FileInfo, fullPath string) error { + str := info.Name() + + if useFullPath { + str = fullPath + } + + // Match + if r.MatchString(str) { + return nil + } + + // No match. + return ErrSkip + } +} + +// Watcher describes a process that watches files for changes. type Watcher struct { Event chan Event Error chan error @@ -88,6 +120,7 @@ type Watcher struct { // mu protects the following. mu *sync.Mutex + ffh []FilterFileHookFunc running bool names map[string]bool // bool for recursive or not. files map[string]os.FileInfo // map of files. @@ -125,6 +158,13 @@ func (w *Watcher) SetMaxEvents(delta int) { w.mu.Unlock() } +// AddFilterHook +func (w *Watcher) AddFilterHook(f FilterFileHookFunc) { + w.mu.Lock() + w.ffh = append(w.ffh, f) + w.mu.Unlock() +} + // IgnoreHiddenFiles sets the watcher to ignore any file or directory // that starts with a dot. func (w *Watcher) IgnoreHiddenFiles(ignore bool) { @@ -157,7 +197,13 @@ func (w *Watcher) Add(name string) (err error) { // If name is on the ignored list or if hidden files are // ignored and name is a hidden file or directory, simply return. _, ignored := w.ignored[name] - if ignored || (w.ignoreHidden && strings.HasPrefix(name, ".")) { + + isHidden, err := isHiddenFile(name) + if err != nil { + return err + } + + if ignored || (w.ignoreHidden && isHidden) { return nil } @@ -200,18 +246,36 @@ func (w *Watcher) list(name string) (map[string]os.FileInfo, error) { // Add all of the files in the directory to the file list as long // as they aren't on the ignored list or are hidden files if ignoreHidden // is set to true. +outer: for _, fInfo := range fInfoList { path := filepath.Join(name, fInfo.Name()) _, ignored := w.ignored[path] - if ignored || (w.ignoreHidden && strings.HasPrefix(fInfo.Name(), ".")) { + + isHidden, err := isHiddenFile(path) + if err != nil { + return nil, err + } + + if ignored || (w.ignoreHidden && isHidden) { continue } + + for _, f := range w.ffh { + err := f(fInfo, path) + if err == ErrSkip { + continue outer + } + if err != nil { + return nil, err + } + } + fileList[path] = fInfo } return fileList, nil } -// Add adds either a single file or directory recursively to the file list. +// AddRecursive adds either a single file or directory recursively to the file list. func (w *Watcher) AddRecursive(name string) (err error) { w.mu.Lock() defer w.mu.Unlock() @@ -242,10 +306,27 @@ func (w *Watcher) listRecursive(name string) (map[string]os.FileInfo, error) { if err != nil { return err } + + for _, f := range w.ffh { + err := f(info, path) + if err == ErrSkip { + return nil + } + if err != nil { + return err + } + } + // If path is ignored and it's a directory, skip the directory. If it's // ignored and it's a single file, skip the file. _, ignored := w.ignored[path] - if ignored || (w.ignoreHidden && strings.HasPrefix(info.Name(), ".")) { + + isHidden, err := isHiddenFile(path) + if err != nil { + return err + } + + if ignored || (w.ignoreHidden && isHidden) { if info.IsDir() { return filepath.SkipDir } @@ -292,7 +373,7 @@ func (w *Watcher) Remove(name string) (err error) { return nil } -// Remove removes either a single file or a directory recursively from +// RemoveRecursive removes either a single file or a directory recursively from // the file's list. func (w *Watcher) RemoveRecursive(name string) (err error) { w.mu.Lock() @@ -346,11 +427,17 @@ func (w *Watcher) Ignore(paths ...string) (err error) { return nil } +// WatchedFiles returns a map of files added to a Watcher. func (w *Watcher) WatchedFiles() map[string]os.FileInfo { w.mu.Lock() defer w.mu.Unlock() - return w.files + files := make(map[string]os.FileInfo) + for k, v := range w.files { + files[k] = v + } + + return files } // fileInfo is an implementation of os.FileInfo that can be used @@ -560,7 +647,7 @@ func (w *Watcher) pollEvents(files map[string]os.FileInfo, evt chan Event, // Check for renames and moves. for path1, info1 := range removes { for path2, info2 := range creates { - if SameFile(info1, info2) { + if sameFile(info1, info2) { e := Event{ Op: Move, Path: fmt.Sprintf("%s -> %s", path1, path2), @@ -606,6 +693,7 @@ func (w *Watcher) Wait() { w.wg.Wait() } +// Close stops a Watcher and unlocks its mutex, then sends a close signal. func (w *Watcher) Close() { w.mu.Lock() if !w.running { diff --git a/vendor/github.com/stretchr/testify/LICENSE b/vendor/github.com/stretchr/testify/LICENSE index 473b670a..f38ec595 100644 --- a/vendor/github.com/stretchr/testify/LICENSE +++ b/vendor/github.com/stretchr/testify/LICENSE @@ -1,22 +1,21 @@ -Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell +MIT License -Please consider promoting this project if you find it useful. +Copyright (c) 2012-2018 Mat Ryer and Tyler Bunnell -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go index 5bdec56c..9bd4a80e 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions.go +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -39,7 +39,7 @@ type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool // for table driven tests. type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool -// ValuesAssertionFunc is a common function prototype when validating an error value. Can be useful +// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful // for table driven tests. type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool @@ -179,7 +179,11 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { return "" } if len(msgAndArgs) == 1 { - return msgAndArgs[0].(string) + msg := msgAndArgs[0] + if msgAsStr, ok := msg.(string); ok { + return msgAsStr + } + return fmt.Sprintf("%+v", msg) } if len(msgAndArgs) > 1 { return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) @@ -415,6 +419,17 @@ func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return Fail(t, "Expected value not to be nil.", msgAndArgs...) } +// containsKind checks if a specified kind in the slice of kinds. +func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool { + for i := 0; i < len(kinds); i++ { + if kind == kinds[i] { + return true + } + } + + return false +} + // isNil checks if a specified object is nil or not, without Failing. func isNil(object interface{}) bool { if object == nil { @@ -423,7 +438,14 @@ func isNil(object interface{}) bool { value := reflect.ValueOf(object) kind := value.Kind() - if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() { + isNilableKind := containsKind( + []reflect.Kind{ + reflect.Chan, reflect.Func, + reflect.Interface, reflect.Map, + reflect.Ptr, reflect.Slice}, + kind) + + if isNilableKind && value.IsNil() { return true } @@ -1327,7 +1349,7 @@ func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { } // diff returns a diff of both values as long as both are of the same type and -// are a struct, map, slice or array. Otherwise it returns an empty string. +// are a struct, map, slice, array or string. Otherwise it returns an empty string. func diff(expected interface{}, actual interface{}) string { if expected == nil || actual == nil { return "" @@ -1345,7 +1367,7 @@ func diff(expected interface{}, actual interface{}) string { } var e, a string - if ek != reflect.String { + if et != reflect.TypeOf("") { e = spewConfig.Sdump(expected) a = spewConfig.Sdump(actual) } else { diff --git a/vendor/modules.txt b/vendor/modules.txt index f4adea27..866473f9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -12,18 +12,18 @@ github.com/google/uuid github.com/huandu/xstrings # github.com/imdario/mergo v0.3.6 github.com/imdario/mergo -# github.com/mattn/go-zglob v0.0.0-20180803001819-2ea3427bfa53 +# github.com/mattn/go-zglob v0.0.1 github.com/mattn/go-zglob github.com/mattn/go-zglob/fastwalk # github.com/mitchellh/go-homedir v1.0.0 github.com/mitchellh/go-homedir # github.com/pmezard/go-difflib v1.0.0 github.com/pmezard/go-difflib/difflib -# github.com/radovskyb/watcher v1.0.2 +# github.com/radovskyb/watcher v1.0.5 github.com/radovskyb/watcher # github.com/spf13/pflag v1.0.3 github.com/spf13/pflag -# github.com/stretchr/testify v1.2.2 +# github.com/stretchr/testify v1.3.0 github.com/stretchr/testify/assert # golang.org/x/crypto v0.0.0-20180830192347-182538f80094 golang.org/x/crypto/ssh/terminal @@ -38,7 +38,7 @@ golang.org/x/sys/unix golang.org/x/sys/windows # gopkg.in/yaml.v2 v2.2.1 gopkg.in/yaml.v2 -# mvdan.cc/sh v2.6.3-0.20181216173157-8aeb0734cd0f+incompatible +# mvdan.cc/sh v2.6.3+incompatible mvdan.cc/sh/expand mvdan.cc/sh/interp mvdan.cc/sh/shell diff --git a/vendor/mvdan.cc/sh/expand/expand.go b/vendor/mvdan.cc/sh/expand/expand.go index 9447ceae..633b43a7 100644 --- a/vendor/mvdan.cc/sh/expand/expand.go +++ b/vendor/mvdan.cc/sh/expand/expand.go @@ -709,7 +709,14 @@ func (cfg *Config) globDir(base, dir string, rx *regexp.Regexp, matches []string } infos, err := cfg.ReadDir(filepath.Join(base, dir)) if err != nil { - return nil, err + // Ignore the error, as this might be a file instead of a + // directory. v3 refactored globbing to only use one ReadDir + // call per directory instead of two, so it knows to skip this + // kind of path at the ReadDir call of its parent. + // Instead of backporting that complex rewrite into v2, just + // work around the edge case here. We might ignore other kinds + // of errors, but at least we don't fail on a correct glob. + return matches, nil } for _, info := range infos { name := info.Name()