mirror of
https://github.com/go-task/task.git
synced 2025-08-10 22:42:19 +02:00
fix(watcher): fix some v3.43.x regressions (#2271)
This commit is contained in:
128
watch.go
128
watch.go
@@ -19,6 +19,8 @@ import (
|
||||
"github.com/go-task/task/v3/internal/fingerprint"
|
||||
"github.com/go-task/task/v3/internal/fsnotifyext"
|
||||
"github.com/go-task/task/v3/internal/logger"
|
||||
"github.com/go-task/task/v3/internal/slicesext"
|
||||
"github.com/go-task/task/v3/taskfile/ast"
|
||||
)
|
||||
|
||||
const defaultWaitTime = 100 * time.Millisecond
|
||||
@@ -85,17 +87,22 @@ func (e *Executor) watchTasks(calls ...*Call) error {
|
||||
for _, c := range calls {
|
||||
c := c
|
||||
go func() {
|
||||
if ShouldIgnore(event.Name) {
|
||||
e.Logger.VerboseErrf(logger.Magenta, "task: event skipped for being an ignored dir: %s\n", event.Name)
|
||||
return
|
||||
}
|
||||
t, err := e.GetTask(c)
|
||||
if err != nil {
|
||||
e.Logger.Errf(logger.Red, "%v\n", err)
|
||||
return
|
||||
}
|
||||
baseDir := filepathext.SmartJoin(e.Dir, t.Dir)
|
||||
files, err := fingerprint.Globs(baseDir, t.Sources)
|
||||
files, err := e.collectSources(calls)
|
||||
if err != nil {
|
||||
e.Logger.Errf(logger.Red, "%v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
if !event.Has(fsnotify.Remove) && !slices.Contains(files, event.Name) {
|
||||
relPath, _ := filepath.Rel(baseDir, event.Name)
|
||||
e.Logger.VerboseErrf(logger.Magenta, "task: skipped for file not in sources: %s\n", relPath)
|
||||
@@ -158,65 +165,36 @@ func closeOnInterrupt(w *fsnotify.Watcher) {
|
||||
}
|
||||
|
||||
func (e *Executor) registerWatchedDirs(w *fsnotify.Watcher, calls ...*Call) error {
|
||||
var registerTaskDirs func(*Call) error
|
||||
registerTaskDirs = func(c *Call) error {
|
||||
task, err := e.CompiledTask(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, d := range task.Deps {
|
||||
if err := registerTaskDirs(&Call{Task: d.Task, Vars: d.Vars}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, c := range task.Cmds {
|
||||
if c.Task != "" {
|
||||
if err := registerTaskDirs(&Call{Task: c.Task, Vars: c.Vars}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
files, err := fingerprint.Globs(task.Dir, task.Sources)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
d := filepath.Dir(f)
|
||||
if isSet, ok := e.watchedDirs.Load(d); ok && isSet {
|
||||
continue
|
||||
}
|
||||
if ShouldIgnoreFile(d) {
|
||||
continue
|
||||
}
|
||||
if err := w.Add(d); err != nil {
|
||||
return err
|
||||
}
|
||||
e.watchedDirs.Store(d, true)
|
||||
relPath, _ := filepath.Rel(e.Dir, d)
|
||||
w.Events <- fsnotify.Event{Name: f, Op: fsnotify.Create}
|
||||
e.Logger.VerboseOutf(logger.Green, "task: watching new dir: %v\n", relPath)
|
||||
}
|
||||
return nil
|
||||
files, err := e.collectSources(calls)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, c := range calls {
|
||||
if err := registerTaskDirs(c); err != nil {
|
||||
for _, f := range files {
|
||||
d := filepath.Dir(f)
|
||||
if isSet, ok := e.watchedDirs.Load(d); ok && isSet {
|
||||
continue
|
||||
}
|
||||
if ShouldIgnore(d) {
|
||||
continue
|
||||
}
|
||||
if err := w.Add(d); err != nil {
|
||||
return err
|
||||
}
|
||||
e.watchedDirs.Store(d, true)
|
||||
relPath, _ := filepath.Rel(e.Dir, d)
|
||||
e.Logger.VerboseOutf(logger.Green, "task: watching new dir: %v\n", relPath)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ShouldIgnoreFile(path string) bool {
|
||||
ignorePaths := []string{
|
||||
"/.task",
|
||||
"/.git",
|
||||
"/.hg",
|
||||
"/node_modules",
|
||||
}
|
||||
var ignorePaths = []string{
|
||||
"/.task",
|
||||
"/.git",
|
||||
"/.hg",
|
||||
"/node_modules",
|
||||
}
|
||||
|
||||
func ShouldIgnore(path string) bool {
|
||||
for _, p := range ignorePaths {
|
||||
if strings.Contains(path, fmt.Sprintf("%s/", p)) || strings.HasSuffix(path, p) {
|
||||
return true
|
||||
@@ -224,3 +202,47 @@ func ShouldIgnoreFile(path string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *Executor) collectSources(calls []*Call) ([]string, error) {
|
||||
var sources []string
|
||||
|
||||
err := e.traverse(calls, func(task *ast.Task) error {
|
||||
files, err := fingerprint.Globs(task.Dir, task.Sources)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sources = append(sources, files...)
|
||||
return nil
|
||||
})
|
||||
|
||||
return slicesext.UniqueJoin(sources), err
|
||||
}
|
||||
|
||||
type traverseFunc func(*ast.Task) error
|
||||
|
||||
func (e *Executor) traverse(calls []*Call, yield traverseFunc) error {
|
||||
for _, c := range calls {
|
||||
task, err := e.CompiledTask(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, dep := range task.Deps {
|
||||
if dep.Task != "" {
|
||||
if err := e.traverse([]*Call{{Task: dep.Task, Vars: dep.Vars}}, yield); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, cmd := range task.Cmds {
|
||||
if cmd.Task != "" {
|
||||
if err := e.traverse([]*Call{{Task: cmd.Task, Vars: cmd.Vars}}, yield); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := yield(task); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -31,16 +31,17 @@ task: Started watching for tasks: default
|
||||
task: [default] echo "Task running!"
|
||||
Task running!
|
||||
task: task "default" finished running
|
||||
task: Task "default" is up to date
|
||||
task: [default] echo "Task running!"
|
||||
Task running!
|
||||
task: task "default" finished running
|
||||
`)
|
||||
|
||||
var buff bytes.Buffer
|
||||
e := task.NewExecutor(
|
||||
task.ExecutorWithDir(dir),
|
||||
task.ExecutorWithStdout(&buff),
|
||||
task.ExecutorWithStderr(&buff),
|
||||
task.ExecutorWithWatch(true),
|
||||
task.WithDir(dir),
|
||||
task.WithStdout(&buff),
|
||||
task.WithStderr(&buff),
|
||||
task.WithWatch(true),
|
||||
)
|
||||
|
||||
require.NoError(t, e.Setup())
|
||||
@@ -71,16 +72,16 @@ task: task "default" finished running
|
||||
}
|
||||
}()
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
err = os.WriteFile(filePath, []byte("test updated"), 0o644)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
cancel()
|
||||
assert.Equal(t, expectedOutput, strings.TrimSpace(buff.String()))
|
||||
}
|
||||
|
||||
func TestShouldIgnoreFile(t *testing.T) {
|
||||
func TestShouldIgnore(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tt := []struct {
|
||||
@@ -95,7 +96,7 @@ func TestShouldIgnoreFile(t *testing.T) {
|
||||
ct := ct
|
||||
t.Run(fmt.Sprintf("ignore - %d", k), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
require.Equal(t, task.ShouldIgnoreFile(ct.path), ct.expect)
|
||||
require.Equal(t, task.ShouldIgnore(ct.path), ct.expect)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user