diff --git a/go.mod b/go.mod index 085bbc595..db2ac0bc7 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/briandowns/spinner v1.12.0 github.com/charmbracelet/glamour v0.2.0 github.com/fatih/color v1.10.0 // indirect + github.com/fsnotify/fsnotify v1.4.7 github.com/getsentry/sentry-go v0.10.0 github.com/golang/mock v1.5.0 github.com/golang/snappy v0.0.3 // indirect @@ -26,7 +27,6 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/pierrec/lz4/v4 v4.1.3 // indirect github.com/rivo/uniseg v0.2.0 // indirect - github.com/rjeczalik/notify v0.9.2 github.com/spf13/cobra v1.1.3 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.7.0 diff --git a/go.sum b/go.sum index 0350c52cc..8b8ce626f 100644 --- a/go.sum +++ b/go.sum @@ -410,8 +410,6 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= -github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -603,7 +601,6 @@ golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/internal/branding/branding.go b/internal/branding/branding.go index 03803c670..550aa7716 100644 --- a/internal/branding/branding.go +++ b/internal/branding/branding.go @@ -4,15 +4,15 @@ import ( "context" "encoding/json" "fmt" + "log" "net" "net/http" - "path/filepath" "text/template" "time" "github.com/auth0/auth0-cli/internal/open" + "github.com/fsnotify/fsnotify" "github.com/guiguan/caster" - "github.com/rjeczalik/notify" ) type Client struct { @@ -119,27 +119,41 @@ func buildRoutes(ctx context.Context, requestTimeout time.Duration, templateData func broadcastCustomTemplateChanges(ctx context.Context, filename string) *caster.Caster { publisher := caster.New(ctx) - dir, file := filepath.Split(filename) - c := make(chan notify.EventInfo) - if err := notify.Watch(dir, c, notify.Write); err != nil { - return publisher + watcher, err := fsnotify.NewWatcher() + if err != nil { + log.Fatal(err) } go func() { - for eventInfo := range c { - if filepath.Base(eventInfo.Path()) == file { - publisher.Pub(true) + for { + select { + case event, ok := <-watcher.Events: + if !ok { + return + } + if event.Op&fsnotify.Write == fsnotify.Write { + publisher.Pub(true) + } + case err, ok := <-watcher.Errors: + if !ok { + return + } + log.Fatal(err) } } }() - // release resources when the file is closed or the input is cancelled go func() { <-ctx.Done() - notify.Stop(c) - close(c) + watcher.Close() + publisher.Close() }() + err = watcher.Add(filename) + if err != nil { + log.Fatal(err) + } + return publisher } diff --git a/vendor/github.com/rjeczalik/notify/.gitignore b/vendor/github.com/rjeczalik/notify/.gitignore deleted file mode 100644 index 32c6eb987..000000000 --- a/vendor/github.com/rjeczalik/notify/.gitignore +++ /dev/null @@ -1,92 +0,0 @@ -# Created by https://www.gitignore.io - -### OSX ### -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - - -# Thumbnails -._* - -# Files that might appear on external disk -.Spotlight-V100 -.Trashes - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - - -### Windows ### -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk - - -### Linux ### -*~ - -# KDE directory preferences -.directory - - -### Go ### -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof - - -### vim ### -[._]*.s[a-w][a-z] -[._]s[a-w][a-z] -*.un~ -Session.vim -.netrwhist -*~ - -### JetBrains files ### -.idea/ -*.iml \ No newline at end of file diff --git a/vendor/github.com/rjeczalik/notify/.travis.yml b/vendor/github.com/rjeczalik/notify/.travis.yml deleted file mode 100644 index 9fbeef655..000000000 --- a/vendor/github.com/rjeczalik/notify/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -language: go - -go: - - 1.10.x - - tip - -os: - - linux - - osx - -matrix: - include: - - os: osx - go: 1.7.5 - env: - - GOFLAGS="-tags kqueue" - allow_failures: - - go: tip - -env: - global: - - GOBIN=$HOME/bin - - PATH=$HOME/bin:$PATH - -install: - - go get -t -v ./... - -script: - - "(go version | grep -q 1.4) || go tool vet -all ." - - go install $GOFLAGS ./... - - go test -v -timeout 60s -race $GOFLAGS ./... diff --git a/vendor/github.com/rjeczalik/notify/AUTHORS b/vendor/github.com/rjeczalik/notify/AUTHORS deleted file mode 100644 index 9262eae69..000000000 --- a/vendor/github.com/rjeczalik/notify/AUTHORS +++ /dev/null @@ -1,10 +0,0 @@ -# List of individuals who contributed to the Notify package. -# -# The up-to-date list of the authors one may obtain with: -# -# ~ $ git shortlog -es | cut -f2 | rev | uniq -f1 | rev -# - -Pawel Blaszczyk -Pawel Knap -Rafal Jeczalik diff --git a/vendor/github.com/rjeczalik/notify/LICENSE b/vendor/github.com/rjeczalik/notify/LICENSE deleted file mode 100644 index 3e678817b..000000000 --- a/vendor/github.com/rjeczalik/notify/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014-2015 The Notify Authors - -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 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/rjeczalik/notify/README.md b/vendor/github.com/rjeczalik/notify/README.md deleted file mode 100644 index ad743b2a2..000000000 --- a/vendor/github.com/rjeczalik/notify/README.md +++ /dev/null @@ -1,22 +0,0 @@ -notify [![GoDoc](https://godoc.org/github.com/rjeczalik/notify?status.svg)](https://godoc.org/github.com/rjeczalik/notify) [![Build Status](https://img.shields.io/travis/rjeczalik/notify/master.svg)](https://travis-ci.org/rjeczalik/notify "inotify + FSEvents + kqueue") [![Build status](https://img.shields.io/appveyor/ci/rjeczalik/notify-246.svg)](https://ci.appveyor.com/project/rjeczalik/notify-246 "ReadDirectoryChangesW") [![Coverage Status](https://img.shields.io/coveralls/rjeczalik/notify/master.svg)](https://coveralls.io/r/rjeczalik/notify?branch=master) -====== - -Filesystem event notification library on steroids. (under active development) - -*Documentation* - -[godoc.org/github.com/rjeczalik/notify](https://godoc.org/github.com/rjeczalik/notify) - -*Installation* - -``` -~ $ go get -u github.com/rjeczalik/notify -``` - -*Projects using notify* - -- [github.com/rjeczalik/cmd/notify](https://godoc.org/github.com/rjeczalik/cmd/notify) -- [github.com/cortesi/devd](https://github.com/cortesi/devd) -- [github.com/cortesi/modd](https://github.com/cortesi/modd) -- [github.com/syncthing/syncthing-inotify](https://github.com/syncthing/syncthing-inotify) -- [github.com/OrlovEvgeny/TinyJPG](https://github.com/OrlovEvgeny/TinyJPG) diff --git a/vendor/github.com/rjeczalik/notify/appveyor.yml b/vendor/github.com/rjeczalik/notify/appveyor.yml deleted file mode 100644 index a0bdc37a3..000000000 --- a/vendor/github.com/rjeczalik/notify/appveyor.yml +++ /dev/null @@ -1,27 +0,0 @@ -version: "{build}" - -os: Windows Server 2012 R2 - -clone_folder: c:\projects\src\github.com\rjeczalik\notify - -environment: - PATH: c:\projects\bin;%PATH% - GOPATH: c:\projects - NOTIFY_TIMEOUT: 10s - GOVERSION: 1.10.3 - -install: - - rmdir c:\go /s /q - - appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.zip - - 7z x go%GOVERSION%.windows-amd64.zip -y -oC:\ > NUL - - - cd %APPVEYOR_BUILD_FOLDER% - - go version - -build_script: - - go build ./... - - go test -v -timeout 120s -race ./... - -test: off - -deploy: off diff --git a/vendor/github.com/rjeczalik/notify/debug.go b/vendor/github.com/rjeczalik/notify/debug.go deleted file mode 100644 index 2a3eb3370..000000000 --- a/vendor/github.com/rjeczalik/notify/debug.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -package notify - -import ( - "log" - "os" - "runtime" - "strings" -) - -var dbgprint func(...interface{}) - -var dbgprintf func(string, ...interface{}) - -var dbgcallstack func(max int) []string - -func init() { - if _, ok := os.LookupEnv("NOTIFY_DEBUG"); ok || debugTag { - log.SetOutput(os.Stdout) - log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds) - dbgprint = func(v ...interface{}) { - v = append([]interface{}{"[D] "}, v...) - log.Println(v...) - } - dbgprintf = func(format string, v ...interface{}) { - format = "[D] " + format - log.Printf(format, v...) - } - dbgcallstack = func(max int) []string { - pc, stack := make([]uintptr, max), make([]string, 0, max) - runtime.Callers(2, pc) - for _, pc := range pc { - if f := runtime.FuncForPC(pc); f != nil { - fname := f.Name() - idx := strings.LastIndex(fname, string(os.PathSeparator)) - if idx != -1 { - stack = append(stack, fname[idx+1:]) - } else { - stack = append(stack, fname) - } - } - } - return stack - } - return - } - dbgprint = func(v ...interface{}) {} - dbgprintf = func(format string, v ...interface{}) {} - dbgcallstack = func(max int) []string { return nil } -} diff --git a/vendor/github.com/rjeczalik/notify/debug_debug.go b/vendor/github.com/rjeczalik/notify/debug_debug.go deleted file mode 100644 index 9d234cedd..000000000 --- a/vendor/github.com/rjeczalik/notify/debug_debug.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) 2014-2018 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build debug - -package notify - -var debugTag = true diff --git a/vendor/github.com/rjeczalik/notify/debug_nodebug.go b/vendor/github.com/rjeczalik/notify/debug_nodebug.go deleted file mode 100644 index 9ebf880d8..000000000 --- a/vendor/github.com/rjeczalik/notify/debug_nodebug.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) 2014-2018 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build !debug - -package notify - -var debugTag = false diff --git a/vendor/github.com/rjeczalik/notify/doc.go b/vendor/github.com/rjeczalik/notify/doc.go deleted file mode 100644 index 60543c083..000000000 --- a/vendor/github.com/rjeczalik/notify/doc.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// Package notify implements access to filesystem events. -// -// Notify is a high-level abstraction over filesystem watchers like inotify, -// kqueue, FSEvents, FEN or ReadDirectoryChangesW. Watcher implementations are -// split into two groups: ones that natively support recursive notifications -// (FSEvents and ReadDirectoryChangesW) and ones that do not (inotify, kqueue, FEN). -// For more details see watcher and recursiveWatcher interfaces in watcher.go -// source file. -// -// On top of filesystem watchers notify maintains a watchpoint tree, which provides -// a strategy for creating and closing filesystem watches and dispatching filesystem -// events to user channels. -// -// An event set is just an event list joint using bitwise OR operator -// into a single event value. -// Both the platform-independent (see Constants) and specific events can be used. -// Refer to the event_*.go source files for information about the available -// events. -// -// A filesystem watch or just a watch is platform-specific entity which represents -// a single path registered for notifications for specific event set. Setting a watch -// means using platform-specific API calls for creating / initializing said watch. -// For each watcher the API call is: -// -// - FSEvents: FSEventStreamCreate -// - inotify: notify_add_watch -// - kqueue: kevent -// - ReadDirectoryChangesW: CreateFile+ReadDirectoryChangesW -// - FEN: port_get -// -// To rewatch means to either shrink or expand an event set that was previously -// registered during watch operation for particular filesystem watch. -// -// A watchpoint is a list of user channel and event set pairs for particular -// path (watchpoint tree's node). A single watchpoint can contain multiple -// different user channels registered to listen for one or more events. A single -// user channel can be registered in one or more watchpoints, recursive and -// non-recursive ones as well. -package notify diff --git a/vendor/github.com/rjeczalik/notify/event.go b/vendor/github.com/rjeczalik/notify/event.go deleted file mode 100644 index c12884197..000000000 --- a/vendor/github.com/rjeczalik/notify/event.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -package notify - -import ( - "fmt" - "strings" -) - -// Event represents the type of filesystem action. -// -// Number of available event values is dependent on the target system or the -// watcher implmenetation used (e.g. it's possible to use either kqueue or -// FSEvents on Darwin). -// -// Please consult documentation for your target platform to see list of all -// available events. -type Event uint32 - -// Create, Remove, Write and Rename are the only event values guaranteed to be -// present on all platforms. -const ( - Create = osSpecificCreate - Remove = osSpecificRemove - Write = osSpecificWrite - Rename = osSpecificRename - - // All is handful alias for all platform-independent event values. - All = Create | Remove | Write | Rename -) - -const internal = recursive | omit - -// String implements fmt.Stringer interface. -func (e Event) String() string { - var s []string - for _, strmap := range []map[Event]string{estr, osestr} { - for ev, str := range strmap { - if e&ev == ev { - s = append(s, str) - } - } - } - return strings.Join(s, "|") -} - -// EventInfo describes an event reported by the underlying filesystem notification -// subsystem. -// -// It always describes single event, even if the OS reported a coalesced action. -// Reported path is absolute and clean. -// -// For non-recursive watchpoints its base is always equal to the path passed -// to corresponding Watch call. -// -// The value of Sys if system-dependent and can be nil. -// -// Sys -// -// Under Darwin (FSEvents) Sys() always returns a non-nil *notify.FSEvent value, -// which is defined as: -// -// type FSEvent struct { -// Path string // real path of the file or directory -// ID uint64 // ID of the event (FSEventStreamEventId) -// Flags uint32 // joint FSEvents* flags (FSEventStreamEventFlags) -// } -// -// For possible values of Flags see Darwin godoc for notify or FSEvents -// documentation for FSEventStreamEventFlags constants: -// -// https://developer.apple.com/library/mac/documentation/Darwin/Reference/FSEvents_Ref/index.html#//apple_ref/doc/constant_group/FSEventStreamEventFlags -// -// Under Linux (inotify) Sys() always returns a non-nil *unix.InotifyEvent -// value, defined as: -// -// type InotifyEvent struct { -// Wd int32 // Watch descriptor -// Mask uint32 // Mask describing event -// Cookie uint32 // Unique cookie associating related events (for rename(2)) -// Len uint32 // Size of name field -// Name [0]uint8 // Optional null-terminated name -// } -// -// More information about inotify masks and the usage of inotify_event structure -// can be found at: -// -// http://man7.org/linux/man-pages/man7/inotify.7.html -// -// Under Darwin, DragonFlyBSD, FreeBSD, NetBSD, OpenBSD (kqueue) Sys() always -// returns a non-nil *notify.Kevent value, which is defined as: -// -// type Kevent struct { -// Kevent *syscall.Kevent_t // Kevent is a kqueue specific structure -// FI os.FileInfo // FI describes file/dir -// } -// -// More information about syscall.Kevent_t can be found at: -// -// https://www.freebsd.org/cgi/man.cgi?query=kqueue -// -// Under Windows (ReadDirectoryChangesW) Sys() always returns nil. The documentation -// of watcher's WinAPI function can be found at: -// -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v=vs.85%29.aspx -type EventInfo interface { - Event() Event // event value for the filesystem action - Path() string // real path of the file or directory - Sys() interface{} // underlying data source (can return nil) -} - -type isDirer interface { - isDir() (bool, error) -} - -var _ fmt.Stringer = (*event)(nil) -var _ isDirer = (*event)(nil) - -// String implements fmt.Stringer interface. -func (e *event) String() string { - return e.Event().String() + `: "` + e.Path() + `"` -} - -var estr = map[Event]string{ - Create: "notify.Create", - Remove: "notify.Remove", - Write: "notify.Write", - Rename: "notify.Rename", - // Display name for recursive event is added only for debugging - // purposes. It's an internal event after all and won't be exposed to the - // user. Having Recursive event printable is helpful, e.g. for reading - // testing failure messages: - // - // --- FAIL: TestWatchpoint (0.00 seconds) - // watchpoint_test.go:64: want diff=[notify.Remove notify.Create|notify.Remove]; - // got [notify.Remove notify.Remove|notify.Create] (i=1) - // - // Yup, here the diff have Recursive event inside. Go figure. - recursive: "recursive", - omit: "omit", -} diff --git a/vendor/github.com/rjeczalik/notify/event_fen.go b/vendor/github.com/rjeczalik/notify/event_fen.go deleted file mode 100644 index 767f04fa8..000000000 --- a/vendor/github.com/rjeczalik/notify/event_fen.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build solaris - -package notify - -const ( - osSpecificCreate Event = 0x00000100 << iota - osSpecificRemove - osSpecificWrite - osSpecificRename - // internal - // recursive is used to distinguish recursive eventsets from non-recursive ones - recursive - // omit is used for dispatching internal events; only those events are sent - // for which both the event and the watchpoint has omit in theirs event sets. - omit -) - -const ( - // FileAccess is an event reported when monitored file/directory was accessed. - FileAccess = fileAccess - // FileModified is an event reported when monitored file/directory was modified. - FileModified = fileModified - // FileAttrib is an event reported when monitored file/directory's ATTRIB - // was changed. - FileAttrib = fileAttrib - // FileDelete is an event reported when monitored file/directory was deleted. - FileDelete = fileDelete - // FileRenameTo to is an event reported when monitored file/directory was renamed. - FileRenameTo = fileRenameTo - // FileRenameFrom is an event reported when monitored file/directory was renamed. - FileRenameFrom = fileRenameFrom - // FileTrunc is an event reported when monitored file/directory was truncated. - FileTrunc = fileTrunc - // FileNoFollow is an flag to indicate not to follow symbolic links. - FileNoFollow = fileNoFollow - // Unmounted is an event reported when monitored filesystem was unmounted. - Unmounted = unmounted - // MountedOver is an event reported when monitored file/directory was mounted on. - MountedOver = mountedOver -) - -var osestr = map[Event]string{ - FileAccess: "notify.FileAccess", - FileModified: "notify.FileModified", - FileAttrib: "notify.FileAttrib", - FileDelete: "notify.FileDelete", - FileRenameTo: "notify.FileRenameTo", - FileRenameFrom: "notify.FileRenameFrom", - FileTrunc: "notify.FileTrunc", - FileNoFollow: "notify.FileNoFollow", - Unmounted: "notify.Unmounted", - MountedOver: "notify.MountedOver", -} diff --git a/vendor/github.com/rjeczalik/notify/event_fsevents.go b/vendor/github.com/rjeczalik/notify/event_fsevents.go deleted file mode 100644 index 6ded80b2c..000000000 --- a/vendor/github.com/rjeczalik/notify/event_fsevents.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build darwin,!kqueue - -package notify - -const ( - osSpecificCreate = Event(FSEventsCreated) - osSpecificRemove = Event(FSEventsRemoved) - osSpecificWrite = Event(FSEventsModified) - osSpecificRename = Event(FSEventsRenamed) - // internal = Event(0x100000) - // recursive is used to distinguish recursive eventsets from non-recursive ones - recursive = Event(0x200000) - // omit is used for dispatching internal events; only those events are sent - // for which both the event and the watchpoint has omit in theirs event sets. - omit = Event(0x400000) -) - -// FSEvents specific event values. -const ( - FSEventsMustScanSubDirs Event = 0x00001 - FSEventsUserDropped = 0x00002 - FSEventsKernelDropped = 0x00004 - FSEventsEventIdsWrapped = 0x00008 - FSEventsHistoryDone = 0x00010 - FSEventsRootChanged = 0x00020 - FSEventsMount = 0x00040 - FSEventsUnmount = 0x00080 - FSEventsCreated = 0x00100 - FSEventsRemoved = 0x00200 - FSEventsInodeMetaMod = 0x00400 - FSEventsRenamed = 0x00800 - FSEventsModified = 0x01000 - FSEventsFinderInfoMod = 0x02000 - FSEventsChangeOwner = 0x04000 - FSEventsXattrMod = 0x08000 - FSEventsIsFile = 0x10000 - FSEventsIsDir = 0x20000 - FSEventsIsSymlink = 0x40000 -) - -var osestr = map[Event]string{ - FSEventsMustScanSubDirs: "notify.FSEventsMustScanSubDirs", - FSEventsUserDropped: "notify.FSEventsUserDropped", - FSEventsKernelDropped: "notify.FSEventsKernelDropped", - FSEventsEventIdsWrapped: "notify.FSEventsEventIdsWrapped", - FSEventsHistoryDone: "notify.FSEventsHistoryDone", - FSEventsRootChanged: "notify.FSEventsRootChanged", - FSEventsMount: "notify.FSEventsMount", - FSEventsUnmount: "notify.FSEventsUnmount", - FSEventsInodeMetaMod: "notify.FSEventsInodeMetaMod", - FSEventsFinderInfoMod: "notify.FSEventsFinderInfoMod", - FSEventsChangeOwner: "notify.FSEventsChangeOwner", - FSEventsXattrMod: "notify.FSEventsXattrMod", - FSEventsIsFile: "notify.FSEventsIsFile", - FSEventsIsDir: "notify.FSEventsIsDir", - FSEventsIsSymlink: "notify.FSEventsIsSymlink", -} - -type event struct { - fse FSEvent - event Event -} - -func (ei *event) Event() Event { return ei.event } -func (ei *event) Path() string { return ei.fse.Path } -func (ei *event) Sys() interface{} { return &ei.fse } -func (ei *event) isDir() (bool, error) { return ei.fse.Flags&FSEventsIsDir != 0, nil } diff --git a/vendor/github.com/rjeczalik/notify/event_inotify.go b/vendor/github.com/rjeczalik/notify/event_inotify.go deleted file mode 100644 index 1f32bb73e..000000000 --- a/vendor/github.com/rjeczalik/notify/event_inotify.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build linux - -package notify - -import "golang.org/x/sys/unix" - -// Platform independent event values. -const ( - osSpecificCreate Event = 0x100000 << iota - osSpecificRemove - osSpecificWrite - osSpecificRename - // internal - // recursive is used to distinguish recursive eventsets from non-recursive ones - recursive - // omit is used for dispatching internal events; only those events are sent - // for which both the event and the watchpoint has omit in theirs event sets. - omit -) - -// Inotify specific masks are legal, implemented events that are guaranteed to -// work with notify package on linux-based systems. -const ( - InAccess = Event(unix.IN_ACCESS) // File was accessed - InModify = Event(unix.IN_MODIFY) // File was modified - InAttrib = Event(unix.IN_ATTRIB) // Metadata changed - InCloseWrite = Event(unix.IN_CLOSE_WRITE) // Writtable file was closed - InCloseNowrite = Event(unix.IN_CLOSE_NOWRITE) // Unwrittable file closed - InOpen = Event(unix.IN_OPEN) // File was opened - InMovedFrom = Event(unix.IN_MOVED_FROM) // File was moved from X - InMovedTo = Event(unix.IN_MOVED_TO) // File was moved to Y - InCreate = Event(unix.IN_CREATE) // Subfile was created - InDelete = Event(unix.IN_DELETE) // Subfile was deleted - InDeleteSelf = Event(unix.IN_DELETE_SELF) // Self was deleted - InMoveSelf = Event(unix.IN_MOVE_SELF) // Self was moved -) - -var osestr = map[Event]string{ - InAccess: "notify.InAccess", - InModify: "notify.InModify", - InAttrib: "notify.InAttrib", - InCloseWrite: "notify.InCloseWrite", - InCloseNowrite: "notify.InCloseNowrite", - InOpen: "notify.InOpen", - InMovedFrom: "notify.InMovedFrom", - InMovedTo: "notify.InMovedTo", - InCreate: "notify.InCreate", - InDelete: "notify.InDelete", - InDeleteSelf: "notify.InDeleteSelf", - InMoveSelf: "notify.InMoveSelf", -} - -// Inotify behavior events are not **currently** supported by notify package. -const ( - inDontFollow = Event(unix.IN_DONT_FOLLOW) - inExclUnlink = Event(unix.IN_EXCL_UNLINK) - inMaskAdd = Event(unix.IN_MASK_ADD) - inOneshot = Event(unix.IN_ONESHOT) - inOnlydir = Event(unix.IN_ONLYDIR) -) - -type event struct { - sys unix.InotifyEvent - path string - event Event -} - -func (e *event) Event() Event { return e.event } -func (e *event) Path() string { return e.path } -func (e *event) Sys() interface{} { return &e.sys } -func (e *event) isDir() (bool, error) { return e.sys.Mask&unix.IN_ISDIR != 0, nil } diff --git a/vendor/github.com/rjeczalik/notify/event_kqueue.go b/vendor/github.com/rjeczalik/notify/event_kqueue.go deleted file mode 100644 index 422ac87f6..000000000 --- a/vendor/github.com/rjeczalik/notify/event_kqueue.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build darwin,kqueue dragonfly freebsd netbsd openbsd - -package notify - -import "syscall" - -// TODO(pblaszczyk): ensure in runtime notify built-in event values do not -// overlap with platform-defined ones. - -// Platform independent event values. -const ( - osSpecificCreate Event = 0x0100 << iota - osSpecificRemove - osSpecificWrite - osSpecificRename - // internal - // recursive is used to distinguish recursive eventsets from non-recursive ones - recursive - // omit is used for dispatching internal events; only those events are sent - // for which both the event and the watchpoint has omit in theirs event sets. - omit -) - -const ( - // NoteDelete is an event reported when the unlink() system call was called - // on the file referenced by the descriptor. - NoteDelete = Event(syscall.NOTE_DELETE) - // NoteWrite is an event reported when a write occurred on the file - // referenced by the descriptor. - NoteWrite = Event(syscall.NOTE_WRITE) - // NoteExtend is an event reported when the file referenced by the - // descriptor was extended. - NoteExtend = Event(syscall.NOTE_EXTEND) - // NoteAttrib is an event reported when the file referenced - // by the descriptor had its attributes changed. - NoteAttrib = Event(syscall.NOTE_ATTRIB) - // NoteLink is an event reported when the link count on the file changed. - NoteLink = Event(syscall.NOTE_LINK) - // NoteRename is an event reported when the file referenced - // by the descriptor was renamed. - NoteRename = Event(syscall.NOTE_RENAME) - // NoteRevoke is an event reported when access to the file was revoked via - // revoke(2) or the underlying file system was unmounted. - NoteRevoke = Event(syscall.NOTE_REVOKE) -) - -var osestr = map[Event]string{ - NoteDelete: "notify.NoteDelete", - NoteWrite: "notify.NoteWrite", - NoteExtend: "notify.NoteExtend", - NoteAttrib: "notify.NoteAttrib", - NoteLink: "notify.NoteLink", - NoteRename: "notify.NoteRename", - NoteRevoke: "notify.NoteRevoke", -} diff --git a/vendor/github.com/rjeczalik/notify/event_readdcw.go b/vendor/github.com/rjeczalik/notify/event_readdcw.go deleted file mode 100644 index f7b82de0c..000000000 --- a/vendor/github.com/rjeczalik/notify/event_readdcw.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build windows - -package notify - -import ( - "os" - "path/filepath" - "syscall" -) - -// Platform independent event values. -const ( - osSpecificCreate Event = 1 << (20 + iota) - osSpecificRemove - osSpecificWrite - osSpecificRename - // recursive is used to distinguish recursive eventsets from non-recursive ones - recursive - // omit is used for dispatching internal events; only those events are sent - // for which both the event and the watchpoint has omit in theirs event sets. - omit - // dirmarker TODO(pknap) - dirmarker -) - -// ReadDirectoryChangesW filters -// On Windows the following events can be passed to Watch. A different set of -// events (see actions below) are received on the channel passed to Watch. -// For more information refer to -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx -const ( - FileNotifyChangeFileName = Event(syscall.FILE_NOTIFY_CHANGE_FILE_NAME) - FileNotifyChangeDirName = Event(syscall.FILE_NOTIFY_CHANGE_DIR_NAME) - FileNotifyChangeAttributes = Event(syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES) - FileNotifyChangeSize = Event(syscall.FILE_NOTIFY_CHANGE_SIZE) - FileNotifyChangeLastWrite = Event(syscall.FILE_NOTIFY_CHANGE_LAST_WRITE) - FileNotifyChangeLastAccess = Event(syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS) - FileNotifyChangeCreation = Event(syscall.FILE_NOTIFY_CHANGE_CREATION) - FileNotifyChangeSecurity = Event(syscallFileNotifyChangeSecurity) -) - -const ( - fileNotifyChangeAll = 0x17f // logical sum of all FileNotifyChange* events. - fileNotifyChangeModified = fileNotifyChangeAll &^ (FileNotifyChangeFileName | FileNotifyChangeDirName) -) - -// according to: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx -// this flag should be declared in: http://golang.org/src/pkg/syscall/ztypes_windows.go -const syscallFileNotifyChangeSecurity = 0x00000100 - -// ReadDirectoryChangesW actions -// The following events are returned on the channel passed to Watch, but cannot -// be passed to Watch itself (see filters above). You can find a table showing -// the relation between actions and filteres at -// https://github.com/rjeczalik/notify/issues/10#issuecomment-66179535 -// The msdn documentation on actions is part of -// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364391(v=vs.85).aspx -const ( - FileActionAdded = Event(syscall.FILE_ACTION_ADDED) << 12 - FileActionRemoved = Event(syscall.FILE_ACTION_REMOVED) << 12 - FileActionModified = Event(syscall.FILE_ACTION_MODIFIED) << 14 - FileActionRenamedOldName = Event(syscall.FILE_ACTION_RENAMED_OLD_NAME) << 15 - FileActionRenamedNewName = Event(syscall.FILE_ACTION_RENAMED_NEW_NAME) << 16 -) - -const fileActionAll = 0x7f000 // logical sum of all FileAction* events. - -var osestr = map[Event]string{ - FileNotifyChangeFileName: "notify.FileNotifyChangeFileName", - FileNotifyChangeDirName: "notify.FileNotifyChangeDirName", - FileNotifyChangeAttributes: "notify.FileNotifyChangeAttributes", - FileNotifyChangeSize: "notify.FileNotifyChangeSize", - FileNotifyChangeLastWrite: "notify.FileNotifyChangeLastWrite", - FileNotifyChangeLastAccess: "notify.FileNotifyChangeLastAccess", - FileNotifyChangeCreation: "notify.FileNotifyChangeCreation", - FileNotifyChangeSecurity: "notify.FileNotifyChangeSecurity", - - FileActionAdded: "notify.FileActionAdded", - FileActionRemoved: "notify.FileActionRemoved", - FileActionModified: "notify.FileActionModified", - FileActionRenamedOldName: "notify.FileActionRenamedOldName", - FileActionRenamedNewName: "notify.FileActionRenamedNewName", -} - -const ( - fTypeUnknown uint8 = iota - fTypeFile - fTypeDirectory -) - -// TODO(ppknap) : doc. -type event struct { - pathw []uint16 - name string - ftype uint8 - action uint32 - filter uint32 - e Event -} - -func (e *event) Event() Event { return e.e } -func (e *event) Path() string { return filepath.Join(syscall.UTF16ToString(e.pathw), e.name) } -func (e *event) Sys() interface{} { return e.ftype } - -func (e *event) isDir() (bool, error) { - if e.ftype != fTypeUnknown { - return e.ftype == fTypeDirectory, nil - } - fi, err := os.Stat(e.Path()) - if err != nil { - return false, err - } - return fi.IsDir(), nil -} diff --git a/vendor/github.com/rjeczalik/notify/event_stub.go b/vendor/github.com/rjeczalik/notify/event_stub.go deleted file mode 100644 index faac7c7cb..000000000 --- a/vendor/github.com/rjeczalik/notify/event_stub.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build !darwin,!linux,!freebsd,!dragonfly,!netbsd,!openbsd,!windows -// +build !kqueue,!solaris - -package notify - -// Platform independent event values. -const ( - osSpecificCreate Event = 1 << iota - osSpecificRemove - osSpecificWrite - osSpecificRename - // internal - // recursive is used to distinguish recursive eventsets from non-recursive ones - recursive - // omit is used for dispatching internal events; only those events are sent - // for which both the event and the watchpoint has omit in theirs event sets. - omit -) - -var osestr = map[Event]string{} - -type event struct{} - -func (e *event) Event() (_ Event) { return } -func (e *event) Path() (_ string) { return } -func (e *event) Sys() (_ interface{}) { return } -func (e *event) isDir() (_ bool, _ error) { return } diff --git a/vendor/github.com/rjeczalik/notify/event_trigger.go b/vendor/github.com/rjeczalik/notify/event_trigger.go deleted file mode 100644 index 94470fd37..000000000 --- a/vendor/github.com/rjeczalik/notify/event_trigger.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build darwin,kqueue dragonfly freebsd netbsd openbsd solaris - -package notify - -type event struct { - p string - e Event - d bool - pe interface{} -} - -func (e *event) Event() Event { return e.e } - -func (e *event) Path() string { return e.p } - -func (e *event) Sys() interface{} { return e.pe } - -func (e *event) isDir() (bool, error) { return e.d, nil } diff --git a/vendor/github.com/rjeczalik/notify/go.mod b/vendor/github.com/rjeczalik/notify/go.mod deleted file mode 100644 index 2bbfbf3bf..000000000 --- a/vendor/github.com/rjeczalik/notify/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/rjeczalik/notify - -require golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7 diff --git a/vendor/github.com/rjeczalik/notify/node.go b/vendor/github.com/rjeczalik/notify/node.go deleted file mode 100644 index aced8b9c4..000000000 --- a/vendor/github.com/rjeczalik/notify/node.go +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -package notify - -import ( - "errors" - "io/ioutil" - "os" - "path/filepath" -) - -var errSkip = errors.New("notify: skip") - -type walkPathFunc func(nd node, isbase bool) error - -type walkFunc func(node) error - -func errnotexist(name string) error { - return &os.PathError{ - Op: "Node", - Path: name, - Err: os.ErrNotExist, - } -} - -type node struct { - Name string - Watch watchpoint - Child map[string]node -} - -func newnode(name string) node { - return node{ - Name: name, - Watch: make(watchpoint), - Child: make(map[string]node), - } -} - -func (nd node) addchild(name, base string) node { - child, ok := nd.Child[base] - if !ok { - child = newnode(name) - nd.Child[base] = child - } - return child -} - -func (nd node) Add(name string) node { - i := indexbase(nd.Name, name) - if i == -1 { - return node{} - } - for j := indexSep(name[i:]); j != -1; j = indexSep(name[i:]) { - nd = nd.addchild(name[:i+j], name[i:i+j]) - i += j + 1 - } - return nd.addchild(name, name[i:]) -} - -func (nd node) AddDir(fn walkFunc) error { - stack := []node{nd} -Traverse: - for n := len(stack); n != 0; n = len(stack) { - nd, stack = stack[n-1], stack[:n-1] - switch err := fn(nd); err { - case nil: - case errSkip: - continue Traverse - default: - return &os.PathError{ - Op: "error while traversing", - Path: nd.Name, - Err: err, - } - } - // TODO(rjeczalik): tolerate open failures - add failed names to - // AddDirError and notify users which names are not added to the tree. - fi, err := ioutil.ReadDir(nd.Name) - if err != nil { - return err - } - for _, fi := range fi { - if fi.Mode()&(os.ModeSymlink|os.ModeDir) == os.ModeDir { - name := filepath.Join(nd.Name, fi.Name()) - stack = append(stack, nd.addchild(name, name[len(nd.Name)+1:])) - } - } - } - return nil -} - -func (nd node) Get(name string) (node, error) { - i := indexbase(nd.Name, name) - if i == -1 { - return node{}, errnotexist(name) - } - ok := false - for j := indexSep(name[i:]); j != -1; j = indexSep(name[i:]) { - if nd, ok = nd.Child[name[i:i+j]]; !ok { - return node{}, errnotexist(name) - } - i += j + 1 - } - if nd, ok = nd.Child[name[i:]]; !ok { - return node{}, errnotexist(name) - } - return nd, nil -} - -func (nd node) Del(name string) error { - i := indexbase(nd.Name, name) - if i == -1 { - return errnotexist(name) - } - stack := []node{nd} - ok := false - for j := indexSep(name[i:]); j != -1; j = indexSep(name[i:]) { - if nd, ok = nd.Child[name[i:i+j]]; !ok { - return errnotexist(name[:i+j]) - } - stack = append(stack, nd) - } - if nd, ok = nd.Child[name[i:]]; !ok { - return errnotexist(name) - } - nd.Child = nil - nd.Watch = nil - for name, i = base(nd.Name), len(stack); i != 0; name, i = base(nd.Name), i-1 { - nd = stack[i-1] - if nd := nd.Child[name]; len(nd.Watch) > 1 || len(nd.Child) != 0 { - break - } else { - nd.Child = nil - nd.Watch = nil - } - delete(nd.Child, name) - } - return nil -} - -func (nd node) Walk(fn walkFunc) error { - stack := []node{nd} -Traverse: - for n := len(stack); n != 0; n = len(stack) { - nd, stack = stack[n-1], stack[:n-1] - switch err := fn(nd); err { - case nil: - case errSkip: - continue Traverse - default: - return err - } - for name, nd := range nd.Child { - if name == "" { - // Node storing inactive watchpoints has empty name, skip it - // form traversing. Root node has also an empty name, but it - // never has a parent node. - continue - } - stack = append(stack, nd) - } - } - return nil -} - -func (nd node) WalkPath(name string, fn walkPathFunc) error { - i := indexbase(nd.Name, name) - if i == -1 { - return errnotexist(name) - } - ok := false - for j := indexSep(name[i:]); j != -1; j = indexSep(name[i:]) { - switch err := fn(nd, false); err { - case nil: - case errSkip: - return nil - default: - return err - } - if nd, ok = nd.Child[name[i:i+j]]; !ok { - return errnotexist(name[:i+j]) - } - i += j + 1 - } - switch err := fn(nd, false); err { - case nil: - case errSkip: - return nil - default: - return err - } - if nd, ok = nd.Child[name[i:]]; !ok { - return errnotexist(name) - } - switch err := fn(nd, true); err { - case nil, errSkip: - return nil - default: - return err - } -} - -type root struct { - nd node -} - -func (r root) addroot(name string) node { - if vol := filepath.VolumeName(name); vol != "" { - root, ok := r.nd.Child[vol] - if !ok { - root = r.nd.addchild(vol, vol) - } - return root - } - return r.nd -} - -func (r root) root(name string) (node, error) { - if vol := filepath.VolumeName(name); vol != "" { - nd, ok := r.nd.Child[vol] - if !ok { - return node{}, errnotexist(name) - } - return nd, nil - } - return r.nd, nil -} - -func (r root) Add(name string) node { - return r.addroot(name).Add(name) -} - -func (r root) AddDir(dir string, fn walkFunc) error { - return r.Add(dir).AddDir(fn) -} - -func (r root) Del(name string) error { - nd, err := r.root(name) - if err != nil { - return err - } - return nd.Del(name) -} - -func (r root) Get(name string) (node, error) { - nd, err := r.root(name) - if err != nil { - return node{}, err - } - if nd.Name != name { - if nd, err = nd.Get(name); err != nil { - return node{}, err - } - } - return nd, nil -} - -func (r root) Walk(name string, fn walkFunc) error { - nd, err := r.Get(name) - if err != nil { - return err - } - return nd.Walk(fn) -} - -func (r root) WalkPath(name string, fn walkPathFunc) error { - nd, err := r.root(name) - if err != nil { - return err - } - return nd.WalkPath(name, fn) -} diff --git a/vendor/github.com/rjeczalik/notify/notify.go b/vendor/github.com/rjeczalik/notify/notify.go deleted file mode 100644 index 7d2eec3a2..000000000 --- a/vendor/github.com/rjeczalik/notify/notify.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// BUG(rjeczalik): Notify does not collect watchpoints, when underlying watches -// were removed by their os-specific watcher implementations. Instead users are -// advised to listen on persistent paths to have guarantee they receive events -// for the whole lifetime of their applications (to discuss see #69). - -// BUG(ppknap): Linux (inotify) does not support watcher behavior masks like -// InOneshot, InOnlydir etc. Instead users are advised to perform the filtering -// themselves (to discuss see #71). - -// BUG(ppknap): Notify was not tested for short path name support under Windows -// (ReadDirectoryChangesW). - -// BUG(ppknap): Windows (ReadDirectoryChangesW) cannot recognize which notification -// triggers FileActionModified event. (to discuss see #75). - -package notify - -var defaultTree = newTree() - -// Watch sets up a watchpoint on path listening for events given by the events -// argument. -// -// File or directory given by the path must exist, otherwise Watch will fail -// with non-nil error. Notify resolves, for its internal purpose, any symlinks -// the provided path may contain, so it may fail if the symlinks form a cycle. -// It does so, since not all watcher implementations treat passed paths as-is. -// E.g. FSEvents reports a real path for every event, setting a watchpoint -// on /tmp will report events with paths rooted at /private/tmp etc. -// -// The c almost always is a buffered channel. Watch will not block sending to c -// - the caller must ensure that c has sufficient buffer space to keep up with -// the expected event rate. -// -// It is allowed to pass the same channel multiple times with different event -// list or different paths. Calling Watch with different event lists for a single -// watchpoint expands its event set. The only way to shrink it, is to call -// Stop on its channel. -// -// Calling Watch with empty event list does expand nor shrink watchpoint's event -// set. If c is the first channel to listen for events on the given path, Watch -// will seamlessly create a watch on the filesystem. -// -// Notify dispatches copies of single filesystem event to all channels registered -// for each path. If a single filesystem event contains multiple coalesced events, -// each of them is dispatched separately. E.g. the following filesystem change: -// -// ~ $ echo Hello > Notify.txt -// -// dispatches two events - notify.Create and notify.Write. However, it may depend -// on the underlying watcher implementation whether OS reports both of them. -// -// Windows and recursive watches -// -// If a directory which path was used to create recursive watch under Windows -// gets deleted, the OS will not report such event. It is advised to keep in -// mind this limitation while setting recursive watchpoints for your application, -// e.g. use persistent paths like %userprofile% or watch additionally parent -// directory of a recursive watchpoint in order to receive delete events for it. -func Watch(path string, c chan<- EventInfo, events ...Event) error { - return defaultTree.Watch(path, c, events...) -} - -// Stop removes all watchpoints registered for c. All underlying watches are -// also removed, for which c was the last channel listening for events. -// -// Stop does not close c. When Stop returns, it is guaranteed that c will -// receive no more signals. -func Stop(c chan<- EventInfo) { - defaultTree.Stop(c) -} diff --git a/vendor/github.com/rjeczalik/notify/tree.go b/vendor/github.com/rjeczalik/notify/tree.go deleted file mode 100644 index cd6afd60d..000000000 --- a/vendor/github.com/rjeczalik/notify/tree.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -package notify - -const buffer = 128 - -type tree interface { - Watch(string, chan<- EventInfo, ...Event) error - Stop(chan<- EventInfo) - Close() error -} - -func newTree() tree { - c := make(chan EventInfo, buffer) - w := newWatcher(c) - if rw, ok := w.(recursiveWatcher); ok { - return newRecursiveTree(rw, c) - } - return newNonrecursiveTree(w, c, make(chan EventInfo, buffer)) -} diff --git a/vendor/github.com/rjeczalik/notify/tree_nonrecursive.go b/vendor/github.com/rjeczalik/notify/tree_nonrecursive.go deleted file mode 100644 index dfa72d1d2..000000000 --- a/vendor/github.com/rjeczalik/notify/tree_nonrecursive.go +++ /dev/null @@ -1,292 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -package notify - -import "sync" - -// nonrecursiveTree TODO(rjeczalik) -type nonrecursiveTree struct { - rw sync.RWMutex // protects root - root root - w watcher - c chan EventInfo - rec chan EventInfo -} - -// newNonrecursiveTree TODO(rjeczalik) -func newNonrecursiveTree(w watcher, c, rec chan EventInfo) *nonrecursiveTree { - if rec == nil { - rec = make(chan EventInfo, buffer) - } - t := &nonrecursiveTree{ - root: root{nd: newnode("")}, - w: w, - c: c, - rec: rec, - } - go t.dispatch(c) - go t.internal(rec) - return t -} - -// dispatch TODO(rjeczalik) -func (t *nonrecursiveTree) dispatch(c <-chan EventInfo) { - for ei := range c { - dbgprintf("dispatching %v on %q", ei.Event(), ei.Path()) - go func(ei EventInfo) { - var nd node - var isrec bool - dir, base := split(ei.Path()) - fn := func(it node, isbase bool) error { - isrec = isrec || it.Watch.IsRecursive() - if isbase { - nd = it - } else { - it.Watch.Dispatch(ei, recursive) - } - return nil - } - t.rw.RLock() - // Notify recursive watchpoints found on the path. - if err := t.root.WalkPath(dir, fn); err != nil { - dbgprint("dispatch did not reach leaf:", err) - t.rw.RUnlock() - return - } - // Notify parent watchpoint. - nd.Watch.Dispatch(ei, 0) - isrec = isrec || nd.Watch.IsRecursive() - // If leaf watchpoint exists, notify it. - if nd, ok := nd.Child[base]; ok { - isrec = isrec || nd.Watch.IsRecursive() - nd.Watch.Dispatch(ei, 0) - } - t.rw.RUnlock() - // If the event describes newly leaf directory created within - if !isrec || ei.Event() != Create { - return - } - if ok, err := ei.(isDirer).isDir(); !ok || err != nil { - return - } - t.rec <- ei - }(ei) - } -} - -// internal TODO(rjeczalik) -func (t *nonrecursiveTree) internal(rec <-chan EventInfo) { - for ei := range rec { - var nd node - var eset = internal - t.rw.Lock() - t.root.WalkPath(ei.Path(), func(it node, _ bool) error { - if e := it.Watch[t.rec]; e != 0 && e > eset { - eset = e - } - nd = it - return nil - }) - if eset == internal { - t.rw.Unlock() - continue - } - err := nd.Add(ei.Path()).AddDir(t.recFunc(eset)) - t.rw.Unlock() - if err != nil { - dbgprintf("internal(%p) error: %v", rec, err) - } - } -} - -// watchAdd TODO(rjeczalik) -func (t *nonrecursiveTree) watchAdd(nd node, c chan<- EventInfo, e Event) eventDiff { - if e&recursive != 0 { - diff := nd.Watch.Add(t.rec, e|Create|omit) - nd.Watch.Add(c, e) - return diff - } - return nd.Watch.Add(c, e) -} - -// watchDelMin TODO(rjeczalik) -func (t *nonrecursiveTree) watchDelMin(min Event, nd node, c chan<- EventInfo, e Event) eventDiff { - old, ok := nd.Watch[t.rec] - if ok { - nd.Watch[t.rec] = min - } - diff := nd.Watch.Del(c, e) - if ok { - switch old &^= diff[0] &^ diff[1]; { - case old|internal == internal: - delete(nd.Watch, t.rec) - if set, ok := nd.Watch[nil]; ok && len(nd.Watch) == 1 && set == 0 { - delete(nd.Watch, nil) - } - default: - nd.Watch.Add(t.rec, old|Create) - switch { - case diff == none: - case diff[1]|Create == diff[0]: - diff = none - default: - diff[1] |= Create - } - } - } - return diff -} - -// watchDel TODO(rjeczalik) -func (t *nonrecursiveTree) watchDel(nd node, c chan<- EventInfo, e Event) eventDiff { - return t.watchDelMin(0, nd, c, e) -} - -// Watch TODO(rjeczalik) -func (t *nonrecursiveTree) Watch(path string, c chan<- EventInfo, events ...Event) error { - if c == nil { - panic("notify: Watch using nil channel") - } - // Expanding with empty event set is a nop. - if len(events) == 0 { - return nil - } - path, isrec, err := cleanpath(path) - if err != nil { - return err - } - eset := joinevents(events) - t.rw.Lock() - defer t.rw.Unlock() - nd := t.root.Add(path) - if isrec { - return t.watchrec(nd, c, eset|recursive) - } - return t.watch(nd, c, eset) -} - -func (t *nonrecursiveTree) watch(nd node, c chan<- EventInfo, e Event) (err error) { - diff := nd.Watch.Add(c, e) - switch { - case diff == none: - return nil - case diff[1] == 0: - // TODO(rjeczalik): cleanup this panic after implementation is stable - panic("eset is empty: " + nd.Name) - case diff[0] == 0: - err = t.w.Watch(nd.Name, diff[1]) - default: - err = t.w.Rewatch(nd.Name, diff[0], diff[1]) - } - if err != nil { - nd.Watch.Del(c, diff.Event()) - return err - } - return nil -} - -func (t *nonrecursiveTree) recFunc(e Event) walkFunc { - return func(nd node) error { - switch diff := nd.Watch.Add(t.rec, e|omit|Create); { - case diff == none: - case diff[1] == 0: - // TODO(rjeczalik): cleanup this panic after implementation is stable - panic("eset is empty: " + nd.Name) - case diff[0] == 0: - t.w.Watch(nd.Name, diff[1]) - default: - t.w.Rewatch(nd.Name, diff[0], diff[1]) - } - return nil - } -} - -func (t *nonrecursiveTree) watchrec(nd node, c chan<- EventInfo, e Event) error { - var traverse func(walkFunc) error - // Non-recursive tree listens on Create event for every recursive - // watchpoint in order to automagically set a watch for every - // created directory. - switch diff := nd.Watch.dryAdd(t.rec, e|Create); { - case diff == none: - t.watchAdd(nd, c, e) - nd.Watch.Add(t.rec, e|omit|Create) - return nil - case diff[1] == 0: - // TODO(rjeczalik): cleanup this panic after implementation is stable - panic("eset is empty: " + nd.Name) - case diff[0] == 0: - // TODO(rjeczalik): BFS into directories and skip subtree as soon as first - // recursive watchpoint is encountered. - traverse = nd.AddDir - default: - traverse = nd.Walk - } - // TODO(rjeczalik): account every path that failed to be (re)watched - // and retry. - if err := traverse(t.recFunc(e)); err != nil { - return err - } - t.watchAdd(nd, c, e) - return nil -} - -type walkWatchpointFunc func(Event, node) error - -func (t *nonrecursiveTree) walkWatchpoint(nd node, fn walkWatchpointFunc) error { - type minode struct { - min Event - nd node - } - mnd := minode{nd: nd} - stack := []minode{mnd} -Traverse: - for n := len(stack); n != 0; n = len(stack) { - mnd, stack = stack[n-1], stack[:n-1] - // There must be no recursive watchpoints if the node has no watchpoints - // itself (every node in subtree rooted at recursive watchpoints must - // have at least nil (total) and t.rec watchpoints). - if len(mnd.nd.Watch) != 0 { - switch err := fn(mnd.min, mnd.nd); err { - case nil: - case errSkip: - continue Traverse - default: - return err - } - } - for _, nd := range mnd.nd.Child { - stack = append(stack, minode{mnd.nd.Watch[t.rec], nd}) - } - } - return nil -} - -// Stop TODO(rjeczalik) -func (t *nonrecursiveTree) Stop(c chan<- EventInfo) { - fn := func(min Event, nd node) error { - // TODO(rjeczalik): aggregate watcher errors and retry; in worst case - // forward to the user. - switch diff := t.watchDelMin(min, nd, c, all); { - case diff == none: - return nil - case diff[1] == 0: - t.w.Unwatch(nd.Name) - default: - t.w.Rewatch(nd.Name, diff[0], diff[1]) - } - return nil - } - t.rw.Lock() - err := t.walkWatchpoint(t.root.nd, fn) // TODO(rjeczalik): store max root per c - t.rw.Unlock() - dbgprintf("Stop(%p) error: %v\n", c, err) -} - -// Close TODO(rjeczalik) -func (t *nonrecursiveTree) Close() error { - err := t.w.Close() - close(t.c) - return err -} diff --git a/vendor/github.com/rjeczalik/notify/tree_recursive.go b/vendor/github.com/rjeczalik/notify/tree_recursive.go deleted file mode 100644 index 7f00dfe35..000000000 --- a/vendor/github.com/rjeczalik/notify/tree_recursive.go +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -package notify - -import "sync" - -// watchAdd TODO(rjeczalik) -func watchAdd(nd node, c chan<- EventInfo, e Event) eventDiff { - diff := nd.Watch.Add(c, e) - if wp := nd.Child[""].Watch; len(wp) != 0 { - e = wp.Total() - diff[0] |= e - diff[1] |= e - if diff[0] == diff[1] { - return none - } - } - return diff -} - -// watchAddInactive TODO(rjeczalik) -func watchAddInactive(nd node, c chan<- EventInfo, e Event) eventDiff { - wp := nd.Child[""].Watch - if wp == nil { - wp = make(watchpoint) - nd.Child[""] = node{Watch: wp} - } - diff := wp.Add(c, e) - e = nd.Watch.Total() - diff[0] |= e - diff[1] |= e - if diff[0] == diff[1] { - return none - } - return diff -} - -// watchCopy TODO(rjeczalik) -func watchCopy(src, dst node) { - for c, e := range src.Watch { - if c == nil { - continue - } - watchAddInactive(dst, c, e) - } - if wpsrc := src.Child[""].Watch; len(wpsrc) != 0 { - wpdst := dst.Child[""].Watch - for c, e := range wpsrc { - if c == nil { - continue - } - wpdst.Add(c, e) - } - } -} - -// watchDel TODO(rjeczalik) -func watchDel(nd node, c chan<- EventInfo, e Event) eventDiff { - diff := nd.Watch.Del(c, e) - if wp := nd.Child[""].Watch; len(wp) != 0 { - diffInactive := wp.Del(c, e) - e = wp.Total() - // TODO(rjeczalik): add e if e != all? - diff[0] |= diffInactive[0] | e - diff[1] |= diffInactive[1] | e - if diff[0] == diff[1] { - return none - } - } - return diff -} - -// watchTotal TODO(rjeczalik) -func watchTotal(nd node) Event { - e := nd.Watch.Total() - if wp := nd.Child[""].Watch; len(wp) != 0 { - e |= wp.Total() - } - return e -} - -// watchIsRecursive TODO(rjeczalik) -func watchIsRecursive(nd node) bool { - ok := nd.Watch.IsRecursive() - // TODO(rjeczalik): add a test for len(wp) != 0 change the condition. - if wp := nd.Child[""].Watch; len(wp) != 0 { - // If a watchpoint holds inactive watchpoints, it means it's a parent - // one, which is recursive by nature even though it may be not recursive - // itself. - ok = true - } - return ok -} - -// recursiveTree TODO(rjeczalik) -type recursiveTree struct { - rw sync.RWMutex // protects root - root root - // TODO(rjeczalik): merge watcher + recursiveWatcher after #5 and #6 - w interface { - watcher - recursiveWatcher - } - c chan EventInfo -} - -// newRecursiveTree TODO(rjeczalik) -func newRecursiveTree(w recursiveWatcher, c chan EventInfo) *recursiveTree { - t := &recursiveTree{ - root: root{nd: newnode("")}, - w: struct { - watcher - recursiveWatcher - }{w.(watcher), w}, - c: c, - } - go t.dispatch() - return t -} - -// dispatch TODO(rjeczalik) -func (t *recursiveTree) dispatch() { - for ei := range t.c { - dbgprintf("dispatching %v on %q", ei.Event(), ei.Path()) - go func(ei EventInfo) { - nd, ok := node{}, false - dir, base := split(ei.Path()) - fn := func(it node, isbase bool) error { - if isbase { - nd = it - } else { - it.Watch.Dispatch(ei, recursive) - } - return nil - } - t.rw.RLock() - defer t.rw.RUnlock() - // Notify recursive watchpoints found on the path. - if err := t.root.WalkPath(dir, fn); err != nil { - dbgprint("dispatch did not reach leaf:", err) - return - } - // Notify parent watchpoint. - nd.Watch.Dispatch(ei, 0) - // If leaf watchpoint exists, notify it. - if nd, ok = nd.Child[base]; ok { - nd.Watch.Dispatch(ei, 0) - } - }(ei) - } -} - -// Watch TODO(rjeczalik) -func (t *recursiveTree) Watch(path string, c chan<- EventInfo, events ...Event) error { - if c == nil { - panic("notify: Watch using nil channel") - } - // Expanding with empty event set is a nop. - if len(events) == 0 { - return nil - } - path, isrec, err := cleanpath(path) - if err != nil { - return err - } - eventset := joinevents(events) - if isrec { - eventset |= recursive - } - t.rw.Lock() - defer t.rw.Unlock() - // case 1: cur is a child - // - // Look for parent watch which already covers the given path. - parent := node{} - self := false - err = t.root.WalkPath(path, func(nd node, isbase bool) error { - if watchTotal(nd) != 0 { - parent = nd - self = isbase - return errSkip - } - return nil - }) - cur := t.root.Add(path) // add after the walk, so it's less to traverse - if err == nil && parent.Watch != nil { - // Parent watch found. Register inactive watchpoint, so we have enough - // information to shrink the eventset on eventual Stop. - // return t.resetwatchpoint(parent, parent, c, eventset|inactive) - var diff eventDiff - if self { - diff = watchAdd(cur, c, eventset) - } else { - diff = watchAddInactive(parent, c, eventset) - } - switch { - case diff == none: - // the parent watchpoint already covers requested subtree with its - // eventset - case diff[0] == 0: - // TODO(rjeczalik): cleanup this panic after implementation is stable - panic("dangling watchpoint: " + parent.Name) - default: - if isrec || watchIsRecursive(parent) { - err = t.w.RecursiveRewatch(parent.Name, parent.Name, diff[0], diff[1]) - } else { - err = t.w.Rewatch(parent.Name, diff[0], diff[1]) - } - if err != nil { - watchDel(parent, c, diff.Event()) - return err - } - watchAdd(cur, c, eventset) - // TODO(rjeczalik): account top-most path for c - return nil - } - if !self { - watchAdd(cur, c, eventset) - } - return nil - } - // case 2: cur is new parent - // - // Look for children nodes, unwatch n-1 of them and rewatch the last one. - var children []node - fn := func(nd node) error { - if len(nd.Watch) == 0 { - return nil - } - children = append(children, nd) - return errSkip - } - switch must(cur.Walk(fn)); len(children) { - case 0: - // no child watches, cur holds a new watch - case 1: - watchAdd(cur, c, eventset) // TODO(rjeczalik): update cache c subtree root? - watchCopy(children[0], cur) - err = t.w.RecursiveRewatch(children[0].Name, cur.Name, watchTotal(children[0]), - watchTotal(cur)) - if err != nil { - // Clean inactive watchpoint. The c chan did not exist before. - cur.Child[""] = node{} - delete(cur.Watch, c) - return err - } - return nil - default: - watchAdd(cur, c, eventset) - // Copy children inactive watchpoints to the new parent. - for _, nd := range children { - watchCopy(nd, cur) - } - // Watch parent subtree. - if err = t.w.RecursiveWatch(cur.Name, watchTotal(cur)); err != nil { - // Clean inactive watchpoint. The c chan did not exist before. - cur.Child[""] = node{} - delete(cur.Watch, c) - return err - } - // Unwatch children subtrees. - var e error - for _, nd := range children { - if watchIsRecursive(nd) { - e = t.w.RecursiveUnwatch(nd.Name) - } else { - e = t.w.Unwatch(nd.Name) - } - if e != nil { - err = nonil(err, e) - // TODO(rjeczalik): child is still watched, warn all its watchpoints - // about possible duplicate events via Error event - } - } - return err - } - // case 3: cur is new, alone node - switch diff := watchAdd(cur, c, eventset); { - case diff == none: - // TODO(rjeczalik): cleanup this panic after implementation is stable - panic("watch requested but no parent watchpoint found: " + cur.Name) - case diff[0] == 0: - if isrec { - err = t.w.RecursiveWatch(cur.Name, diff[1]) - } else { - err = t.w.Watch(cur.Name, diff[1]) - } - if err != nil { - watchDel(cur, c, diff.Event()) - return err - } - default: - // TODO(rjeczalik): cleanup this panic after implementation is stable - panic("watch requested but no parent watchpoint found: " + cur.Name) - } - return nil -} - -// Stop TODO(rjeczalik) -// -// TODO(rjeczalik): Split parent watchpoint - transfer watches to children -// if parent is no longer needed. This carries a risk that underlying -// watcher calls could fail - reconsider if it's worth the effort. -func (t *recursiveTree) Stop(c chan<- EventInfo) { - var err error - fn := func(nd node) (e error) { - diff := watchDel(nd, c, all) - switch { - case diff == none && watchTotal(nd) == 0: - // TODO(rjeczalik): There's no watchpoints deeper in the tree, - // probably we should remove the nodes as well. - return nil - case diff == none: - // Removing c from nd does not require shrinking its eventset. - case diff[1] == 0: - if watchIsRecursive(nd) { - e = t.w.RecursiveUnwatch(nd.Name) - } else { - e = t.w.Unwatch(nd.Name) - } - default: - if watchIsRecursive(nd) { - e = t.w.RecursiveRewatch(nd.Name, nd.Name, diff[0], diff[1]) - } else { - e = t.w.Rewatch(nd.Name, diff[0], diff[1]) - } - } - fn := func(nd node) error { - watchDel(nd, c, all) - return nil - } - err = nonil(err, e, nd.Walk(fn)) - // TODO(rjeczalik): if e != nil store dummy chan in nd.Watch just to - // retry un/rewatching next time and/or let the user handle the failure - // vie Error event? - return errSkip - } - t.rw.Lock() - e := t.root.Walk("", fn) // TODO(rjeczalik): use max root per c - t.rw.Unlock() - if e != nil { - err = nonil(err, e) - } - dbgprintf("Stop(%p) error: %v\n", c, err) -} - -// Close TODO(rjeczalik) -func (t *recursiveTree) Close() error { - err := t.w.Close() - close(t.c) - return err -} diff --git a/vendor/github.com/rjeczalik/notify/util.go b/vendor/github.com/rjeczalik/notify/util.go deleted file mode 100644 index 67e01fbbd..000000000 --- a/vendor/github.com/rjeczalik/notify/util.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -package notify - -import ( - "errors" - "os" - "path/filepath" - "strings" -) - -const all = ^Event(0) -const sep = string(os.PathSeparator) - -var errDepth = errors.New("exceeded allowed iteration count (circular symlink?)") - -func min(i, j int) int { - if i > j { - return j - } - return i -} - -func max(i, j int) int { - if i < j { - return j - } - return i -} - -// must panics if err is non-nil. -func must(err error) { - if err != nil { - panic(err) - } -} - -// nonil gives first non-nil error from the given arguments. -func nonil(err ...error) error { - for _, err := range err { - if err != nil { - return err - } - } - return nil -} - -func cleanpath(path string) (realpath string, isrec bool, err error) { - if strings.HasSuffix(path, "...") { - isrec = true - path = path[:len(path)-3] - } - if path, err = filepath.Abs(path); err != nil { - return "", false, err - } - if path, err = canonical(path); err != nil { - return "", false, err - } - return path, isrec, nil -} - -// canonical resolves any symlink in the given path and returns it in a clean form. -// It expects the path to be absolute. It fails to resolve circular symlinks by -// maintaining a simple iteration limit. -func canonical(p string) (string, error) { - p, err := filepath.Abs(p) - if err != nil { - return "", err - } - for i, j, depth := 1, 0, 1; i < len(p); i, depth = i+1, depth+1 { - if depth > 128 { - return "", &os.PathError{Op: "canonical", Path: p, Err: errDepth} - } - if j = strings.IndexRune(p[i:], '/'); j == -1 { - j, i = i, len(p) - } else { - j, i = i, i+j - } - fi, err := os.Lstat(p[:i]) - if err != nil { - return "", err - } - if fi.Mode()&os.ModeSymlink == os.ModeSymlink { - s, err := os.Readlink(p[:i]) - if err != nil { - return "", err - } - if filepath.IsAbs(s) { - p = "/" + s + p[i:] - } else { - p = p[:j] + s + p[i:] - } - i = 1 // no guarantee s is canonical, start all over - } - } - return filepath.Clean(p), nil -} - -func joinevents(events []Event) (e Event) { - if len(events) == 0 { - e = All - } else { - for _, event := range events { - e |= event - } - } - return -} - -func split(s string) (string, string) { - if i := lastIndexSep(s); i != -1 { - return s[:i], s[i+1:] - } - return "", s -} - -func base(s string) string { - if i := lastIndexSep(s); i != -1 { - return s[i+1:] - } - return s -} - -func indexbase(root, name string) int { - if n, m := len(root), len(name); m >= n && name[:n] == root && - (n == m || name[n] == os.PathSeparator) { - return min(n+1, m) - } - return -1 -} - -func indexSep(s string) int { - for i := 0; i < len(s); i++ { - if s[i] == os.PathSeparator { - return i - } - } - return -1 -} - -func lastIndexSep(s string) int { - for i := len(s) - 1; i >= 0; i-- { - if s[i] == os.PathSeparator { - return i - } - } - return -1 -} diff --git a/vendor/github.com/rjeczalik/notify/watcher.go b/vendor/github.com/rjeczalik/notify/watcher.go deleted file mode 100644 index 34148eff3..000000000 --- a/vendor/github.com/rjeczalik/notify/watcher.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -package notify - -import "errors" - -var ( - errAlreadyWatched = errors.New("path is already watched") - errNotWatched = errors.New("path is not being watched") - errInvalidEventSet = errors.New("invalid event set provided") -) - -// Watcher is a intermediate interface for wrapping inotify, ReadDirChangesW, -// FSEvents, kqueue and poller implementations. -// -// The watcher implementation is expected to do its own mapping between paths and -// create watchers if underlying event notification does not support it. For -// the ease of implementation it is guaranteed that paths provided via Watch and -// Unwatch methods are absolute and clean. -type watcher interface { - // Watch requests a watcher creation for the given path and given event set. - Watch(path string, event Event) error - - // Unwatch requests a watcher deletion for the given path and given event set. - Unwatch(path string) error - - // Rewatch provides a functionality for modifying existing watch-points, like - // expanding its event set. - // - // Rewatch modifies existing watch-point under for the given path. It passes - // the existing event set currently registered for the given path, and the - // new, requested event set. - // - // It is guaranteed that Tree will not pass to Rewatch zero value for any - // of its arguments. If old == new and watcher can be upgraded to - // recursiveWatcher interface, a watch for the corresponding path is expected - // to be changed from recursive to the non-recursive one. - Rewatch(path string, old, new Event) error - - // Close unwatches all paths that are registered. When Close returns, it - // is expected it will report no more events. - Close() error -} - -// RecursiveWatcher is an interface for a Watcher for those OS, which do support -// recursive watching over directories. -type recursiveWatcher interface { - RecursiveWatch(path string, event Event) error - - // RecursiveUnwatch removes a recursive watch-point given by the path. For - // native recursive implementation there is no difference in functionality - // between Unwatch and RecursiveUnwatch, however for those platforms, that - // requires emulation for recursive watch-points, the implementation differs. - RecursiveUnwatch(path string) error - - // RecursiveRewatcher provides a functionality for modifying and/or relocating - // existing recursive watch-points. - // - // To relocate a watch-point means to unwatch oldpath and set a watch-point on - // newpath. - // - // To modify a watch-point means either to expand or shrink its event set. - // - // Tree can want to either relocate, modify or relocate and modify a watch-point - // via single RecursiveRewatch call. - // - // If oldpath == newpath, the watch-point is expected to change its event set value - // from oldevent to newevent. - // - // If oldevent == newevent, the watch-point is expected to relocate from oldpath - // to the newpath. - // - // If oldpath != newpath and oldevent != newevent, the watch-point is expected - // to relocate from oldpath to the newpath first and then change its event set - // value from oldevent to the newevent. In other words the end result must be - // a watch-point set on newpath with newevent value of its event set. - // - // It is guaranteed that Tree will not pass to RecurisveRewatcha zero value - // for any of its arguments. If oldpath == newpath and oldevent == newevent, - // a watch for the corresponding path is expected to be changed for - // non-recursive to the recursive one. - RecursiveRewatch(oldpath, newpath string, oldevent, newevent Event) error -} diff --git a/vendor/github.com/rjeczalik/notify/watcher_fen.go b/vendor/github.com/rjeczalik/notify/watcher_fen.go deleted file mode 100644 index dfe77f2f1..000000000 --- a/vendor/github.com/rjeczalik/notify/watcher_fen.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build solaris - -package notify - -import ( - "fmt" - "os" - "syscall" -) - -// newTrigger returns implementation of trigger. -func newTrigger(pthLkp map[string]*watched) trigger { - return &fen{ - pthLkp: pthLkp, - cf: newCfen(), - } -} - -// fen is a structure implementing trigger for FEN. -type fen struct { - // p is a FEN port identifier - p int - // pthLkp is a structure mapping monitored files/dir with data about them, - // shared with parent trg structure - pthLkp map[string]*watched - // cf wraps C operations for FEN - cf cfen -} - -// watched is a data structure representing watched file/directory. -type watched struct { - trgWatched -} - -// Stop implements trigger. -func (f *fen) Stop() error { - return f.cf.portAlert(f.p) -} - -// Close implements trigger. -func (f *fen) Close() (err error) { - return syscall.Close(f.p) -} - -// NewWatched implements trigger. -func (*fen) NewWatched(p string, fi os.FileInfo) (*watched, error) { - return &watched{trgWatched{p: p, fi: fi}}, nil -} - -// Record implements trigger. -func (f *fen) Record(w *watched) { - f.pthLkp[w.p] = w -} - -// Del implements trigger. -func (f *fen) Del(w *watched) { - delete(f.pthLkp, w.p) -} - -func inter2pe(n interface{}) PortEvent { - pe, ok := n.(PortEvent) - if !ok { - panic(fmt.Sprintf("fen: type should be PortEvent, %T instead", n)) - } - return pe -} - -// Watched implements trigger. -func (f *fen) Watched(n interface{}) (*watched, int64, error) { - pe := inter2pe(n) - fo, ok := pe.PortevObject.(*FileObj) - if !ok || fo == nil { - panic(fmt.Sprintf("fen: type should be *FileObj, %T instead", fo)) - } - w, ok := f.pthLkp[fo.Name] - if !ok { - return nil, 0, errNotWatched - } - return w, int64(pe.PortevEvents), nil -} - -// init initializes FEN. -func (f *fen) Init() (err error) { - f.p, err = f.cf.portCreate() - return -} - -func fi2fo(fi os.FileInfo, p string) FileObj { - st, ok := fi.Sys().(*syscall.Stat_t) - if !ok { - panic(fmt.Sprintf("fen: type should be *syscall.Stat_t, %T instead", st)) - } - return FileObj{Name: p, Atim: st.Atim, Mtim: st.Mtim, Ctim: st.Ctim} -} - -// Unwatch implements trigger. -func (f *fen) Unwatch(w *watched) error { - return f.cf.portDissociate(f.p, FileObj{Name: w.p}) -} - -// Watch implements trigger. -func (f *fen) Watch(fi os.FileInfo, w *watched, e int64) error { - return f.cf.portAssociate(f.p, fi2fo(fi, w.p), int(e)) -} - -// Wait implements trigger. -func (f *fen) Wait() (interface{}, error) { - var ( - pe PortEvent - err error - ) - err = f.cf.portGet(f.p, &pe) - return pe, err -} - -// IsStop implements trigger. -func (f *fen) IsStop(n interface{}, err error) bool { - return err == syscall.EBADF || inter2pe(n).PortevSource == srcAlert -} - -func init() { - encode = func(e Event, dir bool) (o int64) { - // Create event is not supported by FEN. Instead FileModified event will - // be registered. If this event will be reported on dir which is to be - // monitored for Create, dir will be rescanned and Create events will - // be generated and returned for new files. In case of files, - // if not requested FileModified event is reported, it will be ignored. - o = int64(e &^ Create) - if (e&Create != 0 && dir) || e&Write != 0 { - o = (o &^ int64(Write)) | int64(FileModified) - } - // Following events are 'exception events' and as such cannot be requested - // explicitly for monitoring or filtered out. If the will be reported - // by FEN and not subscribed with by user, they will be filtered out by - // watcher's logic. - o &= int64(^Rename & ^Remove &^ FileDelete &^ FileRenameTo &^ - FileRenameFrom &^ Unmounted &^ MountedOver) - return - } - nat2not = map[Event]Event{ - FileModified: Write, - FileRenameFrom: Rename, - FileDelete: Remove, - FileAccess: Event(0), - FileAttrib: Event(0), - FileRenameTo: Event(0), - FileTrunc: Event(0), - FileNoFollow: Event(0), - Unmounted: Event(0), - MountedOver: Event(0), - } - not2nat = map[Event]Event{ - Write: FileModified, - Rename: FileRenameFrom, - Remove: FileDelete, - } -} diff --git a/vendor/github.com/rjeczalik/notify/watcher_fen_cgo.go b/vendor/github.com/rjeczalik/notify/watcher_fen_cgo.go deleted file mode 100644 index 8ec8ead34..000000000 --- a/vendor/github.com/rjeczalik/notify/watcher_fen_cgo.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build solaris - -package notify - -// #include -// #include -// #include -// struct file_obj* newFo() { return (struct file_obj*) malloc(sizeof(struct file_obj)); } -// port_event_t* newPe() { return (port_event_t*) malloc(sizeof(port_event_t)); } -// uintptr_t conv(struct file_obj* fo) { return (uintptr_t) fo; } -// struct file_obj* dconv(uintptr_t fo) { return (struct file_obj*) fo; } -import "C" - -import ( - "syscall" - "unsafe" -) - -const ( - fileAccess = Event(C.FILE_ACCESS) - fileModified = Event(C.FILE_MODIFIED) - fileAttrib = Event(C.FILE_ATTRIB) - fileDelete = Event(C.FILE_DELETE) - fileRenameTo = Event(C.FILE_RENAME_TO) - fileRenameFrom = Event(C.FILE_RENAME_FROM) - fileTrunc = Event(C.FILE_TRUNC) - fileNoFollow = Event(C.FILE_NOFOLLOW) - unmounted = Event(C.UNMOUNTED) - mountedOver = Event(C.MOUNTEDOVER) -) - -// PortEvent is a notify's equivalent of port_event_t. -type PortEvent struct { - PortevEvents int // PortevEvents is an equivalent of portev_events. - PortevSource uint8 // PortevSource is an equivalent of portev_source. - PortevPad uint8 // Portevpad is an equivalent of portev_pad. - PortevObject interface{} // PortevObject is an equivalent of portev_object. - PortevUser uintptr // PortevUser is an equivalent of portev_user. -} - -// FileObj is a notify's equivalent of file_obj. -type FileObj struct { - Atim syscall.Timespec // Atim is an equivalent of fo_atime. - Mtim syscall.Timespec // Mtim is an equivalent of fo_mtime. - Ctim syscall.Timespec // Ctim is an equivalent of fo_ctime. - Pad [3]uintptr // Pad is an equivalent of fo_pad. - Name string // Name is an equivalent of fo_name. -} - -type cfen struct { - p2pe map[string]*C.port_event_t - p2fo map[string]*C.struct_file_obj -} - -func newCfen() cfen { - return cfen{ - p2pe: make(map[string]*C.port_event_t), - p2fo: make(map[string]*C.struct_file_obj), - } -} - -func unix2C(sec int64, nsec int64) (C.time_t, C.long) { - return C.time_t(sec), C.long(nsec) -} - -func (c *cfen) portAssociate(p int, fo FileObj, e int) (err error) { - cfo := C.newFo() - cfo.fo_atime.tv_sec, cfo.fo_atime.tv_nsec = unix2C(fo.Atim.Unix()) - cfo.fo_mtime.tv_sec, cfo.fo_mtime.tv_nsec = unix2C(fo.Mtim.Unix()) - cfo.fo_ctime.tv_sec, cfo.fo_ctime.tv_nsec = unix2C(fo.Ctim.Unix()) - cfo.fo_name = C.CString(fo.Name) - c.p2fo[fo.Name] = cfo - _, err = C.port_associate(C.int(p), srcFile, C.conv(cfo), C.int(e), nil) - return -} - -func (c *cfen) portDissociate(port int, fo FileObj) (err error) { - cfo, ok := c.p2fo[fo.Name] - if !ok { - return errNotWatched - } - _, err = C.port_dissociate(C.int(port), srcFile, C.conv(cfo)) - C.free(unsafe.Pointer(cfo.fo_name)) - C.free(unsafe.Pointer(cfo)) - delete(c.p2fo, fo.Name) - return -} - -const srcAlert = C.PORT_SOURCE_ALERT -const srcFile = C.PORT_SOURCE_FILE -const alertSet = C.PORT_ALERT_SET - -func cfo2fo(cfo *C.struct_file_obj) *FileObj { - // Currently remaining attributes are not used. - if cfo == nil { - return nil - } - var fo FileObj - fo.Name = C.GoString(cfo.fo_name) - return &fo -} - -func (c *cfen) portGet(port int, pe *PortEvent) (err error) { - cpe := C.newPe() - if _, err = C.port_get(C.int(port), cpe, nil); err != nil { - C.free(unsafe.Pointer(cpe)) - return - } - pe.PortevEvents, pe.PortevSource, pe.PortevPad = - int(cpe.portev_events), uint8(cpe.portev_source), uint8(cpe.portev_pad) - pe.PortevObject = cfo2fo(C.dconv(cpe.portev_object)) - pe.PortevUser = uintptr(cpe.portev_user) - C.free(unsafe.Pointer(cpe)) - return -} - -func (c *cfen) portCreate() (int, error) { - p, err := C.port_create() - return int(p), err -} - -func (c *cfen) portAlert(p int) (err error) { - _, err = C.port_alert(C.int(p), alertSet, C.int(666), nil) - return -} - -func (c *cfen) free() { - for i := range c.p2fo { - C.free(unsafe.Pointer(c.p2fo[i].fo_name)) - C.free(unsafe.Pointer(c.p2fo[i])) - } - for i := range c.p2pe { - C.free(unsafe.Pointer(c.p2pe[i])) - } - c.p2fo = make(map[string]*C.struct_file_obj) - c.p2pe = make(map[string]*C.port_event_t) -} diff --git a/vendor/github.com/rjeczalik/notify/watcher_fsevents.go b/vendor/github.com/rjeczalik/notify/watcher_fsevents.go deleted file mode 100644 index 7d9b97b65..000000000 --- a/vendor/github.com/rjeczalik/notify/watcher_fsevents.go +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build darwin,!kqueue - -package notify - -import ( - "errors" - "strings" - "sync/atomic" -) - -const ( - failure = uint32(FSEventsMustScanSubDirs | FSEventsUserDropped | FSEventsKernelDropped) - filter = uint32(FSEventsCreated | FSEventsRemoved | FSEventsRenamed | - FSEventsModified | FSEventsInodeMetaMod) -) - -// FSEvent represents single file event. It is created out of values passed by -// FSEvents to FSEventStreamCallback function. -type FSEvent struct { - Path string // real path of the file or directory - ID uint64 // ID of the event (FSEventStreamEventId) - Flags uint32 // joint FSEvents* flags (FSEventStreamEventFlags) -} - -// splitflags separates event flags from single set into slice of flags. -func splitflags(set uint32) (e []uint32) { - for i := uint32(1); set != 0; i, set = i<<1, set>>1 { - if (set & 1) != 0 { - e = append(e, i) - } - } - return -} - -// watch represents a filesystem watchpoint. It is a higher level abstraction -// over FSEvents' stream, which implements filtering of file events based -// on path and event set. It emulates non-recursive watch-point by filtering out -// events which paths are more than 1 level deeper than the watched path. -type watch struct { - // prev stores last event set per path in order to filter out old flags - // for new events, which appratenly FSEvents likes to retain. It's a disgusting - // hack, it should be researched how to get rid of it. - prev map[string]uint32 - c chan<- EventInfo - stream *stream - path string - events uint32 - isrec int32 - flushed bool -} - -// Example format: -// -// ~ $ (trigger command) # (event set) -> (effective event set) -// -// Heuristics: -// -// 1. Create event is removed when it was present in previous event set. -// Example: -// -// ~ $ echo > file # Create|Write -> Create|Write -// ~ $ echo > file # Create|Write|InodeMetaMod -> Write|InodeMetaMod -// -// 2. Remove event is removed if it was present in previouse event set. -// Example: -// -// ~ $ touch file # Create -> Create -// ~ $ rm file # Create|Remove -> Remove -// ~ $ touch file # Create|Remove -> Create -// -// 3. Write event is removed if not followed by InodeMetaMod on existing -// file. Example: -// -// ~ $ echo > file # Create|Write -> Create|Write -// ~ $ chmod +x file # Create|Write|ChangeOwner -> ChangeOwner -// -// 4. Write&InodeMetaMod is removed when effective event set contain Remove event. -// Example: -// -// ~ $ echo > file # Write|InodeMetaMod -> Write|InodeMetaMod -// ~ $ rm file # Remove|Write|InodeMetaMod -> Remove -// -func (w *watch) strip(base string, set uint32) uint32 { - const ( - write = FSEventsModified | FSEventsInodeMetaMod - both = FSEventsCreated | FSEventsRemoved - ) - switch w.prev[base] { - case FSEventsCreated: - set &^= FSEventsCreated - if set&FSEventsRemoved != 0 { - w.prev[base] = FSEventsRemoved - set &^= write - } - case FSEventsRemoved: - set &^= FSEventsRemoved - if set&FSEventsCreated != 0 { - w.prev[base] = FSEventsCreated - } - default: - switch set & both { - case FSEventsCreated: - w.prev[base] = FSEventsCreated - case FSEventsRemoved: - w.prev[base] = FSEventsRemoved - set &^= write - } - } - dbgprintf("split()=%v\n", Event(set)) - return set -} - -// Dispatch is a stream function which forwards given file events for the watched -// path to underlying FileInfo channel. -func (w *watch) Dispatch(ev []FSEvent) { - events := atomic.LoadUint32(&w.events) - isrec := (atomic.LoadInt32(&w.isrec) == 1) - for i := range ev { - if ev[i].Flags&FSEventsHistoryDone != 0 { - w.flushed = true - continue - } - if !w.flushed { - continue - } - dbgprintf("%v (0x%x) (%s, i=%d, ID=%d, len=%d)\n", Event(ev[i].Flags), - ev[i].Flags, ev[i].Path, i, ev[i].ID, len(ev)) - if ev[i].Flags&failure != 0 { - // TODO(rjeczalik): missing error handling - continue - } - if !strings.HasPrefix(ev[i].Path, w.path) { - continue - } - n := len(w.path) - base := "" - if len(ev[i].Path) > n { - if ev[i].Path[n] != '/' { - continue - } - base = ev[i].Path[n+1:] - if !isrec && strings.IndexByte(base, '/') != -1 { - continue - } - } - // TODO(rjeczalik): get diff only from filtered events? - e := w.strip(string(base), ev[i].Flags) & events - if e == 0 { - continue - } - for _, e := range splitflags(e) { - dbgprintf("%d: single event: %v", ev[i].ID, Event(e)) - w.c <- &event{ - fse: ev[i], - event: Event(e), - } - } - } -} - -// Stop closes underlying FSEvents stream and stops dispatching events. -func (w *watch) Stop() { - w.stream.Stop() - // TODO(rjeczalik): make (*stream).Stop flush synchronously undelivered events, - // so the following hack can be removed. It should flush all the streams - // concurrently as we care not to block too much here. - atomic.StoreUint32(&w.events, 0) - atomic.StoreInt32(&w.isrec, 0) -} - -// fsevents implements Watcher and RecursiveWatcher interfaces backed by FSEvents -// framework. -type fsevents struct { - watches map[string]*watch - c chan<- EventInfo -} - -func newWatcher(c chan<- EventInfo) watcher { - return &fsevents{ - watches: make(map[string]*watch), - c: c, - } -} - -func (fse *fsevents) watch(path string, event Event, isrec int32) (err error) { - if _, ok := fse.watches[path]; ok { - return errAlreadyWatched - } - w := &watch{ - prev: make(map[string]uint32), - c: fse.c, - path: path, - events: uint32(event), - isrec: isrec, - } - w.stream = newStream(path, w.Dispatch) - if err = w.stream.Start(); err != nil { - return err - } - fse.watches[path] = w - return nil -} - -func (fse *fsevents) unwatch(path string) (err error) { - w, ok := fse.watches[path] - if !ok { - return errNotWatched - } - w.stream.Stop() - delete(fse.watches, path) - return nil -} - -// Watch implements Watcher interface. It fails with non-nil error when setting -// the watch-point by FSEvents fails or with errAlreadyWatched error when -// the given path is already watched. -func (fse *fsevents) Watch(path string, event Event) error { - return fse.watch(path, event, 0) -} - -// Unwatch implements Watcher interface. It fails with errNotWatched when -// the given path is not being watched. -func (fse *fsevents) Unwatch(path string) error { - return fse.unwatch(path) -} - -// Rewatch implements Watcher interface. It fails with errNotWatched when -// the given path is not being watched or with errInvalidEventSet when oldevent -// does not match event set the watch-point currently holds. -func (fse *fsevents) Rewatch(path string, oldevent, newevent Event) error { - w, ok := fse.watches[path] - if !ok { - return errNotWatched - } - if !atomic.CompareAndSwapUint32(&w.events, uint32(oldevent), uint32(newevent)) { - return errInvalidEventSet - } - atomic.StoreInt32(&w.isrec, 0) - return nil -} - -// RecursiveWatch implements RecursiveWatcher interface. It fails with non-nil -// error when setting the watch-point by FSEvents fails or with errAlreadyWatched -// error when the given path is already watched. -func (fse *fsevents) RecursiveWatch(path string, event Event) error { - return fse.watch(path, event, 1) -} - -// RecursiveUnwatch implements RecursiveWatcher interface. It fails with -// errNotWatched when the given path is not being watched. -// -// TODO(rjeczalik): fail if w.isrec == 0? -func (fse *fsevents) RecursiveUnwatch(path string) error { - return fse.unwatch(path) -} - -// RecrusiveRewatch implements RecursiveWatcher interface. It fails: -// -// * with errNotWatched when the given path is not being watched -// * with errInvalidEventSet when oldevent does not match the current event set -// * with errAlreadyWatched when watch-point given by the oldpath was meant to -// be relocated to newpath, but the newpath is already watched -// * a non-nil error when setting the watch-point with FSEvents fails -// -// TODO(rjeczalik): Improve handling of watch-point relocation? See two TODOs -// that follows. -func (fse *fsevents) RecursiveRewatch(oldpath, newpath string, oldevent, newevent Event) error { - switch [2]bool{oldpath == newpath, oldevent == newevent} { - case [2]bool{true, true}: - w, ok := fse.watches[oldpath] - if !ok { - return errNotWatched - } - atomic.StoreInt32(&w.isrec, 1) - return nil - case [2]bool{true, false}: - w, ok := fse.watches[oldpath] - if !ok { - return errNotWatched - } - if !atomic.CompareAndSwapUint32(&w.events, uint32(oldevent), uint32(newevent)) { - return errors.New("invalid event state diff") - } - atomic.StoreInt32(&w.isrec, 1) - return nil - default: - // TODO(rjeczalik): rewatch newpath only if exists? - // TODO(rjeczalik): migrate w.prev to new watch? - if _, ok := fse.watches[newpath]; ok { - return errAlreadyWatched - } - if err := fse.Unwatch(oldpath); err != nil { - return err - } - // TODO(rjeczalik): revert unwatch if watch fails? - return fse.watch(newpath, newevent, 1) - } -} - -// Close unwatches all watch-points. -func (fse *fsevents) Close() error { - for _, w := range fse.watches { - w.Stop() - } - fse.watches = nil - return nil -} diff --git a/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go b/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go deleted file mode 100644 index cf0416c37..000000000 --- a/vendor/github.com/rjeczalik/notify/watcher_fsevents_cgo.go +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build darwin,!kqueue - -package notify - -/* -#include - -typedef void (*CFRunLoopPerformCallBack)(void*); - -void gosource(void *); -void gostream(uintptr_t, uintptr_t, size_t, uintptr_t, uintptr_t, uintptr_t); - -static FSEventStreamRef EventStreamCreate(FSEventStreamContext * context, uintptr_t info, CFArrayRef paths, FSEventStreamEventId since, CFTimeInterval latency, FSEventStreamCreateFlags flags) { - context->info = (void*) info; - return FSEventStreamCreate(NULL, (FSEventStreamCallback) gostream, context, paths, since, latency, flags); -} - -#cgo LDFLAGS: -framework CoreServices -*/ -import "C" - -import ( - "errors" - "os" - "runtime" - "sync" - "sync/atomic" - "unsafe" -) - -var nilstream C.FSEventStreamRef - -// Default arguments for FSEventStreamCreate function. -var ( - latency C.CFTimeInterval - flags = C.FSEventStreamCreateFlags(C.kFSEventStreamCreateFlagFileEvents | C.kFSEventStreamCreateFlagNoDefer) - since = uint64(C.FSEventsGetCurrentEventId()) -) - -var runloop C.CFRunLoopRef // global runloop which all streams are registered with -var wg sync.WaitGroup // used to wait until the runloop starts - -// source is used for synchronization purposes - it signals when runloop has -// started and is ready via the wg. It also serves purpose of a dummy source, -// thanks to it the runloop does not return as it also has at least one source -// registered. -var source = C.CFRunLoopSourceCreate(C.kCFAllocatorDefault, 0, &C.CFRunLoopSourceContext{ - perform: (C.CFRunLoopPerformCallBack)(C.gosource), -}) - -// Errors returned when FSEvents functions fail. -var ( - errCreate = os.NewSyscallError("FSEventStreamCreate", errors.New("NULL")) - errStart = os.NewSyscallError("FSEventStreamStart", errors.New("false")) -) - -// initializes the global runloop and ensures any created stream awaits its -// readiness. -func init() { - wg.Add(1) - go func() { - // There is exactly one run loop per thread. Lock this goroutine to its - // thread to ensure that it's not rescheduled on a different thread while - // setting up the run loop. - runtime.LockOSThread() - runloop = C.CFRunLoopGetCurrent() - C.CFRunLoopAddSource(runloop, source, C.kCFRunLoopDefaultMode) - C.CFRunLoopRun() - panic("runloop has just unexpectedly stopped") - }() - C.CFRunLoopSourceSignal(source) -} - -//export gosource -func gosource(unsafe.Pointer) { - wg.Done() -} - -//export gostream -func gostream(_, info uintptr, n C.size_t, paths, flags, ids uintptr) { - const ( - offchar = unsafe.Sizeof((*C.char)(nil)) - offflag = unsafe.Sizeof(C.FSEventStreamEventFlags(0)) - offid = unsafe.Sizeof(C.FSEventStreamEventId(0)) - ) - if n == 0 { - return - } - fn := streamFuncs.get(info) - if fn == nil { - return - } - ev := make([]FSEvent, 0, int(n)) - for i := uintptr(0); i < uintptr(n); i++ { - switch flags := *(*uint32)(unsafe.Pointer((flags + i*offflag))); { - case flags&uint32(FSEventsEventIdsWrapped) != 0: - atomic.StoreUint64(&since, uint64(C.FSEventsGetCurrentEventId())) - default: - ev = append(ev, FSEvent{ - Path: C.GoString(*(**C.char)(unsafe.Pointer(paths + i*offchar))), - Flags: flags, - ID: *(*uint64)(unsafe.Pointer(ids + i*offid)), - }) - } - - } - fn(ev) -} - -// StreamFunc is a callback called when stream receives file events. -type streamFunc func([]FSEvent) - -var streamFuncs = streamFuncRegistry{m: map[uintptr]streamFunc{}} - -type streamFuncRegistry struct { - mu sync.Mutex - m map[uintptr]streamFunc - i uintptr -} - -func (r *streamFuncRegistry) get(id uintptr) streamFunc { - r.mu.Lock() - defer r.mu.Unlock() - return r.m[id] -} - -func (r *streamFuncRegistry) add(fn streamFunc) uintptr { - r.mu.Lock() - defer r.mu.Unlock() - r.i++ - r.m[r.i] = fn - return r.i -} - -func (r *streamFuncRegistry) delete(id uintptr) { - r.mu.Lock() - defer r.mu.Unlock() - delete(r.m, id) -} - -// Stream represents single watch-point which listens for events scheduled by -// the global runloop. -type stream struct { - path string - ref C.FSEventStreamRef - info uintptr -} - -// NewStream creates a stream for given path, listening for file events and -// calling fn upon receiving any. -func newStream(path string, fn streamFunc) *stream { - return &stream{ - path: path, - info: streamFuncs.add(fn), - } -} - -// Start creates a FSEventStream for the given path and schedules it with -// global runloop. It's a nop if the stream was already started. -func (s *stream) Start() error { - if s.ref != nilstream { - return nil - } - wg.Wait() - p := C.CFStringCreateWithCStringNoCopy(C.kCFAllocatorDefault, C.CString(s.path), C.kCFStringEncodingUTF8, C.kCFAllocatorDefault) - path := C.CFArrayCreate(C.kCFAllocatorDefault, (*unsafe.Pointer)(unsafe.Pointer(&p)), 1, nil) - ctx := C.FSEventStreamContext{} - ref := C.EventStreamCreate(&ctx, C.uintptr_t(s.info), path, C.FSEventStreamEventId(atomic.LoadUint64(&since)), latency, flags) - if ref == nilstream { - return errCreate - } - C.FSEventStreamScheduleWithRunLoop(ref, runloop, C.kCFRunLoopDefaultMode) - if C.FSEventStreamStart(ref) == C.Boolean(0) { - C.FSEventStreamInvalidate(ref) - return errStart - } - C.CFRunLoopWakeUp(runloop) - s.ref = ref - return nil -} - -// Stop stops underlying FSEventStream and unregisters it from global runloop. -func (s *stream) Stop() { - if s.ref == nilstream { - return - } - wg.Wait() - C.FSEventStreamStop(s.ref) - C.FSEventStreamInvalidate(s.ref) - C.CFRunLoopWakeUp(runloop) - s.ref = nilstream - streamFuncs.delete(s.info) -} diff --git a/vendor/github.com/rjeczalik/notify/watcher_inotify.go b/vendor/github.com/rjeczalik/notify/watcher_inotify.go deleted file mode 100644 index d082baca0..000000000 --- a/vendor/github.com/rjeczalik/notify/watcher_inotify.go +++ /dev/null @@ -1,405 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build linux - -package notify - -import ( - "bytes" - "errors" - "path/filepath" - "runtime" - "sync" - "sync/atomic" - "unsafe" - - "golang.org/x/sys/unix" -) - -// eventBufferSize defines the size of the buffer given to read(2) function. One -// should not depend on this value, since it was arbitrary chosen and may be -// changed in the future. -const eventBufferSize = 64 * (unix.SizeofInotifyEvent + unix.PathMax + 1) - -// consumersCount defines the number of consumers in producer-consumer based -// implementation. Each consumer is run in a separate goroutine and has read -// access to watched files map. -const consumersCount = 2 - -const invalidDescriptor = -1 - -// watched is a pair of file path and inotify mask used as a value in -// watched files map. -type watched struct { - path string - mask uint32 -} - -// inotify implements Watcher interface. -type inotify struct { - sync.RWMutex // protects inotify.m map - m map[int32]*watched // watch descriptor to watched object - fd int32 // inotify file descriptor - pipefd []int // pipe's read and write descriptors - epfd int // epoll descriptor - epes []unix.EpollEvent // epoll events - buffer [eventBufferSize]byte // inotify event buffer - wg sync.WaitGroup // wait group used to close main loop - c chan<- EventInfo // event dispatcher channel -} - -// NewWatcher creates new non-recursive inotify backed by inotify. -func newWatcher(c chan<- EventInfo) watcher { - i := &inotify{ - m: make(map[int32]*watched), - fd: invalidDescriptor, - pipefd: []int{invalidDescriptor, invalidDescriptor}, - epfd: invalidDescriptor, - epes: make([]unix.EpollEvent, 0), - c: c, - } - runtime.SetFinalizer(i, func(i *inotify) { - i.epollclose() - if i.fd != invalidDescriptor { - unix.Close(int(i.fd)) - } - }) - return i -} - -// Watch implements notify.watcher interface. -func (i *inotify) Watch(path string, e Event) error { - return i.watch(path, e) -} - -// Rewatch implements notify.watcher interface. -func (i *inotify) Rewatch(path string, _, newevent Event) error { - return i.watch(path, newevent) -} - -// watch adds a new watcher to the set of watched objects or modifies the existing -// one. If called for the first time, this function initializes inotify filesystem -// monitor and starts producer-consumers goroutines. -func (i *inotify) watch(path string, e Event) (err error) { - if e&^(All|Event(unix.IN_ALL_EVENTS)) != 0 { - return errors.New("notify: unknown event") - } - if err = i.lazyinit(); err != nil { - return - } - iwd, err := unix.InotifyAddWatch(int(i.fd), path, encode(e)) - if err != nil { - return - } - i.RLock() - wd := i.m[int32(iwd)] - i.RUnlock() - if wd == nil { - i.Lock() - if i.m[int32(iwd)] == nil { - i.m[int32(iwd)] = &watched{path: path, mask: uint32(e)} - } - i.Unlock() - } else { - i.Lock() - wd.mask = uint32(e) - i.Unlock() - } - return nil -} - -// lazyinit sets up all required file descriptors and starts 1+consumersCount -// goroutines. The producer goroutine blocks until file-system notifications -// occur. Then, all events are read from system buffer and sent to consumer -// goroutines which construct valid notify events. This method uses -// Double-Checked Locking optimization. -func (i *inotify) lazyinit() error { - if atomic.LoadInt32(&i.fd) == invalidDescriptor { - i.Lock() - defer i.Unlock() - if atomic.LoadInt32(&i.fd) == invalidDescriptor { - fd, err := unix.InotifyInit1(unix.IN_CLOEXEC) - if err != nil { - return err - } - i.fd = int32(fd) - if err = i.epollinit(); err != nil { - _, _ = i.epollclose(), unix.Close(int(fd)) // Ignore errors. - i.fd = invalidDescriptor - return err - } - esch := make(chan []*event) - go i.loop(esch) - i.wg.Add(consumersCount) - for n := 0; n < consumersCount; n++ { - go i.send(esch) - } - } - } - return nil -} - -// epollinit opens an epoll file descriptor and creates a pipe which will be -// used to wake up the epoll_wait(2) function. Then, file descriptor associated -// with inotify event queue and the read end of the pipe are added to epoll set. -// Note that `fd` member must be set before this function is called. -func (i *inotify) epollinit() (err error) { - if i.epfd, err = unix.EpollCreate1(0); err != nil { - return - } - if err = unix.Pipe(i.pipefd); err != nil { - return - } - i.epes = []unix.EpollEvent{ - {Events: unix.EPOLLIN, Fd: i.fd}, - {Events: unix.EPOLLIN, Fd: int32(i.pipefd[0])}, - } - if err = unix.EpollCtl(i.epfd, unix.EPOLL_CTL_ADD, int(i.fd), &i.epes[0]); err != nil { - return - } - return unix.EpollCtl(i.epfd, unix.EPOLL_CTL_ADD, i.pipefd[0], &i.epes[1]) -} - -// epollclose closes the file descriptor created by the call to epoll_create(2) -// and two file descriptors opened by pipe(2) function. -func (i *inotify) epollclose() (err error) { - if i.epfd != invalidDescriptor { - if err = unix.Close(i.epfd); err == nil { - i.epfd = invalidDescriptor - } - } - for n, fd := range i.pipefd { - if fd != invalidDescriptor { - switch e := unix.Close(fd); { - case e != nil && err == nil: - err = e - case e == nil: - i.pipefd[n] = invalidDescriptor - } - } - } - return -} - -// loop blocks until either inotify or pipe file descriptor is ready for I/O. -// All read operations triggered by filesystem notifications are forwarded to -// one of the event's consumers. If pipe fd became ready, loop function closes -// all file descriptors opened by lazyinit method and returns afterwards. -func (i *inotify) loop(esch chan<- []*event) { - epes := make([]unix.EpollEvent, 1) - fd := atomic.LoadInt32(&i.fd) - for { - switch _, err := unix.EpollWait(i.epfd, epes, -1); err { - case nil: - switch epes[0].Fd { - case fd: - esch <- i.read() - epes[0].Fd = 0 - case int32(i.pipefd[0]): - i.Lock() - defer i.Unlock() - if err = unix.Close(int(fd)); err != nil && err != unix.EINTR { - panic("notify: close(2) error " + err.Error()) - } - atomic.StoreInt32(&i.fd, invalidDescriptor) - if err = i.epollclose(); err != nil && err != unix.EINTR { - panic("notify: epollclose error " + err.Error()) - } - close(esch) - return - } - case unix.EINTR: - continue - default: // We should never reach this line. - panic("notify: epoll_wait(2) error " + err.Error()) - } - } -} - -// read reads events from an inotify file descriptor. It does not handle errors -// returned from read(2) function since they are not critical to watcher logic. -func (i *inotify) read() (es []*event) { - n, err := unix.Read(int(i.fd), i.buffer[:]) - if err != nil || n < unix.SizeofInotifyEvent { - return - } - var sys *unix.InotifyEvent - nmin := n - unix.SizeofInotifyEvent - for pos, path := 0, ""; pos <= nmin; { - sys = (*unix.InotifyEvent)(unsafe.Pointer(&i.buffer[pos])) - pos += unix.SizeofInotifyEvent - if path = ""; sys.Len > 0 { - endpos := pos + int(sys.Len) - path = string(bytes.TrimRight(i.buffer[pos:endpos], "\x00")) - pos = endpos - } - es = append(es, &event{ - sys: unix.InotifyEvent{ - Wd: sys.Wd, - Mask: sys.Mask, - Cookie: sys.Cookie, - }, - path: path, - }) - } - return -} - -// send is a consumer function which sends events to event dispatcher channel. -// It is run in a separate goroutine in order to not block loop method when -// possibly expensive write operations are performed on inotify map. -func (i *inotify) send(esch <-chan []*event) { - for es := range esch { - for _, e := range i.transform(es) { - if e != nil { - i.c <- e - } - } - } - i.wg.Done() -} - -// transform prepares events read from inotify file descriptor for sending to -// user. It removes invalid events and these which are no longer present in -// inotify map. This method may also split one raw event into two different ones -// when system-dependent result is required. -func (i *inotify) transform(es []*event) []*event { - var multi []*event - i.RLock() - for idx, e := range es { - if e.sys.Mask&(unix.IN_IGNORED|unix.IN_Q_OVERFLOW) != 0 { - es[idx] = nil - continue - } - wd, ok := i.m[e.sys.Wd] - if !ok || e.sys.Mask&encode(Event(wd.mask)) == 0 { - es[idx] = nil - continue - } - if e.path == "" { - e.path = wd.path - } else { - e.path = filepath.Join(wd.path, e.path) - } - multi = append(multi, decode(Event(wd.mask), e)) - if e.event == 0 { - es[idx] = nil - } - } - i.RUnlock() - es = append(es, multi...) - return es -} - -// encode converts notify system-independent events to valid inotify mask -// which can be passed to inotify_add_watch(2) function. -func encode(e Event) uint32 { - if e&Create != 0 { - e = (e ^ Create) | InCreate | InMovedTo - } - if e&Remove != 0 { - e = (e ^ Remove) | InDelete | InDeleteSelf - } - if e&Write != 0 { - e = (e ^ Write) | InModify - } - if e&Rename != 0 { - e = (e ^ Rename) | InMovedFrom | InMoveSelf - } - return uint32(e) -} - -// decode uses internally stored mask to distinguish whether system-independent -// or system-dependent event is requested. The first one is created by modifying -// `e` argument. decode method sets e.event value to 0 when an event should be -// skipped. System-dependent event is set as the function's return value which -// can be nil when the event should not be passed on. -func decode(mask Event, e *event) (syse *event) { - if sysmask := uint32(mask) & e.sys.Mask; sysmask != 0 { - syse = &event{sys: unix.InotifyEvent{ - Wd: e.sys.Wd, - Mask: e.sys.Mask, - Cookie: e.sys.Cookie, - }, event: Event(sysmask), path: e.path} - } - imask := encode(mask) - switch { - case mask&Create != 0 && imask&uint32(InCreate|InMovedTo)&e.sys.Mask != 0: - e.event = Create - case mask&Remove != 0 && imask&uint32(InDelete|InDeleteSelf)&e.sys.Mask != 0: - e.event = Remove - case mask&Write != 0 && imask&uint32(InModify)&e.sys.Mask != 0: - e.event = Write - case mask&Rename != 0 && imask&uint32(InMovedFrom|InMoveSelf)&e.sys.Mask != 0: - e.event = Rename - default: - e.event = 0 - } - return -} - -// Unwatch implements notify.watcher interface. It looks for watch descriptor -// related to registered path and if found, calls inotify_rm_watch(2) function. -// This method is allowed to return EINVAL error when concurrently requested to -// delete identical path. -func (i *inotify) Unwatch(path string) (err error) { - iwd := int32(invalidDescriptor) - i.RLock() - for iwdkey, wd := range i.m { - if wd.path == path { - iwd = iwdkey - break - } - } - i.RUnlock() - if iwd == invalidDescriptor { - return errors.New("notify: path " + path + " is already watched") - } - fd := atomic.LoadInt32(&i.fd) - if err = removeInotifyWatch(fd, iwd); err != nil { - return - } - i.Lock() - delete(i.m, iwd) - i.Unlock() - return nil -} - -// Close implements notify.watcher interface. It removes all existing watch -// descriptors and wakes up producer goroutine by sending data to the write end -// of the pipe. The function waits for a signal from producer which means that -// all operations on current monitoring instance are done. -func (i *inotify) Close() (err error) { - i.Lock() - if fd := atomic.LoadInt32(&i.fd); fd == invalidDescriptor { - i.Unlock() - return nil - } - for iwd := range i.m { - if e := removeInotifyWatch(i.fd, iwd); e != nil && err == nil { - err = e - } - delete(i.m, iwd) - } - switch _, errwrite := unix.Write(i.pipefd[1], []byte{0x00}); { - case errwrite != nil && err == nil: - err = errwrite - fallthrough - case errwrite != nil: - i.Unlock() - default: - i.Unlock() - i.wg.Wait() - } - return -} - -// if path was removed, notify already removed the watch and returns EINVAL error -func removeInotifyWatch(fd int32, iwd int32) (err error) { - if _, err = unix.InotifyRmWatch(int(fd), uint32(iwd)); err != nil && err != unix.EINVAL { - return - } - return nil -} diff --git a/vendor/github.com/rjeczalik/notify/watcher_kqueue.go b/vendor/github.com/rjeczalik/notify/watcher_kqueue.go deleted file mode 100644 index 22e3c2c4a..000000000 --- a/vendor/github.com/rjeczalik/notify/watcher_kqueue.go +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build darwin,kqueue dragonfly freebsd netbsd openbsd - -package notify - -import ( - "fmt" - "os" - "syscall" -) - -// newTrigger returns implementation of trigger. -func newTrigger(pthLkp map[string]*watched) trigger { - return &kq{ - pthLkp: pthLkp, - idLkp: make(map[int]*watched), - } -} - -// kq is a structure implementing trigger for kqueue. -type kq struct { - // fd is a kqueue file descriptor - fd int - // pipefds are file descriptors used to stop `Kevent` call. - pipefds [2]int - // idLkp is a data structure mapping file descriptors with data about watching - // represented by them files/directories. - idLkp map[int]*watched - // pthLkp is a structure mapping monitored files/dir with data about them, - // shared with parent trg structure - pthLkp map[string]*watched -} - -// watched is a data structure representing watched file/directory. -type watched struct { - trgWatched - // fd is a file descriptor for watched file/directory. - fd int -} - -// Stop implements trigger. -func (k *kq) Stop() (err error) { - // trigger event used to interrupt Kevent call. - _, err = syscall.Write(k.pipefds[1], []byte{0x00}) - return -} - -// Close implements trigger. -func (k *kq) Close() error { - return syscall.Close(k.fd) -} - -// NewWatched implements trigger. -func (*kq) NewWatched(p string, fi os.FileInfo) (*watched, error) { - fd, err := syscall.Open(p, syscall.O_NONBLOCK|syscall.O_RDONLY, 0) - if err != nil { - return nil, err - } - return &watched{ - trgWatched: trgWatched{p: p, fi: fi}, - fd: fd, - }, nil -} - -// Record implements trigger. -func (k *kq) Record(w *watched) { - k.idLkp[w.fd], k.pthLkp[w.p] = w, w -} - -// Del implements trigger. -func (k *kq) Del(w *watched) { - syscall.Close(w.fd) - delete(k.idLkp, w.fd) - delete(k.pthLkp, w.p) -} - -func inter2kq(n interface{}) syscall.Kevent_t { - kq, ok := n.(syscall.Kevent_t) - if !ok { - panic(fmt.Sprintf("kqueue: type should be Kevent_t, %T instead", n)) - } - return kq -} - -// Init implements trigger. -func (k *kq) Init() (err error) { - if k.fd, err = syscall.Kqueue(); err != nil { - return - } - // Creates pipe used to stop `Kevent` call by registering it, - // watching read end and writing to other end of it. - if err = syscall.Pipe(k.pipefds[:]); err != nil { - return nonil(err, k.Close()) - } - var kevn [1]syscall.Kevent_t - syscall.SetKevent(&kevn[0], k.pipefds[0], syscall.EVFILT_READ, syscall.EV_ADD) - if _, err = syscall.Kevent(k.fd, kevn[:], nil, nil); err != nil { - return nonil(err, k.Close()) - } - return -} - -// Unwatch implements trigger. -func (k *kq) Unwatch(w *watched) (err error) { - var kevn [1]syscall.Kevent_t - syscall.SetKevent(&kevn[0], w.fd, syscall.EVFILT_VNODE, syscall.EV_DELETE) - - _, err = syscall.Kevent(k.fd, kevn[:], nil, nil) - return -} - -// Watch implements trigger. -func (k *kq) Watch(fi os.FileInfo, w *watched, e int64) (err error) { - var kevn [1]syscall.Kevent_t - syscall.SetKevent(&kevn[0], w.fd, syscall.EVFILT_VNODE, - syscall.EV_ADD|syscall.EV_CLEAR) - kevn[0].Fflags = uint32(e) - - _, err = syscall.Kevent(k.fd, kevn[:], nil, nil) - return -} - -// Wait implements trigger. -func (k *kq) Wait() (interface{}, error) { - var ( - kevn [1]syscall.Kevent_t - err error - ) - kevn[0] = syscall.Kevent_t{} - _, err = syscall.Kevent(k.fd, nil, kevn[:], nil) - - return kevn[0], err -} - -// Watched implements trigger. -func (k *kq) Watched(n interface{}) (*watched, int64, error) { - kevn, ok := n.(syscall.Kevent_t) - if !ok { - panic(fmt.Sprintf("kq: type should be syscall.Kevent_t, %T instead", kevn)) - } - if _, ok = k.idLkp[int(kevn.Ident)]; !ok { - return nil, 0, errNotWatched - } - return k.idLkp[int(kevn.Ident)], int64(kevn.Fflags), nil -} - -// IsStop implements trigger. -func (k *kq) IsStop(n interface{}, err error) bool { - return int(inter2kq(n).Ident) == k.pipefds[0] -} - -func init() { - encode = func(e Event, dir bool) (o int64) { - // Create event is not supported by kqueue. Instead NoteWrite event will - // be registered for a directory. If this event will be reported on dir - // which is to be monitored for Create, dir will be rescanned - // and Create events will be generated and returned for new files. - // In case of files, if not requested NoteRename event is reported, - // it will be ignored. - o = int64(e &^ Create) - if (e&Create != 0 && dir) || e&Write != 0 { - o = (o &^ int64(Write)) | int64(NoteWrite) - } - if e&Rename != 0 { - o = (o &^ int64(Rename)) | int64(NoteRename) - } - if e&Remove != 0 { - o = (o &^ int64(Remove)) | int64(NoteDelete) - } - return - } - nat2not = map[Event]Event{ - NoteWrite: Write, - NoteRename: Rename, - NoteDelete: Remove, - NoteExtend: Event(0), - NoteAttrib: Event(0), - NoteRevoke: Event(0), - NoteLink: Event(0), - } - not2nat = map[Event]Event{ - Write: NoteWrite, - Rename: NoteRename, - Remove: NoteDelete, - } -} diff --git a/vendor/github.com/rjeczalik/notify/watcher_notimplemented.go b/vendor/github.com/rjeczalik/notify/watcher_notimplemented.go deleted file mode 100644 index bb0672fd8..000000000 --- a/vendor/github.com/rjeczalik/notify/watcher_notimplemented.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2014-2018 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build !darwin,!linux,!freebsd,!dragonfly,!netbsd,!openbsd,!windows -// +build !kqueue,!solaris - -package notify - -import "errors" - -// newWatcher stub. -func newWatcher(chan<- EventInfo) watcher { - return watcherStub{errors.New("notify: not implemented")} -} diff --git a/vendor/github.com/rjeczalik/notify/watcher_readdcw.go b/vendor/github.com/rjeczalik/notify/watcher_readdcw.go deleted file mode 100644 index b69811a69..000000000 --- a/vendor/github.com/rjeczalik/notify/watcher_readdcw.go +++ /dev/null @@ -1,605 +0,0 @@ -// Copyright (c) 2014-2018 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build windows - -package notify - -import ( - "errors" - "runtime" - "sync" - "sync/atomic" - "syscall" - "unsafe" -) - -// readBufferSize defines the size of an array in which read statuses are stored. -// The buffer have to be DWORD-aligned and, if notify is used in monitoring a -// directory over the network, its size must not be greater than 64KB. Each of -// watched directories uses its own buffer for storing events. -const readBufferSize = 4096 - -// Since all operations which go through the Windows completion routine are done -// asynchronously, filter may set one of the constants below. They were defined -// in order to distinguish whether current folder should be re-registered in -// ReadDirectoryChangesW function or some control operations need to be executed. -const ( - stateRewatch uint32 = 1 << (28 + iota) - stateUnwatch - stateCPClose -) - -// Filter used in current implementation was split into four segments: -// - bits 0-11 store ReadDirectoryChangesW filters, -// - bits 12-19 store File notify actions, -// - bits 20-27 store notify specific events and flags, -// - bits 28-31 store states which are used in loop's FSM. -// Constants below are used as masks to retrieve only specific filter parts. -const ( - onlyNotifyChanges uint32 = 0x00000FFF - onlyNGlobalEvents uint32 = 0x0FF00000 - onlyMachineStates uint32 = 0xF0000000 -) - -// grip represents a single watched directory. It stores the data required by -// ReadDirectoryChangesW function. Only the filter, recursive, and handle members -// may by modified by watcher implementation. Rest of the them have to remain -// constant since they are used by Windows completion routine. This indicates that -// grip can be removed only when all operations on the file handle are finished. -type grip struct { - handle syscall.Handle - filter uint32 - recursive bool - pathw []uint16 - buffer [readBufferSize]byte - parent *watched - ovlapped *overlappedEx -} - -// overlappedEx stores information used in asynchronous input and output. -// Additionally, overlappedEx contains a pointer to 'grip' item which is used in -// order to gather the structure in which the overlappedEx object was created. -type overlappedEx struct { - syscall.Overlapped - parent *grip -} - -// newGrip creates a new file handle that can be used in overlapped operations. -// Then, the handle is associated with I/O completion port 'cph' and its value -// is stored in newly created 'grip' object. -func newGrip(cph syscall.Handle, parent *watched, filter uint32) (*grip, error) { - g := &grip{ - handle: syscall.InvalidHandle, - filter: filter, - recursive: parent.recursive, - pathw: parent.pathw, - parent: parent, - ovlapped: &overlappedEx{}, - } - if err := g.register(cph); err != nil { - return nil, err - } - g.ovlapped.parent = g - return g, nil -} - -// NOTE : Thread safe -func (g *grip) register(cph syscall.Handle) (err error) { - if g.handle, err = syscall.CreateFile( - &g.pathw[0], - syscall.FILE_LIST_DIRECTORY, - syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, - nil, - syscall.OPEN_EXISTING, - syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OVERLAPPED, - 0, - ); err != nil { - return - } - if _, err = syscall.CreateIoCompletionPort(g.handle, cph, 0, 0); err != nil { - syscall.CloseHandle(g.handle) - return - } - return g.readDirChanges() -} - -// readDirChanges tells the system to store file change information in grip's -// buffer. Directory changes that occur between calls to this function are added -// to the buffer and then, returned with the next call. -func (g *grip) readDirChanges() error { - handle := syscall.Handle(atomic.LoadUintptr((*uintptr)(&g.handle))) - if handle == syscall.InvalidHandle { - return nil // Handle was closed. - } - - return syscall.ReadDirectoryChanges( - handle, - &g.buffer[0], - uint32(unsafe.Sizeof(g.buffer)), - g.recursive, - encode(g.filter), - nil, - (*syscall.Overlapped)(unsafe.Pointer(g.ovlapped)), - 0, - ) -} - -// encode transforms a generic filter, which contains platform independent and -// implementation specific bit fields, to value that can be used as NotifyFilter -// parameter in ReadDirectoryChangesW function. -func encode(filter uint32) uint32 { - e := Event(filter & (onlyNGlobalEvents | onlyNotifyChanges)) - if e&dirmarker != 0 { - return uint32(FileNotifyChangeDirName) - } - if e&Create != 0 { - e = (e ^ Create) | FileNotifyChangeFileName - } - if e&Remove != 0 { - e = (e ^ Remove) | FileNotifyChangeFileName - } - if e&Write != 0 { - e = (e ^ Write) | FileNotifyChangeAttributes | FileNotifyChangeSize | - FileNotifyChangeCreation | FileNotifyChangeSecurity - } - if e&Rename != 0 { - e = (e ^ Rename) | FileNotifyChangeFileName - } - return uint32(e) -} - -// watched is made in order to check whether an action comes from a directory or -// file. This approach requires two file handlers per single monitored folder. The -// second grip handles actions which include creating or deleting a directory. If -// these processes are not monitored, only the first grip is created. -type watched struct { - filter uint32 - recursive bool - count uint8 - pathw []uint16 - digrip [2]*grip -} - -// newWatched creates a new watched instance. It splits the filter variable into -// two parts. The first part is responsible for watching all events which can be -// created for a file in watched directory structure and the second one watches -// only directory Create/Remove actions. If all operations succeed, the Create -// message is sent to I/O completion port queue for further processing. -func newWatched(cph syscall.Handle, filter uint32, recursive bool, - path string) (wd *watched, err error) { - wd = &watched{ - filter: filter, - recursive: recursive, - } - if wd.pathw, err = syscall.UTF16FromString(path); err != nil { - return - } - if err = wd.recreate(cph); err != nil { - return - } - return wd, nil -} - -// TODO : doc -func (wd *watched) recreate(cph syscall.Handle) (err error) { - filefilter := wd.filter &^ uint32(FileNotifyChangeDirName) - if err = wd.updateGrip(0, cph, filefilter == 0, filefilter); err != nil { - return - } - dirfilter := wd.filter & uint32(FileNotifyChangeDirName|Create|Remove) - if err = wd.updateGrip(1, cph, dirfilter == 0, wd.filter|uint32(dirmarker)); err != nil { - return - } - wd.filter &^= onlyMachineStates - return -} - -// TODO : doc -func (wd *watched) updateGrip(idx int, cph syscall.Handle, reset bool, - newflag uint32) (err error) { - if reset { - wd.digrip[idx] = nil - } else { - if wd.digrip[idx] == nil { - if wd.digrip[idx], err = newGrip(cph, wd, newflag); err != nil { - wd.closeHandle() - return - } - } else { - wd.digrip[idx].filter = newflag - wd.digrip[idx].recursive = wd.recursive - if err = wd.digrip[idx].register(cph); err != nil { - wd.closeHandle() - return - } - } - wd.count++ - } - return -} - -// closeHandle closes handles that are stored in digrip array. Function always -// tries to close all of the handlers before it exits, even when there are errors -// returned from the operating system kernel. -func (wd *watched) closeHandle() (err error) { - for _, g := range wd.digrip { - if g == nil { - continue - } - - for { - handle := syscall.Handle(atomic.LoadUintptr((*uintptr)(&g.handle))) - if handle == syscall.InvalidHandle { - break // Already closed. - } - - e := syscall.CloseHandle(handle) - if e != nil && err == nil { - err = e - } - - // Set invalid handle even when CloseHandle fails. This will leak - // the handle but, since we can't close it anyway, there won't be - // any difference. - if atomic.CompareAndSwapUintptr((*uintptr)(&g.handle), - (uintptr)(handle), (uintptr)(syscall.InvalidHandle)) { - break - } - } - } - return -} - -// watcher implements Watcher interface. It stores a set of watched directories. -// All operations which remove watched objects from map `m` must be performed in -// loop goroutine since these structures are used internally by operating system. -type readdcw struct { - sync.Mutex - m map[string]*watched - cph syscall.Handle - start bool - wg sync.WaitGroup - c chan<- EventInfo -} - -// NewWatcher creates new non-recursive watcher backed by ReadDirectoryChangesW. -func newWatcher(c chan<- EventInfo) watcher { - r := &readdcw{ - m: make(map[string]*watched), - cph: syscall.InvalidHandle, - c: c, - } - runtime.SetFinalizer(r, func(r *readdcw) { - if r.cph != syscall.InvalidHandle { - syscall.CloseHandle(r.cph) - } - }) - return r -} - -// Watch implements notify.Watcher interface. -func (r *readdcw) Watch(path string, event Event) error { - return r.watch(path, event, false) -} - -// RecursiveWatch implements notify.RecursiveWatcher interface. -func (r *readdcw) RecursiveWatch(path string, event Event) error { - return r.watch(path, event, true) -} - -// watch inserts a directory to the group of watched folders. If watched folder -// already exists, function tries to rewatch it with new filters(NOT VALID). Moreover, -// watch starts the main event loop goroutine when called for the first time. -func (r *readdcw) watch(path string, event Event, recursive bool) error { - if event&^(All|fileNotifyChangeAll) != 0 { - return errors.New("notify: unknown event") - } - - r.Lock() - defer r.Unlock() - - if wd, ok := r.m[path]; ok { - dbgprint("watch: already exists") - wd.filter &^= stateUnwatch - return nil - } - - if err := r.lazyinit(); err != nil { - return err - } - - wd, err := newWatched(r.cph, uint32(event), recursive, path) - if err != nil { - return err - } - - r.m[path] = wd - dbgprint("watch: new watch added") - - return nil -} - -// lazyinit creates an I/O completion port and starts the main event loop. -func (r *readdcw) lazyinit() (err error) { - invalid := uintptr(syscall.InvalidHandle) - - if atomic.LoadUintptr((*uintptr)(&r.cph)) == invalid { - cph := syscall.InvalidHandle - if cph, err = syscall.CreateIoCompletionPort(cph, 0, 0, 0); err != nil { - return - } - - r.cph, r.start = cph, true - go r.loop() - } - - return -} - -// TODO(pknap) : doc -func (r *readdcw) loop() { - var n, key uint32 - var overlapped *syscall.Overlapped - for { - err := syscall.GetQueuedCompletionStatus(r.cph, &n, &key, &overlapped, syscall.INFINITE) - if key == stateCPClose { - r.Lock() - handle := r.cph - r.cph = syscall.InvalidHandle - r.Unlock() - syscall.CloseHandle(handle) - r.wg.Done() - return - } - if overlapped == nil { - // TODO: check key == rewatch delete or 0(panic) - continue - } - overEx := (*overlappedEx)(unsafe.Pointer(overlapped)) - if n != 0 { - r.loopevent(n, overEx) - if err = overEx.parent.readDirChanges(); err != nil { - // TODO: error handling - } - } - r.loopstate(overEx) - } -} - -// TODO(pknap) : doc -func (r *readdcw) loopstate(overEx *overlappedEx) { - r.Lock() - defer r.Unlock() - filter := overEx.parent.parent.filter - if filter&onlyMachineStates == 0 { - return - } - if overEx.parent.parent.count--; overEx.parent.parent.count == 0 { - switch filter & onlyMachineStates { - case stateRewatch: - dbgprint("loopstate rewatch") - overEx.parent.parent.recreate(r.cph) - case stateUnwatch: - dbgprint("loopstate unwatch") - overEx.parent.parent.closeHandle() - delete(r.m, syscall.UTF16ToString(overEx.parent.pathw)) - case stateCPClose: - default: - panic(`notify: windows loopstate logic error`) - } - } -} - -// TODO(pknap) : doc -func (r *readdcw) loopevent(n uint32, overEx *overlappedEx) { - events := []*event{} - var currOffset uint32 - for { - raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&overEx.parent.buffer[currOffset])) - name := syscall.UTF16ToString((*[syscall.MAX_LONG_PATH]uint16)(unsafe.Pointer(&raw.FileName))[:raw.FileNameLength>>1]) - events = append(events, &event{ - pathw: overEx.parent.pathw, - filter: overEx.parent.filter, - action: raw.Action, - name: name, - }) - if raw.NextEntryOffset == 0 { - break - } - if currOffset += raw.NextEntryOffset; currOffset >= n { - break - } - } - r.send(events) -} - -// TODO(pknap) : doc -func (r *readdcw) send(es []*event) { - for _, e := range es { - var syse Event - if e.e, syse = decode(e.filter, e.action); e.e == 0 && syse == 0 { - continue - } - switch { - case e.action == syscall.FILE_ACTION_MODIFIED: - e.ftype = fTypeUnknown - case e.filter&uint32(dirmarker) != 0: - e.ftype = fTypeDirectory - default: - e.ftype = fTypeFile - } - switch { - case e.e == 0: - e.e = syse - case syse != 0: - r.c <- &event{ - pathw: e.pathw, - name: e.name, - ftype: e.ftype, - action: e.action, - filter: e.filter, - e: syse, - } - } - r.c <- e - } -} - -// Rewatch implements notify.Rewatcher interface. -func (r *readdcw) Rewatch(path string, oldevent, newevent Event) error { - return r.rewatch(path, uint32(oldevent), uint32(newevent), false) -} - -// RecursiveRewatch implements notify.RecursiveRewatcher interface. -func (r *readdcw) RecursiveRewatch(oldpath, newpath string, oldevent, - newevent Event) error { - if oldpath != newpath { - if err := r.unwatch(oldpath); err != nil { - return err - } - return r.watch(newpath, newevent, true) - } - return r.rewatch(newpath, uint32(oldevent), uint32(newevent), true) -} - -// TODO : (pknap) doc. -func (r *readdcw) rewatch(path string, oldevent, newevent uint32, recursive bool) (err error) { - if Event(newevent)&^(All|fileNotifyChangeAll) != 0 { - return errors.New("notify: unknown event") - } - var wd *watched - r.Lock() - defer r.Unlock() - if wd, err = r.nonStateWatchedLocked(path); err != nil { - return - } - if wd.filter&(onlyNotifyChanges|onlyNGlobalEvents) != oldevent { - panic(`notify: windows re-watcher logic error`) - } - wd.filter = stateRewatch | newevent - wd.recursive, recursive = recursive, wd.recursive - if err = wd.closeHandle(); err != nil { - wd.filter = oldevent - wd.recursive = recursive - return - } - return -} - -// TODO : pknap -func (r *readdcw) nonStateWatchedLocked(path string) (wd *watched, err error) { - wd, ok := r.m[path] - if !ok || wd == nil { - err = errors.New(`notify: ` + path + ` path is unwatched`) - return - } - if wd.filter&onlyMachineStates != 0 { - err = errors.New(`notify: another re/unwatching operation in progress`) - return - } - return -} - -// Unwatch implements notify.Watcher interface. -func (r *readdcw) Unwatch(path string) error { - return r.unwatch(path) -} - -// RecursiveUnwatch implements notify.RecursiveWatcher interface. -func (r *readdcw) RecursiveUnwatch(path string) error { - return r.unwatch(path) -} - -// TODO : pknap -func (r *readdcw) unwatch(path string) (err error) { - var wd *watched - - r.Lock() - defer r.Unlock() - if wd, err = r.nonStateWatchedLocked(path); err != nil { - return - } - - wd.filter |= stateUnwatch - dbgprint("unwatch: set unwatch state") - - if _, attrErr := syscall.GetFileAttributes(&wd.pathw[0]); attrErr != nil { - for _, g := range wd.digrip { - if g == nil { - continue - } - - dbgprint("unwatch: posting") - if err = syscall.PostQueuedCompletionStatus(r.cph, 0, 0, (*syscall.Overlapped)(unsafe.Pointer(g.ovlapped))); err != nil { - wd.filter &^= stateUnwatch - return - } - } - } - - return -} - -// Close resets the whole watcher object, closes all existing file descriptors, -// and sends stateCPClose state as completion key to the main watcher's loop. -func (r *readdcw) Close() (err error) { - r.Lock() - if !r.start { - r.Unlock() - return nil - } - for _, wd := range r.m { - wd.filter &^= onlyMachineStates - wd.filter |= stateCPClose - if e := wd.closeHandle(); e != nil && err == nil { - err = e - } - } - r.start = false - r.Unlock() - r.wg.Add(1) - if e := syscall.PostQueuedCompletionStatus(r.cph, 0, stateCPClose, nil); e != nil && err == nil { - return e - } - r.wg.Wait() - return -} - -// decode creates a notify event from both non-raw filter and action which was -// returned from completion routine. Function may return Event(0) in case when -// filter was replaced by a new value which does not contain fields that are -// valid with passed action. -func decode(filter, action uint32) (Event, Event) { - switch action { - case syscall.FILE_ACTION_ADDED: - return gensys(filter, Create, FileActionAdded) - case syscall.FILE_ACTION_REMOVED: - return gensys(filter, Remove, FileActionRemoved) - case syscall.FILE_ACTION_MODIFIED: - return gensys(filter, Write, FileActionModified) - case syscall.FILE_ACTION_RENAMED_OLD_NAME: - return gensys(filter, Rename, FileActionRenamedOldName) - case syscall.FILE_ACTION_RENAMED_NEW_NAME: - return gensys(filter, Rename, FileActionRenamedNewName) - } - panic(`notify: cannot decode internal mask`) -} - -// gensys decides whether the Windows action, system-independent event or both -// of them should be returned. Since the grip's filter may be atomically changed -// during watcher lifetime, it is possible that neither Windows nor notify masks -// are watched by the user when this function is called. -func gensys(filter uint32, ge, se Event) (gene, syse Event) { - isdir := filter&uint32(dirmarker) != 0 - if isdir && filter&uint32(FileNotifyChangeDirName) != 0 || - !isdir && filter&uint32(FileNotifyChangeFileName) != 0 || - filter&uint32(fileNotifyChangeModified) != 0 { - syse = se - } - if filter&uint32(ge) != 0 { - gene = ge - } - return -} diff --git a/vendor/github.com/rjeczalik/notify/watcher_stub.go b/vendor/github.com/rjeczalik/notify/watcher_stub.go deleted file mode 100644 index 9b284ddc8..000000000 --- a/vendor/github.com/rjeczalik/notify/watcher_stub.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2014-2018 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -package notify - -type watcherStub struct{ error } - -// Following methods implement notify.watcher interface. -func (s watcherStub) Watch(string, Event) error { return s } -func (s watcherStub) Rewatch(string, Event, Event) error { return s } -func (s watcherStub) Unwatch(string) (err error) { return s } -func (s watcherStub) Close() error { return s } diff --git a/vendor/github.com/rjeczalik/notify/watcher_trigger.go b/vendor/github.com/rjeczalik/notify/watcher_trigger.go deleted file mode 100644 index 1ebe04829..000000000 --- a/vendor/github.com/rjeczalik/notify/watcher_trigger.go +++ /dev/null @@ -1,450 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build darwin,kqueue dragonfly freebsd netbsd openbsd solaris - -// watcher_trigger is used for FEN and kqueue which behave similarly: -// only files and dirs can be watched directly, but not files inside dirs. -// As a result Create events have to be generated by implementation when -// after Write event is returned for watched dir, it is rescanned and Create -// event is returned for new files and these are automatically added -// to watchlist. In case of removal of watched directory, native system returns -// events for all files, but for Rename, they also need to be generated. -// As a result native system works as something like trigger for rescan, -// but contains additional data about dir in which changes occurred. For files -// detailed data is returned. -// Usage of watcher_trigger requires: -// - trigger implementation, -// - encode func, -// - not2nat, nat2not maps. -// Required manual operations on filesystem can lead to loss of precision. - -package notify - -import ( - "fmt" - "os" - "path/filepath" - "strings" - "sync" - "syscall" -) - -// trigger is to be implemented by platform implementation like FEN or kqueue. -type trigger interface { - // Close closes watcher's main native file descriptor. - Close() error - // Stop waiting for new events. - Stop() error - // Create new instance of watched. - NewWatched(string, os.FileInfo) (*watched, error) - // Record internally new *watched instance. - Record(*watched) - // Del removes internal copy of *watched instance. - Del(*watched) - // Watched returns *watched instance and native events for native type. - Watched(interface{}) (*watched, int64, error) - // Init initializes native watcher call. - Init() error - // Watch starts watching provided file/dir. - Watch(os.FileInfo, *watched, int64) error - // Unwatch stops watching provided file/dir. - Unwatch(*watched) error - // Wait for new events. - Wait() (interface{}, error) - // IsStop checks if Wait finished because of request watcher's stop. - IsStop(n interface{}, err error) bool -} - -// trgWatched is a the base data structure representing watched file/directory. -// The platform specific full data structure (watched) must embed this type. -type trgWatched struct { - // p is a path to watched file/directory. - p string - // fi provides information about watched file/dir. - fi os.FileInfo - // eDir represents events watched directly. - eDir Event - // eNonDir represents events watched indirectly. - eNonDir Event -} - -// encode Event to native representation. Implementation is to be provided by -// platform specific implementation. -var encode func(Event, bool) int64 - -var ( - // nat2not matches native events to notify's ones. To be initialized by - // platform dependent implementation. - nat2not map[Event]Event - // not2nat matches notify's events to native ones. To be initialized by - // platform dependent implementation. - not2nat map[Event]Event -) - -// trg is a main structure implementing watcher. -type trg struct { - sync.Mutex - // s is a channel used to stop monitoring. - s chan struct{} - // c is a channel used to pass events further. - c chan<- EventInfo - // pthLkp is a data structure mapping file names with data about watching - // represented by them files/directories. - pthLkp map[string]*watched - // t is a platform dependent implementation of trigger. - t trigger -} - -// newWatcher returns new watcher's implementation. -func newWatcher(c chan<- EventInfo) watcher { - t := &trg{ - s: make(chan struct{}, 1), - pthLkp: make(map[string]*watched, 0), - c: c, - } - t.t = newTrigger(t.pthLkp) - if err := t.t.Init(); err != nil { - t.Close() - return watcherStub{fmt.Errorf("failed setting up watcher: %v", err)} - } - go t.monitor() - return t -} - -// Close implements watcher. -func (t *trg) Close() (err error) { - t.Lock() - if err = t.t.Stop(); err != nil { - t.Unlock() - return - } - <-t.s - var e error - for _, w := range t.pthLkp { - if e = t.unwatch(w.p, w.fi); e != nil { - dbgprintf("trg: unwatch %q failed: %q\n", w.p, e) - err = nonil(err, e) - } - } - if e = t.t.Close(); e != nil { - dbgprintf("trg: closing native watch failed: %q\n", e) - err = nonil(err, e) - } - if remaining := len(t.pthLkp); remaining != 0 { - err = nonil(err, fmt.Errorf("Not all watches were removed: len(t.pthLkp) == %v", len(t.pthLkp))) - } - t.Unlock() - return -} - -// send reported events one by one through chan. -func (t *trg) send(evn []event) { - for i := range evn { - t.c <- &evn[i] - } -} - -// singlewatch starts to watch given p file/directory. -func (t *trg) singlewatch(p string, e Event, direct mode, fi os.FileInfo) (err error) { - w, ok := t.pthLkp[p] - if !ok { - if w, err = t.t.NewWatched(p, fi); err != nil { - return - } - } - switch direct { - case dir: - w.eDir |= e - case ndir: - w.eNonDir |= e - case both: - w.eDir |= e - w.eNonDir |= e - } - if err = t.t.Watch(fi, w, encode(w.eDir|w.eNonDir, fi.IsDir())); err != nil { - return - } - if !ok { - t.t.Record(w) - return nil - } - return errAlreadyWatched -} - -// decode converts event received from native to notify.Event -// representation taking into account requested events (w). -func decode(o int64, w Event) (e Event) { - for f, n := range nat2not { - if o&int64(f) != 0 { - if w&f != 0 { - e |= f - } - if w&n != 0 { - e |= n - } - } - } - - return -} - -func (t *trg) watch(p string, e Event, fi os.FileInfo) error { - if err := t.singlewatch(p, e, dir, fi); err != nil { - if err != errAlreadyWatched { - return err - } - } - if fi.IsDir() { - err := t.walk(p, func(fi os.FileInfo) (err error) { - if err = t.singlewatch(filepath.Join(p, fi.Name()), e, ndir, - fi); err != nil { - if err != errAlreadyWatched { - return - } - } - return nil - }) - if err != nil { - return err - } - } - return nil -} - -// walk runs f func on each file/dir from p directory. -func (t *trg) walk(p string, fn func(os.FileInfo) error) error { - fp, err := os.Open(p) - if err != nil { - return err - } - ls, err := fp.Readdir(0) - fp.Close() - if err != nil { - return err - } - for i := range ls { - if err := fn(ls[i]); err != nil { - return err - } - } - return nil -} - -func (t *trg) unwatch(p string, fi os.FileInfo) error { - if fi.IsDir() { - err := t.walk(p, func(fi os.FileInfo) error { - err := t.singleunwatch(filepath.Join(p, fi.Name()), ndir) - if err != errNotWatched { - return err - } - return nil - }) - if err != nil { - return err - } - } - return t.singleunwatch(p, dir) -} - -// Watch implements Watcher interface. -func (t *trg) Watch(p string, e Event) error { - fi, err := os.Stat(p) - if err != nil { - return err - } - t.Lock() - err = t.watch(p, e, fi) - t.Unlock() - return err -} - -// Unwatch implements Watcher interface. -func (t *trg) Unwatch(p string) error { - fi, err := os.Stat(p) - if err != nil { - return err - } - t.Lock() - err = t.unwatch(p, fi) - t.Unlock() - return err -} - -// Rewatch implements Watcher interface. -// -// TODO(rjeczalik): This is a naive hack. Rewrite might help. -func (t *trg) Rewatch(p string, _, e Event) error { - fi, err := os.Stat(p) - if err != nil { - return err - } - t.Lock() - if err = t.unwatch(p, fi); err == nil { - // TODO(rjeczalik): If watch fails then we leave trigger in inconsistent - // state. Handle? Panic? Native version of rewatch? - err = t.watch(p, e, fi) - } - t.Unlock() - return nil -} - -func (*trg) file(w *watched, n interface{}, e Event) (evn []event) { - evn = append(evn, event{w.p, e, w.fi.IsDir(), n}) - return -} - -func (t *trg) dir(w *watched, n interface{}, e, ge Event) (evn []event) { - // If it's dir and delete we have to send it and continue, because - // other processing relies on opening (in this case not existing) dir. - // Events for contents of this dir are reported by native impl. - // However events for rename must be generated for all monitored files - // inside of moved directory, because native impl does not report it independently - // for each file descriptor being moved in result of move action on - // parent directory. - if (ge & (not2nat[Rename] | not2nat[Remove])) != 0 { - // Write is reported also for Remove on directory. Because of that - // we have to filter it out explicitly. - evn = append(evn, event{w.p, e & ^Write & ^not2nat[Write], true, n}) - if ge¬2nat[Rename] != 0 { - for p := range t.pthLkp { - if strings.HasPrefix(p, w.p+string(os.PathSeparator)) { - if err := t.singleunwatch(p, both); err != nil && err != errNotWatched && - !os.IsNotExist(err) { - dbgprintf("trg: failed stop watching moved file (%q): %q\n", - p, err) - } - if (w.eDir|w.eNonDir)&(not2nat[Rename]|Rename) != 0 { - evn = append(evn, event{ - p, (w.eDir | w.eNonDir) & e &^ Write &^ not2nat[Write], - w.fi.IsDir(), nil, - }) - } - } - } - } - t.t.Del(w) - return - } - if (ge & not2nat[Write]) != 0 { - switch err := t.walk(w.p, func(fi os.FileInfo) error { - p := filepath.Join(w.p, fi.Name()) - switch err := t.singlewatch(p, w.eDir, ndir, fi); { - case os.IsNotExist(err) && ((w.eDir & Remove) != 0): - evn = append(evn, event{p, Remove, fi.IsDir(), n}) - case err == errAlreadyWatched: - case err != nil: - dbgprintf("trg: watching %q failed: %q", p, err) - case (w.eDir & Create) != 0: - evn = append(evn, event{p, Create, fi.IsDir(), n}) - default: - } - return nil - }); { - case os.IsNotExist(err): - return - case err != nil: - dbgprintf("trg: dir processing failed: %q", err) - default: - } - } - return -} - -type mode uint - -const ( - dir mode = iota - ndir - both -) - -// unwatch stops watching p file/directory. -func (t *trg) singleunwatch(p string, direct mode) error { - w, ok := t.pthLkp[p] - if !ok { - return errNotWatched - } - switch direct { - case dir: - w.eDir = 0 - case ndir: - w.eNonDir = 0 - case both: - w.eDir, w.eNonDir = 0, 0 - } - if err := t.t.Unwatch(w); err != nil { - return err - } - if w.eNonDir|w.eDir != 0 { - mod := dir - if w.eNonDir != 0 { - mod = ndir - } - if err := t.singlewatch(p, w.eNonDir|w.eDir, mod, - w.fi); err != nil && err != errAlreadyWatched { - return err - } - } else { - t.t.Del(w) - } - return nil -} - -func (t *trg) monitor() { - var ( - n interface{} - err error - ) - for { - switch n, err = t.t.Wait(); { - case err == syscall.EINTR: - case t.t.IsStop(n, err): - t.s <- struct{}{} - return - case err != nil: - dbgprintf("trg: failed to read events: %q\n", err) - default: - t.send(t.process(n)) - } - } -} - -// process event returned by native call. -func (t *trg) process(n interface{}) (evn []event) { - t.Lock() - w, ge, err := t.t.Watched(n) - if err != nil { - t.Unlock() - dbgprintf("trg: %v event lookup failed: %q", Event(ge), err) - return - } - - e := decode(ge, w.eDir|w.eNonDir) - if ge&int64(not2nat[Remove]|not2nat[Rename]) == 0 { - switch fi, err := os.Stat(w.p); { - case err != nil: - default: - if err = t.t.Watch(fi, w, encode(w.eDir|w.eNonDir, fi.IsDir())); err != nil { - dbgprintf("trg: %q is no longer watched: %q", w.p, err) - t.t.Del(w) - } - } - } - if e == Event(0) && (!w.fi.IsDir() || (ge&int64(not2nat[Write])) == 0) { - t.Unlock() - return - } - - if w.fi.IsDir() { - evn = append(evn, t.dir(w, n, e, Event(ge))...) - } else { - evn = append(evn, t.file(w, n, e)...) - } - if Event(ge)&(not2nat[Remove]|not2nat[Rename]) != 0 { - t.t.Del(w) - } - t.Unlock() - return -} diff --git a/vendor/github.com/rjeczalik/notify/watchpoint.go b/vendor/github.com/rjeczalik/notify/watchpoint.go deleted file mode 100644 index 5afc914f4..000000000 --- a/vendor/github.com/rjeczalik/notify/watchpoint.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -package notify - -// EventDiff describes a change to an event set - EventDiff[0] is an old state, -// while EventDiff[1] is a new state. If event set has not changed (old == new), -// functions typically return the None value. -type eventDiff [2]Event - -func (diff eventDiff) Event() Event { - return diff[1] &^ diff[0] -} - -// Watchpoint -// -// The nil key holds total event set - logical sum for all registered events. -// It speeds up computing EventDiff for Add method. -// -// The rec key holds an event set for a watchpoints created by RecursiveWatch -// for a Watcher implementation which is not natively recursive. -type watchpoint map[chan<- EventInfo]Event - -// None is an empty event diff, think null object. -var none eventDiff - -// rec is just a placeholder -var rec = func() (ch chan<- EventInfo) { - ch = make(chan<- EventInfo) - close(ch) - return -}() - -func (wp watchpoint) dryAdd(ch chan<- EventInfo, e Event) eventDiff { - if e &^= internal; wp[ch]&e == e { - return none - } - total := wp[ch] &^ internal - return eventDiff{total, total | e} -} - -// Add assumes neither c nor e are nil or zero values. -func (wp watchpoint) Add(c chan<- EventInfo, e Event) (diff eventDiff) { - wp[c] |= e - diff[0] = wp[nil] - diff[1] = diff[0] | e - wp[nil] = diff[1] &^ omit - // Strip diff from internal events. - diff[0] &^= internal - diff[1] &^= internal - if diff[0] == diff[1] { - return none - } - return -} - -func (wp watchpoint) Del(c chan<- EventInfo, e Event) (diff eventDiff) { - wp[c] &^= e - if wp[c] == 0 { - delete(wp, c) - } - diff[0] = wp[nil] - delete(wp, nil) - if len(wp) != 0 { - // Recalculate total event set. - for _, e := range wp { - diff[1] |= e - } - wp[nil] = diff[1] &^ omit - } - // Strip diff from internal events. - diff[0] &^= internal - diff[1] &^= internal - if diff[0] == diff[1] { - return none - } - return -} - -func (wp watchpoint) Dispatch(ei EventInfo, extra Event) { - e := eventmask(ei, extra) - if !matches(wp[nil], e) { - return - } - for ch, eset := range wp { - if ch != nil && matches(eset, e) { - select { - case ch <- ei: - default: // Drop event if receiver is too slow - dbgprintf("dropped %s on %q: receiver too slow", ei.Event(), ei.Path()) - } - } - } -} - -func (wp watchpoint) Total() Event { - return wp[nil] &^ internal -} - -func (wp watchpoint) IsRecursive() bool { - return wp[nil]&recursive != 0 -} diff --git a/vendor/github.com/rjeczalik/notify/watchpoint_other.go b/vendor/github.com/rjeczalik/notify/watchpoint_other.go deleted file mode 100644 index 9bb381db7..000000000 --- a/vendor/github.com/rjeczalik/notify/watchpoint_other.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build !windows - -package notify - -// eventmask uses ei to create a new event which contains internal flags used by -// notify package logic. -func eventmask(ei EventInfo, extra Event) Event { - return ei.Event() | extra -} - -// matches reports a match only when: -// -// - for user events, when event is present in the given set -// - for internal events, when additionally both event and set have omit bit set -// -// Internal events must not be sent to user channels and vice versa. -func matches(set, event Event) bool { - return (set&omit)^(event&omit) == 0 && set&event == event -} diff --git a/vendor/github.com/rjeczalik/notify/watchpoint_readdcw.go b/vendor/github.com/rjeczalik/notify/watchpoint_readdcw.go deleted file mode 100644 index 9fd1e1df3..000000000 --- a/vendor/github.com/rjeczalik/notify/watchpoint_readdcw.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2014-2015 The Notify Authors. All rights reserved. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -// +build windows - -package notify - -// eventmask uses ei to create a new event which contains internal flags used by -// notify package logic. If one of FileAction* masks is detected, this function -// adds corresponding FileNotifyChange* values. This allows non registered -// FileAction* events to be passed on. -func eventmask(ei EventInfo, extra Event) (e Event) { - if e = ei.Event() | extra; e&fileActionAll != 0 { - if ev, ok := ei.(*event); ok { - switch ev.ftype { - case fTypeFile: - e |= FileNotifyChangeFileName - case fTypeDirectory: - e |= FileNotifyChangeDirName - case fTypeUnknown: - e |= fileNotifyChangeModified - } - return e &^ fileActionAll - } - } - return -} - -// matches reports a match only when: -// -// - for user events, when event is present in the given set -// - for internal events, when additionally both event and set have omit bit set -// -// Internal events must not be sent to user channels and vice versa. -func matches(set, event Event) bool { - return (set&omit)^(event&omit) == 0 && (set&event == event || set&fileNotifyChangeModified&event != 0) -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 87f605792..eb854ea39 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -73,6 +73,7 @@ github.com/dsnet/compress/internal/prefix ## explicit github.com/fatih/color # github.com/fsnotify/fsnotify v1.4.7 +## explicit github.com/fsnotify/fsnotify # github.com/getsentry/sentry-go v0.10.0 ## explicit @@ -210,9 +211,6 @@ github.com/pmezard/go-difflib/difflib # github.com/rivo/uniseg v0.2.0 ## explicit github.com/rivo/uniseg -# github.com/rjeczalik/notify v0.9.2 -## explicit -github.com/rjeczalik/notify # github.com/spf13/afero v1.1.2 github.com/spf13/afero github.com/spf13/afero/mem