deals with go modules and sub-packages

Этот коммит содержится в:
hgouchet 2018-09-29 12:28:54 +02:00
родитель 6943e03b65
коммит b03bcc9c55

Просмотреть файл

@ -4,6 +4,7 @@ package godog
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"go/build" "go/build"
"go/parser" "go/parser"
@ -303,45 +304,68 @@ func makeImportValid(r rune) rune {
// it scans test files for contexts // it scans test files for contexts
// and produces a testmain source code. // and produces a testmain source code.
func buildTestMain(pkg *build.Package) ([]byte, bool, error) { func buildTestMain(pkg *build.Package) ([]byte, bool, error) {
var contexts []string var (
var importPath string contexts []string
name := "main" err error
name, importPath string
)
if nil != pkg { if nil != pkg {
ctxs, err := processPackageTestFiles( contexts, err = processPackageTestFiles(
pkg.TestGoFiles, pkg.TestGoFiles,
pkg.XTestGoFiles, pkg.XTestGoFiles,
) )
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }
contexts = ctxs importPath = parseImport(pkg.ImportPath)
// for module support, query the module import path
// @TODO: maybe there is a better way to read it
out, err := exec.Command("go", "list", "-m").CombinedOutput()
if err != nil {
// is not using modules or older go version
importPath = pkg.ImportPath
} else {
// otherwise read the module name from command output
importPath = strings.TrimSpace(string(out))
}
name = pkg.Name name = pkg.Name
} else {
name = "main"
} }
data := struct { data := struct {
Name string Name string
Contexts []string Contexts []string
ImportPath string ImportPath string
}{name, contexts, importPath} }{
Name: name,
Contexts: contexts,
ImportPath: importPath,
}
var buf bytes.Buffer var buf bytes.Buffer
if err := runnerTemplate.Execute(&buf, data); err != nil { if err = runnerTemplate.Execute(&buf, data); err != nil {
return nil, len(contexts) > 0, err return nil, len(contexts) > 0, err
} }
return buf.Bytes(), len(contexts) > 0, nil return buf.Bytes(), len(contexts) > 0, nil
} }
// parseImport parses the import path to deal with go module.
func parseImport(rawPath string) string {
// for module support, query the module import path
cmd := exec.Command("go", "list", "-m", "-json")
out, err := cmd.StdoutPipe()
if err != nil {
// Unable to read stdout
return rawPath
}
if cmd.Start() != nil {
// Does not using modules
return rawPath
}
var mod struct {
Dir string `json:"Dir"`
Path string `json:"Path"`
}
if json.NewDecoder(out).Decode(&mod) != nil {
// Unexpected result
return rawPath
}
if cmd.Wait() != nil {
return rawPath
}
// Concatenates the module path with the current sub-folders if needed
return mod.Path + filepath.ToSlash(strings.TrimPrefix(strings.TrimPrefix(rawPath, "_"), mod.Dir))
}
// processPackageTestFiles runs through ast of each test // processPackageTestFiles runs through ast of each test
// file pack and looks for godog suite contexts to register // file pack and looks for godog suite contexts to register
// on run // on run
@ -389,16 +413,13 @@ func dependencies(pkg *build.Package, visited map[string]string, vendor bool) er
if i := strings.LastIndex(name, "vendor/"); vendor && i == -1 { if i := strings.LastIndex(name, "vendor/"); vendor && i == -1 {
continue // only interested in vendor packages continue // only interested in vendor packages
} }
if _, ok := visited[name]; ok { if _, ok := visited[name]; ok {
continue continue
} }
next, err := locatePackage(name) next, err := locatePackage(name)
if err != nil { if err != nil {
return err return err
} }
visited[name] = pkg.PkgObj visited[name] = pkg.PkgObj
if err := dependencies(next, visited, vendor); err != nil { if err := dependencies(next, visited, vendor); err != nil {
return err return err