From 02a3129e1788d6ecbdfe474fffcd3a500f4aaa82 Mon Sep 17 00:00:00 2001 From: Oleg Butuzov Date: Sun, 15 Mar 2026 20:07:08 +0200 Subject: [PATCH 1/2] fix: Selective watching (#2715) Attempt of fixing selective watching, that become broken after switch to fsnotify. --- watch.go | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/watch.go b/watch.go index 8e7f7ccf7d..11e8e2987d 100644 --- a/watch.go +++ b/watch.go @@ -8,6 +8,7 @@ import ( "path/filepath" "slices" "strings" + "sync" "syscall" "time" @@ -69,6 +70,8 @@ func (e *Executor) watchTasks(calls ...*Call) error { closeOnInterrupt(w) go func() { + var mu sync.Mutex + for { select { case event, ok := <-eventsChan: @@ -76,24 +79,27 @@ func (e *Executor) watchTasks(calls ...*Call) error { cancel() return } - e.Logger.VerboseErrf(logger.Magenta, "task: received watch event: %v\n", event) - cancel() - ctx, cancel = context.WithCancel(context.Background()) - - e.Compiler.ResetCache() + e.Logger.VerboseErrf(logger.Magenta, "task: received watch event: %v\n", event) + var wg sync.WaitGroup + var okCalls = make([]*Call, 0, len(calls)) for _, c := range calls { - go func() { + wg.Add(1) + wg.Go(func() { + defer wg.Done() + 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 := e.collectSources(calls) if err != nil { @@ -106,14 +112,37 @@ func (e *Executor) watchTasks(calls ...*Call) error { e.Logger.VerboseErrf(logger.Magenta, "task: skipped for file not in sources: %s\n", relPath) return } + + mu.Lock() + okCalls = append(okCalls, c) + mu.Unlock() + }) + } + wg.Wait() + + if len(okCalls) == 0 { + e.Logger.VerboseErrf(logger.Magenta, "task: no valid calls, skipping execution\n") + continue + } + + cancel() + ctx, cancel = context.WithCancel(context.Background()) + e.Compiler.ResetCache() + + for _, c := range okCalls { + go func() { err = e.RunTask(ctx, c) if err == nil { e.Logger.Errf(logger.Green, "task: task \"%s\" finished running\n", c.Task) - } else if !isContextError(err) { + return + } + + if !isContextError(err) { e.Logger.Errf(logger.Red, "%v\n", err) } }() } + case err, ok := <-w.Errors: switch { case !ok: From cfb78dae23e3e73da91c15096a8c23b1e9a673ed Mon Sep 17 00:00:00 2001 From: Oleg Butuzov Date: Sun, 15 Mar 2026 20:19:49 +0200 Subject: [PATCH 2/2] fix: linter --- watch.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/watch.go b/watch.go index 11e8e2987d..e930dbe5e5 100644 --- a/watch.go +++ b/watch.go @@ -83,7 +83,7 @@ func (e *Executor) watchTasks(calls ...*Call) error { e.Logger.VerboseErrf(logger.Magenta, "task: received watch event: %v\n", event) var wg sync.WaitGroup - var okCalls = make([]*Call, 0, len(calls)) + okCalls := make([]*Call, 0, len(calls)) for _, c := range calls { wg.Add(1) wg.Go(func() {