Skip to content

Commit

Permalink
watch: Add support for debugging while watching
Browse files Browse the repository at this point in the history
  • Loading branch information
dnephin committed Nov 21, 2020
1 parent a6916e7 commit 3ab60fc
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 18 deletions.
26 changes: 26 additions & 0 deletions cmd/delve.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package cmd

import (
"os"
"os/exec"
)

type delveOpts struct {
pkgPath string
args []string
}

func runDelve(opts delveOpts) error {
pkg := opts.pkgPath
args := []string{"dlv", "test", "--wd", pkg}
args = append(args, "--output", "gotestsum-watch-debug.test")
args = append(args, pkg, "--")
args = append(args, opts.args...)

cmd := exec.Command(args[0], args[1:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

return cmd.Run()
}
14 changes: 12 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,20 @@ func Run(name string, args []string) error {

func runWatcher(opts *options) error {
fn := func(runOpts filewatcher.RunOptions) error {
if runOpts.Debug {
o := delveOpts{
pkgPath: runOpts.PkgPath,
args: opts.args,
}
if err := runDelve(o); !isExitCoder(err) {
return err
}
return nil
}

opts := *opts
opts.packages = []string{runOpts.PkgPath}
err := run(&opts)
if !isExitCoder(err) {
if err := run(&opts); !isExitCoder(err) {
return err
}
return nil
Expand Down
42 changes: 29 additions & 13 deletions internal/filewatcher/term_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,22 @@ type redoHandler struct {
}

func newRedoHandler() *redoHandler {
h := &redoHandler{ch: make(chan RunOptions)}
h.SetupTerm()
return h
}

func (r *redoHandler) SetupTerm() {
if r == nil {
return
}
fd := int(os.Stdin.Fd())
reset, err := enableNonBlockingRead(fd)
if err != nil {
log.Warnf("failed to put terminal (fd %d) into raw mode: %v", fd, err)
return nil
return
}
return &redoHandler{ch: make(chan RunOptions), reset: reset}
r.reset = reset
}

func enableNonBlockingRead(fd int) (func(), error) {
Expand Down Expand Up @@ -57,24 +66,32 @@ func (r *redoHandler) Run(ctx context.Context) {
}
in := bufio.NewReader(os.Stdin)
for {
if ctx.Err() != nil {
return
}

char, err := in.ReadByte()
if err != nil {
log.Warnf("failed to read input: %v", err)
return
}
log.Debugf("received byte %v (%v)", char, string(char))

var chResume chan struct{}
switch char {
case 'r':
r.ch <- RunOptions{PkgPath: r.prevPath}
chResume = make(chan struct{})
r.ch <- RunOptions{PkgPath: r.prevPath, resume: chResume}
case 'd':
r.ch <- RunOptions{PkgPath: r.prevPath, Debug: true}
chResume = make(chan struct{})
r.ch <- RunOptions{PkgPath: r.prevPath, Debug: true, resume: chResume}
case '\n':
fmt.Println()
continue
default:
continue
}

select {
case <-ctx.Done():
return
case <-chResume:
}
}
}
Expand All @@ -86,15 +103,14 @@ func (r *redoHandler) Ch() <-chan RunOptions {
return r.ch
}

func (r *redoHandler) Reset() {
if r != nil {
func (r *redoHandler) ResetTerm() {
if r != nil && r.reset != nil {
r.reset()
}
}

func (r *redoHandler) Save(path string) {
if r == nil {
return
if r != nil {
r.prevPath = path
}
r.prevPath = path
}
4 changes: 3 additions & 1 deletion internal/filewatcher/term_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ func (r *redoHandler) Ch() <-chan RunOptions {
return nil
}

func (r *redoHandler) Reset() {}
func (r *redoHandler) SetupTerm() {}

func (r *redoHandler) ResetTerm() {}

func (r *redoHandler) Save(_ string) {}
9 changes: 7 additions & 2 deletions internal/filewatcher/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const maxDepth = 7
type RunOptions struct {
PkgPath string
Debug bool
resume chan struct{}
}

func Watch(dirs []string, run func(opts RunOptions) error) error {
Expand All @@ -42,7 +43,7 @@ func Watch(dirs []string, run func(opts RunOptions) error) error {
defer timer.Stop()

redo := newRedoHandler()
defer redo.Reset()
defer redo.ResetTerm()
go redo.Run(ctx)

h := &handler{last: time.Now(), fn: run}
Expand All @@ -53,9 +54,13 @@ func Watch(dirs []string, run func(opts RunOptions) error) error {

case opts := <-redo.Ch():
resetTimer(timer)

redo.ResetTerm()
if err := h.runTests(opts); err != nil {
return fmt.Errorf("failed to rerun tests for %v: %v", opts.PkgPath, err)
}
redo.SetupTerm()
close(opts.resume)

case event := <-watcher.Events:
resetTimer(timer)
Expand Down Expand Up @@ -216,9 +221,9 @@ func (h *handler) handleEvent(event fsnotify.Event) error {
}

func (h *handler) runTests(opts RunOptions) error {
opts.PkgPath = "./" + filepath.Dir(opts.PkgPath)
fmt.Printf("\nRunning tests in %v\n", opts.PkgPath)

opts.PkgPath = "./" + filepath.Dir(opts.PkgPath)
if err := h.fn(opts); err != nil {
return err
}
Expand Down

0 comments on commit 3ab60fc

Please sign in to comment.