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{}