]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: add hints to more missing sum error messages
authorJay Conrod <jayconrod@google.com>
Fri, 8 Jan 2021 20:14:22 +0000 (15:14 -0500)
committerJay Conrod <jayconrod@google.com>
Wed, 13 Jan 2021 23:37:31 +0000 (23:37 +0000)
When a command fails due to a module zip sum missing from go.sum,
if the module is in the build list, the go command will print a
'go mod download' command the user can run to fix it.

Previously, a hint was only printed if the module provided a package
in 'all'. We don't print a 'go get' hint, since we may not want to add
a new requirement to go.mod.

Fixes #43572

Change-Id: I88c61b1b42ad56c04e4482f6a1bb97ce758aaeff
Reviewed-on: https://go-review.googlesource.com/c/go/+/282712
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
Trust: Jay Conrod <jayconrod@google.com>

src/cmd/go/internal/modload/import.go
src/cmd/go/internal/modload/load.go
src/cmd/go/testdata/script/mod_sum_ambiguous.txt
src/cmd/go/testdata/script/mod_sum_readonly.txt

index 9925d5b9054a587b597d606a1b24e472f23d6a1d..182429aee41b95121da18f25cc8ed7a46df1b38e 100644 (file)
@@ -130,25 +130,57 @@ func (e *AmbiguousImportError) Error() string {
 }
 
 // ImportMissingSumError is reported in readonly mode when we need to check
-// if a module in the build list contains a package, but we don't have a sum
-// for its .zip file.
+// if a module contains a package, but we don't have a sum for its .zip file.
+// We might need sums for multiple modules to verify the package is unique.
+//
+// TODO(#43653): consolidate multiple errors of this type into a single error
+// that suggests a 'go get' command for root packages that transtively import
+// packages from modules with missing sums. load.CheckPackageErrors would be
+// a good place to consolidate errors, but we'll need to attach the import
+// stack here.
 type ImportMissingSumError struct {
-       importPath   string
-       modPaths     []string
-       found, inAll bool
+       importPath                string
+       found                     bool
+       mods                      []module.Version
+       importer, importerVersion string // optional, but used for additional context
+       importerIsTest            bool
 }
 
 func (e *ImportMissingSumError) Error() string {
+       var importParen string
+       if e.importer != "" {
+               importParen = fmt.Sprintf(" (imported by %s)", e.importer)
+       }
        var message string
        if e.found {
-               message = fmt.Sprintf("missing go.sum entry needed to verify package %s is provided by exactly one module", e.importPath)
+               message = fmt.Sprintf("missing go.sum entry needed to verify package %s%s is provided by exactly one module", e.importPath, importParen)
        } else {
-               message = fmt.Sprintf("missing go.sum entry for module providing package %s", e.importPath)
+               message = fmt.Sprintf("missing go.sum entry for module providing package %s%s", e.importPath, importParen)
        }
-       if e.inAll {
-               return message + fmt.Sprintf("; to add it:\n\tgo mod download %s", strings.Join(e.modPaths, " "))
+       var hint string
+       if e.importer == "" {
+               // Importing package is unknown, or the missing package was named on the
+               // command line. Recommend 'go mod download' for the modules that could
+               // provide the package, since that shouldn't change go.mod.
+               args := make([]string, len(e.mods))
+               for i, mod := range e.mods {
+                       args[i] = mod.Path
+               }
+               hint = fmt.Sprintf("; to add:\n\tgo mod download %s", strings.Join(args, " "))
+       } else {
+               // Importing package is known (common case). Recommend 'go get' on the
+               // current version of the importing package.
+               tFlag := ""
+               if e.importerIsTest {
+                       tFlag = " -t"
+               }
+               version := ""
+               if e.importerVersion != "" {
+                       version = "@" + e.importerVersion
+               }
+               hint = fmt.Sprintf("; to add:\n\tgo get%s %s%s", tFlag, e.importer, version)
        }
-       return message
+       return message + hint
 }
 
 func (e *ImportMissingSumError) ImportPath() string {
@@ -239,7 +271,7 @@ func importFromBuildList(ctx context.Context, path string, buildList []module.Ve
        // Check each module on the build list.
        var dirs []string
        var mods []module.Version
-       var sumErrModPaths []string
+       var sumErrMods []module.Version
        for _, m := range buildList {
                if !maybeInModule(path, m.Path) {
                        // Avoid possibly downloading irrelevant modules.
@@ -253,8 +285,8 @@ func importFromBuildList(ctx context.Context, path string, buildList []module.Ve
                                // We can't verify that the package is unique, and we may not find
                                // the package at all. Keep checking other modules to decide which
                                // error to report. Multiple sums may be missing if we need to look in
-                               // multiple nested modules to resolve the import; we'll report them all.
-                               sumErrModPaths = append(sumErrModPaths, m.Path)
+                               // multiple nested modules to resolve the import.
+                               sumErrMods = append(sumErrMods, m)
                                continue
                        }
                        // Report fetch error.
@@ -275,8 +307,12 @@ func importFromBuildList(ctx context.Context, path string, buildList []module.Ve
        if len(mods) > 1 {
                return module.Version{}, "", &AmbiguousImportError{importPath: path, Dirs: dirs, Modules: mods}
        }
-       if len(sumErrModPaths) > 0 {
-               return module.Version{}, "", &ImportMissingSumError{importPath: path, modPaths: sumErrModPaths, found: len(mods) > 0}
+       if len(sumErrMods) > 0 {
+               return module.Version{}, "", &ImportMissingSumError{
+                       importPath: path,
+                       mods:       sumErrMods,
+                       found:      len(mods) > 0,
+               }
        }
        if len(mods) == 1 {
                return mods[0], dirs[0], nil
index cd36da6a87d584e1852b1b9dc8f6a6a8e7647130..6d87acc6d3b7c9371cdb62e08339b585dd149833 100644 (file)
@@ -280,9 +280,11 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
        checkMultiplePaths()
        for _, pkg := range loaded.pkgs {
                if pkg.err != nil {
-                       if pkg.flags.has(pkgInAll) {
-                               if sumErr := (*ImportMissingSumError)(nil); errors.As(pkg.err, &sumErr) {
-                                       sumErr.inAll = true
+                       if sumErr := (*ImportMissingSumError)(nil); errors.As(pkg.err, &sumErr) {
+                               if importer := pkg.stack; importer != nil {
+                                       sumErr.importer = importer.path
+                                       sumErr.importerVersion = importer.mod.Version
+                                       sumErr.importerIsTest = importer.testOf != nil
                                }
                        }
 
index 5344dc00297da90b6cc6b93d2b44e6b15744afb3..07c66591770342f262b64c83980184dc3fd0ee62 100644 (file)
@@ -23,19 +23,21 @@ grep '^example.com/ambiguous/a/b v0.0.0-empty h1:' go.sum
 # provides the package.
 cp go.sum.a-only go.sum
 ! go list example.com/ambiguous/a/b
-stderr '^missing go.sum entry needed to verify package example.com/ambiguous/a/b is provided by exactly one module$'
+stderr '^missing go.sum entry needed to verify package example.com/ambiguous/a/b is provided by exactly one module; to add:\n\tgo mod download example.com/ambiguous/a/b$'
 ! go list -deps .
-stderr '^use.go:3:8: missing go.sum entry needed to verify package example.com/ambiguous/a/b is provided by exactly one module; to add it:\n\tgo mod download example.com/ambiguous/a/b$'
+stderr '^use.go:3:8: missing go.sum entry needed to verify package example.com/ambiguous/a/b \(imported by m\) is provided by exactly one module; to add:\n\tgo get m$'
 
 cp go.sum.b-only go.sum
 ! go list example.com/ambiguous/a/b
-stderr '^missing go.sum entry for module providing package example.com/ambiguous/a/b$'
+stderr '^missing go.sum entry for module providing package example.com/ambiguous/a/b; to add:\n\tgo mod download example.com/ambiguous/a$'
 ! go list -deps .
-stderr '^use.go:3:8: missing go.sum entry for module providing package example.com/ambiguous/a/b; to add it:\n\tgo mod download example.com/ambiguous/a$'
+stderr '^use.go:3:8: missing go.sum entry for module providing package example.com/ambiguous/a/b \(imported by m\); to add:\n\tgo get m$'
 
 cp go.sum.buildlist-only go.sum
+! go list example.com/ambiguous/a/b
+stderr '^missing go.sum entry for module providing package example.com/ambiguous/a/b; to add:\n\tgo mod download example.com/ambiguous/a example.com/ambiguous/a/b$'
 ! go list -deps .
-stderr '^use.go:3:8: missing go.sum entry for module providing package example.com/ambiguous/a/b; to add it:\n\tgo mod download example.com/ambiguous/a example.com/ambiguous/a/b$'
+stderr '^use.go:3:8: missing go.sum entry for module providing package example.com/ambiguous/a/b \(imported by m\); to add:\n\tgo get m$'
 
 -- go.mod --
 module m
index 00b4d7b5d2e912c47526c4d876baa949903fe90b..57c5bbeefdf0203c43f28b50d8294500b6dff7a7 100644 (file)
@@ -40,14 +40,14 @@ stderr '^no required module provides package example.com/doesnotexist; to add it
 # When a sum is needed to load a .zip file, we get a more specific error.
 # The .zip file is not downloaded.
 ! go list rsc.io/quote
-stderr '^missing go.sum entry for module providing package rsc.io/quote$'
+stderr '^missing go.sum entry for module providing package rsc.io/quote; to add:\n\tgo mod download rsc.io/quote$'
 ! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
 
 # The error is attached to the package from the missing module. We can load
 # a package that imports it without that error.
 go list -e -deps -f '{{.ImportPath}}{{with .Error}} {{.Err}}{{end}}' .
 stdout '^m$'
-stdout '^rsc.io/quote missing go.sum entry for module providing package rsc.io/quote; to add it:\n\tgo mod download rsc.io/quote$'
+stdout '^rsc.io/quote missing go.sum entry for module providing package rsc.io/quote \(imported by m\); to add:\n\tgo get m$'
 ! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
 
 # go.sum should not have been written.