1
0
mirror of https://github.com/go-task/task.git synced 2024-12-14 10:52:43 +02:00
task/watch.go
Andrey Nering c591ea4185 Use context together with errgroup
This will let other deps to be killed when one of the deps returns an
error.

Before this change, the process could keep running even after Task
exited.
2017-04-12 20:53:41 -03:00

100 lines
1.9 KiB
Go

package task
import (
"context"
"fmt"
"log"
"strings"
"time"
"github.com/fsnotify/fsnotify"
"github.com/mattn/go-zglob"
)
// WatchTasks start watching the given tasks
func WatchTasks(args []string) error {
log.Printf("task: Started watching for tasks: %s", strings.Join(args, ", "))
// run tasks on init
for _, a := range args {
if err := RunTask(context.Background(), a); err != nil {
fmt.Println(err)
break
}
}
watcher, err := fsnotify.NewWatcher()
if err != nil {
return err
}
defer watcher.Close()
go func() {
for {
if err := registerWatchedFiles(watcher, args); err != nil {
log.Printf("Error watching files: %v", err)
}
time.Sleep(time.Second * 2)
}
}()
loop:
for {
select {
case <-watcher.Events:
for _, a := range args {
if err := RunTask(context.Background(), a); err != nil {
fmt.Println(err)
continue loop
}
}
case err := <-watcher.Errors:
fmt.Println(err)
continue loop
}
}
}
var watchingFiles map[string]struct{}
func registerWatchedFiles(w *fsnotify.Watcher, args []string) error {
oldWatchingFiles := watchingFiles
watchingFiles = make(map[string]struct{}, len(oldWatchingFiles))
for k := range oldWatchingFiles {
if err := w.Remove(k); err != nil {
return err
}
}
for _, a := range args {
task, ok := Tasks[a]
if !ok {
return &taskNotFoundError{a}
}
if err := registerWatchedFiles(w, task.Deps); err != nil {
return err
}
for _, s := range task.Sources {
files, err := zglob.Glob(s)
if err != nil {
return err
}
for _, f := range files {
if err := w.Add(f); err != nil {
return err
}
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
}