aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Matloob <matloob@golang.org>2022-05-03 13:17:08 -0400
committerMichael Matloob <matloob@golang.org>2022-06-06 19:32:49 +0000
commit11195c60e6197016c0d5d32b04d4cb0ca7594014 (patch)
tree4b7ab50aadc2ad6e665b34eb61f5458e5fbb1efb
parentea5d7cbc2644643331bd675b1ebdf0aaac7419f1 (diff)
downloadgo-11195c60e6197016c0d5d32b04d4cb0ca7594014.tar.gz
go-11195c60e6197016c0d5d32b04d4cb0ca7594014.zip
cmd/go: use index to match packages in dependency modules
If we're trying to search in a module in the module cache, instead iterate over the packages in the index. Change-Id: Ia94cbe6e9690110c28b93dbb33810680e3010381 Reviewed-on: https://go-review.googlesource.com/c/go/+/403756 Reviewed-by: Michael Matloob <matloob@golang.org> Reviewed-by: Peter Weinberger <pjw@google.com> Run-TryBot: Michael Matloob <matloob@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org>
-rw-r--r--src/cmd/go/internal/modindex/read.go2
-rw-r--r--src/cmd/go/internal/modindex/scan.go7
-rw-r--r--src/cmd/go/internal/modload/search.go63
3 files changed, 68 insertions, 4 deletions
diff --git a/src/cmd/go/internal/modindex/read.go b/src/cmd/go/internal/modindex/read.go
index 4f02ca5d10..f259a8dbe3 100644
--- a/src/cmd/go/internal/modindex/read.go
+++ b/src/cmd/go/internal/modindex/read.go
@@ -210,7 +210,7 @@ func (mi *ModuleIndex) Packages() []string {
// RelPath returns the path relative to the module's root.
func (mi *ModuleIndex) RelPath(path string) string {
- return filepath.Clean(str.TrimFilePathPrefix(path, mi.modroot))
+ return str.TrimFilePathPrefix(path, mi.modroot)
}
// ImportPackage is the equivalent of build.Import given the information in ModuleIndex.
diff --git a/src/cmd/go/internal/modindex/scan.go b/src/cmd/go/internal/modindex/scan.go
index e40d3e0f53..d1f73dbb53 100644
--- a/src/cmd/go/internal/modindex/scan.go
+++ b/src/cmd/go/internal/modindex/scan.go
@@ -4,6 +4,7 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/fsys"
"cmd/go/internal/par"
+ "cmd/go/internal/str"
"encoding/json"
"errors"
"fmt"
@@ -54,10 +55,10 @@ func indexModule(modroot string) ([]byte, error) {
if !info.IsDir() {
return nil
}
- rel, err := filepath.Rel(modroot, path)
- if err != nil {
- panic(err)
+ if !str.HasFilePathPrefix(path, modroot) {
+ panic(fmt.Errorf("path %v in walk doesn't have modroot %v as prefix:", path, modroot))
}
+ rel := str.TrimFilePathPrefix(path, modroot)
packages = append(packages, importRaw(modroot, rel))
return nil
})
diff --git a/src/cmd/go/internal/modload/search.go b/src/cmd/go/internal/modload/search.go
index cddb9f8067..60c68860ed 100644
--- a/src/cmd/go/internal/modload/search.go
+++ b/src/cmd/go/internal/modload/search.go
@@ -6,15 +6,18 @@ package modload
import (
"context"
+ "errors"
"fmt"
"io/fs"
"os"
+ "path"
"path/filepath"
"strings"
"cmd/go/internal/cfg"
"cmd/go/internal/fsys"
"cmd/go/internal/imports"
+ "cmd/go/internal/modindex"
"cmd/go/internal/search"
"golang.org/x/mod/module"
@@ -165,6 +168,12 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f
}
modPrefix = mod.Path
}
+ if mi, err := modindex.Get(root); err == nil {
+ walkFromIndex(ctx, m, tags, root, mi, have, modPrefix)
+ continue
+ } else if !errors.Is(err, modindex.ErrNotIndexed) {
+ m.AddError(err)
+ }
prune := pruneVendor
if isLocal {
@@ -176,6 +185,60 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f
return
}
+// walkFromIndex matches packages in a module using the module index. modroot
+// is the module's root directory on disk, index is the ModuleIndex for the
+// module, and importPathRoot is the module's path prefix.
+func walkFromIndex(ctx context.Context, m *search.Match, tags map[string]bool, modroot string, index *modindex.ModuleIndex, have map[string]bool, importPathRoot string) {
+ isMatch := func(string) bool { return true }
+ treeCanMatch := func(string) bool { return true }
+ if !m.IsMeta() {
+ isMatch = search.MatchPattern(m.Pattern())
+ treeCanMatch = search.TreeCanMatchPattern(m.Pattern())
+ }
+loopPackages:
+ for _, reldir := range index.Packages() {
+ // Avoid .foo, _foo, and testdata subdirectory trees.
+ p := reldir
+ for {
+ elem, rest, found := strings.Cut(p, string(filepath.Separator))
+ if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
+ continue loopPackages
+ }
+ if found && elem == "vendor" {
+ // Ignore this path if it contains the element "vendor" anywhere
+ // except for the last element (packages named vendor are allowed
+ // for historical reasons). Note that found is true when this
+ // isn't the last path element.
+ continue loopPackages
+ }
+ if !found {
+ // Didn't find the separator, so we're considering the last element.
+ break
+ }
+ p = rest
+ }
+
+ // Don't use GOROOT/src.
+ if reldir == "" && importPathRoot == "" {
+ continue
+ }
+
+ name := path.Join(importPathRoot, filepath.ToSlash(reldir))
+ if !treeCanMatch(name) {
+ continue
+ }
+
+ if !have[name] {
+ have[name] = true
+ if isMatch(name) {
+ if _, _, err := index.ScanDir(reldir, tags); err != imports.ErrNoGo {
+ m.Pkgs = append(m.Pkgs, name)
+ }
+ }
+ }
+ }
+}
+
// MatchInModule identifies the packages matching the given pattern within the
// given module version, which does not need to be in the build list or module
// requirement graph.