1
0
mirror of https://github.com/go-task/task.git synced 2025-07-17 01:43:07 +02:00

watch: switch to watcher as waych lib and few fixes

watcher whould be more consistent across differente OSes
This commit is contained in:
Andrey Nering
2017-08-05 11:50:39 -03:00
parent ddd063f29e
commit c210e34ce3
2 changed files with 66 additions and 48 deletions

View File

@ -36,8 +36,7 @@ type Executor struct {
Stdout io.Writer Stdout io.Writer
Stderr io.Writer Stderr io.Writer
taskvars Vars taskvars Vars
watchingFiles map[string]struct{}
taskCallCount map[string]*int32 taskCallCount map[string]*int32

111
watch.go
View File

@ -5,8 +5,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/fsnotify/fsnotify"
"github.com/mattn/go-zglob" "github.com/mattn/go-zglob"
"github.com/radovskyb/watcher"
) )
// watchTasks start watching the given tasks // watchTasks start watching the given tasks
@ -31,81 +31,100 @@ func (e *Executor) watchTasks(args ...string) error {
}() }()
} }
watcher, err := fsnotify.NewWatcher() w := watcher.New()
if err != nil { defer w.Close()
return err w.SetMaxEvents(1)
}
defer watcher.Close()
go func() { go func() {
for { for {
if err := e.registerWatchedFiles(watcher, args); err != nil { select {
e.printfln("Error watching files: %v", err) case event := <-w.Event:
e.verbosePrintfln("task: received watch event: %v", event)
cancel()
ctx, cancel = context.WithCancel(context.Background())
for _, a := range args {
a := a
go func() {
if err := e.RunTask(ctx, Call{Task: a}); err != nil && !isCtxErr(err) {
e.println(err)
}
}()
}
case err := <-w.Error:
switch err {
case watcher.ErrWatchedFileDeleted:
go func() {
w.TriggerEvent(watcher.Remove, nil)
}()
default:
e.println(err)
}
case <-w.Closed:
return
} }
time.Sleep(time.Second * 2)
} }
}() }()
for { go func() {
select { // re-register each second because we can have new files
case <-watcher.Events: for {
cancel() if err := e.registerWatchedFiles(w, args); err != nil {
ctx, cancel = context.WithCancel(context.Background()) e.println(err)
for _, a := range args {
a := a
go func() {
if err := e.RunTask(ctx, Call{Task: a}); err != nil && !isCtxErr(err) {
e.println(err)
}
}()
} }
case err := <-watcher.Errors: time.Sleep(time.Second)
e.println(err)
} }
} }()
return w.Start(time.Second)
} }
func (e *Executor) registerWatchedFiles(w *fsnotify.Watcher, args []string) error { func (e *Executor) registerWatchedFiles(w *watcher.Watcher, args []string) error {
oldWatchingFiles := e.watchingFiles oldWatchedFiles := make(map[string]struct{})
e.watchingFiles = make(map[string]struct{}, len(oldWatchingFiles)) for f := range w.WatchedFiles() {
oldWatchedFiles[f] = struct{}{}
}
for k := range oldWatchingFiles { for f := range oldWatchedFiles {
if err := w.Remove(k); err != nil { if err := w.Remove(f); err != nil {
return err return err
} }
} }
for _, a := range args { var registerTaskFiles func(string) error
task, ok := e.Tasks[a] registerTaskFiles = func(t string) error {
task, ok := e.Tasks[t]
if !ok { if !ok {
return &taskNotFoundError{a} return &taskNotFoundError{t}
} }
deps := make([]string, len(task.Deps))
for i, d := range task.Deps { for _, d := range task.Deps {
deps[i] = d.Task if err := registerTaskFiles(d.Task); err != nil {
} return err
if err := e.registerWatchedFiles(w, deps); err != nil { }
return err
} }
for _, s := range task.Sources { for _, s := range task.Sources {
files, err := zglob.Glob(s) files, err := zglob.Glob(s)
if err != nil { if err != nil {
return err return err
} }
for _, f := range files { for _, f := range files {
if _, ok := oldWatchedFiles[f]; ok {
continue
}
if err := w.Add(f); err != nil { if err := w.Add(f); err != nil {
return err return err
} }
e.watchingFiles[f] = struct{}{}
// run if is new file
if oldWatchingFiles != nil {
if _, ok := oldWatchingFiles[f]; !ok {
w.Events <- fsnotify.Event{Name: f, Op: fsnotify.Create}
}
}
} }
} }
return nil
}
for _, a := range args {
if err := registerTaskFiles(a); err != nil {
return err
}
} }
return nil return nil
} }