Merge pull request #1060 from aledbf/fix-notify
Update fsnotify dependency to fix arm64 issue
This commit is contained in:
commit
15dfa8883b
15 changed files with 278 additions and 212 deletions
4
Godeps/Godeps.json
generated
4
Godeps/Godeps.json
generated
|
@ -391,8 +391,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "gopkg.in/fsnotify.v1",
|
"ImportPath": "gopkg.in/fsnotify.v1",
|
||||||
"Comment": "v1.2.9",
|
"Comment": "v1.4.2",
|
||||||
"Rev": "8611c35ab31c1c28aa903d33cf8b6e44a399b09e"
|
"Rev": "629574ca2a5df945712d3079857300b5e4da0236"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "gopkg.in/gcfg.v1",
|
"ImportPath": "gopkg.in/gcfg.v1",
|
||||||
|
|
5
vendor/gopkg.in/fsnotify.v1/.editorconfig
generated
vendored
Normal file
5
vendor/gopkg.in/fsnotify.v1/.editorconfig
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 4
|
7
vendor/gopkg.in/fsnotify.v1/.travis.yml
generated
vendored
7
vendor/gopkg.in/fsnotify.v1/.travis.yml
generated
vendored
|
@ -2,7 +2,12 @@ sudo: false
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.5.2
|
- 1.6.3
|
||||||
|
- tip
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- go: tip
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- go get -u github.com/golang/lint/golint
|
- go get -u github.com/golang/lint/golint
|
||||||
|
|
6
vendor/gopkg.in/fsnotify.v1/AUTHORS
generated
vendored
6
vendor/gopkg.in/fsnotify.v1/AUTHORS
generated
vendored
|
@ -9,6 +9,9 @@
|
||||||
# Please keep the list sorted.
|
# Please keep the list sorted.
|
||||||
|
|
||||||
Adrien Bustany <adrien@bustany.org>
|
Adrien Bustany <adrien@bustany.org>
|
||||||
|
Amit Krishnan <amit.krishnan@oracle.com>
|
||||||
|
Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
|
||||||
|
Bruno Bigras <bigras.bruno@gmail.com>
|
||||||
Caleb Spare <cespare@gmail.com>
|
Caleb Spare <cespare@gmail.com>
|
||||||
Case Nelson <case@teammating.com>
|
Case Nelson <case@teammating.com>
|
||||||
Chris Howey <chris@howey.me> <howeyc@gmail.com>
|
Chris Howey <chris@howey.me> <howeyc@gmail.com>
|
||||||
|
@ -23,13 +26,16 @@ Kelvin Fo <vmirage@gmail.com>
|
||||||
Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
|
Ken-ichirou MATSUZAWA <chamas@h4.dion.ne.jp>
|
||||||
Matt Layher <mdlayher@gmail.com>
|
Matt Layher <mdlayher@gmail.com>
|
||||||
Nathan Youngman <git@nathany.com>
|
Nathan Youngman <git@nathany.com>
|
||||||
|
Patrick <patrick@dropbox.com>
|
||||||
Paul Hammond <paul@paulhammond.org>
|
Paul Hammond <paul@paulhammond.org>
|
||||||
Pawel Knap <pawelknap88@gmail.com>
|
Pawel Knap <pawelknap88@gmail.com>
|
||||||
Pieter Droogendijk <pieter@binky.org.uk>
|
Pieter Droogendijk <pieter@binky.org.uk>
|
||||||
Pursuit92 <JoshChase@techpursuit.net>
|
Pursuit92 <JoshChase@techpursuit.net>
|
||||||
Riku Voipio <riku.voipio@linaro.org>
|
Riku Voipio <riku.voipio@linaro.org>
|
||||||
Rob Figueiredo <robfig@gmail.com>
|
Rob Figueiredo <robfig@gmail.com>
|
||||||
|
Slawek Ligus <root@ooz.ie>
|
||||||
Soge Zhang <zhssoge@gmail.com>
|
Soge Zhang <zhssoge@gmail.com>
|
||||||
|
Tiffany Jernigan <tiffany.jernigan@intel.com>
|
||||||
Tilak Sharma <tilaks@google.com>
|
Tilak Sharma <tilaks@google.com>
|
||||||
Travis Cline <travis.cline@gmail.com>
|
Travis Cline <travis.cline@gmail.com>
|
||||||
Tudor Golubenco <tudor.g@gmail.com>
|
Tudor Golubenco <tudor.g@gmail.com>
|
||||||
|
|
72
vendor/gopkg.in/fsnotify.v1/CHANGELOG.md
generated
vendored
72
vendor/gopkg.in/fsnotify.v1/CHANGELOG.md
generated
vendored
|
@ -1,72 +1,96 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v1.4.2 / 2016-10-10
|
||||||
|
|
||||||
|
* Linux: use InotifyInit1 with IN_CLOEXEC to stop leaking a file descriptor to a child process when using fork/exec [#178](https://github.com/fsnotify/fsnotify/pull/178) (thanks @pattyshack)
|
||||||
|
|
||||||
|
## v1.4.1 / 2016-10-04
|
||||||
|
|
||||||
|
* Fix flaky inotify stress test on Linux [#177](https://github.com/fsnotify/fsnotify/pull/177) (thanks @pattyshack)
|
||||||
|
|
||||||
|
## v1.4.0 / 2016-10-01
|
||||||
|
|
||||||
|
* add a String() method to Event.Op [#165](https://github.com/fsnotify/fsnotify/pull/165) (thanks @oozie)
|
||||||
|
|
||||||
|
## v1.3.1 / 2016-06-28
|
||||||
|
|
||||||
|
* Windows: fix for double backslash when watching the root of a drive [#151](https://github.com/fsnotify/fsnotify/issues/151) (thanks @brunoqc)
|
||||||
|
|
||||||
|
## v1.3.0 / 2016-04-19
|
||||||
|
|
||||||
|
* Support linux/arm64 by [patching](https://go-review.googlesource.com/#/c/21971/) x/sys/unix and switching to to it from syscall (thanks @suihkulokki) [#135](https://github.com/fsnotify/fsnotify/pull/135)
|
||||||
|
|
||||||
|
## v1.2.10 / 2016-03-02
|
||||||
|
|
||||||
|
* Fix golint errors in windows.go [#121](https://github.com/fsnotify/fsnotify/pull/121) (thanks @tiffanyfj)
|
||||||
|
|
||||||
## v1.2.9 / 2016-01-13
|
## v1.2.9 / 2016-01-13
|
||||||
|
|
||||||
kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/go-fsnotify/fsnotify/pull/111) (thanks @bep)
|
kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsnotify/pull/111) (thanks @bep)
|
||||||
|
|
||||||
## v1.2.8 / 2015-12-17
|
## v1.2.8 / 2015-12-17
|
||||||
|
|
||||||
* kqueue: fix race condition in Close [#105](https://github.com/go-fsnotify/fsnotify/pull/105) (thanks @djui for reporting the issue and @ppknap for writing a failing test)
|
* kqueue: fix race condition in Close [#105](https://github.com/fsnotify/fsnotify/pull/105) (thanks @djui for reporting the issue and @ppknap for writing a failing test)
|
||||||
* inotify: fix race in test
|
* inotify: fix race in test
|
||||||
* enable race detection for continuous integration (Linux, Mac, Windows)
|
* enable race detection for continuous integration (Linux, Mac, Windows)
|
||||||
|
|
||||||
## v1.2.5 / 2015-10-17
|
## v1.2.5 / 2015-10-17
|
||||||
|
|
||||||
* inotify: use epoll_create1 for arm64 support (requires Linux 2.6.27 or later) [#100](https://github.com/go-fsnotify/fsnotify/pull/100) (thanks @suihkulokki)
|
* inotify: use epoll_create1 for arm64 support (requires Linux 2.6.27 or later) [#100](https://github.com/fsnotify/fsnotify/pull/100) (thanks @suihkulokki)
|
||||||
* inotify: fix path leaks [#73](https://github.com/go-fsnotify/fsnotify/pull/73) (thanks @chamaken)
|
* inotify: fix path leaks [#73](https://github.com/fsnotify/fsnotify/pull/73) (thanks @chamaken)
|
||||||
* kqueue: watch for rename events on subdirectories [#83](https://github.com/go-fsnotify/fsnotify/pull/83) (thanks @guotie)
|
* kqueue: watch for rename events on subdirectories [#83](https://github.com/fsnotify/fsnotify/pull/83) (thanks @guotie)
|
||||||
* kqueue: avoid infinite loops from symlinks cycles [#101](https://github.com/go-fsnotify/fsnotify/pull/101) (thanks @illicitonion)
|
* kqueue: avoid infinite loops from symlinks cycles [#101](https://github.com/fsnotify/fsnotify/pull/101) (thanks @illicitonion)
|
||||||
|
|
||||||
## v1.2.1 / 2015-10-14
|
## v1.2.1 / 2015-10-14
|
||||||
|
|
||||||
* kqueue: don't watch named pipes [#98](https://github.com/go-fsnotify/fsnotify/pull/98) (thanks @evanphx)
|
* kqueue: don't watch named pipes [#98](https://github.com/fsnotify/fsnotify/pull/98) (thanks @evanphx)
|
||||||
|
|
||||||
## v1.2.0 / 2015-02-08
|
## v1.2.0 / 2015-02-08
|
||||||
|
|
||||||
* inotify: use epoll to wake up readEvents [#66](https://github.com/go-fsnotify/fsnotify/pull/66) (thanks @PieterD)
|
* inotify: use epoll to wake up readEvents [#66](https://github.com/fsnotify/fsnotify/pull/66) (thanks @PieterD)
|
||||||
* inotify: closing watcher should now always shut down goroutine [#63](https://github.com/go-fsnotify/fsnotify/pull/63) (thanks @PieterD)
|
* inotify: closing watcher should now always shut down goroutine [#63](https://github.com/fsnotify/fsnotify/pull/63) (thanks @PieterD)
|
||||||
* kqueue: close kqueue after removing watches, fixes [#59](https://github.com/go-fsnotify/fsnotify/issues/59)
|
* kqueue: close kqueue after removing watches, fixes [#59](https://github.com/fsnotify/fsnotify/issues/59)
|
||||||
|
|
||||||
## v1.1.1 / 2015-02-05
|
## v1.1.1 / 2015-02-05
|
||||||
|
|
||||||
* inotify: Retry read on EINTR [#61](https://github.com/go-fsnotify/fsnotify/issues/61) (thanks @PieterD)
|
* inotify: Retry read on EINTR [#61](https://github.com/fsnotify/fsnotify/issues/61) (thanks @PieterD)
|
||||||
|
|
||||||
## v1.1.0 / 2014-12-12
|
## v1.1.0 / 2014-12-12
|
||||||
|
|
||||||
* kqueue: rework internals [#43](https://github.com/go-fsnotify/fsnotify/pull/43)
|
* kqueue: rework internals [#43](https://github.com/fsnotify/fsnotify/pull/43)
|
||||||
* add low-level functions
|
* add low-level functions
|
||||||
* only need to store flags on directories
|
* only need to store flags on directories
|
||||||
* less mutexes [#13](https://github.com/go-fsnotify/fsnotify/issues/13)
|
* less mutexes [#13](https://github.com/fsnotify/fsnotify/issues/13)
|
||||||
* done can be an unbuffered channel
|
* done can be an unbuffered channel
|
||||||
* remove calls to os.NewSyscallError
|
* remove calls to os.NewSyscallError
|
||||||
* More efficient string concatenation for Event.String() [#52](https://github.com/go-fsnotify/fsnotify/pull/52) (thanks @mdlayher)
|
* More efficient string concatenation for Event.String() [#52](https://github.com/fsnotify/fsnotify/pull/52) (thanks @mdlayher)
|
||||||
* kqueue: fix regression in rework causing subdirectories to be watched [#48](https://github.com/go-fsnotify/fsnotify/issues/48)
|
* kqueue: fix regression in rework causing subdirectories to be watched [#48](https://github.com/fsnotify/fsnotify/issues/48)
|
||||||
* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/go-fsnotify/fsnotify/issues/51)
|
* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/fsnotify/fsnotify/issues/51)
|
||||||
|
|
||||||
## v1.0.4 / 2014-09-07
|
## v1.0.4 / 2014-09-07
|
||||||
|
|
||||||
* kqueue: add dragonfly to the build tags.
|
* kqueue: add dragonfly to the build tags.
|
||||||
* Rename source code files, rearrange code so exported APIs are at the top.
|
* Rename source code files, rearrange code so exported APIs are at the top.
|
||||||
* Add done channel to example code. [#37](https://github.com/go-fsnotify/fsnotify/pull/37) (thanks @chenyukang)
|
* Add done channel to example code. [#37](https://github.com/fsnotify/fsnotify/pull/37) (thanks @chenyukang)
|
||||||
|
|
||||||
## v1.0.3 / 2014-08-19
|
## v1.0.3 / 2014-08-19
|
||||||
|
|
||||||
* [Fix] Windows MOVED_TO now translates to Create like on BSD and Linux. [#36](https://github.com/go-fsnotify/fsnotify/issues/36)
|
* [Fix] Windows MOVED_TO now translates to Create like on BSD and Linux. [#36](https://github.com/fsnotify/fsnotify/issues/36)
|
||||||
|
|
||||||
## v1.0.2 / 2014-08-17
|
## v1.0.2 / 2014-08-17
|
||||||
|
|
||||||
* [Fix] Missing create events on OS X. [#14](https://github.com/go-fsnotify/fsnotify/issues/14) (thanks @zhsso)
|
* [Fix] Missing create events on OS X. [#14](https://github.com/fsnotify/fsnotify/issues/14) (thanks @zhsso)
|
||||||
* [Fix] Make ./path and path equivalent. (thanks @zhsso)
|
* [Fix] Make ./path and path equivalent. (thanks @zhsso)
|
||||||
|
|
||||||
## v1.0.0 / 2014-08-15
|
## v1.0.0 / 2014-08-15
|
||||||
|
|
||||||
* [API] Remove AddWatch on Windows, use Add.
|
* [API] Remove AddWatch on Windows, use Add.
|
||||||
* Improve documentation for exported identifiers. [#30](https://github.com/go-fsnotify/fsnotify/issues/30)
|
* Improve documentation for exported identifiers. [#30](https://github.com/fsnotify/fsnotify/issues/30)
|
||||||
* Minor updates based on feedback from golint.
|
* Minor updates based on feedback from golint.
|
||||||
|
|
||||||
## dev / 2014-07-09
|
## dev / 2014-07-09
|
||||||
|
|
||||||
* Moved to [github.com/go-fsnotify/fsnotify](https://github.com/go-fsnotify/fsnotify).
|
* Moved to [github.com/fsnotify/fsnotify](https://github.com/fsnotify/fsnotify).
|
||||||
* Use os.NewSyscallError instead of returning errno (thanks @hariharan-uno)
|
* Use os.NewSyscallError instead of returning errno (thanks @hariharan-uno)
|
||||||
|
|
||||||
## dev / 2014-07-04
|
## dev / 2014-07-04
|
||||||
|
@ -76,7 +100,7 @@ kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/go-fsnotify/
|
||||||
|
|
||||||
## dev / 2014-06-28
|
## dev / 2014-06-28
|
||||||
|
|
||||||
* [API] Don't set the Write Op for attribute notifications [#4](https://github.com/go-fsnotify/fsnotify/issues/4)
|
* [API] Don't set the Write Op for attribute notifications [#4](https://github.com/fsnotify/fsnotify/issues/4)
|
||||||
* Fix for String() method on Event (thanks Alex Brainman)
|
* Fix for String() method on Event (thanks Alex Brainman)
|
||||||
* Don't build on Plan 9 or Solaris (thanks @4ad)
|
* Don't build on Plan 9 or Solaris (thanks @4ad)
|
||||||
|
|
||||||
|
@ -114,11 +138,11 @@ kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/go-fsnotify/
|
||||||
|
|
||||||
## v0.9.3 / 2014-12-31
|
## v0.9.3 / 2014-12-31
|
||||||
|
|
||||||
* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/go-fsnotify/fsnotify/issues/51)
|
* kqueue: cleanup internal watch before sending remove event [#51](https://github.com/fsnotify/fsnotify/issues/51)
|
||||||
|
|
||||||
## v0.9.2 / 2014-08-17
|
## v0.9.2 / 2014-08-17
|
||||||
|
|
||||||
* [Backport] Fix missing create events on OS X. [#14](https://github.com/go-fsnotify/fsnotify/issues/14) (thanks @zhsso)
|
* [Backport] Fix missing create events on OS X. [#14](https://github.com/fsnotify/fsnotify/issues/14) (thanks @zhsso)
|
||||||
|
|
||||||
## v0.9.1 / 2014-06-12
|
## v0.9.1 / 2014-06-12
|
||||||
|
|
||||||
|
|
10
vendor/gopkg.in/fsnotify.v1/CONTRIBUTING.md
generated
vendored
10
vendor/gopkg.in/fsnotify.v1/CONTRIBUTING.md
generated
vendored
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
|
|
||||||
* Request features and report bugs using the [GitHub Issue Tracker](https://github.com/go-fsnotify/fsnotify/issues).
|
* Request features and report bugs using the [GitHub Issue Tracker](https://github.com/fsnotify/fsnotify/issues).
|
||||||
* Please indicate the platform you are using fsnotify on.
|
* Please indicate the platform you are using fsnotify on.
|
||||||
* A code example to reproduce the problem is appreciated.
|
* A code example to reproduce the problem is appreciated.
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
### Contributor License Agreement
|
### Contributor License Agreement
|
||||||
|
|
||||||
fsnotify is derived from code in the [golang.org/x/exp](https://godoc.org/golang.org/x/exp) package and it may be included [in the standard library](https://github.com/go-fsnotify/fsnotify/issues/1) in the future. Therefore fsnotify carries the same [LICENSE](https://github.com/go-fsnotify/fsnotify/blob/master/LICENSE) as Go. Contributors retain their copyright, so you need to fill out a short form before we can accept your contribution: [Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual).
|
fsnotify is derived from code in the [golang.org/x/exp](https://godoc.org/golang.org/x/exp) package and it may be included [in the standard library](https://github.com/fsnotify/fsnotify/issues/1) in the future. Therefore fsnotify carries the same [LICENSE](https://github.com/fsnotify/fsnotify/blob/master/LICENSE) as Go. Contributors retain their copyright, so you need to fill out a short form before we can accept your contribution: [Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual).
|
||||||
|
|
||||||
Please indicate that you have signed the CLA in your pull request.
|
Please indicate that you have signed the CLA in your pull request.
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ Please indicate that you have signed the CLA in your pull request.
|
||||||
|
|
||||||
For smooth sailing, always use the original import path. Installing with `go get` makes this easy.
|
For smooth sailing, always use the original import path. Installing with `go get` makes this easy.
|
||||||
|
|
||||||
1. Install from GitHub (`go get -u github.com/go-fsnotify/fsnotify`)
|
1. Install from GitHub (`go get -u github.com/fsnotify/fsnotify`)
|
||||||
2. Create your feature branch (`git checkout -b my-new-feature`)
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
||||||
3. Ensure everything works and the tests pass (see below)
|
3. Ensure everything works and the tests pass (see below)
|
||||||
4. Commit your changes (`git commit -am 'Add some feature'`)
|
4. Commit your changes (`git commit -am 'Add some feature'`)
|
||||||
|
@ -40,7 +40,7 @@ Contribute upstream:
|
||||||
3. Push to the branch (`git push fork my-new-feature`)
|
3. Push to the branch (`git push fork my-new-feature`)
|
||||||
4. Create a new Pull Request on GitHub
|
4. Create a new Pull Request on GitHub
|
||||||
|
|
||||||
This workflow is [thoroughly explained by Katrina Owen](https://blog.splice.com/contributing-open-source-git-repositories-go/).
|
This workflow is [thoroughly explained by Katrina Owen](https://splice.com/blog/contributing-open-source-git-repositories-go/).
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ To aid in cross-platform testing there is a Vagrantfile for Linux and BSD.
|
||||||
* Install [Vagrant](http://www.vagrantup.com/) and [VirtualBox](https://www.virtualbox.org/)
|
* Install [Vagrant](http://www.vagrantup.com/) and [VirtualBox](https://www.virtualbox.org/)
|
||||||
* Setup [Vagrant Gopher](https://github.com/nathany/vagrant-gopher) in your `src` folder.
|
* Setup [Vagrant Gopher](https://github.com/nathany/vagrant-gopher) in your `src` folder.
|
||||||
* Run `vagrant up` from the project folder. You can also setup just one box with `vagrant up linux` or `vagrant up bsd` (note: the BSD box doesn't support Windows hosts at this time, and NFS may prompt for your host OS password)
|
* Run `vagrant up` from the project folder. You can also setup just one box with `vagrant up linux` or `vagrant up bsd` (note: the BSD box doesn't support Windows hosts at this time, and NFS may prompt for your host OS password)
|
||||||
* Once setup, you can run the test suite on a given OS with a single command `vagrant ssh linux -c 'cd go-fsnotify/fsnotify; go test'`.
|
* Once setup, you can run the test suite on a given OS with a single command `vagrant ssh linux -c 'cd fsnotify/fsnotify; go test'`.
|
||||||
* When you're done, you will want to halt or destroy the Vagrant boxes.
|
* When you're done, you will want to halt or destroy the Vagrant boxes.
|
||||||
|
|
||||||
Notice: fsnotify file system events won't trigger in shared folders. The tests get around this limitation by using the /tmp directory.
|
Notice: fsnotify file system events won't trigger in shared folders. The tests get around this limitation by using the /tmp directory.
|
||||||
|
|
52
vendor/gopkg.in/fsnotify.v1/README.md
generated
vendored
52
vendor/gopkg.in/fsnotify.v1/README.md
generated
vendored
|
@ -1,51 +1,37 @@
|
||||||
# File system notifications for Go
|
# File system notifications for Go
|
||||||
|
|
||||||
[](https://godoc.org/gopkg.in/fsnotify.v1) [](http://gocover.io/github.com/go-fsnotify/fsnotify)
|
[](https://godoc.org/github.com/fsnotify/fsnotify) [](https://goreportcard.com/report/github.com/fsnotify/fsnotify)
|
||||||
|
|
||||||
Go 1.3+ required.
|
fsnotify utilizes [golang.org/x/sys](https://godoc.org/golang.org/x/sys) rather than `syscall` from the standard library. Ensure you have the latest version installed by running:
|
||||||
|
|
||||||
|
```console
|
||||||
|
go get -u golang.org/x/sys/...
|
||||||
|
```
|
||||||
|
|
||||||
Cross platform: Windows, Linux, BSD and OS X.
|
Cross platform: Windows, Linux, BSD and OS X.
|
||||||
|
|
||||||
|Adapter |OS |Status |
|
|Adapter |OS |Status |
|
||||||
|----------|----------|----------|
|
|----------|----------|----------|
|
||||||
|inotify |Linux 2.6.27 or later, Android\*|Supported [](https://travis-ci.org/go-fsnotify/fsnotify)|
|
|inotify |Linux 2.6.27 or later, Android\*|Supported [](https://travis-ci.org/fsnotify/fsnotify)|
|
||||||
|kqueue |BSD, OS X, iOS\*|Supported [](https://travis-ci.org/go-fsnotify/fsnotify)|
|
|kqueue |BSD, OS X, iOS\*|Supported [](https://travis-ci.org/fsnotify/fsnotify)|
|
||||||
|ReadDirectoryChangesW|Windows|Supported [](https://ci.appveyor.com/project/NathanYoungman/fsnotify/branch/master)|
|
|ReadDirectoryChangesW|Windows|Supported [](https://ci.appveyor.com/project/NathanYoungman/fsnotify/branch/master)|
|
||||||
|FSEvents |OS X |[Planned](https://github.com/go-fsnotify/fsnotify/issues/11)|
|
|FSEvents |OS X |[Planned](https://github.com/fsnotify/fsnotify/issues/11)|
|
||||||
|FEN |Solaris 11 |[Planned](https://github.com/go-fsnotify/fsnotify/issues/12)|
|
|FEN |Solaris 11 |[In Progress](https://github.com/fsnotify/fsnotify/issues/12)|
|
||||||
|fanotify |Linux 2.6.37+ | |
|
|fanotify |Linux 2.6.37+ | |
|
||||||
|USN Journals |Windows |[Maybe](https://github.com/go-fsnotify/fsnotify/issues/53)|
|
|USN Journals |Windows |[Maybe](https://github.com/fsnotify/fsnotify/issues/53)|
|
||||||
|Polling |*All* |[Maybe](https://github.com/go-fsnotify/fsnotify/issues/9)|
|
|Polling |*All* |[Maybe](https://github.com/fsnotify/fsnotify/issues/9)|
|
||||||
|
|
||||||
\* Android and iOS are untested.
|
\* Android and iOS are untested.
|
||||||
|
|
||||||
Please see [the documentation](https://godoc.org/gopkg.in/fsnotify.v1) for usage. Consult the [Wiki](https://github.com/go-fsnotify/fsnotify/wiki) for the FAQ and further information.
|
Please see [the documentation](https://godoc.org/github.com/fsnotify/fsnotify) for usage. Consult the [Wiki](https://github.com/fsnotify/fsnotify/wiki) for the FAQ and further information.
|
||||||
|
|
||||||
## API stability
|
## API stability
|
||||||
|
|
||||||
Two major versions of fsnotify exist.
|
fsnotify is a fork of [howeyc/fsnotify](https://godoc.org/github.com/howeyc/fsnotify) with a new API as of v1.0. The API is based on [this design document](http://goo.gl/MrYxyA).
|
||||||
|
|
||||||
**[fsnotify.v0](https://gopkg.in/fsnotify.v0)** is API-compatible with [howeyc/fsnotify](https://godoc.org/github.com/howeyc/fsnotify). Bugfixes *may* be backported, but I recommend upgrading to v1.
|
All [releases](https://github.com/fsnotify/fsnotify/releases) are tagged based on [Semantic Versioning](http://semver.org/). Further API changes are [planned](https://github.com/fsnotify/fsnotify/milestones), and will be tagged with a new major revision number.
|
||||||
|
|
||||||
```go
|
Go 1.6 supports dependencies located in the `vendor/` folder. Unless you are creating a library, it is recommended that you copy fsnotify into `vendor/github.com/fsnotify/fsnotify` within your project, and likewise for `golang.org/x/sys`.
|
||||||
import "gopkg.in/fsnotify.v0"
|
|
||||||
```
|
|
||||||
|
|
||||||
\* Refer to the package as fsnotify (without the .v0 suffix).
|
|
||||||
|
|
||||||
**[fsnotify.v1](https://gopkg.in/fsnotify.v1)** provides [a new API](https://godoc.org/gopkg.in/fsnotify.v1) based on [this design document](http://goo.gl/MrYxyA). You can import v1 with:
|
|
||||||
|
|
||||||
```go
|
|
||||||
import "gopkg.in/fsnotify.v1"
|
|
||||||
```
|
|
||||||
|
|
||||||
Further API changes are [planned](https://github.com/go-fsnotify/fsnotify/milestones), but a new major revision will be tagged, so you can depend on the v1 API.
|
|
||||||
|
|
||||||
**Master** may have unreleased changes. Use it to test the very latest code or when [contributing][], but don't expect it to remain API-compatible:
|
|
||||||
|
|
||||||
```go
|
|
||||||
import "github.com/go-fsnotify/fsnotify"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
@ -53,12 +39,12 @@ Please refer to [CONTRIBUTING][] before opening an issue or pull request.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
See [example_test.go](https://github.com/go-fsnotify/fsnotify/blob/master/example_test.go).
|
See [example_test.go](https://github.com/fsnotify/fsnotify/blob/master/example_test.go).
|
||||||
|
|
||||||
[contributing]: https://github.com/go-fsnotify/fsnotify/blob/master/CONTRIBUTING.md
|
[contributing]: https://github.com/fsnotify/fsnotify/blob/master/CONTRIBUTING.md
|
||||||
|
|
||||||
## Related Projects
|
## Related Projects
|
||||||
|
|
||||||
* [notify](https://github.com/rjeczalik/notify)
|
* [notify](https://github.com/rjeczalik/notify)
|
||||||
* [fsevents](https://github.com/go-fsnotify/fsevents)
|
* [fsevents](https://github.com/fsnotify/fsevents)
|
||||||
|
|
||||||
|
|
37
vendor/gopkg.in/fsnotify.v1/fen.go
generated
vendored
Normal file
37
vendor/gopkg.in/fsnotify.v1/fen.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build solaris
|
||||||
|
|
||||||
|
package fsnotify
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Watcher watches a set of files, delivering events to a channel.
|
||||||
|
type Watcher struct {
|
||||||
|
Events chan Event
|
||||||
|
Errors chan error
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events.
|
||||||
|
func NewWatcher() (*Watcher, error) {
|
||||||
|
return nil, errors.New("FEN based watcher not yet supported for fsnotify\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close removes all watches and closes the events channel.
|
||||||
|
func (w *Watcher) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add starts watching the named file or directory (non-recursively).
|
||||||
|
func (w *Watcher) Add(name string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove stops watching the the named file or directory (non-recursively).
|
||||||
|
func (w *Watcher) Remove(name string) error {
|
||||||
|
return nil
|
||||||
|
}
|
30
vendor/gopkg.in/fsnotify.v1/fsnotify.go
generated
vendored
30
vendor/gopkg.in/fsnotify.v1/fsnotify.go
generated
vendored
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !plan9,!solaris
|
// +build !plan9
|
||||||
|
|
||||||
// Package fsnotify provides a platform-independent interface for file system notifications.
|
// Package fsnotify provides a platform-independent interface for file system notifications.
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
@ -30,33 +30,33 @@ const (
|
||||||
Chmod
|
Chmod
|
||||||
)
|
)
|
||||||
|
|
||||||
// String returns a string representation of the event in the form
|
func (op Op) String() string {
|
||||||
// "file: REMOVE|WRITE|..."
|
|
||||||
func (e Event) String() string {
|
|
||||||
// Use a buffer for efficient string concatenation
|
// Use a buffer for efficient string concatenation
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
|
|
||||||
if e.Op&Create == Create {
|
if op&Create == Create {
|
||||||
buffer.WriteString("|CREATE")
|
buffer.WriteString("|CREATE")
|
||||||
}
|
}
|
||||||
if e.Op&Remove == Remove {
|
if op&Remove == Remove {
|
||||||
buffer.WriteString("|REMOVE")
|
buffer.WriteString("|REMOVE")
|
||||||
}
|
}
|
||||||
if e.Op&Write == Write {
|
if op&Write == Write {
|
||||||
buffer.WriteString("|WRITE")
|
buffer.WriteString("|WRITE")
|
||||||
}
|
}
|
||||||
if e.Op&Rename == Rename {
|
if op&Rename == Rename {
|
||||||
buffer.WriteString("|RENAME")
|
buffer.WriteString("|RENAME")
|
||||||
}
|
}
|
||||||
if e.Op&Chmod == Chmod {
|
if op&Chmod == Chmod {
|
||||||
buffer.WriteString("|CHMOD")
|
buffer.WriteString("|CHMOD")
|
||||||
}
|
}
|
||||||
|
|
||||||
// If buffer remains empty, return no event names
|
|
||||||
if buffer.Len() == 0 {
|
if buffer.Len() == 0 {
|
||||||
return fmt.Sprintf("%q: ", e.Name)
|
return ""
|
||||||
}
|
}
|
||||||
|
return buffer.String()[1:] // Strip leading pipe
|
||||||
// Return a list of event names, with leading pipe character stripped
|
}
|
||||||
return fmt.Sprintf("%q: %s", e.Name, buffer.String()[1:])
|
|
||||||
|
// String returns a string representation of the event in the form
|
||||||
|
// "file: REMOVE|WRITE|..."
|
||||||
|
func (e Event) String() string {
|
||||||
|
return fmt.Sprintf("%q: %s", e.Name, e.Op.String())
|
||||||
}
|
}
|
||||||
|
|
59
vendor/gopkg.in/fsnotify.v1/inotify.go
generated
vendored
59
vendor/gopkg.in/fsnotify.v1/inotify.go
generated
vendored
|
@ -14,8 +14,9 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Watcher watches a set of files, delivering events to a channel.
|
// Watcher watches a set of files, delivering events to a channel.
|
||||||
|
@ -35,14 +36,14 @@ type Watcher struct {
|
||||||
// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events.
|
// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events.
|
||||||
func NewWatcher() (*Watcher, error) {
|
func NewWatcher() (*Watcher, error) {
|
||||||
// Create inotify fd
|
// Create inotify fd
|
||||||
fd, errno := syscall.InotifyInit()
|
fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC)
|
||||||
if fd == -1 {
|
if fd == -1 {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
// Create epoll
|
// Create epoll
|
||||||
poller, err := newFdPoller(fd)
|
poller, err := newFdPoller(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
syscall.Close(fd)
|
unix.Close(fd)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
w := &Watcher{
|
w := &Watcher{
|
||||||
|
@ -95,9 +96,9 @@ func (w *Watcher) Add(name string) error {
|
||||||
return errors.New("inotify instance already closed")
|
return errors.New("inotify instance already closed")
|
||||||
}
|
}
|
||||||
|
|
||||||
const agnosticEvents = syscall.IN_MOVED_TO | syscall.IN_MOVED_FROM |
|
const agnosticEvents = unix.IN_MOVED_TO | unix.IN_MOVED_FROM |
|
||||||
syscall.IN_CREATE | syscall.IN_ATTRIB | syscall.IN_MODIFY |
|
unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY |
|
||||||
syscall.IN_MOVE_SELF | syscall.IN_DELETE | syscall.IN_DELETE_SELF
|
unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF
|
||||||
|
|
||||||
var flags uint32 = agnosticEvents
|
var flags uint32 = agnosticEvents
|
||||||
|
|
||||||
|
@ -106,9 +107,9 @@ func (w *Watcher) Add(name string) error {
|
||||||
w.mu.Unlock()
|
w.mu.Unlock()
|
||||||
if found {
|
if found {
|
||||||
watchEntry.flags |= flags
|
watchEntry.flags |= flags
|
||||||
flags |= syscall.IN_MASK_ADD
|
flags |= unix.IN_MASK_ADD
|
||||||
}
|
}
|
||||||
wd, errno := syscall.InotifyAddWatch(w.fd, name, flags)
|
wd, errno := unix.InotifyAddWatch(w.fd, name, flags)
|
||||||
if wd == -1 {
|
if wd == -1 {
|
||||||
return errno
|
return errno
|
||||||
}
|
}
|
||||||
|
@ -140,7 +141,7 @@ func (w *Watcher) Remove(name string) error {
|
||||||
// by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE
|
// by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE
|
||||||
// so that EINVAL means that the wd is being rm_watch()ed or its file removed
|
// so that EINVAL means that the wd is being rm_watch()ed or its file removed
|
||||||
// by another thread and we have not received IN_IGNORE event.
|
// by another thread and we have not received IN_IGNORE event.
|
||||||
success, errno := syscall.InotifyRmWatch(w.fd, watch.wd)
|
success, errno := unix.InotifyRmWatch(w.fd, watch.wd)
|
||||||
if success == -1 {
|
if success == -1 {
|
||||||
// TODO: Perhaps it's not helpful to return an error here in every case.
|
// TODO: Perhaps it's not helpful to return an error here in every case.
|
||||||
// the only two possible errors are:
|
// the only two possible errors are:
|
||||||
|
@ -170,16 +171,16 @@ type watch struct {
|
||||||
// received events into Event objects and sends them via the Events channel
|
// received events into Event objects and sends them via the Events channel
|
||||||
func (w *Watcher) readEvents() {
|
func (w *Watcher) readEvents() {
|
||||||
var (
|
var (
|
||||||
buf [syscall.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events
|
buf [unix.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events
|
||||||
n int // Number of bytes read with read()
|
n int // Number of bytes read with read()
|
||||||
errno error // Syscall errno
|
errno error // Syscall errno
|
||||||
ok bool // For poller.wait
|
ok bool // For poller.wait
|
||||||
)
|
)
|
||||||
|
|
||||||
defer close(w.doneResp)
|
defer close(w.doneResp)
|
||||||
defer close(w.Errors)
|
defer close(w.Errors)
|
||||||
defer close(w.Events)
|
defer close(w.Events)
|
||||||
defer syscall.Close(w.fd)
|
defer unix.Close(w.fd)
|
||||||
defer w.poller.close()
|
defer w.poller.close()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
@ -202,26 +203,26 @@ func (w *Watcher) readEvents() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
n, errno = syscall.Read(w.fd, buf[:])
|
n, errno = unix.Read(w.fd, buf[:])
|
||||||
// If a signal interrupted execution, see if we've been asked to close, and try again.
|
// If a signal interrupted execution, see if we've been asked to close, and try again.
|
||||||
// http://man7.org/linux/man-pages/man7/signal.7.html :
|
// http://man7.org/linux/man-pages/man7/signal.7.html :
|
||||||
// "Before Linux 3.8, reads from an inotify(7) file descriptor were not restartable"
|
// "Before Linux 3.8, reads from an inotify(7) file descriptor were not restartable"
|
||||||
if errno == syscall.EINTR {
|
if errno == unix.EINTR {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// syscall.Read might have been woken up by Close. If so, we're done.
|
// unix.Read might have been woken up by Close. If so, we're done.
|
||||||
if w.isClosed() {
|
if w.isClosed() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if n < syscall.SizeofInotifyEvent {
|
if n < unix.SizeofInotifyEvent {
|
||||||
var err error
|
var err error
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
// If EOF is received. This should really never happen.
|
// If EOF is received. This should really never happen.
|
||||||
err = io.EOF
|
err = io.EOF
|
||||||
} else if n < 0 {
|
} else if n < 0 {
|
||||||
// If an error occured while reading.
|
// If an error occurred while reading.
|
||||||
err = errno
|
err = errno
|
||||||
} else {
|
} else {
|
||||||
// Read was too short.
|
// Read was too short.
|
||||||
|
@ -238,9 +239,9 @@ func (w *Watcher) readEvents() {
|
||||||
var offset uint32
|
var offset uint32
|
||||||
// We don't know how many events we just read into the buffer
|
// We don't know how many events we just read into the buffer
|
||||||
// While the offset points to at least one whole event...
|
// While the offset points to at least one whole event...
|
||||||
for offset <= uint32(n-syscall.SizeofInotifyEvent) {
|
for offset <= uint32(n-unix.SizeofInotifyEvent) {
|
||||||
// Point "raw" to the event in the buffer
|
// Point "raw" to the event in the buffer
|
||||||
raw := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset]))
|
raw := (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset]))
|
||||||
|
|
||||||
mask := uint32(raw.Mask)
|
mask := uint32(raw.Mask)
|
||||||
nameLen := uint32(raw.Len)
|
nameLen := uint32(raw.Len)
|
||||||
|
@ -253,7 +254,7 @@ func (w *Watcher) readEvents() {
|
||||||
w.mu.Unlock()
|
w.mu.Unlock()
|
||||||
if nameLen > 0 {
|
if nameLen > 0 {
|
||||||
// Point "bytes" at the first byte of the filename
|
// Point "bytes" at the first byte of the filename
|
||||||
bytes := (*[syscall.PathMax]byte)(unsafe.Pointer(&buf[offset+syscall.SizeofInotifyEvent]))
|
bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))
|
||||||
// The filename is padded with NULL bytes. TrimRight() gets rid of those.
|
// The filename is padded with NULL bytes. TrimRight() gets rid of those.
|
||||||
name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
|
name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000")
|
||||||
}
|
}
|
||||||
|
@ -270,7 +271,7 @@ func (w *Watcher) readEvents() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move to the next event in the buffer
|
// Move to the next event in the buffer
|
||||||
offset += syscall.SizeofInotifyEvent + nameLen
|
offset += unix.SizeofInotifyEvent + nameLen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,7 +281,7 @@ func (w *Watcher) readEvents() {
|
||||||
// against files that do not exist.
|
// against files that do not exist.
|
||||||
func (e *Event) ignoreLinux(w *Watcher, wd int32, mask uint32) bool {
|
func (e *Event) ignoreLinux(w *Watcher, wd int32, mask uint32) bool {
|
||||||
// Ignore anything the inotify API says to ignore
|
// Ignore anything the inotify API says to ignore
|
||||||
if mask&syscall.IN_IGNORED == syscall.IN_IGNORED {
|
if mask&unix.IN_IGNORED == unix.IN_IGNORED {
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
defer w.mu.Unlock()
|
defer w.mu.Unlock()
|
||||||
name := w.paths[int(wd)]
|
name := w.paths[int(wd)]
|
||||||
|
@ -305,19 +306,19 @@ func (e *Event) ignoreLinux(w *Watcher, wd int32, mask uint32) bool {
|
||||||
// newEvent returns an platform-independent Event based on an inotify mask.
|
// newEvent returns an platform-independent Event based on an inotify mask.
|
||||||
func newEvent(name string, mask uint32) Event {
|
func newEvent(name string, mask uint32) Event {
|
||||||
e := Event{Name: name}
|
e := Event{Name: name}
|
||||||
if mask&syscall.IN_CREATE == syscall.IN_CREATE || mask&syscall.IN_MOVED_TO == syscall.IN_MOVED_TO {
|
if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO {
|
||||||
e.Op |= Create
|
e.Op |= Create
|
||||||
}
|
}
|
||||||
if mask&syscall.IN_DELETE_SELF == syscall.IN_DELETE_SELF || mask&syscall.IN_DELETE == syscall.IN_DELETE {
|
if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF || mask&unix.IN_DELETE == unix.IN_DELETE {
|
||||||
e.Op |= Remove
|
e.Op |= Remove
|
||||||
}
|
}
|
||||||
if mask&syscall.IN_MODIFY == syscall.IN_MODIFY {
|
if mask&unix.IN_MODIFY == unix.IN_MODIFY {
|
||||||
e.Op |= Write
|
e.Op |= Write
|
||||||
}
|
}
|
||||||
if mask&syscall.IN_MOVE_SELF == syscall.IN_MOVE_SELF || mask&syscall.IN_MOVED_FROM == syscall.IN_MOVED_FROM {
|
if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM {
|
||||||
e.Op |= Rename
|
e.Op |= Rename
|
||||||
}
|
}
|
||||||
if mask&syscall.IN_ATTRIB == syscall.IN_ATTRIB {
|
if mask&unix.IN_ATTRIB == unix.IN_ATTRIB {
|
||||||
e.Op |= Chmod
|
e.Op |= Chmod
|
||||||
}
|
}
|
||||||
return e
|
return e
|
||||||
|
|
53
vendor/gopkg.in/fsnotify.v1/inotify_poller.go
generated
vendored
53
vendor/gopkg.in/fsnotify.v1/inotify_poller.go
generated
vendored
|
@ -8,7 +8,8 @@ package fsnotify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"syscall"
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
type fdPoller struct {
|
type fdPoller struct {
|
||||||
|
@ -39,32 +40,32 @@ func newFdPoller(fd int) (*fdPoller, error) {
|
||||||
poller.fd = fd
|
poller.fd = fd
|
||||||
|
|
||||||
// Create epoll fd
|
// Create epoll fd
|
||||||
poller.epfd, errno = syscall.EpollCreate1(0)
|
poller.epfd, errno = unix.EpollCreate1(0)
|
||||||
if poller.epfd == -1 {
|
if poller.epfd == -1 {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
// Create pipe; pipe[0] is the read end, pipe[1] the write end.
|
// Create pipe; pipe[0] is the read end, pipe[1] the write end.
|
||||||
errno = syscall.Pipe2(poller.pipe[:], syscall.O_NONBLOCK)
|
errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK)
|
||||||
if errno != nil {
|
if errno != nil {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register inotify fd with epoll
|
// Register inotify fd with epoll
|
||||||
event := syscall.EpollEvent{
|
event := unix.EpollEvent{
|
||||||
Fd: int32(poller.fd),
|
Fd: int32(poller.fd),
|
||||||
Events: syscall.EPOLLIN,
|
Events: unix.EPOLLIN,
|
||||||
}
|
}
|
||||||
errno = syscall.EpollCtl(poller.epfd, syscall.EPOLL_CTL_ADD, poller.fd, &event)
|
errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.fd, &event)
|
||||||
if errno != nil {
|
if errno != nil {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register pipe fd with epoll
|
// Register pipe fd with epoll
|
||||||
event = syscall.EpollEvent{
|
event = unix.EpollEvent{
|
||||||
Fd: int32(poller.pipe[0]),
|
Fd: int32(poller.pipe[0]),
|
||||||
Events: syscall.EPOLLIN,
|
Events: unix.EPOLLIN,
|
||||||
}
|
}
|
||||||
errno = syscall.EpollCtl(poller.epfd, syscall.EPOLL_CTL_ADD, poller.pipe[0], &event)
|
errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.pipe[0], &event)
|
||||||
if errno != nil {
|
if errno != nil {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
|
@ -80,11 +81,11 @@ func (poller *fdPoller) wait() (bool, error) {
|
||||||
// I don't know whether epoll_wait returns the number of events returned,
|
// I don't know whether epoll_wait returns the number of events returned,
|
||||||
// or the total number of events ready.
|
// or the total number of events ready.
|
||||||
// I decided to catch both by making the buffer one larger than the maximum.
|
// I decided to catch both by making the buffer one larger than the maximum.
|
||||||
events := make([]syscall.EpollEvent, 7)
|
events := make([]unix.EpollEvent, 7)
|
||||||
for {
|
for {
|
||||||
n, errno := syscall.EpollWait(poller.epfd, events, -1)
|
n, errno := unix.EpollWait(poller.epfd, events, -1)
|
||||||
if n == -1 {
|
if n == -1 {
|
||||||
if errno == syscall.EINTR {
|
if errno == unix.EINTR {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return false, errno
|
return false, errno
|
||||||
|
@ -103,31 +104,31 @@ func (poller *fdPoller) wait() (bool, error) {
|
||||||
epollin := false
|
epollin := false
|
||||||
for _, event := range ready {
|
for _, event := range ready {
|
||||||
if event.Fd == int32(poller.fd) {
|
if event.Fd == int32(poller.fd) {
|
||||||
if event.Events&syscall.EPOLLHUP != 0 {
|
if event.Events&unix.EPOLLHUP != 0 {
|
||||||
// This should not happen, but if it does, treat it as a wakeup.
|
// This should not happen, but if it does, treat it as a wakeup.
|
||||||
epollhup = true
|
epollhup = true
|
||||||
}
|
}
|
||||||
if event.Events&syscall.EPOLLERR != 0 {
|
if event.Events&unix.EPOLLERR != 0 {
|
||||||
// If an error is waiting on the file descriptor, we should pretend
|
// If an error is waiting on the file descriptor, we should pretend
|
||||||
// something is ready to read, and let syscall.Read pick up the error.
|
// something is ready to read, and let unix.Read pick up the error.
|
||||||
epollerr = true
|
epollerr = true
|
||||||
}
|
}
|
||||||
if event.Events&syscall.EPOLLIN != 0 {
|
if event.Events&unix.EPOLLIN != 0 {
|
||||||
// There is data to read.
|
// There is data to read.
|
||||||
epollin = true
|
epollin = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if event.Fd == int32(poller.pipe[0]) {
|
if event.Fd == int32(poller.pipe[0]) {
|
||||||
if event.Events&syscall.EPOLLHUP != 0 {
|
if event.Events&unix.EPOLLHUP != 0 {
|
||||||
// Write pipe descriptor was closed, by us. This means we're closing down the
|
// Write pipe descriptor was closed, by us. This means we're closing down the
|
||||||
// watcher, and we should wake up.
|
// watcher, and we should wake up.
|
||||||
}
|
}
|
||||||
if event.Events&syscall.EPOLLERR != 0 {
|
if event.Events&unix.EPOLLERR != 0 {
|
||||||
// If an error is waiting on the pipe file descriptor.
|
// If an error is waiting on the pipe file descriptor.
|
||||||
// This is an absolute mystery, and should never ever happen.
|
// This is an absolute mystery, and should never ever happen.
|
||||||
return false, errors.New("Error on the pipe descriptor.")
|
return false, errors.New("Error on the pipe descriptor.")
|
||||||
}
|
}
|
||||||
if event.Events&syscall.EPOLLIN != 0 {
|
if event.Events&unix.EPOLLIN != 0 {
|
||||||
// This is a regular wakeup, so we have to clear the buffer.
|
// This is a regular wakeup, so we have to clear the buffer.
|
||||||
err := poller.clearWake()
|
err := poller.clearWake()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -147,9 +148,9 @@ func (poller *fdPoller) wait() (bool, error) {
|
||||||
// Close the write end of the poller.
|
// Close the write end of the poller.
|
||||||
func (poller *fdPoller) wake() error {
|
func (poller *fdPoller) wake() error {
|
||||||
buf := make([]byte, 1)
|
buf := make([]byte, 1)
|
||||||
n, errno := syscall.Write(poller.pipe[1], buf)
|
n, errno := unix.Write(poller.pipe[1], buf)
|
||||||
if n == -1 {
|
if n == -1 {
|
||||||
if errno == syscall.EAGAIN {
|
if errno == unix.EAGAIN {
|
||||||
// Buffer is full, poller will wake.
|
// Buffer is full, poller will wake.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -161,9 +162,9 @@ func (poller *fdPoller) wake() error {
|
||||||
func (poller *fdPoller) clearWake() error {
|
func (poller *fdPoller) clearWake() error {
|
||||||
// You have to be woken up a LOT in order to get to 100!
|
// You have to be woken up a LOT in order to get to 100!
|
||||||
buf := make([]byte, 100)
|
buf := make([]byte, 100)
|
||||||
n, errno := syscall.Read(poller.pipe[0], buf)
|
n, errno := unix.Read(poller.pipe[0], buf)
|
||||||
if n == -1 {
|
if n == -1 {
|
||||||
if errno == syscall.EAGAIN {
|
if errno == unix.EAGAIN {
|
||||||
// Buffer is empty, someone else cleared our wake.
|
// Buffer is empty, someone else cleared our wake.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -175,12 +176,12 @@ func (poller *fdPoller) clearWake() error {
|
||||||
// Close all poller file descriptors, but not the one passed to it.
|
// Close all poller file descriptors, but not the one passed to it.
|
||||||
func (poller *fdPoller) close() {
|
func (poller *fdPoller) close() {
|
||||||
if poller.pipe[1] != -1 {
|
if poller.pipe[1] != -1 {
|
||||||
syscall.Close(poller.pipe[1])
|
unix.Close(poller.pipe[1])
|
||||||
}
|
}
|
||||||
if poller.pipe[0] != -1 {
|
if poller.pipe[0] != -1 {
|
||||||
syscall.Close(poller.pipe[0])
|
unix.Close(poller.pipe[0])
|
||||||
}
|
}
|
||||||
if poller.epfd != -1 {
|
if poller.epfd != -1 {
|
||||||
syscall.Close(poller.epfd)
|
unix.Close(poller.epfd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
51
vendor/gopkg.in/fsnotify.v1/kqueue.go
generated
vendored
51
vendor/gopkg.in/fsnotify.v1/kqueue.go
generated
vendored
|
@ -13,8 +13,9 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Watcher watches a set of files, delivering events to a channel.
|
// Watcher watches a set of files, delivering events to a channel.
|
||||||
|
@ -113,12 +114,12 @@ func (w *Watcher) Remove(name string) error {
|
||||||
return fmt.Errorf("can't remove non-existent kevent watch for: %s", name)
|
return fmt.Errorf("can't remove non-existent kevent watch for: %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
const registerRemove = syscall.EV_DELETE
|
const registerRemove = unix.EV_DELETE
|
||||||
if err := register(w.kq, []int{watchfd}, registerRemove, 0); err != nil {
|
if err := register(w.kq, []int{watchfd}, registerRemove, 0); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
syscall.Close(watchfd)
|
unix.Close(watchfd)
|
||||||
|
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
isDir := w.paths[watchfd].isDir
|
isDir := w.paths[watchfd].isDir
|
||||||
|
@ -152,7 +153,7 @@ func (w *Watcher) Remove(name string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE)
|
// Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE)
|
||||||
const noteAllEvents = syscall.NOTE_DELETE | syscall.NOTE_WRITE | syscall.NOTE_ATTRIB | syscall.NOTE_RENAME
|
const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME
|
||||||
|
|
||||||
// keventWaitTime to block on each read from kevent
|
// keventWaitTime to block on each read from kevent
|
||||||
var keventWaitTime = durationToTimespec(100 * time.Millisecond)
|
var keventWaitTime = durationToTimespec(100 * time.Millisecond)
|
||||||
|
@ -219,7 +220,7 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watchfd, err = syscall.Open(name, openMode, 0700)
|
watchfd, err = unix.Open(name, openMode, 0700)
|
||||||
if watchfd == -1 {
|
if watchfd == -1 {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -227,9 +228,9 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
|
||||||
isDir = fi.IsDir()
|
isDir = fi.IsDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
const registerAdd = syscall.EV_ADD | syscall.EV_CLEAR | syscall.EV_ENABLE
|
const registerAdd = unix.EV_ADD | unix.EV_CLEAR | unix.EV_ENABLE
|
||||||
if err := register(w.kq, []int{watchfd}, registerAdd, flags); err != nil {
|
if err := register(w.kq, []int{watchfd}, registerAdd, flags); err != nil {
|
||||||
syscall.Close(watchfd)
|
unix.Close(watchfd)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,8 +246,8 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
|
||||||
// or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles)
|
// or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles)
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
|
|
||||||
watchDir := (flags&syscall.NOTE_WRITE) == syscall.NOTE_WRITE &&
|
watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE &&
|
||||||
(!alreadyWatching || (w.dirFlags[name]&syscall.NOTE_WRITE) != syscall.NOTE_WRITE)
|
(!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE)
|
||||||
// Store flags so this watch can be updated later
|
// Store flags so this watch can be updated later
|
||||||
w.dirFlags[name] = flags
|
w.dirFlags[name] = flags
|
||||||
w.mu.Unlock()
|
w.mu.Unlock()
|
||||||
|
@ -263,13 +264,13 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) {
|
||||||
// readEvents reads from kqueue and converts the received kevents into
|
// readEvents reads from kqueue and converts the received kevents into
|
||||||
// Event values that it sends down the Events channel.
|
// Event values that it sends down the Events channel.
|
||||||
func (w *Watcher) readEvents() {
|
func (w *Watcher) readEvents() {
|
||||||
eventBuffer := make([]syscall.Kevent_t, 10)
|
eventBuffer := make([]unix.Kevent_t, 10)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// See if there is a message on the "done" channel
|
// See if there is a message on the "done" channel
|
||||||
select {
|
select {
|
||||||
case <-w.done:
|
case <-w.done:
|
||||||
err := syscall.Close(w.kq)
|
err := unix.Close(w.kq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.Errors <- err
|
w.Errors <- err
|
||||||
}
|
}
|
||||||
|
@ -282,7 +283,7 @@ func (w *Watcher) readEvents() {
|
||||||
// Get new events
|
// Get new events
|
||||||
kevents, err := read(w.kq, eventBuffer, &keventWaitTime)
|
kevents, err := read(w.kq, eventBuffer, &keventWaitTime)
|
||||||
// EINTR is okay, the syscall was interrupted before timeout expired.
|
// EINTR is okay, the syscall was interrupted before timeout expired.
|
||||||
if err != nil && err != syscall.EINTR {
|
if err != nil && err != unix.EINTR {
|
||||||
w.Errors <- err
|
w.Errors <- err
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -356,16 +357,16 @@ func (w *Watcher) readEvents() {
|
||||||
// newEvent returns an platform-independent Event based on kqueue Fflags.
|
// newEvent returns an platform-independent Event based on kqueue Fflags.
|
||||||
func newEvent(name string, mask uint32) Event {
|
func newEvent(name string, mask uint32) Event {
|
||||||
e := Event{Name: name}
|
e := Event{Name: name}
|
||||||
if mask&syscall.NOTE_DELETE == syscall.NOTE_DELETE {
|
if mask&unix.NOTE_DELETE == unix.NOTE_DELETE {
|
||||||
e.Op |= Remove
|
e.Op |= Remove
|
||||||
}
|
}
|
||||||
if mask&syscall.NOTE_WRITE == syscall.NOTE_WRITE {
|
if mask&unix.NOTE_WRITE == unix.NOTE_WRITE {
|
||||||
e.Op |= Write
|
e.Op |= Write
|
||||||
}
|
}
|
||||||
if mask&syscall.NOTE_RENAME == syscall.NOTE_RENAME {
|
if mask&unix.NOTE_RENAME == unix.NOTE_RENAME {
|
||||||
e.Op |= Rename
|
e.Op |= Rename
|
||||||
}
|
}
|
||||||
if mask&syscall.NOTE_ATTRIB == syscall.NOTE_ATTRIB {
|
if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB {
|
||||||
e.Op |= Chmod
|
e.Op |= Chmod
|
||||||
}
|
}
|
||||||
return e
|
return e
|
||||||
|
@ -451,7 +452,7 @@ func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, erro
|
||||||
flags := w.dirFlags[name]
|
flags := w.dirFlags[name]
|
||||||
w.mu.Unlock()
|
w.mu.Unlock()
|
||||||
|
|
||||||
flags |= syscall.NOTE_DELETE | syscall.NOTE_RENAME
|
flags |= unix.NOTE_DELETE | unix.NOTE_RENAME
|
||||||
return w.addWatch(name, flags)
|
return w.addWatch(name, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,7 +462,7 @@ func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, erro
|
||||||
|
|
||||||
// kqueue creates a new kernel event queue and returns a descriptor.
|
// kqueue creates a new kernel event queue and returns a descriptor.
|
||||||
func kqueue() (kq int, err error) {
|
func kqueue() (kq int, err error) {
|
||||||
kq, err = syscall.Kqueue()
|
kq, err = unix.Kqueue()
|
||||||
if kq == -1 {
|
if kq == -1 {
|
||||||
return kq, err
|
return kq, err
|
||||||
}
|
}
|
||||||
|
@ -470,16 +471,16 @@ func kqueue() (kq int, err error) {
|
||||||
|
|
||||||
// register events with the queue
|
// register events with the queue
|
||||||
func register(kq int, fds []int, flags int, fflags uint32) error {
|
func register(kq int, fds []int, flags int, fflags uint32) error {
|
||||||
changes := make([]syscall.Kevent_t, len(fds))
|
changes := make([]unix.Kevent_t, len(fds))
|
||||||
|
|
||||||
for i, fd := range fds {
|
for i, fd := range fds {
|
||||||
// SetKevent converts int to the platform-specific types:
|
// SetKevent converts int to the platform-specific types:
|
||||||
syscall.SetKevent(&changes[i], fd, syscall.EVFILT_VNODE, flags)
|
unix.SetKevent(&changes[i], fd, unix.EVFILT_VNODE, flags)
|
||||||
changes[i].Fflags = fflags
|
changes[i].Fflags = fflags
|
||||||
}
|
}
|
||||||
|
|
||||||
// register the events
|
// register the events
|
||||||
success, err := syscall.Kevent(kq, changes, nil, nil)
|
success, err := unix.Kevent(kq, changes, nil, nil)
|
||||||
if success == -1 {
|
if success == -1 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -488,8 +489,8 @@ func register(kq int, fds []int, flags int, fflags uint32) error {
|
||||||
|
|
||||||
// read retrieves pending events, or waits until an event occurs.
|
// read retrieves pending events, or waits until an event occurs.
|
||||||
// A timeout of nil blocks indefinitely, while 0 polls the queue.
|
// A timeout of nil blocks indefinitely, while 0 polls the queue.
|
||||||
func read(kq int, events []syscall.Kevent_t, timeout *syscall.Timespec) ([]syscall.Kevent_t, error) {
|
func read(kq int, events []unix.Kevent_t, timeout *unix.Timespec) ([]unix.Kevent_t, error) {
|
||||||
n, err := syscall.Kevent(kq, nil, events, timeout)
|
n, err := unix.Kevent(kq, nil, events, timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -497,6 +498,6 @@ func read(kq int, events []syscall.Kevent_t, timeout *syscall.Timespec) ([]sysca
|
||||||
}
|
}
|
||||||
|
|
||||||
// durationToTimespec prepares a timeout value
|
// durationToTimespec prepares a timeout value
|
||||||
func durationToTimespec(d time.Duration) syscall.Timespec {
|
func durationToTimespec(d time.Duration) unix.Timespec {
|
||||||
return syscall.NsecToTimespec(d.Nanoseconds())
|
return unix.NsecToTimespec(d.Nanoseconds())
|
||||||
}
|
}
|
||||||
|
|
4
vendor/gopkg.in/fsnotify.v1/open_mode_bsd.go
generated
vendored
4
vendor/gopkg.in/fsnotify.v1/open_mode_bsd.go
generated
vendored
|
@ -6,6 +6,6 @@
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
|
||||||
import "syscall"
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
const openMode = syscall.O_NONBLOCK | syscall.O_RDONLY
|
const openMode = unix.O_NONBLOCK | unix.O_RDONLY
|
||||||
|
|
4
vendor/gopkg.in/fsnotify.v1/open_mode_darwin.go
generated
vendored
4
vendor/gopkg.in/fsnotify.v1/open_mode_darwin.go
generated
vendored
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
package fsnotify
|
package fsnotify
|
||||||
|
|
||||||
import "syscall"
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
// note: this constant is not defined on BSD
|
// note: this constant is not defined on BSD
|
||||||
const openMode = syscall.O_EVTONLY
|
const openMode = unix.O_EVTONLY
|
||||||
|
|
96
vendor/gopkg.in/fsnotify.v1/windows.go
generated
vendored
96
vendor/gopkg.in/fsnotify.v1/windows.go
generated
vendored
|
@ -71,7 +71,7 @@ func (w *Watcher) Add(name string) error {
|
||||||
in := &input{
|
in := &input{
|
||||||
op: opAddWatch,
|
op: opAddWatch,
|
||||||
path: filepath.Clean(name),
|
path: filepath.Clean(name),
|
||||||
flags: sys_FS_ALL_EVENTS,
|
flags: sysFSALLEVENTS,
|
||||||
reply: make(chan error),
|
reply: make(chan error),
|
||||||
}
|
}
|
||||||
w.input <- in
|
w.input <- in
|
||||||
|
@ -97,43 +97,43 @@ func (w *Watcher) Remove(name string) error {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Options for AddWatch
|
// Options for AddWatch
|
||||||
sys_FS_ONESHOT = 0x80000000
|
sysFSONESHOT = 0x80000000
|
||||||
sys_FS_ONLYDIR = 0x1000000
|
sysFSONLYDIR = 0x1000000
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
sys_FS_ACCESS = 0x1
|
sysFSACCESS = 0x1
|
||||||
sys_FS_ALL_EVENTS = 0xfff
|
sysFSALLEVENTS = 0xfff
|
||||||
sys_FS_ATTRIB = 0x4
|
sysFSATTRIB = 0x4
|
||||||
sys_FS_CLOSE = 0x18
|
sysFSCLOSE = 0x18
|
||||||
sys_FS_CREATE = 0x100
|
sysFSCREATE = 0x100
|
||||||
sys_FS_DELETE = 0x200
|
sysFSDELETE = 0x200
|
||||||
sys_FS_DELETE_SELF = 0x400
|
sysFSDELETESELF = 0x400
|
||||||
sys_FS_MODIFY = 0x2
|
sysFSMODIFY = 0x2
|
||||||
sys_FS_MOVE = 0xc0
|
sysFSMOVE = 0xc0
|
||||||
sys_FS_MOVED_FROM = 0x40
|
sysFSMOVEDFROM = 0x40
|
||||||
sys_FS_MOVED_TO = 0x80
|
sysFSMOVEDTO = 0x80
|
||||||
sys_FS_MOVE_SELF = 0x800
|
sysFSMOVESELF = 0x800
|
||||||
|
|
||||||
// Special events
|
// Special events
|
||||||
sys_FS_IGNORED = 0x8000
|
sysFSIGNORED = 0x8000
|
||||||
sys_FS_Q_OVERFLOW = 0x4000
|
sysFSQOVERFLOW = 0x4000
|
||||||
)
|
)
|
||||||
|
|
||||||
func newEvent(name string, mask uint32) Event {
|
func newEvent(name string, mask uint32) Event {
|
||||||
e := Event{Name: name}
|
e := Event{Name: name}
|
||||||
if mask&sys_FS_CREATE == sys_FS_CREATE || mask&sys_FS_MOVED_TO == sys_FS_MOVED_TO {
|
if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO {
|
||||||
e.Op |= Create
|
e.Op |= Create
|
||||||
}
|
}
|
||||||
if mask&sys_FS_DELETE == sys_FS_DELETE || mask&sys_FS_DELETE_SELF == sys_FS_DELETE_SELF {
|
if mask&sysFSDELETE == sysFSDELETE || mask&sysFSDELETESELF == sysFSDELETESELF {
|
||||||
e.Op |= Remove
|
e.Op |= Remove
|
||||||
}
|
}
|
||||||
if mask&sys_FS_MODIFY == sys_FS_MODIFY {
|
if mask&sysFSMODIFY == sysFSMODIFY {
|
||||||
e.Op |= Write
|
e.Op |= Write
|
||||||
}
|
}
|
||||||
if mask&sys_FS_MOVE == sys_FS_MOVE || mask&sys_FS_MOVE_SELF == sys_FS_MOVE_SELF || mask&sys_FS_MOVED_FROM == sys_FS_MOVED_FROM {
|
if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM {
|
||||||
e.Op |= Rename
|
e.Op |= Rename
|
||||||
}
|
}
|
||||||
if mask&sys_FS_ATTRIB == sys_FS_ATTRIB {
|
if mask&sysFSATTRIB == sysFSATTRIB {
|
||||||
e.Op |= Chmod
|
e.Op |= Chmod
|
||||||
}
|
}
|
||||||
return e
|
return e
|
||||||
|
@ -242,7 +242,7 @@ func (w *Watcher) addWatch(pathname string, flags uint64) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if flags&sys_FS_ONLYDIR != 0 && pathname != dir {
|
if flags&sysFSONLYDIR != 0 && pathname != dir {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ino, err := getIno(dir)
|
ino, err := getIno(dir)
|
||||||
|
@ -302,11 +302,11 @@ func (w *Watcher) remWatch(pathname string) error {
|
||||||
return fmt.Errorf("can't remove non-existent watch for: %s", pathname)
|
return fmt.Errorf("can't remove non-existent watch for: %s", pathname)
|
||||||
}
|
}
|
||||||
if pathname == dir {
|
if pathname == dir {
|
||||||
w.sendEvent(watch.path, watch.mask&sys_FS_IGNORED)
|
w.sendEvent(watch.path, watch.mask&sysFSIGNORED)
|
||||||
watch.mask = 0
|
watch.mask = 0
|
||||||
} else {
|
} else {
|
||||||
name := filepath.Base(pathname)
|
name := filepath.Base(pathname)
|
||||||
w.sendEvent(watch.path+"\\"+name, watch.names[name]&sys_FS_IGNORED)
|
w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED)
|
||||||
delete(watch.names, name)
|
delete(watch.names, name)
|
||||||
}
|
}
|
||||||
return w.startRead(watch)
|
return w.startRead(watch)
|
||||||
|
@ -316,13 +316,13 @@ func (w *Watcher) remWatch(pathname string) error {
|
||||||
func (w *Watcher) deleteWatch(watch *watch) {
|
func (w *Watcher) deleteWatch(watch *watch) {
|
||||||
for name, mask := range watch.names {
|
for name, mask := range watch.names {
|
||||||
if mask&provisional == 0 {
|
if mask&provisional == 0 {
|
||||||
w.sendEvent(watch.path+"\\"+name, mask&sys_FS_IGNORED)
|
w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED)
|
||||||
}
|
}
|
||||||
delete(watch.names, name)
|
delete(watch.names, name)
|
||||||
}
|
}
|
||||||
if watch.mask != 0 {
|
if watch.mask != 0 {
|
||||||
if watch.mask&provisional == 0 {
|
if watch.mask&provisional == 0 {
|
||||||
w.sendEvent(watch.path, watch.mask&sys_FS_IGNORED)
|
w.sendEvent(watch.path, watch.mask&sysFSIGNORED)
|
||||||
}
|
}
|
||||||
watch.mask = 0
|
watch.mask = 0
|
||||||
}
|
}
|
||||||
|
@ -353,8 +353,8 @@ func (w *Watcher) startRead(watch *watch) error {
|
||||||
err := os.NewSyscallError("ReadDirectoryChanges", e)
|
err := os.NewSyscallError("ReadDirectoryChanges", e)
|
||||||
if e == syscall.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 {
|
if e == syscall.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 {
|
||||||
// Watched directory was probably removed
|
// Watched directory was probably removed
|
||||||
if w.sendEvent(watch.path, watch.mask&sys_FS_DELETE_SELF) {
|
if w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) {
|
||||||
if watch.mask&sys_FS_ONESHOT != 0 {
|
if watch.mask&sysFSONESHOT != 0 {
|
||||||
watch.mask = 0
|
watch.mask = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -428,7 +428,7 @@ func (w *Watcher) readEvents() {
|
||||||
}
|
}
|
||||||
case syscall.ERROR_ACCESS_DENIED:
|
case syscall.ERROR_ACCESS_DENIED:
|
||||||
// Watched directory was probably removed
|
// Watched directory was probably removed
|
||||||
w.sendEvent(watch.path, watch.mask&sys_FS_DELETE_SELF)
|
w.sendEvent(watch.path, watch.mask&sysFSDELETESELF)
|
||||||
w.deleteWatch(watch)
|
w.deleteWatch(watch)
|
||||||
w.startRead(watch)
|
w.startRead(watch)
|
||||||
continue
|
continue
|
||||||
|
@ -444,7 +444,7 @@ func (w *Watcher) readEvents() {
|
||||||
var offset uint32
|
var offset uint32
|
||||||
for {
|
for {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
w.Events <- newEvent("", sys_FS_Q_OVERFLOW)
|
w.Events <- newEvent("", sysFSQOVERFLOW)
|
||||||
w.Errors <- errors.New("short read in readEvents()")
|
w.Errors <- errors.New("short read in readEvents()")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -453,27 +453,27 @@ func (w *Watcher) readEvents() {
|
||||||
raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset]))
|
raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset]))
|
||||||
buf := (*[syscall.MAX_PATH]uint16)(unsafe.Pointer(&raw.FileName))
|
buf := (*[syscall.MAX_PATH]uint16)(unsafe.Pointer(&raw.FileName))
|
||||||
name := syscall.UTF16ToString(buf[:raw.FileNameLength/2])
|
name := syscall.UTF16ToString(buf[:raw.FileNameLength/2])
|
||||||
fullname := watch.path + "\\" + name
|
fullname := filepath.Join(watch.path, name)
|
||||||
|
|
||||||
var mask uint64
|
var mask uint64
|
||||||
switch raw.Action {
|
switch raw.Action {
|
||||||
case syscall.FILE_ACTION_REMOVED:
|
case syscall.FILE_ACTION_REMOVED:
|
||||||
mask = sys_FS_DELETE_SELF
|
mask = sysFSDELETESELF
|
||||||
case syscall.FILE_ACTION_MODIFIED:
|
case syscall.FILE_ACTION_MODIFIED:
|
||||||
mask = sys_FS_MODIFY
|
mask = sysFSMODIFY
|
||||||
case syscall.FILE_ACTION_RENAMED_OLD_NAME:
|
case syscall.FILE_ACTION_RENAMED_OLD_NAME:
|
||||||
watch.rename = name
|
watch.rename = name
|
||||||
case syscall.FILE_ACTION_RENAMED_NEW_NAME:
|
case syscall.FILE_ACTION_RENAMED_NEW_NAME:
|
||||||
if watch.names[watch.rename] != 0 {
|
if watch.names[watch.rename] != 0 {
|
||||||
watch.names[name] |= watch.names[watch.rename]
|
watch.names[name] |= watch.names[watch.rename]
|
||||||
delete(watch.names, watch.rename)
|
delete(watch.names, watch.rename)
|
||||||
mask = sys_FS_MOVE_SELF
|
mask = sysFSMOVESELF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sendNameEvent := func() {
|
sendNameEvent := func() {
|
||||||
if w.sendEvent(fullname, watch.names[name]&mask) {
|
if w.sendEvent(fullname, watch.names[name]&mask) {
|
||||||
if watch.names[name]&sys_FS_ONESHOT != 0 {
|
if watch.names[name]&sysFSONESHOT != 0 {
|
||||||
delete(watch.names, name)
|
delete(watch.names, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -482,16 +482,16 @@ func (w *Watcher) readEvents() {
|
||||||
sendNameEvent()
|
sendNameEvent()
|
||||||
}
|
}
|
||||||
if raw.Action == syscall.FILE_ACTION_REMOVED {
|
if raw.Action == syscall.FILE_ACTION_REMOVED {
|
||||||
w.sendEvent(fullname, watch.names[name]&sys_FS_IGNORED)
|
w.sendEvent(fullname, watch.names[name]&sysFSIGNORED)
|
||||||
delete(watch.names, name)
|
delete(watch.names, name)
|
||||||
}
|
}
|
||||||
if w.sendEvent(fullname, watch.mask&toFSnotifyFlags(raw.Action)) {
|
if w.sendEvent(fullname, watch.mask&toFSnotifyFlags(raw.Action)) {
|
||||||
if watch.mask&sys_FS_ONESHOT != 0 {
|
if watch.mask&sysFSONESHOT != 0 {
|
||||||
watch.mask = 0
|
watch.mask = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if raw.Action == syscall.FILE_ACTION_RENAMED_NEW_NAME {
|
if raw.Action == syscall.FILE_ACTION_RENAMED_NEW_NAME {
|
||||||
fullname = watch.path + "\\" + watch.rename
|
fullname = filepath.Join(watch.path, watch.rename)
|
||||||
sendNameEvent()
|
sendNameEvent()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,16 +529,16 @@ func (w *Watcher) sendEvent(name string, mask uint64) bool {
|
||||||
|
|
||||||
func toWindowsFlags(mask uint64) uint32 {
|
func toWindowsFlags(mask uint64) uint32 {
|
||||||
var m uint32
|
var m uint32
|
||||||
if mask&sys_FS_ACCESS != 0 {
|
if mask&sysFSACCESS != 0 {
|
||||||
m |= syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS
|
m |= syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS
|
||||||
}
|
}
|
||||||
if mask&sys_FS_MODIFY != 0 {
|
if mask&sysFSMODIFY != 0 {
|
||||||
m |= syscall.FILE_NOTIFY_CHANGE_LAST_WRITE
|
m |= syscall.FILE_NOTIFY_CHANGE_LAST_WRITE
|
||||||
}
|
}
|
||||||
if mask&sys_FS_ATTRIB != 0 {
|
if mask&sysFSATTRIB != 0 {
|
||||||
m |= syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES
|
m |= syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES
|
||||||
}
|
}
|
||||||
if mask&(sys_FS_MOVE|sys_FS_CREATE|sys_FS_DELETE) != 0 {
|
if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 {
|
||||||
m |= syscall.FILE_NOTIFY_CHANGE_FILE_NAME | syscall.FILE_NOTIFY_CHANGE_DIR_NAME
|
m |= syscall.FILE_NOTIFY_CHANGE_FILE_NAME | syscall.FILE_NOTIFY_CHANGE_DIR_NAME
|
||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
|
@ -547,15 +547,15 @@ func toWindowsFlags(mask uint64) uint32 {
|
||||||
func toFSnotifyFlags(action uint32) uint64 {
|
func toFSnotifyFlags(action uint32) uint64 {
|
||||||
switch action {
|
switch action {
|
||||||
case syscall.FILE_ACTION_ADDED:
|
case syscall.FILE_ACTION_ADDED:
|
||||||
return sys_FS_CREATE
|
return sysFSCREATE
|
||||||
case syscall.FILE_ACTION_REMOVED:
|
case syscall.FILE_ACTION_REMOVED:
|
||||||
return sys_FS_DELETE
|
return sysFSDELETE
|
||||||
case syscall.FILE_ACTION_MODIFIED:
|
case syscall.FILE_ACTION_MODIFIED:
|
||||||
return sys_FS_MODIFY
|
return sysFSMODIFY
|
||||||
case syscall.FILE_ACTION_RENAMED_OLD_NAME:
|
case syscall.FILE_ACTION_RENAMED_OLD_NAME:
|
||||||
return sys_FS_MOVED_FROM
|
return sysFSMOVEDFROM
|
||||||
case syscall.FILE_ACTION_RENAMED_NEW_NAME:
|
case syscall.FILE_ACTION_RENAMED_NEW_NAME:
|
||||||
return sys_FS_MOVED_TO
|
return sysFSMOVEDTO
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue