diff --git a/pkg/watch/notify_test.go b/pkg/watch/notify_test.go index 1d3a7c05..e873c94e 100644 --- a/pkg/watch/notify_test.go +++ b/pkg/watch/notify_test.go @@ -1,5 +1,3 @@ -// +build !windows - package watch import ( @@ -41,6 +39,9 @@ func TestNoWatches(t *testing.T) { } func TestEventOrdering(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("Skipping on windows for now") + } f := newNotifyFixture(t) defer f.tearDown() @@ -73,6 +74,9 @@ func TestEventOrdering(t *testing.T) { // of directories, creates files in them, then deletes // them all quickly. Make sure there are no errors. func TestGitBranchSwitch(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("Skipping on windows for now") + } f := newNotifyFixture(t) defer f.tearDown() @@ -143,10 +147,11 @@ func TestWatchesAreRecursive(t *testing.T) { f.events = nil // change sub directory changeFilePath := filepath.Join(subPath, "change") - _, err := os.OpenFile(changeFilePath, os.O_RDONLY|os.O_CREATE, 0666) + h, err := os.OpenFile(changeFilePath, os.O_RDONLY|os.O_CREATE, 0666) if err != nil { t.Fatal(err) } + defer h.Close() f.assertEvents(changeFilePath) } @@ -168,10 +173,12 @@ func TestNewDirectoriesAreRecursivelyWatched(t *testing.T) { // change something inside sub directory changeFilePath := filepath.Join(subPath, "change") - _, err := os.OpenFile(changeFilePath, os.O_RDONLY|os.O_CREATE, 0666) + h, err := os.OpenFile(changeFilePath, os.O_RDONLY|os.O_CREATE, 0666) if err != nil { t.Fatal(err) } + defer h.Close() + f.assertEvents(subPath, changeFilePath) } @@ -278,6 +285,9 @@ func TestSingleFile(t *testing.T) { } func TestWriteBrokenLink(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("Symlink creation requires admin privileges on Windows") + } f := newNotifyFixture(t) defer f.tearDown() @@ -292,6 +302,9 @@ func TestWriteBrokenLink(t *testing.T) { } func TestWriteGoodLink(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("Symlink creation requires admin privileges on Windows") + } f := newNotifyFixture(t) defer f.tearDown() @@ -311,6 +324,9 @@ func TestWriteGoodLink(t *testing.T) { } func TestWatchBrokenLink(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("Symlink creation requires admin privileges on Windows") + } f := newNotifyFixture(t) defer f.tearDown() @@ -339,6 +355,10 @@ func TestWatchBrokenLink(t *testing.T) { } func TestMoveAndReplace(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("Skipping on windows for now") + } + f := newNotifyFixture(t) defer f.tearDown() diff --git a/pkg/watch/watcher_naive.go b/pkg/watch/watcher_naive.go index 2c61b721..46f90828 100644 --- a/pkg/watch/watcher_naive.go +++ b/pkg/watch/watcher_naive.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "path/filepath" + "runtime" "github.com/pkg/errors" "github.com/windmilleng/fsnotify" @@ -135,7 +136,7 @@ func (d *naiveNotify) loop() { defer close(d.wrappedEvents) for e := range d.events { if e.Op&fsnotify.Create != fsnotify.Create { - if d.shouldNotify(e.Name) { + if d.shouldNotify(e.Name) && !isSpuriousWindowsDirChange(e) { d.wrappedEvents <- FileEvent{e.Name} } continue @@ -262,6 +263,22 @@ func newWatcher(paths []string, ignore PathMatcher, l logger.Logger) (*naiveNoti return wmw, nil } +// Windows' inotify implementation sometimes fires +// of spurious WRITE events on directories when the +// files inside change. +func isSpuriousWindowsDirChange(e fsnotify.Event) bool { + if runtime.GOOS != "windows" { + return false + } + + if e.Op != fsnotify.Write { + return false + } + + eIsDir, _ := isDir(e.Name) + return eIsDir +} + func isDir(pth string) (bool, error) { fi, err := os.Lstat(pth) if os.IsNotExist(err) { diff --git a/pkg/watch/watcher_naive_test.go b/pkg/watch/watcher_naive_test.go index 35ec894b..d709d4d3 100644 --- a/pkg/watch/watcher_naive_test.go +++ b/pkg/watch/watcher_naive_test.go @@ -1,4 +1,4 @@ -// +build !darwin,!windows +// +build !darwin package watch @@ -6,6 +6,7 @@ import ( "fmt" "os" "os/exec" + "runtime" "strconv" "strings" "testing" @@ -92,6 +93,9 @@ func TestDontWatchEachFile(t *testing.T) { f.events = nil pid := os.Getpid() + if runtime.GOOS == "windows" { + return // skip the inotify count + } output, err := exec.Command("bash", "-c", fmt.Sprintf( "find /proc/%d/fd -lname anon_inode:inotify -printf '%%hinfo/%%f\n' | xargs cat | grep -c '^inotify'", pid)).Output()