From 645c38514148e524d70f811d421cc153399738be Mon Sep 17 00:00:00 2001 From: Yuichi Shiwaku Date: Thu, 15 Jan 2015 15:25:13 +0900 Subject: [PATCH 01/10] Create gitignore --- .gitignore | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b023c5d --- /dev/null +++ b/.gitignore @@ -0,0 +1,77 @@ +# Created by .ignore support plugin (hsz.mobi) +### Go template +# 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 + + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm + +*.iml + +## Directory-based project format: +.idea/ +# if you remove the above rule, at least ignore the following: + +# User-specific stuff: +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/dictionaries + +# Sensitive or high-churn files: +# .idea/dataSources.ids +# .idea/dataSources.xml +# .idea/sqlDataSources.xml +# .idea/dynamic.xml +# .idea/uiDesigner.xml + +# Gradle: +# .idea/gradle.xml +# .idea/libraries + +# Mongo Explorer plugin: +# .idea/mongoSettings.xml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties + + From 0faed11e94907e326f8158ef7026eee74e4664e8 Mon Sep 17 00:00:00 2001 From: Yuichi Shiwaku Date: Fri, 16 Jan 2015 17:09:36 +0900 Subject: [PATCH 02/10] Support fsnotify update --- fsmonitor.go | 21 ++++++++++----------- fsmonitor_test.go | 9 +++++++++ 2 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 fsmonitor_test.go diff --git a/fsmonitor.go b/fsmonitor.go index 90c5f66..13e3cbf 100644 --- a/fsmonitor.go +++ b/fsmonitor.go @@ -1,7 +1,7 @@ package fsmonitor import ( - "code.google.com/p/go.exp/fsnotify" + "github.com/go-fsnotify/fsnotify" "os" "path/filepath" ) @@ -25,15 +25,14 @@ func NewWatcherWithSkipFolders(skipFolders []string) (*Watcher, error) { } func initWatcher(watcher *fsnotify.Watcher, skipFolders []string) *Watcher { - event := make(chan *fsnotify.FileEvent) + event := make(chan fsnotify.Event) watcherError := make(chan error) - monitorWatcher := &Watcher{Event: event, Error: watcherError, watcher: watcher, SkipFolders: skipFolders} + monitorWatcher := &Watcher{Events: event, Error: watcherError, watcher: watcher, SkipFolders: skipFolders} go func() { for { select { - case ev := <-watcher.Event: - event <- ev - if ev.IsCreate() { + case ev := <-watcher.Events: + if ev.Op&fsnotify.Create == fsnotify.Create { go func() { if f, err := os.Stat(ev.Name); err == nil { if f.IsDir() { @@ -43,12 +42,12 @@ func initWatcher(watcher *fsnotify.Watcher, skipFolders []string) *Watcher { }() } - if ev.IsDelete() { + if ev.Op&fsnotify.Remove == fsnotify.Remove { go func() { - watcher.RemoveWatch(ev.Name) + watcher.Remove(ev.Name) }() } - case e := <-watcher.Error: + case e := <-watcher.Errors: watcherError <- e } } @@ -57,7 +56,7 @@ func initWatcher(watcher *fsnotify.Watcher, skipFolders []string) *Watcher { } type Watcher struct { - Event chan *fsnotify.FileEvent + Events chan fsnotify.Event Error chan error SkipFolders []string watcher *fsnotify.Watcher @@ -95,6 +94,6 @@ func (self *Watcher) watchAllFolders(path string) (err error) { } func (self *Watcher) addWatcher(path string) (err error) { - err = self.watcher.Watch(path) + err = self.watcher.Add(path) return } diff --git a/fsmonitor_test.go b/fsmonitor_test.go new file mode 100644 index 0000000..d2a7a74 --- /dev/null +++ b/fsmonitor_test.go @@ -0,0 +1,9 @@ +package fsmonitor + +import ( + "testing" +) + +func TestConstructor(t *testing.T) { + +} From 9cb078f2614abda0c6092ff828942aeacddee7c6 Mon Sep 17 00:00:00 2001 From: Yuichi Shiwaku Date: Fri, 16 Jan 2015 17:41:26 +0900 Subject: [PATCH 03/10] Fix --- fsmonitor.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fsmonitor.go b/fsmonitor.go index 13e3cbf..2676601 100644 --- a/fsmonitor.go +++ b/fsmonitor.go @@ -25,7 +25,7 @@ func NewWatcherWithSkipFolders(skipFolders []string) (*Watcher, error) { } func initWatcher(watcher *fsnotify.Watcher, skipFolders []string) *Watcher { - event := make(chan fsnotify.Event) + event := make(chan *fsnotify.Event) watcherError := make(chan error) monitorWatcher := &Watcher{Events: event, Error: watcherError, watcher: watcher, SkipFolders: skipFolders} go func() { @@ -47,6 +47,7 @@ func initWatcher(watcher *fsnotify.Watcher, skipFolders []string) *Watcher { watcher.Remove(ev.Name) }() } + monitorWatcher.Events <- &ev case e := <-watcher.Errors: watcherError <- e } @@ -56,7 +57,7 @@ func initWatcher(watcher *fsnotify.Watcher, skipFolders []string) *Watcher { } type Watcher struct { - Events chan fsnotify.Event + Events chan *fsnotify.Event Error chan error SkipFolders []string watcher *fsnotify.Watcher From b30d98af0ad03bd4ce9d82416fc9e4a1921ba925 Mon Sep 17 00:00:00 2001 From: Christoph Brand Date: Wed, 6 May 2015 00:34:07 +0200 Subject: [PATCH 04/10] fsmonitor: added comments and pinned the used fsnotify verison to v1. --- fsmonitor.go | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/fsmonitor.go b/fsmonitor.go index 2676601..20533bc 100644 --- a/fsmonitor.go +++ b/fsmonitor.go @@ -1,11 +1,14 @@ package fsmonitor import ( - "github.com/go-fsnotify/fsnotify" "os" "path/filepath" + + "gopkg.in/fsnotify.v1" ) +// NewWatcher initializes a new watcher which is able to recursively scan +// the directory structure. func NewWatcher() (*Watcher, error) { watcher, err := fsnotify.NewWatcher() if err != nil { @@ -15,6 +18,8 @@ func NewWatcher() (*Watcher, error) { return monitorWatcher, nil } +// NewWatcherWithSkipFolders initializes a new watcher capable of watching +// for file system events of a recursive directory structure. func NewWatcherWithSkipFolders(skipFolders []string) (*Watcher, error) { watcher, err := fsnotify.NewWatcher() if err != nil { @@ -24,6 +29,7 @@ func NewWatcherWithSkipFolders(skipFolders []string) (*Watcher, error) { return monitorWatcher, nil } +// initWatcher starts the underlying watcher interface. func initWatcher(watcher *fsnotify.Watcher, skipFolders []string) *Watcher { event := make(chan *fsnotify.Event) watcherError := make(chan error) @@ -56,6 +62,8 @@ func initWatcher(watcher *fsnotify.Watcher, skipFolders []string) *Watcher { return monitorWatcher } +// Watcher is the struct handling the watching of file system events over a recursive +// directory tree. type Watcher struct { Events chan *fsnotify.Event Error chan error @@ -63,14 +71,13 @@ type Watcher struct { watcher *fsnotify.Watcher } +// Watch starts watching the given path and all it's subdirectories for file system +// changes. func (self *Watcher) Watch(path string) error { - err := self.watchAllFolders(path) - if err != nil { - return err - } - return nil + return self.watchAllFolders(path) } +// watchAllFolders starts watching all subdirectories via the underlying fsnotify watchers. func (self *Watcher) watchAllFolders(path string) (err error) { err = filepath.Walk(path, func(path string, f os.FileInfo, err error) error { if f != nil && f.IsDir() { @@ -91,10 +98,10 @@ func (self *Watcher) watchAllFolders(path string) (err error) { } return nil }) - return + return err } +// addWatcher adds the given path to the underyling fsnotify watcher. func (self *Watcher) addWatcher(path string) (err error) { - err = self.watcher.Add(path) - return + return self.watcher.Add(path) } From d95bbdf575c49e57157d58b12854b2e4e9ef1776 Mon Sep 17 00:00:00 2001 From: Christoph Brand Date: Wed, 6 May 2015 00:51:59 +0200 Subject: [PATCH 05/10] fsmonitor: Implemented Close() method to the fsmonitor Watcher struct. --- fsmonitor.go | 66 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/fsmonitor.go b/fsmonitor.go index 20533bc..2742108 100644 --- a/fsmonitor.go +++ b/fsmonitor.go @@ -33,29 +33,38 @@ func NewWatcherWithSkipFolders(skipFolders []string) (*Watcher, error) { func initWatcher(watcher *fsnotify.Watcher, skipFolders []string) *Watcher { event := make(chan *fsnotify.Event) watcherError := make(chan error) - monitorWatcher := &Watcher{Events: event, Error: watcherError, watcher: watcher, SkipFolders: skipFolders} + closeChannel := make(chan struct{}) + monitorWatcher := &Watcher{ + Events: event, + Error: watcherError, + watcher: watcher, + SkipFolders: skipFolders, + closeChannel: closeChannel, + } go func() { for { select { - case ev := <-watcher.Events: - if ev.Op&fsnotify.Create == fsnotify.Create { - go func() { - if f, err := os.Stat(ev.Name); err == nil { - if f.IsDir() { - monitorWatcher.watchAllFolders(ev.Name) - } - } + case ev := <-watcher.Events: + if ev.Op&fsnotify.Create == fsnotify.Create { + go func() { + if f, err := os.Stat(ev.Name); err == nil { + if f.IsDir() { + monitorWatcher.watchAllFolders(ev.Name) + } + } - }() - } - if ev.Op&fsnotify.Remove == fsnotify.Remove { - go func() { - watcher.Remove(ev.Name) - }() - } - monitorWatcher.Events <- &ev - case e := <-watcher.Errors: - watcherError <- e + }() + } + if ev.Op&fsnotify.Remove == fsnotify.Remove { + go func() { + watcher.Remove(ev.Name) + }() + } + monitorWatcher.Events <- &ev + case chanErr := <-watcher.Errors: + watcherError <- chanErr + case <-monitorWatcher.closeChannel: + return } } }() @@ -65,10 +74,11 @@ func initWatcher(watcher *fsnotify.Watcher, skipFolders []string) *Watcher { // Watcher is the struct handling the watching of file system events over a recursive // directory tree. type Watcher struct { - Events chan *fsnotify.Event - Error chan error - SkipFolders []string - watcher *fsnotify.Watcher + Events chan *fsnotify.Event + Error chan error + SkipFolders []string + watcher *fsnotify.Watcher + closeChannel chan struct{} } // Watch starts watching the given path and all it's subdirectories for file system @@ -98,10 +108,16 @@ func (self *Watcher) watchAllFolders(path string) (err error) { } return nil }) - return err + return } // addWatcher adds the given path to the underyling fsnotify watcher. -func (self *Watcher) addWatcher(path string) (err error) { +func (self *Watcher) addWatcher(path string) error { return self.watcher.Add(path) } + +// Close stops the internal watcher. +func (self *Watcher) Close() error { + close(self.closeChannel) + return self.watcher.Close() +} From 676b7a4455da5bbebaaa5a53f04c7e31c524c3f3 Mon Sep 17 00:00:00 2001 From: Christoph Brand Date: Wed, 6 May 2015 01:36:14 +0200 Subject: [PATCH 06/10] added tests for common cases. --- common_test.go | 11 ++++ fsmonitor_test.go | 143 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 common_test.go diff --git a/common_test.go b/common_test.go new file mode 100644 index 0000000..08545cf --- /dev/null +++ b/common_test.go @@ -0,0 +1,11 @@ +package fsmonitor + +import ( + "testing" + + . "gopkg.in/check.v1" +) + +func Test(t *testing.T) { + TestingT(t) +} diff --git a/fsmonitor_test.go b/fsmonitor_test.go index d2a7a74..00fe6dc 100644 --- a/fsmonitor_test.go +++ b/fsmonitor_test.go @@ -1,9 +1,148 @@ package fsmonitor import ( - "testing" + "path/filepath" + "io/ioutil" + "os" + + "gopkg.in/fsnotify.v1" + + . "gopkg.in/check.v1" +) + +const ( + // default permissions + defaultFilePerms = 0600 + defaultDirPerms = 0700 ) -func TestConstructor(t *testing.T) { +type WatcherTests struct { + dir string + watcher *Watcher +} + +var _ = Suite(&WatcherTests{}) + +func (t *WatcherTests) SetUpTest(c *C) { + t.dir = c.MkDir() + watcher, err := NewWatcher() + c.Assert(err, IsNil) + t.watcher = watcher +} + +func (t *WatcherTests) TearDownTest(c *C) { + err := t.watcher.Close() + c.Assert(err, IsNil) +} + +func (t *WatcherTests) TestFileCreation(c *C) { + err := t.watcher.Watch(t.dir) + c.Assert(err, IsNil) + + name := filepath.Join(t.dir, "test.txt") + err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) + + event := <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Create) +} + +func (t *WatcherTests) TestFileDeletion(c *C) { + name := filepath.Join(t.dir, "test.txt") + err := ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) + + err = t.watcher.Watch(t.dir) + c.Assert(err, IsNil) + + err = os.Remove(name) + c.Assert(err, IsNil) + + event := <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Remove) +} + +func (t *WatcherTests) TestFileModification(c *C) { + name := filepath.Join(t.dir, "test.txt") + err := ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) + + err = t.watcher.Watch(t.dir) + c.Assert(err, IsNil) + + err = ioutil.WriteFile(name, []byte("asdfefadsjklvafh7öafdsü+38"), defaultFilePerms) + c.Assert(err, IsNil) + + event := <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Write) +} + +func (t *WatcherTests) TestFileRename(c *C) { + name := filepath.Join(t.dir, "test.txt") + err := ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) + + err = t.watcher.Watch(t.dir) + c.Assert(err, IsNil) + + newName := filepath.Join(t.dir, "test2.txt") + err = os.Rename(name, newName) + c.Assert(err, IsNil) + + event := <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Rename) +} + +func (t *WatcherTests) TestCreateEventInDir(c *C) { + dirName := filepath.Join(t.dir, "test") + err := os.Mkdir(dirName, defaultDirPerms) + c.Assert(err, IsNil) + + err = t.watcher.Watch(t.dir) + c.Assert(err, IsNil) + + name := filepath.Join(dirName, "test.txt") + err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) + + event := <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Create) +} + +func (t *WatcherTests) TestCreateEventInCreatedDir(c *C) { + err := t.watcher.Watch(t.dir) + c.Assert(err, IsNil) + + dirName := filepath.Join(t.dir, "test") + err = os.Mkdir(dirName, defaultDirPerms) + c.Assert(err, IsNil) + + event := <-t.watcher.Events + c.Assert(event.Name, Equals, dirName) + c.Assert(event.Op, Equals, fsnotify.Create) + + name := filepath.Join(dirName, "test.txt") + err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) + + event = <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Create) +} + +func (t *WatcherTests) TestClose(c *C) { + err := t.watcher.Watch(t.dir) + c.Assert(err, IsNil) + + err = t.watcher.Close() + c.Assert(err, IsNil) + watcher, err := NewWatcher() + c.Assert(err, IsNil) + t.watcher = watcher } From 68d4788ace19cbab3527fdb9bf09293d8420fc70 Mon Sep 17 00:00:00 2001 From: Christoph Brand Date: Wed, 6 May 2015 01:58:46 +0200 Subject: [PATCH 07/10] added deletion tests in a nested directory. --- fsmonitor_test.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/fsmonitor_test.go b/fsmonitor_test.go index 00fe6dc..50b5b10 100644 --- a/fsmonitor_test.go +++ b/fsmonitor_test.go @@ -135,6 +135,57 @@ func (t *WatcherTests) TestCreateEventInCreatedDir(c *C) { c.Assert(event.Op, Equals, fsnotify.Create) } +func (t *WatcherTests) TestDeleteInDir(c *C) { + dirName := filepath.Join(t.dir, "test") + err := os.Mkdir(dirName, defaultDirPerms) + c.Assert(err, IsNil) + + name := filepath.Join(dirName, "test.txt") + err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) + + err = t.watcher.Watch(t.dir) + c.Assert(err, IsNil) + + err = os.Remove(name) + c.Assert(err, IsNil) + + event := <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Remove) +} + +func (t *WatcherTests) TestDeleteInCreatedDir(c *C) { + err := t.watcher.Watch(t.dir) + c.Assert(err, IsNil) + + dirName := filepath.Join(t.dir, "test") + err = os.Mkdir(dirName, defaultDirPerms) + c.Assert(err, IsNil) + + event := <-t.watcher.Events + c.Assert(event.Name, Equals, dirName) + c.Assert(event.Op, Equals, fsnotify.Create) + + name := filepath.Join(dirName, "test.txt") + err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) + + event = <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Create) + event = <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Write) + + err = os.Remove(name) + c.Assert(err, IsNil) + + event = <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Remove) +} + func (t *WatcherTests) TestClose(c *C) { err := t.watcher.Watch(t.dir) c.Assert(err, IsNil) From 5f3d9a209d0a94bea7cedcef185b98a695af45e0 Mon Sep 17 00:00:00 2001 From: Christoph Brand Date: Wed, 6 May 2015 02:00:42 +0200 Subject: [PATCH 08/10] go fmt changes. --- common_test.go | 6 +- fsmonitor.go | 62 +++++------ fsmonitor_test.go | 256 +++++++++++++++++++++++----------------------- 3 files changed, 162 insertions(+), 162 deletions(-) diff --git a/common_test.go b/common_test.go index 08545cf..ae1696d 100644 --- a/common_test.go +++ b/common_test.go @@ -1,11 +1,11 @@ package fsmonitor import ( - "testing" + "testing" - . "gopkg.in/check.v1" + . "gopkg.in/check.v1" ) func Test(t *testing.T) { - TestingT(t) + TestingT(t) } diff --git a/fsmonitor.go b/fsmonitor.go index 2742108..c712b92 100644 --- a/fsmonitor.go +++ b/fsmonitor.go @@ -4,7 +4,7 @@ import ( "os" "path/filepath" - "gopkg.in/fsnotify.v1" + "gopkg.in/fsnotify.v1" ) // NewWatcher initializes a new watcher which is able to recursively scan @@ -33,38 +33,38 @@ func NewWatcherWithSkipFolders(skipFolders []string) (*Watcher, error) { func initWatcher(watcher *fsnotify.Watcher, skipFolders []string) *Watcher { event := make(chan *fsnotify.Event) watcherError := make(chan error) - closeChannel := make(chan struct{}) + closeChannel := make(chan struct{}) monitorWatcher := &Watcher{ - Events: event, - Error: watcherError, - watcher: watcher, - SkipFolders: skipFolders, - closeChannel: closeChannel, - } + Events: event, + Error: watcherError, + watcher: watcher, + SkipFolders: skipFolders, + closeChannel: closeChannel, + } go func() { for { select { - case ev := <-watcher.Events: - if ev.Op&fsnotify.Create == fsnotify.Create { - go func() { - if f, err := os.Stat(ev.Name); err == nil { - if f.IsDir() { - monitorWatcher.watchAllFolders(ev.Name) - } - } + case ev := <-watcher.Events: + if ev.Op&fsnotify.Create == fsnotify.Create { + go func() { + if f, err := os.Stat(ev.Name); err == nil { + if f.IsDir() { + monitorWatcher.watchAllFolders(ev.Name) + } + } - }() - } - if ev.Op&fsnotify.Remove == fsnotify.Remove { - go func() { - watcher.Remove(ev.Name) - }() - } - monitorWatcher.Events <- &ev - case chanErr := <-watcher.Errors: - watcherError <- chanErr - case <-monitorWatcher.closeChannel: - return + }() + } + if ev.Op&fsnotify.Remove == fsnotify.Remove { + go func() { + watcher.Remove(ev.Name) + }() + } + monitorWatcher.Events <- &ev + case chanErr := <-watcher.Errors: + watcherError <- chanErr + case <-monitorWatcher.closeChannel: + return } } }() @@ -78,7 +78,7 @@ type Watcher struct { Error chan error SkipFolders []string watcher *fsnotify.Watcher - closeChannel chan struct{} + closeChannel chan struct{} } // Watch starts watching the given path and all it's subdirectories for file system @@ -118,6 +118,6 @@ func (self *Watcher) addWatcher(path string) error { // Close stops the internal watcher. func (self *Watcher) Close() error { - close(self.closeChannel) - return self.watcher.Close() + close(self.closeChannel) + return self.watcher.Close() } diff --git a/fsmonitor_test.go b/fsmonitor_test.go index 50b5b10..5a1d140 100644 --- a/fsmonitor_test.go +++ b/fsmonitor_test.go @@ -1,199 +1,199 @@ package fsmonitor import ( - "path/filepath" - "io/ioutil" - "os" + "io/ioutil" + "os" + "path/filepath" - "gopkg.in/fsnotify.v1" + "gopkg.in/fsnotify.v1" - . "gopkg.in/check.v1" + . "gopkg.in/check.v1" ) const ( - // default permissions - defaultFilePerms = 0600 - defaultDirPerms = 0700 + // default permissions + defaultFilePerms = 0600 + defaultDirPerms = 0700 ) type WatcherTests struct { - dir string - watcher *Watcher + dir string + watcher *Watcher } var _ = Suite(&WatcherTests{}) func (t *WatcherTests) SetUpTest(c *C) { - t.dir = c.MkDir() - watcher, err := NewWatcher() - c.Assert(err, IsNil) - t.watcher = watcher + t.dir = c.MkDir() + watcher, err := NewWatcher() + c.Assert(err, IsNil) + t.watcher = watcher } func (t *WatcherTests) TearDownTest(c *C) { - err := t.watcher.Close() - c.Assert(err, IsNil) + err := t.watcher.Close() + c.Assert(err, IsNil) } func (t *WatcherTests) TestFileCreation(c *C) { - err := t.watcher.Watch(t.dir) - c.Assert(err, IsNil) + err := t.watcher.Watch(t.dir) + c.Assert(err, IsNil) - name := filepath.Join(t.dir, "test.txt") - err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) - c.Assert(err, IsNil) + name := filepath.Join(t.dir, "test.txt") + err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) - event := <-t.watcher.Events - c.Assert(event.Name, Equals, name) - c.Assert(event.Op, Equals, fsnotify.Create) + event := <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Create) } func (t *WatcherTests) TestFileDeletion(c *C) { - name := filepath.Join(t.dir, "test.txt") - err := ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) - c.Assert(err, IsNil) + name := filepath.Join(t.dir, "test.txt") + err := ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) - err = t.watcher.Watch(t.dir) - c.Assert(err, IsNil) + err = t.watcher.Watch(t.dir) + c.Assert(err, IsNil) - err = os.Remove(name) - c.Assert(err, IsNil) + err = os.Remove(name) + c.Assert(err, IsNil) - event := <-t.watcher.Events - c.Assert(event.Name, Equals, name) - c.Assert(event.Op, Equals, fsnotify.Remove) + event := <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Remove) } func (t *WatcherTests) TestFileModification(c *C) { - name := filepath.Join(t.dir, "test.txt") - err := ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) - c.Assert(err, IsNil) + name := filepath.Join(t.dir, "test.txt") + err := ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) - err = t.watcher.Watch(t.dir) - c.Assert(err, IsNil) + err = t.watcher.Watch(t.dir) + c.Assert(err, IsNil) - err = ioutil.WriteFile(name, []byte("asdfefadsjklvafh7öafdsü+38"), defaultFilePerms) - c.Assert(err, IsNil) + err = ioutil.WriteFile(name, []byte("asdfefadsjklvafh7öafdsü+38"), defaultFilePerms) + c.Assert(err, IsNil) - event := <-t.watcher.Events - c.Assert(event.Name, Equals, name) - c.Assert(event.Op, Equals, fsnotify.Write) + event := <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Write) } func (t *WatcherTests) TestFileRename(c *C) { - name := filepath.Join(t.dir, "test.txt") - err := ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) - c.Assert(err, IsNil) + name := filepath.Join(t.dir, "test.txt") + err := ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) - err = t.watcher.Watch(t.dir) - c.Assert(err, IsNil) + err = t.watcher.Watch(t.dir) + c.Assert(err, IsNil) - newName := filepath.Join(t.dir, "test2.txt") - err = os.Rename(name, newName) - c.Assert(err, IsNil) + newName := filepath.Join(t.dir, "test2.txt") + err = os.Rename(name, newName) + c.Assert(err, IsNil) - event := <-t.watcher.Events - c.Assert(event.Name, Equals, name) - c.Assert(event.Op, Equals, fsnotify.Rename) + event := <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Rename) } func (t *WatcherTests) TestCreateEventInDir(c *C) { - dirName := filepath.Join(t.dir, "test") - err := os.Mkdir(dirName, defaultDirPerms) - c.Assert(err, IsNil) + dirName := filepath.Join(t.dir, "test") + err := os.Mkdir(dirName, defaultDirPerms) + c.Assert(err, IsNil) - err = t.watcher.Watch(t.dir) - c.Assert(err, IsNil) + err = t.watcher.Watch(t.dir) + c.Assert(err, IsNil) - name := filepath.Join(dirName, "test.txt") - err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) - c.Assert(err, IsNil) + name := filepath.Join(dirName, "test.txt") + err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) - event := <-t.watcher.Events - c.Assert(event.Name, Equals, name) - c.Assert(event.Op, Equals, fsnotify.Create) + event := <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Create) } func (t *WatcherTests) TestCreateEventInCreatedDir(c *C) { - err := t.watcher.Watch(t.dir) - c.Assert(err, IsNil) + err := t.watcher.Watch(t.dir) + c.Assert(err, IsNil) - dirName := filepath.Join(t.dir, "test") - err = os.Mkdir(dirName, defaultDirPerms) - c.Assert(err, IsNil) + dirName := filepath.Join(t.dir, "test") + err = os.Mkdir(dirName, defaultDirPerms) + c.Assert(err, IsNil) - event := <-t.watcher.Events - c.Assert(event.Name, Equals, dirName) - c.Assert(event.Op, Equals, fsnotify.Create) + event := <-t.watcher.Events + c.Assert(event.Name, Equals, dirName) + c.Assert(event.Op, Equals, fsnotify.Create) - name := filepath.Join(dirName, "test.txt") - err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) - c.Assert(err, IsNil) + name := filepath.Join(dirName, "test.txt") + err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) - event = <-t.watcher.Events - c.Assert(event.Name, Equals, name) - c.Assert(event.Op, Equals, fsnotify.Create) + event = <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Create) } func (t *WatcherTests) TestDeleteInDir(c *C) { - dirName := filepath.Join(t.dir, "test") - err := os.Mkdir(dirName, defaultDirPerms) - c.Assert(err, IsNil) + dirName := filepath.Join(t.dir, "test") + err := os.Mkdir(dirName, defaultDirPerms) + c.Assert(err, IsNil) - name := filepath.Join(dirName, "test.txt") - err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) - c.Assert(err, IsNil) + name := filepath.Join(dirName, "test.txt") + err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) - err = t.watcher.Watch(t.dir) - c.Assert(err, IsNil) + err = t.watcher.Watch(t.dir) + c.Assert(err, IsNil) - err = os.Remove(name) - c.Assert(err, IsNil) + err = os.Remove(name) + c.Assert(err, IsNil) - event := <-t.watcher.Events - c.Assert(event.Name, Equals, name) - c.Assert(event.Op, Equals, fsnotify.Remove) + event := <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Remove) } func (t *WatcherTests) TestDeleteInCreatedDir(c *C) { - err := t.watcher.Watch(t.dir) - c.Assert(err, IsNil) - - dirName := filepath.Join(t.dir, "test") - err = os.Mkdir(dirName, defaultDirPerms) - c.Assert(err, IsNil) - - event := <-t.watcher.Events - c.Assert(event.Name, Equals, dirName) - c.Assert(event.Op, Equals, fsnotify.Create) - - name := filepath.Join(dirName, "test.txt") - err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) - c.Assert(err, IsNil) - - event = <-t.watcher.Events - c.Assert(event.Name, Equals, name) - c.Assert(event.Op, Equals, fsnotify.Create) - event = <-t.watcher.Events - c.Assert(event.Name, Equals, name) - c.Assert(event.Op, Equals, fsnotify.Write) - - err = os.Remove(name) - c.Assert(err, IsNil) - - event = <-t.watcher.Events - c.Assert(event.Name, Equals, name) - c.Assert(event.Op, Equals, fsnotify.Remove) + err := t.watcher.Watch(t.dir) + c.Assert(err, IsNil) + + dirName := filepath.Join(t.dir, "test") + err = os.Mkdir(dirName, defaultDirPerms) + c.Assert(err, IsNil) + + event := <-t.watcher.Events + c.Assert(event.Name, Equals, dirName) + c.Assert(event.Op, Equals, fsnotify.Create) + + name := filepath.Join(dirName, "test.txt") + err = ioutil.WriteFile(name, []byte("asdf"), defaultFilePerms) + c.Assert(err, IsNil) + + event = <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Create) + event = <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Write) + + err = os.Remove(name) + c.Assert(err, IsNil) + + event = <-t.watcher.Events + c.Assert(event.Name, Equals, name) + c.Assert(event.Op, Equals, fsnotify.Remove) } func (t *WatcherTests) TestClose(c *C) { - err := t.watcher.Watch(t.dir) - c.Assert(err, IsNil) + err := t.watcher.Watch(t.dir) + c.Assert(err, IsNil) - err = t.watcher.Close() - c.Assert(err, IsNil) + err = t.watcher.Close() + c.Assert(err, IsNil) - watcher, err := NewWatcher() - c.Assert(err, IsNil) - t.watcher = watcher + watcher, err := NewWatcher() + c.Assert(err, IsNil) + t.watcher = watcher } From 7f0e20a6a8e8be65e8b4d828046c65a3a11b2dee Mon Sep 17 00:00:00 2001 From: Christoph Brand Date: Wed, 6 May 2015 02:07:30 +0200 Subject: [PATCH 09/10] golint fixes. --- fsmonitor.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/fsmonitor.go b/fsmonitor.go index c712b92..b3d666c 100644 --- a/fsmonitor.go +++ b/fsmonitor.go @@ -83,16 +83,16 @@ type Watcher struct { // Watch starts watching the given path and all it's subdirectories for file system // changes. -func (self *Watcher) Watch(path string) error { - return self.watchAllFolders(path) +func (w *Watcher) Watch(path string) error { + return w.watchAllFolders(path) } // watchAllFolders starts watching all subdirectories via the underlying fsnotify watchers. -func (self *Watcher) watchAllFolders(path string) (err error) { +func (w *Watcher) watchAllFolders(path string) (err error) { err = filepath.Walk(path, func(path string, f os.FileInfo, err error) error { if f != nil && f.IsDir() { filename := f.Name() - for _, skipFolder := range self.SkipFolders { + for _, skipFolder := range w.SkipFolders { match, err := filepath.Match(skipFolder, filename) if err != nil { return err @@ -101,7 +101,7 @@ func (self *Watcher) watchAllFolders(path string) (err error) { return filepath.SkipDir } } - err := self.addWatcher(path) + err := w.addWatcher(path) if err != nil { return err } @@ -112,12 +112,12 @@ func (self *Watcher) watchAllFolders(path string) (err error) { } // addWatcher adds the given path to the underyling fsnotify watcher. -func (self *Watcher) addWatcher(path string) error { - return self.watcher.Add(path) +func (w *Watcher) addWatcher(path string) error { + return w.watcher.Add(path) } // Close stops the internal watcher. -func (self *Watcher) Close() error { - close(self.closeChannel) - return self.watcher.Close() +func (w *Watcher) Close() error { + close(w.closeChannel) + return w.watcher.Close() } From 1cae2d65926087561796c79f3eaa7f33eed5a4f5 Mon Sep 17 00:00:00 2001 From: Christoph Brand Date: Wed, 6 May 2015 02:17:50 +0200 Subject: [PATCH 10/10] added a isClosed method. Tests adjusted to verify if the function works correctly. --- fsmonitor.go | 14 ++++++++++++-- fsmonitor_test.go | 2 ++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/fsmonitor.go b/fsmonitor.go index b3d666c..1c4e996 100644 --- a/fsmonitor.go +++ b/fsmonitor.go @@ -40,6 +40,7 @@ func initWatcher(watcher *fsnotify.Watcher, skipFolders []string) *Watcher { watcher: watcher, SkipFolders: skipFolders, closeChannel: closeChannel, + isClosed: false, } go func() { for { @@ -79,6 +80,7 @@ type Watcher struct { SkipFolders []string watcher *fsnotify.Watcher closeChannel chan struct{} + isClosed bool } // Watch starts watching the given path and all it's subdirectories for file system @@ -118,6 +120,14 @@ func (w *Watcher) addWatcher(path string) error { // Close stops the internal watcher. func (w *Watcher) Close() error { - close(w.closeChannel) - return w.watcher.Close() + if(!w.IsClosed()) { + close(w.closeChannel) + w.isClosed = true + } + return w.watcher.Close() +} + +// IsClose returns if the watcher has been closed. +func (w *Watcher) IsClosed() bool { + return w.isClosed } diff --git a/fsmonitor_test.go b/fsmonitor_test.go index 5a1d140..fa59abf 100644 --- a/fsmonitor_test.go +++ b/fsmonitor_test.go @@ -190,8 +190,10 @@ func (t *WatcherTests) TestClose(c *C) { err := t.watcher.Watch(t.dir) c.Assert(err, IsNil) + c.Assert(t.watcher.IsClosed(), Equals, false) err = t.watcher.Close() c.Assert(err, IsNil) + c.Assert(t.watcher.IsClosed(), Equals, true) watcher, err := NewWatcher() c.Assert(err, IsNil)