github.com/tilt-dev/wat@v0.0.2-0.20180626175338-9349b638e250/cli/wat/plugin_go.go (about) 1 package wat 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "fmt" 8 "os/exec" 9 "path/filepath" 10 11 "github.com/windmilleng/wat/os/ospath" 12 ) 13 14 type PluginGo struct{} 15 16 func (PluginGo) name() string { return "go populate" } 17 18 func (PluginGo) run(ctx context.Context, root string) ([]WatCommand, error) { 19 var result []WatCommand 20 21 goListEntries, err := goList(ctx, root) 22 if err != nil { 23 return nil, err 24 } 25 26 for _, e := range goListEntries { 27 cmd := e.toWatCommand(root) 28 if cmd.Empty() { 29 continue 30 } 31 result = append(result, cmd) 32 } 33 return result, nil 34 } 35 36 type goListEntry struct { 37 Dir string 38 ImportPath string 39 TestGoFiles []string 40 } 41 42 func (e goListEntry) toWatCommand(root string) WatCommand { 43 if len(e.TestGoFiles) == 0 { 44 return WatCommand{} 45 } 46 47 // We do not expect to have commands that reach outside 48 // the wat workspace, but if we do, skipping them for 49 // now seems like the right way to handle the error. 50 child, isUnderRoot := ospath.Child(root, e.Dir) 51 if !isUnderRoot { 52 return WatCommand{} 53 } 54 55 return WatCommand{ 56 Command: fmt.Sprintf("go test %s", e.ImportPath), 57 FilePattern: filepath.Join(child, "*"), 58 } 59 } 60 61 func goList(ctx context.Context, root string) ([]goListEntry, error) { 62 cmd := exec.CommandContext(ctx, "go", "list", "-json", "./...") 63 cmd.Dir = root 64 65 output, err := cmd.Output() 66 if err != nil { 67 exitErr, isExit := err.(*exec.ExitError) 68 if isExit { 69 return nil, fmt.Errorf("go list: %s (%q)", err.Error(), string(exitErr.Stderr)) 70 } 71 return nil, err 72 } 73 74 decoder := json.NewDecoder(bytes.NewBuffer(output)) 75 var result []goListEntry 76 for decoder.More() { 77 var entry goListEntry 78 err = decoder.Decode(&entry) 79 if err != nil { 80 return nil, err 81 } 82 result = append(result, entry) 83 } 84 85 return result, nil 86 } 87 88 var _ plugin = PluginGo{}