]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: print hint when 'go install' run without version outside module
authorJay Conrod <jayconrod@google.com>
Fri, 11 Dec 2020 21:45:39 +0000 (16:45 -0500)
committerJay Conrod <jayconrod@google.com>
Mon, 14 Dec 2020 15:40:56 +0000 (15:40 +0000)
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>
src/cmd/go/internal/work/build.go
src/cmd/go/testdata/script/mod_outside.txt

index 1f99ed6e07daa10402281746768cc5b5b8e693c0..7f2617cf1cedf8e1ffbf63b8d18757a7dc1ae15c 100644 (file)
@@ -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 {
index 28379ab40d886f090977526c98c2a019c397fcab..8f01b5d242677502a87260d0a5e4d3a12459c2d3 100644 (file)
@@ -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