Skip to content

Commit

Permalink
filewatcher: fix event.Op comparison
Browse files Browse the repository at this point in the history
Previously it was matching all events, which caused problems in editors
like vim, which rename the file. It seemed to be running before the file
was finished writing.
  • Loading branch information
dnephin committed Oct 24, 2020
1 parent a94234d commit c11beca
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 2 deletions.
7 changes: 5 additions & 2 deletions internal/filewatcher/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ func Watch(dirs []string, run func(pkg string) error) error {
case <-timer.C:
return fmt.Errorf("exceeded idle timeout while watching files")
case event := <-watcher.Events:
if !timer.Stop() {
<-timer.C
}
log.Debugf("handling event %v", event)

if handleDirCreated(watcher, event) {
Expand Down Expand Up @@ -129,7 +132,7 @@ func noGoFiles(path string) bool {
}
}

func handleDirCreated(watcher *fsnotify.Watcher, event fsnotify.Event) bool {
func handleDirCreated(watcher *fsnotify.Watcher, event fsnotify.Event) (handled bool) {
if event.Op&fsnotify.Create != fsnotify.Create {
return false
}
Expand Down Expand Up @@ -158,7 +161,7 @@ type handler struct {
const floodThreshold = 250 * time.Millisecond

func (h *handler) handleEvent(event fsnotify.Event) error {
if event.Op&fsnotify.Write|fsnotify.Create == 0 {
if event.Op&(fsnotify.Write|fsnotify.Create) == 0 {
return nil
}

Expand Down
78 changes: 78 additions & 0 deletions internal/filewatcher/watch_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package filewatcher

import (
"testing"
"time"

"github.com/fsnotify/fsnotify"
"gotest.tools/v3/assert"
)

func TestHandler_HandleEvent(t *testing.T) {
type testCase struct {
name string
last time.Time
expectedRun bool
event fsnotify.Event
}

fn := func(t *testing.T, tc testCase) {
var ran bool
run := func(pkg string) error {
ran = true
return nil
}

h := handler{last: tc.last, fn: run}
err := h.handleEvent(tc.event)
assert.NilError(t, err)
assert.Equal(t, ran, tc.expectedRun)
if tc.expectedRun {
assert.Assert(t, !h.last.IsZero())
}
}

var testCases = []testCase{
{
name: "Op is rename",
event: fsnotify.Event{Op: fsnotify.Rename, Name: "file_test.go"},
},
{
name: "Op is remove",
event: fsnotify.Event{Op: fsnotify.Remove, Name: "file_test.go"},
},
{
name: "Op is chmod",
event: fsnotify.Event{Op: fsnotify.Chmod, Name: "file_test.go"},
},
{
name: "Op is write+chmod",
event: fsnotify.Event{Op: fsnotify.Write | fsnotify.Chmod, Name: "file_test.go"},
expectedRun: true,
},
{
name: "Op is write",
event: fsnotify.Event{Op: fsnotify.Write, Name: "file_test.go"},
expectedRun: true,
},
{
name: "Op is create",
event: fsnotify.Event{Op: fsnotify.Create, Name: "file_test.go"},
expectedRun: true,
},
{
name: "file is not a go file",
event: fsnotify.Event{Op: fsnotify.Write, Name: "readme.md"},
},
{
name: "under flood threshold",
event: fsnotify.Event{Op: fsnotify.Create, Name: "file_test.go"},
last: time.Now(),
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
fn(t, tc)
})
}
}

0 comments on commit c11beca

Please sign in to comment.