From cdd0de15cffeb2b32b8768194fed50235a345698 Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Fri, 28 May 2021 15:06:35 -0400 Subject: [PATCH] Add 'l' action for watch mode --- README.md | 7 ++++-- internal/filewatcher/term_unix.go | 3 +++ internal/filewatcher/watch.go | 36 +++++++++++++++++++++++-------- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index cc52fe3c..f7ffe4c4 100644 --- a/README.md +++ b/README.md @@ -309,8 +309,8 @@ When the `--watch` flag is set, `gotestsum` will watch directories using [file system notifications](https://pkg.go.dev/github.com/fsnotify/fsnotify). When a Go file in one of those directories is modified, `gotestsum` will run the tests for the package which contains the changed file. By default all -directories under the current directory will be watched. Use the `--packages` flag -to specify a different list. +directories with at least one file with a `.go` extension, under the current +directory will be watched. Use the `--packages` flag to specify a different list. While in watch mode, pressing some keys will perform an action: @@ -321,6 +321,9 @@ While in watch mode, pressing some keys will perform an action: breakpoints can be added with [`runtime.Breakpoint`](https://golang.org/pkg/runtime/#Breakpoint) or by using the delve command prompt. * `a` will run tests for all packages, by using `./...` as the package selector. +* `l` will scan the directory list again, and if there are any new directories + which contain a file with a `.go` extension, they will be added to the watch + list. Note that [delve] must be installed in order to use debug (`d`). diff --git a/internal/filewatcher/term_unix.go b/internal/filewatcher/term_unix.go index 303d6bcc..c9e2e76f 100644 --- a/internal/filewatcher/term_unix.go +++ b/internal/filewatcher/term_unix.go @@ -83,6 +83,9 @@ func (r *redoHandler) Run(ctx context.Context) { case 'a': chResume = make(chan struct{}) r.ch <- RunOptions{resume: chResume, PkgPath: "./..."} + case 'l': + chResume = make(chan struct{}) + r.ch <- RunOptions{resume: chResume, reloadPaths: true} case '\n': fmt.Println() continue diff --git a/internal/filewatcher/watch.go b/internal/filewatcher/watch.go index e80c4e5d..9db8b118 100644 --- a/internal/filewatcher/watch.go +++ b/internal/filewatcher/watch.go @@ -16,27 +16,26 @@ import ( const maxDepth = 7 type RunOptions struct { - PkgPath string - Debug bool - resume chan struct{} + PkgPath string + Debug bool + resume chan struct{} + reloadPaths bool } +// Watch dirs for filesystem events, and run tests when .go files are saved. +// nolint: gocyclo func Watch(dirs []string, run func(opts RunOptions) error) error { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - toWatch := findAllDirs(dirs, maxDepth) watcher, err := fsnotify.NewWatcher() if err != nil { return fmt.Errorf("failed to create file watcher: %w", err) } defer watcher.Close() // nolint: errcheck // always returns nil error - fmt.Printf("Watching %v directories. Use Ctrl-c to to stop a run or exit.\n", len(toWatch)) - for _, dir := range toWatch { - if err = watcher.Add(dir); err != nil { - return fmt.Errorf("failed to watch directory %v: %w", dir, err) - } + if err := loadPaths(watcher, dirs); err != nil { + return err } timer := time.NewTimer(maxIdleTime) @@ -55,6 +54,14 @@ func Watch(dirs []string, run func(opts RunOptions) error) error { case opts := <-redo.Ch(): resetTimer(timer) + if opts.reloadPaths { + if err := loadPaths(watcher, dirs); err != nil { + return err + } + close(opts.resume) + continue + } + redo.ResetTerm() if err := h.runTests(opts); err != nil { return fmt.Errorf("failed to rerun tests for %v: %v", opts.PkgPath, err) @@ -89,6 +96,17 @@ func resetTimer(timer *time.Timer) { timer.Reset(maxIdleTime) } +func loadPaths(watcher *fsnotify.Watcher, dirs []string) error { + toWatch := findAllDirs(dirs, maxDepth) + fmt.Printf("Watching %v directories. Use Ctrl-c to to stop a run or exit.\n", len(toWatch)) + for _, dir := range toWatch { + if err := watcher.Add(dir); err != nil { + return fmt.Errorf("failed to watch directory %v: %w", dir, err) + } + } + return nil +} + func findAllDirs(dirs []string, maxDepth int) []string { if len(dirs) == 0 { dirs = []string{"./..."}