From b03bcc9c558080949597bb49e5bd749ccfaa604e Mon Sep 17 00:00:00 2001 From: hgouchet Date: Sat, 29 Sep 2018 12:28:54 +0200 Subject: [PATCH] deals with go modules and sub-packages --- builder_go110.go | 67 +++++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/builder_go110.go b/builder_go110.go index 29bbbab..fbd8af3 100644 --- a/builder_go110.go +++ b/builder_go110.go @@ -4,6 +4,7 @@ package godog import ( "bytes" + "encoding/json" "fmt" "go/build" "go/parser" @@ -303,45 +304,68 @@ func makeImportValid(r rune) rune { // it scans test files for contexts // and produces a testmain source code. func buildTestMain(pkg *build.Package) ([]byte, bool, error) { - var contexts []string - var importPath string - name := "main" + var ( + contexts []string + err error + name, importPath string + ) if nil != pkg { - ctxs, err := processPackageTestFiles( + contexts, err = processPackageTestFiles( pkg.TestGoFiles, pkg.XTestGoFiles, ) if err != nil { return nil, false, err } - contexts = ctxs - - // 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)) - } + importPath = parseImport(pkg.ImportPath) name = pkg.Name + } else { + name = "main" } - data := struct { Name string Contexts []string ImportPath string - }{name, contexts, importPath} - + }{ + Name: name, + Contexts: contexts, + ImportPath: importPath, + } 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 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 // file pack and looks for godog suite contexts to register // 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 { continue // only interested in vendor packages } - if _, ok := visited[name]; ok { continue } - next, err := locatePackage(name) if err != nil { return err } - visited[name] = pkg.PkgObj if err := dependencies(next, visited, vendor); err != nil { return err