aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/go/internal/modload/build.go
diff options
context:
space:
mode:
authorBryan C. Mills <bcmills@google.com>2021-03-03 10:27:19 -0500
committerBryan C. Mills <bcmills@google.com>2021-03-25 03:17:36 +0000
commit954879d6d19175a5f0066c0ac0df0edda7f731b3 (patch)
tree891e4d63c5fa5cd41bbb957d6030d4e910105151 /src/cmd/go/internal/modload/build.go
parenta95e2ae2804becdda6c265c6d589ae8184a34160 (diff)
downloadgo-954879d6d19175a5f0066c0ac0df0edda7f731b3.tar.gz
go-954879d6d19175a5f0066c0ac0df0edda7f731b3.zip
cmd/go/internal/modload: replace the global buildList with structured requirements
This is intended to be a pure-refactoring change, with very little observable change in the behavior of the 'go' command. A few error messages have prefixes changed (by virtue of being attached to packages or modules instead of the build list overall), and 'go list -m' (without arguments) no longer loads the complete module graph in order to provide the name of the (local) main module. The previous modload.buildList variable contained a flattened build list, from which the go.mod file was reconstructed using various heuristics and metadata cobbled together from the original go.mod file, the package loader (which was occasionally constructed without actually loading packages, for the sole purpose of populating otherwise-unrelated metadata!), and the updated build list. This change replaces that variable with a new package-level variable, named "requirements". The new variable is structured to match the structure of the go.mod file: it explicitly specifies the roots of the module graph, from which the complete module graph and complete build list can be reconstructed (and cached) on demand. Similarly, the "direct" markings on the go.mod requirements are now stored alongside the requirements themselves, rather than side-channeled through the loader. The requirements are now plumbed explicitly though the modload package, with accesses to the package-level variable occurring only within top-level exported functions. The structured requirements are logically immutable, so a new copy of the requirements is constructed whenever the requirements are changed, substantially reducing implicit communication-by-sharing in the package. For #36460 Updates #40775 Change-Id: I97bb0381708f9d3e42af385b5c88a7038e1f0556 Reviewed-on: https://go-review.googlesource.com/c/go/+/293689 Trust: Bryan C. Mills <bcmills@google.com> Run-TryBot: Bryan C. Mills <bcmills@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Matloob <matloob@golang.org>
Diffstat (limited to 'src/cmd/go/internal/modload/build.go')
-rw-r--r--src/cmd/go/internal/modload/build.go67
1 files changed, 42 insertions, 25 deletions
diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go
index 5f18a38e93..48d20bb5fa 100644
--- a/src/cmd/go/internal/modload/build.go
+++ b/src/cmd/go/internal/modload/build.go
@@ -50,17 +50,18 @@ func findStandardImportPath(path string) string {
// a given package. If modules are not enabled or if the package is in the
// standard library or if the package was not successfully loaded with
// LoadPackages or ImportFromFiles, nil is returned.
-func PackageModuleInfo(pkgpath string) *modinfo.ModulePublic {
+func PackageModuleInfo(ctx context.Context, pkgpath string) *modinfo.ModulePublic {
if isStandardImportPath(pkgpath) || !Enabled() {
return nil
}
- m, ok := findModule(pkgpath)
+ m, ok := findModule(loaded, pkgpath)
if !ok {
return nil
}
- fromBuildList := true
+
+ rs := LoadModFile(ctx)
listRetracted := false
- return moduleInfo(context.TODO(), m, fromBuildList, listRetracted)
+ return moduleInfo(ctx, rs, m, listRetracted)
}
func ModuleInfo(ctx context.Context, path string) *modinfo.ModulePublic {
@@ -71,23 +72,36 @@ func ModuleInfo(ctx context.Context, path string) *modinfo.ModulePublic {
listRetracted := false
if i := strings.Index(path, "@"); i >= 0 {
m := module.Version{Path: path[:i], Version: path[i+1:]}
- fromBuildList := false
- return moduleInfo(ctx, m, fromBuildList, listRetracted)
+ return moduleInfo(ctx, nil, m, listRetracted)
}
- for _, m := range buildList {
- if m.Path == path {
- fromBuildList := true
- return moduleInfo(ctx, m, fromBuildList, listRetracted)
+ rs := LoadModFile(ctx)
+
+ var (
+ v string
+ ok bool
+ )
+ if go117LazyTODO {
+ v, ok = rs.rootSelected(path)
+ }
+ if !ok {
+ mg, err := rs.Graph(ctx)
+ if err != nil {
+ base.Fatalf("go: %v", err)
}
+ v = mg.Selected(path)
}
- return &modinfo.ModulePublic{
- Path: path,
- Error: &modinfo.ModuleError{
- Err: "module not in current build",
- },
+ if v == "none" {
+ return &modinfo.ModulePublic{
+ Path: path,
+ Error: &modinfo.ModuleError{
+ Err: "module not in current build",
+ },
+ }
}
+
+ return moduleInfo(ctx, rs, module.Version{Path: path, Version: v}, listRetracted)
}
// addUpdate fills in m.Update if an updated version is available.
@@ -140,7 +154,10 @@ func addRetraction(ctx context.Context, m *modinfo.ModulePublic) {
}
}
-func moduleInfo(ctx context.Context, m module.Version, fromBuildList, listRetracted bool) *modinfo.ModulePublic {
+// moduleInfo returns information about module m, loaded from the requirements
+// in rs (which may be nil to indicate that m was not loaded from a requirement
+// graph).
+func moduleInfo(ctx context.Context, rs *Requirements, m module.Version, listRetracted bool) *modinfo.ModulePublic {
if m == Target {
info := &modinfo.ModulePublic{
Path: m.Path,
@@ -162,7 +179,7 @@ func moduleInfo(ctx context.Context, m module.Version, fromBuildList, listRetrac
info := &modinfo.ModulePublic{
Path: m.Path,
Version: m.Version,
- Indirect: fromBuildList && loaded != nil && !loaded.direct[m.Path],
+ Indirect: rs != nil && !rs.direct[m.Path],
}
if v, ok := rawGoVersion.Load(m); ok {
info.GoVersion = v.(string)
@@ -171,7 +188,7 @@ func moduleInfo(ctx context.Context, m module.Version, fromBuildList, listRetrac
// completeFromModCache fills in the extra fields in m using the module cache.
completeFromModCache := func(m *modinfo.ModulePublic) {
checksumOk := func(suffix string) bool {
- return !fromBuildList || m.Version == "" || cfg.BuildMod == "mod" ||
+ return rs == nil || m.Version == "" || cfg.BuildMod == "mod" ||
modfetch.HaveSum(module.Version{Path: m.Path, Version: m.Version + suffix})
}
@@ -215,7 +232,7 @@ func moduleInfo(ctx context.Context, m module.Version, fromBuildList, listRetrac
}
}
- if !fromBuildList {
+ if rs == nil {
// If this was an explicitly-versioned argument to 'go mod download' or
// 'go list -m', report the actual requested version, not its replacement.
completeFromModCache(info) // Will set m.Error in vendor mode.
@@ -273,11 +290,11 @@ func PackageBuildInfo(path string, deps []string) string {
return ""
}
- target := mustFindModule(path, path)
+ target := mustFindModule(loaded, path, path)
mdeps := make(map[module.Version]bool)
for _, dep := range deps {
if !isStandardImportPath(dep) {
- mdeps[mustFindModule(path, dep)] = true
+ mdeps[mustFindModule(loaded, path, dep)] = true
}
}
var mods []module.Version
@@ -316,8 +333,8 @@ func PackageBuildInfo(path string, deps []string) string {
//
// TODO(jayconrod): remove this. Callers should use findModule and return
// errors instead of relying on base.Fatalf.
-func mustFindModule(target, path string) module.Version {
- pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
+func mustFindModule(ld *loader, target, path string) module.Version {
+ pkg, ok := ld.pkgCache.Get(path).(*loadPkg)
if ok {
if pkg.err != nil {
base.Fatalf("build %v: cannot load %v: %v", target, path, pkg.err)
@@ -336,8 +353,8 @@ func mustFindModule(target, path string) module.Version {
// findModule searches for the module that contains the package at path.
// If the package was loaded, its containing module and true are returned.
// Otherwise, module.Version{} and false are returend.
-func findModule(path string) (module.Version, bool) {
- if pkg, ok := loaded.pkgCache.Get(path).(*loadPkg); ok {
+func findModule(ld *loader, path string) (module.Version, bool) {
+ if pkg, ok := ld.pkgCache.Get(path).(*loadPkg); ok {
return pkg.mod, pkg.mod != module.Version{}
}
if path == "command-line-arguments" {