diff options
author | Jay Conrod <jayconrod@google.com> | 2020-12-11 16:45:39 -0500 |
---|---|---|
committer | Jay Conrod <jayconrod@google.com> | 2020-12-14 15:40:56 +0000 |
commit | 64d8846aaef4b64d2649917581069c0ec30ca561 (patch) | |
tree | 41ab69260465f5a2871ea532307b40402d660411 | |
parent | 451b6b38fd3f87957c39fdb6572740f74ea27931 (diff) | |
download | go-64d8846aaef4b64d2649917581069c0ec30ca561.tar.gz go-64d8846aaef4b64d2649917581069c0ec30ca561.zip |
cmd/go: print hint when 'go install' run without version outside module
If 'go install' is invoked in module mode outside a module with a
package that could only be loaded from a module, it will now suggest
running 'go install pkg@latest'.
'go install' will still work outside a module on packages in std and
cmd, as well as .go files specified on the command line.
Fixes #42638
Change-Id: Ib0963935f028b7656178bc04a279b1114de35fbb
Reviewed-on: https://go-review.googlesource.com/c/go/+/277355
Run-TryBot: Jay Conrod <jayconrod@google.com>
Trust: Jay Conrod <jayconrod@google.com>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
-rw-r--r-- | src/cmd/go/internal/work/build.go | 26 | ||||
-rw-r--r-- | src/cmd/go/testdata/script/mod_outside.txt | 5 |
2 files changed, 29 insertions, 2 deletions
diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index 1f99ed6e07..7f2617cf1c 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -583,8 +583,31 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) { return } } + BuildInit() pkgs := load.PackagesAndErrors(ctx, args) + if cfg.ModulesEnabled && !modload.HasModRoot() { + haveErrors := false + allMissingErrors := true + for _, pkg := range pkgs { + if pkg.Error == nil { + continue + } + haveErrors = true + if missingErr := (*modload.ImportMissingError)(nil); !errors.As(pkg.Error, &missingErr) { + allMissingErrors = false + break + } + } + if haveErrors && allMissingErrors { + latestArgs := make([]string, len(args)) + for i := range args { + latestArgs[i] = args[i] + "@latest" + } + hint := strings.Join(latestArgs, " ") + base.Fatalf("go install: version is required when current directory is not in a module\n\tTry 'go install %s' to install the latest version", hint) + } + } load.CheckPackageErrors(pkgs) if cfg.BuildI { allGoroot := true @@ -598,6 +621,7 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) { fmt.Fprint(os.Stderr, "go install: -i flag is deprecated\n") } } + InstallPackages(ctx, args, pkgs) } @@ -815,7 +839,7 @@ func installOutsideModule(ctx context.Context, args []string) { // Load packages for all arguments. Ignore non-main packages. // Print a warning if an argument contains "..." and matches no main packages. - // PackagesForBuild already prints warnings for patterns that don't match any + // PackagesAndErrors already prints warnings for patterns that don't match any // packages, so be careful not to double print. matchers := make([]func(string) bool, len(patterns)) for i, p := range patterns { diff --git a/src/cmd/go/testdata/script/mod_outside.txt b/src/cmd/go/testdata/script/mod_outside.txt index 28379ab40d..8f01b5d242 100644 --- a/src/cmd/go/testdata/script/mod_outside.txt +++ b/src/cmd/go/testdata/script/mod_outside.txt @@ -189,13 +189,16 @@ exists $GOPATH/bin/printversion$GOEXE # 'go install' should fail if a package argument must be resolved to a module. ! go install example.com/printversion -stderr 'no required module provides package example.com/printversion: working directory is not part of a module' +stderr '^go install: version is required when current directory is not in a module\n\tTry ''go install example.com/printversion@latest'' to install the latest version$' # 'go install' should fail if a source file imports a package that must be # resolved to a module. ! go install ./needmod/needmod.go stderr 'needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: working directory is not part of a module' +# 'go install' should succeed with a package in GOROOT. +go install cmd/addr2line +! stderr . # 'go run' with a verison should fail due to syntax. ! go run example.com/printversion@v1.0.0 |