aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/go/internal/modload/import.go
diff options
context:
space:
mode:
authorBryan C. Mills <bcmills@google.com>2020-09-28 20:59:47 -0400
committerBryan C. Mills <bcmills@google.com>2020-10-16 19:13:28 +0000
commitff052737a946b5f9381dc054d61857ee4d500899 (patch)
treea643debe137e7836ade19bb129371d0757c20b7f /src/cmd/go/internal/modload/import.go
parentae162554f9e0078b325fb32e2e10ddda15b2acdc (diff)
downloadgo-ff052737a946b5f9381dc054d61857ee4d500899.tar.gz
go-ff052737a946b5f9381dc054d61857ee4d500899.zip
cmd/go/internal/modload: allow 'go get' to use replaced versions
'go mod tidy' has been able to use replaced versions since CL 152739, but 'go get' failed for many of the same paths. Now that we are recommending 'go get' more aggressively due to #40728, we should make that work too. In the future, we might consider factoring out the new replacementRepo type so that 'go list' can report the new versions as well. For #41577 For #41416 For #37438 Updates #26241 Change-Id: I9140c556424b584fdd9bdd0a747842774664a7d8 Reviewed-on: https://go-review.googlesource.com/c/go/+/258220 Trust: Bryan C. Mills <bcmills@google.com> Trust: Jay Conrod <jayconrod@google.com> Run-TryBot: Bryan C. Mills <bcmills@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Matloob <matloob@golang.org> Reviewed-by: Jay Conrod <jayconrod@google.com>
Diffstat (limited to 'src/cmd/go/internal/modload/import.go')
-rw-r--r--src/cmd/go/internal/modload/import.go93
1 files changed, 55 insertions, 38 deletions
diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go
index 8641cfec08..1c572d5d6d 100644
--- a/src/cmd/go/internal/modload/import.go
+++ b/src/cmd/go/internal/modload/import.go
@@ -35,6 +35,12 @@ type ImportMissingError struct {
// and thus would be added by 'go mod tidy'.
inAll bool
+ // isStd indicates whether we would expect to find the package in the standard
+ // library. This is normally true for all dotless import paths, but replace
+ // directives can cause us to treat the replaced paths as also being in
+ // modules.
+ isStd bool
+
// newMissingVersion is set to a newer version of Module if one is present
// in the build list. When set, we can't automatically upgrade.
newMissingVersion string
@@ -42,7 +48,7 @@ type ImportMissingError struct {
func (e *ImportMissingError) Error() string {
if e.Module.Path == "" {
- if search.IsStandardImportPath(e.Path) {
+ if e.isStd {
return fmt.Sprintf("package %s is not in GOROOT (%s)", e.Path, filepath.Join(cfg.GOROOT, "src", e.Path))
}
if e.QueryErr != nil {
@@ -230,46 +236,67 @@ func importFromBuildList(ctx context.Context, path string) (m module.Version, di
return module.Version{}, "", &AmbiguousImportError{importPath: path, Dirs: dirs, Modules: mods}
}
- return module.Version{}, "", &ImportMissingError{Path: path}
+ return module.Version{}, "", &ImportMissingError{Path: path, isStd: pathIsStd}
}
// queryImport attempts to locate a module that can be added to the current
// build list to provide the package with the given import path.
+//
+// Unlike QueryPattern, queryImport prefers to add a replaced version of a
+// module *before* checking the proxies for a version to add.
func queryImport(ctx context.Context, path string) (module.Version, error) {
pathIsStd := search.IsStandardImportPath(path)
- // Not on build list.
- // To avoid spurious remote fetches, next try the latest replacement for each
- // module (golang.org/issue/26241). This should give a useful message
- // in -mod=readonly, and it will allow us to add a requirement with -mod=mod.
- if modFile != nil {
- latest := map[string]string{} // path -> version
- for _, r := range modFile.Replace {
- if maybeInModule(path, r.Old.Path) {
- // Don't use semver.Max here; need to preserve +incompatible suffix.
- v := latest[r.Old.Path]
- if semver.Compare(r.Old.Version, v) > 0 {
- v = r.Old.Version
+ if cfg.BuildMod == "readonly" {
+ if pathIsStd {
+ // If the package would be in the standard library and none of the
+ // available replacement modules could concievably provide it, report it
+ // as a missing standard-library package instead of complaining that
+ // module lookups are disabled.
+ maybeReplaced := false
+ if index != nil {
+ for p := range index.highestReplaced {
+ if maybeInModule(path, p) {
+ maybeReplaced = true
+ break
+ }
}
- latest[r.Old.Path] = v
}
+ if !maybeReplaced {
+ return module.Version{}, &ImportMissingError{Path: path, isStd: true}
+ }
+ }
+
+ var queryErr error
+ if cfg.BuildModExplicit {
+ queryErr = fmt.Errorf("import lookup disabled by -mod=%s", cfg.BuildMod)
+ } else if cfg.BuildModReason != "" {
+ queryErr = fmt.Errorf("import lookup disabled by -mod=%s\n\t(%s)", cfg.BuildMod, cfg.BuildModReason)
}
+ return module.Version{}, &ImportMissingError{Path: path, QueryErr: queryErr}
+ }
- mods := make([]module.Version, 0, len(latest))
- for p, v := range latest {
- // If the replacement didn't specify a version, synthesize a
- // pseudo-version with an appropriate major version and a timestamp below
- // any real timestamp. That way, if the main module is used from within
- // some other module, the user will be able to upgrade the requirement to
- // any real version they choose.
- if v == "" {
- if _, pathMajor, ok := module.SplitPathVersion(p); ok && len(pathMajor) > 0 {
- v = modfetch.PseudoVersion(pathMajor[1:], "", time.Time{}, "000000000000")
+ // To avoid spurious remote fetches, try the latest replacement for each
+ // module (golang.org/issue/26241).
+ if index != nil {
+ var mods []module.Version
+ for mp, mv := range index.highestReplaced {
+ if !maybeInModule(path, mp) {
+ continue
+ }
+ if mv == "" {
+ // The only replacement is a wildcard that doesn't specify a version, so
+ // synthesize a pseudo-version with an appropriate major version and a
+ // timestamp below any real timestamp. That way, if the main module is
+ // used from within some other module, the user will be able to upgrade
+ // the requirement to any real version they choose.
+ if _, pathMajor, ok := module.SplitPathVersion(mp); ok && len(pathMajor) > 0 {
+ mv = modfetch.PseudoVersion(pathMajor[1:], "", time.Time{}, "000000000000")
} else {
- v = modfetch.PseudoVersion("v0", "", time.Time{}, "000000000000")
+ mv = modfetch.PseudoVersion("v0", "", time.Time{}, "000000000000")
}
}
- mods = append(mods, module.Version{Path: p, Version: v})
+ mods = append(mods, module.Version{Path: mp, Version: mv})
}
// Every module path in mods is a prefix of the import path.
@@ -310,17 +337,7 @@ func queryImport(ctx context.Context, path string) (module.Version, error) {
// QueryPattern cannot possibly find a module containing this package.
//
// Instead of trying QueryPattern, report an ImportMissingError immediately.
- return module.Version{}, &ImportMissingError{Path: path}
- }
-
- if cfg.BuildMod == "readonly" {
- var queryErr error
- if cfg.BuildModExplicit {
- queryErr = fmt.Errorf("import lookup disabled by -mod=%s", cfg.BuildMod)
- } else if cfg.BuildModReason != "" {
- queryErr = fmt.Errorf("import lookup disabled by -mod=%s\n\t(%s)", cfg.BuildMod, cfg.BuildModReason)
- }
- return module.Version{}, &ImportMissingError{Path: path, QueryErr: queryErr}
+ return module.Version{}, &ImportMissingError{Path: path, isStd: true}
}
// Look up module containing the package, for addition to the build list.