aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/go/internal/modload/modfile.go
diff options
context:
space:
mode:
authorBryan C. Mills <bcmills@google.com>2021-04-29 09:27:40 -0400
committerBryan C. Mills <bcmills@google.com>2021-04-30 18:06:46 +0000
commit7dedc237c528fa268934a8ed81c01fc65db5f800 (patch)
treee86aba58db59d7d67ecfab1b3e23859366c234b8 /src/cmd/go/internal/modload/modfile.go
parent0e315ad79ae388eedb03dce27101c40b29292e2a (diff)
downloadgo-7dedc237c528fa268934a8ed81c01fc65db5f800.tar.gz
go-7dedc237c528fa268934a8ed81c01fc65db5f800.zip
cmd/go: smooth out upgrade paths for lazy loading
This change adds two possible upgrade paths for lazy loading: 1. Run 'go mod tidy -go=1.17'. 2. Starting in a module with no existing 'go' directive, run any 'go' command that updates the go.mod file. In the latter case, commands other than 'go mod tidy' may leave the go.mod file *very* untidy if it had non-trivial dependencies. (The 'go' invocation will promote all implicit eager dependencies to explicit lazy ones, which preserves the original module graph — most of which is not actually relevant.) 'go mod tidy -go=1.17' can be used to enable lazy loading without accidentally downgrading existing transitive dependencies. 'go mod tidy -go=1.16' can be used to disable lazy loading and clear away redundant roots in a single step (if reducing the go version), or to prune away dependencies of tests-of-external-tests (if increasing the go version). 'go mod tidy -go=1.15' can be used to add dependencies of tests-of-external-tests, although there isn't much point to that. DO NOT MERGE This change still needs an explicit test and a release note. Fixes #45094 For #36460 Change-Id: I68f057e39489dfd6a667cd11dc1e320c1ee1aec1 Reviewed-on: https://go-review.googlesource.com/c/go/+/315210 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/modfile.go')
-rw-r--r--src/cmd/go/internal/modload/modfile.go81
1 files changed, 38 insertions, 43 deletions
diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go
index cd08fa5859..7595db7755 100644
--- a/src/cmd/go/internal/modload/modfile.go
+++ b/src/cmd/go/internal/modload/modfile.go
@@ -51,6 +51,27 @@ const (
var modFile *modfile.File
+// modFileGoVersion returns the (non-empty) Go version at which the requirements
+// in modFile are intepreted, or the latest Go version if modFile is nil.
+func modFileGoVersion() string {
+ if modFile == nil {
+ return latestGoVersion()
+ }
+ if modFile.Go == nil || modFile.Go.Version == "" {
+ // The main module necessarily has a go.mod file, and that file lacks a
+ // 'go' directive. The 'go' command has been adding that directive
+ // automatically since Go 1.12, so this module either dates to Go 1.11 or
+ // has been erroneously hand-edited.
+ //
+ // The semantics of the go.mod file are more-or-less the same from Go 1.11
+ // through Go 1.16, changing at 1.17 for lazy loading. So even though a
+ // go.mod file without a 'go' directive is theoretically a Go 1.11 file,
+ // scripts may assume that it ends up as a Go 1.16 module.
+ return "1.16"
+ }
+ return modFile.Go.Version
+}
+
// A modFileIndex is an index of data corresponding to a modFile
// at a specific point in time.
type modFileIndex struct {
@@ -79,6 +100,16 @@ const (
eager // load all transitive dependencies eagerly
)
+func modDepthFromGoVersion(goVersion string) modDepth {
+ if !go117EnableLazyLoading {
+ return eager
+ }
+ if semver.Compare("v"+goVersion, lazyLoadingVersionV) < 0 {
+ return eager
+ }
+ return lazy
+}
+
// CheckAllowed returns an error equivalent to ErrDisallowed if m is excluded by
// the main module's go.mod or retracted by its author. Most version queries use
// this to filter out versions that should not be used.
@@ -344,32 +375,6 @@ func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileInd
return i
}
-// allPatternClosesOverTests reports whether the "all" pattern includes
-// dependencies of tests outside the main module (as in Go 1.11–1.15).
-// (Otherwise — as in Go 1.16+ — the "all" pattern includes only the packages
-// transitively *imported by* the packages and tests in the main module.)
-func (i *modFileIndex) allPatternClosesOverTests() bool {
- if i != nil && i.goVersionV != "" && semver.Compare(i.goVersionV, narrowAllVersionV) < 0 {
- // The module explicitly predates the change in "all" for lazy loading, so
- // continue to use the older interpretation. (If i == nil, we not in any
- // module at all and should use the latest semantics.)
- return true
- }
- return false
-}
-
-// depth reports the modDepth indicated by the indexed go.mod file,
-// or lazy if the go.mod file has not been indexed.
-func (i *modFileIndex) depth() modDepth {
- if !go117EnableLazyLoading {
- return eager
- }
- if i != nil && semver.Compare(i.goVersionV, lazyLoadingVersionV) < 0 {
- return eager
- }
- return lazy
-}
-
// modFileIsDirty reports whether the go.mod file differs meaningfully
// from what was indexed.
// If modFile has been changed (even cosmetically) since it was first read,
@@ -396,7 +401,7 @@ func (i *modFileIndex) modFileIsDirty(modFile *modfile.File) bool {
return true
}
} else if "v"+modFile.Go.Version != i.goVersionV {
- if i.goVersionV == "" && cfg.BuildMod == "readonly" {
+ if i.goVersionV == "" && cfg.BuildMod != "mod" {
// go.mod files did not always require a 'go' version, so do not error out
// if one is missing — we may be inside an older module in the module
// cache, and should bias toward providing useful behavior.
@@ -452,7 +457,8 @@ var rawGoVersion sync.Map // map[module.Version]string
// module.
type modFileSummary struct {
module module.Version
- goVersionV string // GoVersion with "v" prefix
+ goVersion string
+ depth modDepth
require []module.Version
retract []retraction
deprecated string
@@ -465,20 +471,6 @@ type retraction struct {
Rationale string
}
-func (s *modFileSummary) depth() modDepth {
- if !go117EnableLazyLoading {
- return eager
- }
- // The 'go' command fills in the 'go' directive automatically, so an empty
- // goVersionV in a dependency implies either Go 1.11 (eager loading) or no
- // explicit go.mod file at all (no difference between eager and lazy because
- // the module doesn't specify any requirements at all).
- if s.goVersionV == "" || semver.Compare(s.goVersionV, lazyLoadingVersionV) < 0 {
- return eager
- }
- return lazy
-}
-
// goModSummary returns a summary of the go.mod file for module m,
// taking into account any replacements for m, exclusions of its dependencies,
// and/or vendoring.
@@ -638,7 +630,10 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) {
}
if f.Go != nil && f.Go.Version != "" {
rawGoVersion.LoadOrStore(m, f.Go.Version)
- summary.goVersionV = "v" + f.Go.Version
+ summary.goVersion = f.Go.Version
+ summary.depth = modDepthFromGoVersion(f.Go.Version)
+ } else {
+ summary.depth = eager
}
if len(f.Require) > 0 {
summary.require = make([]module.Version, 0, len(f.Require))