mirror of
https://github.com/golang/go
synced 2024-11-18 18:54:42 -07:00
go/packages: allow absolute paths when using the fallback
Another change to bring the go1.10 fallback's functionality in line with the go1.11 go list implementation. The fallback now uses go env to determine GOPATH and GOROOT and searches them to see if any match an absolute path, and if so trims the GOPATH/GOROOT entry off the start of the path. Fixes golang/go#27734 Change-Id: Ibd2313fc4301d42fd8c0cd98f1f3e7a313d65eb7 Reviewed-on: https://go-review.googlesource.com/137096 Run-TryBot: Michael Matloob <matloob@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com>
This commit is contained in:
parent
51aacb1402
commit
16720d5f2d
@ -10,6 +10,7 @@ import (
|
||||
"go/build"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
@ -27,6 +28,12 @@ import (
|
||||
// in Q1 2019.
|
||||
|
||||
func golistDriverFallback(cfg *Config, words ...string) (*driverResponse, error) {
|
||||
// Turn absolute paths into GOROOT and GOPATH-relative paths to provide to go list.
|
||||
// This will have surprising behavior if GOROOT or GOPATH contain multiple packages with the same
|
||||
// path and a user provides an absolute path to a directory that's shadowed by an earlier
|
||||
// directory in GOROOT or GOPATH with the same package path.
|
||||
words = cleanAbsPaths(cfg, words)
|
||||
|
||||
original, deps, err := getDeps(cfg, words...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -283,6 +290,47 @@ func createTestVariants(response *driverResponse, pkgUnderTest, xtestPkg *Packag
|
||||
}
|
||||
}
|
||||
|
||||
// cleanAbsPaths replaces all absolute paths with GOPATH- and GOROOT-relative
|
||||
// paths. If an absolute path is not GOPATH- or GOROOT- relative, it is left as an
|
||||
// absolute path so an error can be returned later.
|
||||
func cleanAbsPaths(cfg *Config, words []string) []string {
|
||||
var searchpaths []string
|
||||
var cleaned = make([]string, len(words))
|
||||
for i := range cleaned {
|
||||
cleaned[i] = words[i]
|
||||
if !filepath.IsAbs(cleaned[i]) {
|
||||
continue
|
||||
}
|
||||
// otherwise, it's an absolute path. Search GOPATH and GOROOT to find it.
|
||||
if searchpaths == nil {
|
||||
cmd := exec.Command("go", "env", "GOPATH", "GOROOT")
|
||||
cmd.Env = cfg.Env
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
searchpaths = []string{}
|
||||
continue // suppress the error, it will show up again when running go list
|
||||
}
|
||||
lines := strings.Split(string(out), "\n")
|
||||
if len(lines) != 3 || lines[0] == "" || lines[1] == "" || lines[2] != "" {
|
||||
continue // suppress error
|
||||
}
|
||||
// first line is GOPATH
|
||||
for _, path := range filepath.SplitList(lines[0]) {
|
||||
searchpaths = append(searchpaths, filepath.Join(path, "src"))
|
||||
}
|
||||
// second line is GOROOT
|
||||
searchpaths = append(searchpaths, filepath.Join(lines[1], "src"))
|
||||
}
|
||||
for _, sp := range searchpaths {
|
||||
if strings.HasPrefix(cleaned[i], sp) {
|
||||
cleaned[i] = strings.TrimPrefix(cleaned[i], sp)
|
||||
cleaned[i] = strings.TrimLeft(cleaned[i], string(filepath.Separator))
|
||||
}
|
||||
}
|
||||
}
|
||||
return cleaned
|
||||
}
|
||||
|
||||
// vendorlessPath returns the devendorized version of the import path ipath.
|
||||
// For example, VendorlessPath("foo/bar/vendor/a/b") returns "a/b".
|
||||
// Copied from golang.org/x/tools/imports/fix.go.
|
||||
|
@ -331,6 +331,33 @@ func TestLoadImportsC(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadAbsolutePath(t *testing.T) {
|
||||
tmp, cleanup := makeTree(t, map[string]string{
|
||||
"gopatha/src/a/a.go": `package a`,
|
||||
"gopathb/src/b/b.go": `package b`,
|
||||
})
|
||||
defer cleanup()
|
||||
|
||||
cfg := &packages.Config{
|
||||
Mode: packages.LoadImports,
|
||||
Env: append(os.Environ(),
|
||||
"GOPATH="+filepath.Join(tmp, "gopatha")+string(filepath.ListSeparator)+filepath.Join(tmp, "gopathb"),
|
||||
"GO111MODULE=off"),
|
||||
}
|
||||
initial, err := packages.Load(cfg, filepath.Join(tmp, "gopatha", "src", "a"), filepath.Join(tmp, "gopathb", "src", "b"))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load imports: %v", err)
|
||||
}
|
||||
|
||||
got := []string{}
|
||||
for _, p := range initial {
|
||||
got = append(got, p.ID)
|
||||
}
|
||||
if !reflect.DeepEqual(got, []string{"a", "b"}) {
|
||||
t.Fatalf("initial packages loaded: got [%s], want [a b]", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVendorImports(t *testing.T) {
|
||||
tmp, cleanup := makeTree(t, map[string]string{
|
||||
"src/a/a.go": `package a; import _ "b"; import _ "c";`,
|
||||
|
Loading…
Reference in New Issue
Block a user