diff --git a/src/file/watcher.go b/src/file/watcher.go index a96d3c69..d2516852 100644 --- a/src/file/watcher.go +++ b/src/file/watcher.go @@ -122,16 +122,14 @@ func (w *Watcher) watchFsEvents() { } func (w *Watcher) onEvent(event watcher.Event) bool { - if event.IsDir() { - if isEventType(event.Op, watcher.Create) { - w.fsWatcher.Add(event.Path) - } - return false - } events := map[string]Event{} - for _, event := range w.translateEvent(event) { - events[event.Path] = event + for _, e := range w.translateEvent(event) { + events[e.Path] = e } + if len(events) == 0 { + return false + } + drainTimer := time.NewTimer(drainTimeout) defer drainTimer.Stop() for { @@ -164,7 +162,11 @@ func (w *Watcher) updateChecksum(e Event) { func (w *Watcher) translateEvent(event watcher.Event) []Event { oldPath, currentPath := w.parsePath(event.OldPath), w.parsePath(event.Path) - if isEventType(event.Op, watcher.Rename, watcher.Move) { + if event.IsDir() { + if isEventType(event.Op, watcher.Create) { + w.fsWatcher.Add(event.Path) + } + } else if isEventType(event.Op, watcher.Rename, watcher.Move) { return []Event{{Op: Remove, Path: oldPath}, {Op: Update, Path: currentPath, LastKnownChecksum: w.checksums[currentPath]}} } else if isEventType(event.Op, watcher.Remove) { return []Event{{Op: Remove, Path: currentPath}} diff --git a/src/file/watcher_test.go b/src/file/watcher_test.go index 423517b2..70be9ab6 100644 --- a/src/file/watcher_test.go +++ b/src/file/watcher_test.go @@ -166,6 +166,43 @@ func TestFileWatcher_OnEvent(t *testing.T) { } } +func TestFileWatcher_translateEvent(t *testing.T) { + testcases := []struct { + filename, oldname string + op watcher.Op + expectedOp OptSlice + }{ + {expectedOp: OptSlice{Update}, filename: "_testdata/project/templates/template.liquid", op: watcher.Write}, + {expectedOp: OptSlice{Update}, filename: "_testdata/project/templates/customers/test.liquid", op: watcher.Create}, + {expectedOp: OptSlice{}, filename: "_testdata/project/config", op: watcher.Create}, + {expectedOp: OptSlice{Remove}, filename: "_testdata/project/templates/customers/test.liquid", op: watcher.Remove}, + {expectedOp: OptSlice{Remove, Update}, filename: "_testdata/project/assets/application.js.liquid", oldname: "_testdata/project/assets/application.js", op: watcher.Rename}, + {expectedOp: OptSlice{Remove, Update}, filename: "_testdata/project/assets/application.js.liquid", oldname: "_testdata/project/assets/application.js", op: watcher.Move}, + } + + for _, testcase := range testcases { + info, _ := os.Stat(testcase.filename) + evt := watcher.Event{ + Op: testcase.op, + Path: testcase.filename, + OldPath: testcase.oldname, + FileInfo: info, + } + + w := createTestWatcher(t) + events := w.translateEvent(evt) + assert.Equal(t, len(testcase.expectedOp), len(events)) + recievedEvents := OptSlice{} + for _, e := range events { + recievedEvents = append(recievedEvents, e.Op) + } + sort.Sort(testcase.expectedOp) + sort.Sort(recievedEvents) + assert.Equal(t, testcase.expectedOp, recievedEvents) + w.Stop() + } +} + func TestFileWatcher_debouncing(t *testing.T) { w := createTestWatcher(t) w.Events = make(chan Event, 10)