mirror of
https://github.com/golang/go
synced 2024-11-23 18:00:06 -07:00
cmd/api: use 'go list' to locate transitive dependencies of std
With standard-library modules and vendoring, the mapping from import path to directory within the standard library is no longer entirely trivial. Fortunately, 'go list' makes that mapping straightforward to compute. Updates #30241 Updates #30228 Change-Id: Iddd77c21a527b7acdb30c17bec8b4bbd43e23756 Reviewed-on: https://go-review.googlesource.com/c/go/+/165497 Run-TryBot: Bryan C. Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Jay Conrod <jayconrod@google.com>
This commit is contained in:
parent
49662bc6b0
commit
361a01983f
@ -8,6 +8,7 @@ package main
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
@ -153,6 +154,7 @@ func main() {
|
||||
var featureCtx = make(map[string]map[string]bool) // feature -> context name -> true
|
||||
for _, context := range contexts {
|
||||
w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src"))
|
||||
w.loadImports(pkgNames, w.context)
|
||||
|
||||
for _, name := range pkgNames {
|
||||
// Vendored packages do not contribute to our
|
||||
@ -355,6 +357,8 @@ type Walker struct {
|
||||
current *types.Package
|
||||
features map[string]bool // set
|
||||
imported map[string]*types.Package // packages already imported
|
||||
importMap map[string]map[string]string // importer dir -> import path -> canonical path
|
||||
importDir map[string]string // canonical import path -> dir
|
||||
}
|
||||
|
||||
func NewWalker(context *build.Context, root string) *Walker {
|
||||
@ -434,11 +438,74 @@ func tagKey(dir string, context *build.Context, tags []string) string {
|
||||
return key
|
||||
}
|
||||
|
||||
func (w *Walker) loadImports(paths []string, context *build.Context) {
|
||||
if context == nil {
|
||||
context = &build.Default
|
||||
}
|
||||
|
||||
var (
|
||||
tags = context.BuildTags
|
||||
cgoEnabled = "0"
|
||||
)
|
||||
if context.CgoEnabled {
|
||||
tags = append(tags[:len(tags):len(tags)], "cgo")
|
||||
cgoEnabled = "1"
|
||||
}
|
||||
|
||||
// TODO(golang.org/issue/29666): Request only the fields that we need.
|
||||
cmd := exec.Command(goCmd(), "list", "-e", "-deps", "-json")
|
||||
if len(tags) > 0 {
|
||||
cmd.Args = append(cmd.Args, "-tags", strings.Join(tags, " "))
|
||||
}
|
||||
cmd.Args = append(cmd.Args, paths...)
|
||||
|
||||
cmd.Env = append(os.Environ(),
|
||||
"GOOS="+context.GOOS,
|
||||
"GOARCH="+context.GOARCH,
|
||||
"CGO_ENABLED="+cgoEnabled,
|
||||
)
|
||||
|
||||
stdout := new(bytes.Buffer)
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = new(strings.Builder)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Fatalf("%s failed: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr)
|
||||
}
|
||||
|
||||
w.importDir = make(map[string]string)
|
||||
w.importMap = make(map[string]map[string]string)
|
||||
dec := json.NewDecoder(stdout)
|
||||
for {
|
||||
var pkg struct {
|
||||
ImportPath, Dir string
|
||||
ImportMap map[string]string
|
||||
}
|
||||
if err := dec.Decode(&pkg); err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
log.Fatalf("%s: invalid output: %v", strings.Join(cmd.Args, " "), err)
|
||||
}
|
||||
|
||||
w.importDir[pkg.ImportPath] = pkg.Dir
|
||||
w.importMap[pkg.Dir] = pkg.ImportMap
|
||||
}
|
||||
}
|
||||
|
||||
// Importing is a sentinel taking the place in Walker.imported
|
||||
// for a package that is in the process of being imported.
|
||||
var importing types.Package
|
||||
|
||||
func (w *Walker) Import(name string) (*types.Package, error) {
|
||||
return w.ImportFrom(name, "", 0)
|
||||
}
|
||||
|
||||
func (w *Walker) ImportFrom(fromPath, fromDir string, mode types.ImportMode) (*types.Package, error) {
|
||||
name := fromPath
|
||||
if canonical, ok := w.importMap[fromDir][fromPath]; ok {
|
||||
name = canonical
|
||||
}
|
||||
|
||||
pkg := w.imported[name]
|
||||
if pkg != nil {
|
||||
if pkg == &importing {
|
||||
@ -449,7 +516,10 @@ func (w *Walker) Import(name string) (*types.Package, error) {
|
||||
w.imported[name] = &importing
|
||||
|
||||
// Determine package files.
|
||||
dir := filepath.Join(w.root, filepath.FromSlash(name))
|
||||
dir := w.importDir[name]
|
||||
if dir == "" {
|
||||
dir = filepath.Join(w.root, filepath.FromSlash(name))
|
||||
}
|
||||
if fi, err := os.Stat(dir); err != nil || !fi.IsDir() {
|
||||
log.Fatalf("no source in tree for import %q: %v", name, err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user