go/packages: remove named query

I removed the usage of this from goimports.

Change-Id: If10a5d6265e412e77f7b0a2671ee2106ee4abbf6
Reviewed-on: https://go-review.googlesource.com/c/tools/+/215937
Run-TryBot: Heschi Kreinick <heschi@google.com>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
Heschi Kreinick 2020-01-22 14:18:31 -05:00
parent 0a06c69952
commit 7b0c362a2f
23 changed files with 0 additions and 440 deletions

View File

@ -9,14 +9,12 @@ import (
"encoding/json"
"fmt"
"go/types"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"reflect"
"regexp"
"strconv"
"strings"
"sync"
@ -24,8 +22,6 @@ import (
"unicode"
"golang.org/x/tools/go/internal/packagesdriver"
"golang.org/x/tools/internal/gopathwalk"
"golang.org/x/tools/internal/semver"
)
// debug controls verbose logging.
@ -139,7 +135,6 @@ func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
// Determine files requested in contains patterns
var containFiles []string
var packagesNamed []string
restPatterns := make([]string, 0, len(patterns))
// Extract file= and other [querytype]= patterns. Report an error if querytype
// doesn't exist.
@ -155,8 +150,6 @@ extractQueries:
containFiles = append(containFiles, value)
case "pattern":
restPatterns = append(restPatterns, value)
case "iamashamedtousethedisabledqueryname":
packagesNamed = append(packagesNamed, value)
case "": // not a reserved query
restPatterns = append(restPatterns, pattern)
default:
@ -203,12 +196,6 @@ extractQueries:
}
}
if len(packagesNamed) != 0 {
if err := runNamedQueries(cfg, golistDriver, response, packagesNamed); err != nil {
return nil, err
}
}
modifiedPkgs, needPkgs, err := processGolistOverlay(cfg, response, getGoInfo)
if err != nil {
return nil, err
@ -342,278 +329,10 @@ func runContainsQueries(cfg *Config, driver driver, response *responseDeduper, q
return nil
}
// modCacheRegexp splits a path in a module cache into module, module version, and package.
var modCacheRegexp = regexp.MustCompile(`(.*)@([^/\\]*)(.*)`)
func runNamedQueries(cfg *Config, driver driver, response *responseDeduper, queries []string) error {
// calling `go env` isn't free; bail out if there's nothing to do.
if len(queries) == 0 {
return nil
}
// Determine which directories are relevant to scan.
roots, modRoot, err := roots(cfg)
if err != nil {
return err
}
// Scan the selected directories. Simple matches, from GOPATH/GOROOT
// or the local module, can simply be "go list"ed. Matches from the
// module cache need special treatment.
var matchesMu sync.Mutex
var simpleMatches, modCacheMatches []string
add := func(root gopathwalk.Root, dir string) {
// Walk calls this concurrently; protect the result slices.
matchesMu.Lock()
defer matchesMu.Unlock()
path := dir
if dir != root.Path {
path = dir[len(root.Path)+1:]
}
if pathMatchesQueries(path, queries) {
switch root.Type {
case gopathwalk.RootModuleCache:
modCacheMatches = append(modCacheMatches, path)
case gopathwalk.RootCurrentModule:
// We'd need to read go.mod to find the full
// import path. Relative's easier.
rel, err := filepath.Rel(cfg.Dir, dir)
if err != nil {
// This ought to be impossible, since
// we found dir in the current module.
panic(err)
}
simpleMatches = append(simpleMatches, "./"+rel)
case gopathwalk.RootGOPATH, gopathwalk.RootGOROOT:
simpleMatches = append(simpleMatches, path)
}
}
}
startWalk := time.Now()
gopathwalk.Walk(roots, add, gopathwalk.Options{ModulesEnabled: modRoot != "", Debug: debug})
cfg.Logf("%v for walk", time.Since(startWalk))
// Weird special case: the top-level package in a module will be in
// whatever directory the user checked the repository out into. It's
// more reasonable for that to not match the package name. So, if there
// are any Go files in the mod root, query it just to be safe.
if modRoot != "" {
rel, err := filepath.Rel(cfg.Dir, modRoot)
if err != nil {
panic(err) // See above.
}
files, err := ioutil.ReadDir(modRoot)
if err != nil {
panic(err) // See above.
}
for _, f := range files {
if strings.HasSuffix(f.Name(), ".go") {
simpleMatches = append(simpleMatches, rel)
break
}
}
}
addResponse := func(r *driverResponse) {
for _, pkg := range r.Packages {
response.addPackage(pkg)
for _, name := range queries {
if pkg.Name == name {
response.addRoot(pkg.ID)
break
}
}
}
}
if len(simpleMatches) != 0 {
resp, err := driver(cfg, simpleMatches...)
if err != nil {
return err
}
addResponse(resp)
}
// Module cache matches are tricky. We want to avoid downloading new
// versions of things, so we need to use the ones present in the cache.
// go list doesn't accept version specifiers, so we have to write out a
// temporary module, and do the list in that module.
if len(modCacheMatches) != 0 {
// Collect all the matches, deduplicating by major version
// and preferring the newest.
type modInfo struct {
mod string
major string
}
mods := make(map[modInfo]string)
var imports []string
for _, modPath := range modCacheMatches {
matches := modCacheRegexp.FindStringSubmatch(modPath)
mod, ver := filepath.ToSlash(matches[1]), matches[2]
importPath := filepath.ToSlash(filepath.Join(matches[1], matches[3]))
major := semver.Major(ver)
if prevVer, ok := mods[modInfo{mod, major}]; !ok || semver.Compare(ver, prevVer) > 0 {
mods[modInfo{mod, major}] = ver
}
imports = append(imports, importPath)
}
// Build the temporary module.
var gomod bytes.Buffer
gomod.WriteString("module modquery\nrequire (\n")
for mod, version := range mods {
gomod.WriteString("\t" + mod.mod + " " + version + "\n")
}
gomod.WriteString(")\n")
tmpCfg := *cfg
// We're only trying to look at stuff in the module cache, so
// disable the network. This should speed things up, and has
// prevented errors in at least one case, #28518.
tmpCfg.Env = append([]string{"GOPROXY=off"}, cfg.Env...)
var err error
tmpCfg.Dir, err = ioutil.TempDir("", "gopackages-modquery")
if err != nil {
return err
}
defer os.RemoveAll(tmpCfg.Dir)
if err := ioutil.WriteFile(filepath.Join(tmpCfg.Dir, "go.mod"), gomod.Bytes(), 0777); err != nil {
return fmt.Errorf("writing go.mod for module cache query: %v", err)
}
// Run the query, using the import paths calculated from the matches above.
resp, err := driver(&tmpCfg, imports...)
if err != nil {
return fmt.Errorf("querying module cache matches: %v", err)
}
addResponse(resp)
}
return nil
}
func getSizes(cfg *Config) (types.Sizes, error) {
return packagesdriver.GetSizesGolist(cfg.Context, cfg.BuildFlags, cfg.Env, cfg.Dir, usesExportData(cfg))
}
// roots selects the appropriate paths to walk based on the passed-in configuration,
// particularly the environment and the presence of a go.mod in cfg.Dir's parents.
func roots(cfg *Config) ([]gopathwalk.Root, string, error) {
stdout, err := invokeGo(cfg, "env", "GOROOT", "GOPATH", "GOMOD")
if err != nil {
return nil, "", err
}
fields := strings.Split(stdout.String(), "\n")
if len(fields) != 4 || len(fields[3]) != 0 {
return nil, "", fmt.Errorf("go env returned unexpected output: %q", stdout.String())
}
goroot, gopath, gomod := fields[0], filepath.SplitList(fields[1]), fields[2]
var modDir string
if gomod != "" {
modDir = filepath.Dir(gomod)
}
var roots []gopathwalk.Root
// Always add GOROOT.
roots = append(roots, gopathwalk.Root{
Path: filepath.Join(goroot, "/src"),
Type: gopathwalk.RootGOROOT,
})
// If modules are enabled, scan the module dir.
if modDir != "" {
roots = append(roots, gopathwalk.Root{
Path: modDir,
Type: gopathwalk.RootCurrentModule,
})
}
// Add either GOPATH/src or GOPATH/pkg/mod, depending on module mode.
for _, p := range gopath {
if modDir != "" {
roots = append(roots, gopathwalk.Root{
Path: filepath.Join(p, "/pkg/mod"),
Type: gopathwalk.RootModuleCache,
})
} else {
roots = append(roots, gopathwalk.Root{
Path: filepath.Join(p, "/src"),
Type: gopathwalk.RootGOPATH,
})
}
}
return roots, modDir, nil
}
// These functions were copied from goimports. See further documentation there.
// pathMatchesQueries is adapted from pkgIsCandidate.
// TODO: is it reasonable to do Contains here, rather than an exact match on a path component?
func pathMatchesQueries(path string, queries []string) bool {
lastTwo := lastTwoComponents(path)
for _, query := range queries {
if strings.Contains(lastTwo, query) {
return true
}
if hasHyphenOrUpperASCII(lastTwo) && !hasHyphenOrUpperASCII(query) {
lastTwo = lowerASCIIAndRemoveHyphen(lastTwo)
if strings.Contains(lastTwo, query) {
return true
}
}
}
return false
}
// lastTwoComponents returns at most the last two path components
// of v, using either / or \ as the path separator.
func lastTwoComponents(v string) string {
nslash := 0
for i := len(v) - 1; i >= 0; i-- {
if v[i] == '/' || v[i] == '\\' {
nslash++
if nslash == 2 {
return v[i:]
}
}
}
return v
}
func hasHyphenOrUpperASCII(s string) bool {
for i := 0; i < len(s); i++ {
b := s[i]
if b == '-' || ('A' <= b && b <= 'Z') {
return true
}
}
return false
}
func lowerASCIIAndRemoveHyphen(s string) (ret string) {
buf := make([]byte, 0, len(s))
for i := 0; i < len(s); i++ {
b := s[i]
switch {
case b == '-':
continue
case 'A' <= b && b <= 'Z':
buf = append(buf, b+('a'-'A'))
default:
buf = append(buf, b)
}
}
return string(buf)
}
// Fields must match go list;
// see $GOROOT/src/cmd/go/internal/load/pkg.go.
type jsonPackage struct {

View File

@ -1595,138 +1595,6 @@ func testContainsFallbackSticks(t *testing.T, exporter packagestest.Exporter) {
}
}
func TestName(t *testing.T) { packagestest.TestAll(t, testName) }
func testName(t *testing.T, exporter packagestest.Exporter) {
exported := packagestest.Export(t, exporter, []packagestest.Module{{
Name: "golang.org/fake",
Files: map[string]interface{}{
"a/needle/needle.go": `package needle; import "golang.org/fake/c"`,
"b/needle/needle.go": `package needle;`,
"c/c.go": `package c;`,
"irrelevant/irrelevant.go": `package irrelevant;`,
}}})
defer exported.Cleanup()
exported.Config.Mode = packages.LoadImports
initial, err := packages.Load(exported.Config, "iamashamedtousethedisabledqueryname=needle")
if err != nil {
t.Fatal(err)
}
graph, _ := importGraph(initial)
wantGraph := `
* golang.org/fake/a/needle
* golang.org/fake/b/needle
golang.org/fake/c
golang.org/fake/a/needle -> golang.org/fake/c
`[1:]
if graph != wantGraph {
t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
}
}
func TestName_Modules(t *testing.T) {
// Test the top-level package case described in runNamedQueries.
exported := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
{
Name: "golang.org/pkg",
Files: map[string]interface{}{
"pkg.go": `package pkg`,
},
},
{
Name: "example.com/tools-testrepo",
Files: map[string]interface{}{
"pkg/pkg.go": `package pkg`,
},
},
{
Name: "example.com/tools-testrepo/v2",
Files: map[string]interface{}{
"pkg/pkg.go": `package pkg`,
},
},
})
defer exported.Cleanup()
exported.Config.Mode = packages.LoadImports
initial, err := packages.Load(exported.Config, "iamashamedtousethedisabledqueryname=pkg")
if err != nil {
t.Fatal(err)
}
graph, _ := importGraph(initial)
wantGraph := `
* example.com/tools-testrepo/pkg
* example.com/tools-testrepo/v2/pkg
* golang.org/pkg
`[1:]
if graph != wantGraph {
t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
}
}
func TestName_ModulesDedup(t *testing.T) {
exported := packagestest.Export(t, packagestest.Modules, []packagestest.Module{{
Name: "golang.org/fake",
Files: map[string]interface{}{
"fake.go": `package fake`,
}}})
defer exported.Cleanup()
wd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
gopath, err := ioutil.TempDir("", "TestName_ModulesDedup")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(gopath)
if err := copyAll(filepath.Join(wd, "testdata", "TestName_ModulesDedup"), gopath); err != nil {
t.Fatal(err)
}
// testdata/TestNamed_ModulesDedup contains:
// - pkg/mod/github.com/heschik/tools-testrepo/v2@v2.0.2/pkg/pkg.go
// - pkg/mod/github.com/heschik/tools-testrepo/v2@v2.0.1/pkg/pkg.go
// - pkg/mod/github.com/heschik/tools-testrepo@v1.0.0/pkg/pkg.go
// but, inexplicably, not v2.0.0. Nobody knows why.
exported.Config.Mode = packages.LoadImports
exported.Config.Env = append(exported.Config.Env, "GOPATH="+gopath)
initial, err := packages.Load(exported.Config, "iamashamedtousethedisabledqueryname=pkg")
if err != nil {
t.Fatal(err)
}
for _, pkg := range initial {
if strings.Contains(pkg.PkgPath, "v2") {
if strings.Contains(pkg.GoFiles[0], "v2.0.2") {
return
}
}
}
t.Errorf("didn't find v2.0.2 of pkg in Load results: %v", initial)
}
// Test that Load doesn't get confused when two different patterns match the same package. See #29297.
func TestRedundantQueries(t *testing.T) { packagestest.TestAll(t, testRedundantQueries) }
func testRedundantQueries(t *testing.T, exporter packagestest.Exporter) {
exported := packagestest.Export(t, exporter, []packagestest.Module{{
Name: "golang.org/fake",
Files: map[string]interface{}{
"a/a.go": `package a;`,
}}})
defer exported.Cleanup()
cfg := *exported.Config
cfg.Tests = false
initial, err := packages.Load(&cfg, "errors", "iamashamedtousethedisabledqueryname=errors")
if err != nil {
t.Fatal(err)
}
if len(initial) != 1 || initial[0].Name != "errors" {
t.Fatalf(`Load("errors", "iamashamedtousethedisabledqueryname=errors") = %v, wanted just the errors package`, initial)
}
}
// Test that Load with no patterns is equivalent to loading "." via the golist
// driver.
func TestNoPatterns(t *testing.T) { packagestest.TestAll(t, testNoPatterns) }

View File

@ -1,3 +0,0 @@
Test data directories here were created by running go commands with GOPATH set as such:
GOPATH=......./testdata/TestNamed_ModulesDedup go get github.com/heschik/tools-testrepo/v2@v2.0.1
and then removing the vcs cache directories, which appear to be unnecessary.

View File

@ -1 +0,0 @@
{"Version":"v1.0.0","Time":"2018-09-28T22:09:08Z"}

View File

@ -1 +0,0 @@
module github.com/heschik/tools-testrepo

View File

@ -1 +0,0 @@
h1:D2qc+R2eCTCyoT8WAYoExXhPBThJWmlYSfB4coWbfBE=

View File

@ -1 +0,0 @@
{"Version":"v2.0.1","Time":"2018-09-28T22:12:08Z"}

View File

@ -1 +0,0 @@
module github.com/heschik/tools-testrepo/v2

View File

@ -1 +0,0 @@
h1:efPBVdJ45IMcA/KXBOWyOZLo1TETKCXvzrZgfY+gqZk=

View File

@ -1 +0,0 @@
{"Version":"v2.0.2","Time":"2018-09-28T22:12:08Z"}

View File

@ -1 +0,0 @@
module github.com/heschik/tools-testrepo/v2

View File

@ -1 +0,0 @@
h1:vUnR/JOkfEQt/wvMqbT9G2gODHVgVD1saTJ8x2ngAck=

View File

@ -1,3 +0,0 @@
module github.com/heschik/tools-testrepo/v2
go 1.12

View File

@ -1,3 +0,0 @@
module github.com/heschik/tools-testrepo/v2
go 1.12

View File

@ -1,3 +0,0 @@
module github.com/heschik/tools-testrepo
go 1.12