diff --git a/cmd/watch.go b/cmd/watch.go index b0665a67..8b9737ee 100644 --- a/cmd/watch.go +++ b/cmd/watch.go @@ -40,8 +40,11 @@ func (w *watchRuns) run(event filewatcher.Event) error { return nil } - opts := w.opts - opts.packages = []string{event.PkgPath} + opts := w.opts // shallow copy opts + opts.packages = append([]string{}, opts.packages...) + opts.packages = append(opts.packages, event.PkgPath) + opts.packages = append(opts.packages, event.Args...) + var err error if w.prevExec, err = runSingle(&opts); !IsExitCoder(err) { return err diff --git a/internal/filewatcher/term_unix.go b/internal/filewatcher/term_unix.go index b0c41f0a..4b68a4f1 100644 --- a/internal/filewatcher/term_unix.go +++ b/internal/filewatcher/term_unix.go @@ -77,20 +77,18 @@ func (r *terminal) Monitor(ctx context.Context) { } log.Debugf("received byte %v (%v)", char, string(char)) - var chResume chan struct{} + chResume := make(chan struct{}) switch char { case 'r': - chResume = make(chan struct{}) - r.ch <- Event{resume: chResume} + r.ch <- Event{resume: chResume, useLastPath: true} case 'd': - chResume = make(chan struct{}) - r.ch <- Event{Debug: true, resume: chResume} + r.ch <- Event{resume: chResume, useLastPath: true, Debug: true} case 'a': - chResume = make(chan struct{}) r.ch <- Event{resume: chResume, PkgPath: "./..."} case 'l': - chResume = make(chan struct{}) r.ch <- Event{resume: chResume, reloadPaths: true} + case 'u': + r.ch <- Event{resume: chResume, useLastPath: true, Args: []string{"-update"}} case '\n': fmt.Println() continue diff --git a/internal/filewatcher/watch.go b/internal/filewatcher/watch.go index ce8be930..5e4ddc8d 100644 --- a/internal/filewatcher/watch.go +++ b/internal/filewatcher/watch.go @@ -19,10 +19,20 @@ import ( const maxDepth = 7 type Event struct { - PkgPath string - Debug bool - resume chan struct{} + // PkgPath of the package that triggered the event. + PkgPath string + // Args will be appended to the command line args for 'go test'. + Args []string + // Debug runs the tests with delve. + Debug bool + // resume the Watch goroutine when this channel is closed. Used to block + // the Watch goroutine while tests are running. + resume chan struct{} + // reloadPaths will cause the watched path list to be reloaded, to watch + // new directories. reloadPaths bool + // useLastPath when true will use the PkgPath from the previous run. + useLastPath bool } // Watch dirs for filesystem events, and run tests when .go files are saved. @@ -48,7 +58,7 @@ func Watch(dirs []string, run func(Event) error) error { defer term.Reset() go term.Monitor(ctx) - h := &handler{last: time.Now(), fn: run} + h := &fsEventHandler{last: time.Now(), fn: run} for { select { case <-timer.C: @@ -218,7 +228,7 @@ func handleDirCreated(watcher *fsnotify.Watcher, event fsnotify.Event) (handled return true } -type handler struct { +type fsEventHandler struct { last time.Time lastPath string fn func(opts Event) error @@ -226,7 +236,7 @@ type handler struct { const floodThreshold = 250 * time.Millisecond -func (h *handler) handleEvent(event fsnotify.Event) error { +func (h *fsEventHandler) handleEvent(event fsnotify.Event) error { if event.Op&(fsnotify.Write|fsnotify.Create) == 0 { return nil } @@ -242,8 +252,8 @@ func (h *handler) handleEvent(event fsnotify.Event) error { return h.runTests(Event{PkgPath: "./" + filepath.Dir(event.Name)}) } -func (h *handler) runTests(opts Event) error { - if opts.PkgPath == "" { +func (h *fsEventHandler) runTests(opts Event) error { + if opts.useLastPath { opts.PkgPath = h.lastPath } fmt.Printf("\nRunning tests in %v\n", opts.PkgPath) diff --git a/internal/filewatcher/watch_test.go b/internal/filewatcher/watch_test.go index f02f8a3e..18d918f8 100644 --- a/internal/filewatcher/watch_test.go +++ b/internal/filewatcher/watch_test.go @@ -27,7 +27,7 @@ func TestHandler_HandleEvent(t *testing.T) { return nil } - h := handler{last: tc.last, fn: run} + h := fsEventHandler{last: tc.last, fn: run} err := h.handleEvent(tc.event) assert.NilError(t, err) assert.Equal(t, ran, tc.expectedRun)