]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: suppress errors from 'go get -d' for packages that only conditionally exist
authorBryan C. Mills <bcmills@google.com>
Thu, 4 Feb 2021 20:26:52 +0000 (15:26 -0500)
committerBryan C. Mills <bcmills@google.com>
Tue, 9 Feb 2021 18:40:13 +0000 (18:40 +0000)
Fixes #44106
Fixes #29268

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

src/cmd/go/internal/modget/get.go
src/cmd/go/testdata/script/mod_get_pkgtags.txt [new file with mode: 0644]

index 574f3e194d168ed6c2cda6c9d2a64b2cd2fb98ed..1a8c9d37255e1cf9c425c64dbd6f579b2b67e552 100644 (file)
@@ -380,10 +380,9 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
                pkgs := load.PackagesAndErrors(ctx, pkgPatterns)
                load.CheckPackageErrors(pkgs)
                work.InstallPackages(ctx, pkgPatterns, pkgs)
-               // TODO(#40276): After Go 1.16, print a deprecation notice when building
-               // and installing main packages. 'go install pkg' or
-               // 'go install pkg@version' should be used instead.
-               // Give the specific argument to use if possible.
+               // TODO(#40276): After Go 1.16, print a deprecation notice when building and
+               // installing main packages. 'go install pkg' or 'go install pkg@version'
+               // should be used instead. Give the specific argument to use if possible.
        }
 
        if !modload.HasModRoot() {
@@ -1453,7 +1452,18 @@ func (r *resolver) checkPackagesAndRetractions(ctx context.Context, pkgPatterns
                        }
                }
                for _, pkg := range pkgs {
-                       if _, _, err := modload.Lookup("", false, pkg); err != nil {
+                       if dir, _, err := modload.Lookup("", false, pkg); err != nil {
+                               if dir != "" && errors.Is(err, imports.ErrNoGo) {
+                                       // Since dir is non-empty, we must have located source files
+                                       // associated with either the package or its test — ErrNoGo must
+                                       // indicate that none of those source files happen to apply in this
+                                       // configuration. If we are actually building the package (no -d
+                                       // flag), the compiler will report the problem; otherwise, assume that
+                                       // the user is going to build or test it in some other configuration
+                                       // and suppress the error.
+                                       continue
+                               }
+
                                base.SetExitStatus(1)
                                if ambiguousErr := (*modload.AmbiguousImportError)(nil); errors.As(err, &ambiguousErr) {
                                        for _, m := range ambiguousErr.Modules {
diff --git a/src/cmd/go/testdata/script/mod_get_pkgtags.txt b/src/cmd/go/testdata/script/mod_get_pkgtags.txt
new file mode 100644 (file)
index 0000000..c0a57f3
--- /dev/null
@@ -0,0 +1,116 @@
+# https://golang.org/issue/44106
+# 'go get' should fetch the transitive dependencies of packages regardless of
+# tags, but shouldn't error out if the package is missing tag-guarded
+# dependencies.
+
+# Control case: just adding the top-level module to the go.mod file does not
+# fetch its dependencies.
+
+go mod edit -require example.net/tools@v0.1.0
+! go list -deps example.net/cmd/tool
+stderr '^module example\.net/cmd provides package example\.net/cmd/tool and is replaced but not required; to add it:\n\tgo get example\.net/cmd@v0\.1\.0$'
+go mod edit -droprequire example.net/tools
+
+
+# 'go get -d' makes a best effort to fetch those dependencies, but shouldn't
+# error out if dependencies of tag-guarded files are missing.
+
+go get -d example.net/tools@v0.1.0
+
+! go list example.net/tools
+stderr '^package example.net/tools: build constraints exclude all Go files in .*[/\\]tools$'
+
+go list -tags=tools -e -deps example.net/tools
+stdout '^example.net/cmd/tool$'
+stdout '^example.net/missing$'
+
+go list -deps example.net/cmd/tool
+
+! go list example.net/missing
+stderr '^no required module provides package example.net/missing; to add it:\n\tgo get example.net/missing$'
+
+
+# https://golang.org/issue/29268
+# 'go get' should fetch modules whose roots contain test-only packages, but
+# without the -t flag shouldn't error out if the test has missing dependencies.
+
+go get -d example.net/testonly@v0.1.0
+
+# With the -t flag, the test dependencies must resolve successfully.
+! go get -d -t example.net/testonly@v0.1.0
+stderr '^example.net/testonly tested by\n\texample.net/testonly\.test imports\n\texample.net/missing: cannot find module providing package example.net/missing$'
+
+
+# 'go get -d' should succeed for a module path that does not contain a package,
+# but fail for a non-package subdirectory of a module.
+
+! go get -d example.net/missing/subdir@v0.1.0
+stderr '^go get: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$'
+
+go get -d example.net/missing@v0.1.0
+
+
+# Getting the subdirectory should continue to fail even if the corresponding
+# module is already present in the build list.
+
+! go get -d example.net/missing/subdir@v0.1.0
+stderr '^go get: module example.net/missing@v0.1.0 found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$'
+
+
+-- go.mod --
+module example.net/m
+
+go 1.15
+
+replace (
+       example.net/tools v0.1.0 => ./tools
+       example.net/cmd v0.1.0 => ./cmd
+       example.net/testonly v0.1.0 => ./testonly
+       example.net/missing v0.1.0 => ./missing
+)
+
+-- tools/go.mod --
+module example.net/tools
+
+go 1.15
+
+// Requirements intentionally omitted.
+
+-- tools/tools.go --
+// +build tools
+
+package tools
+
+import (
+       _ "example.net/cmd/tool"
+       _ "example.net/missing"
+)
+
+-- cmd/go.mod --
+module example.net/cmd
+
+go 1.16
+-- cmd/tool/tool.go --
+package main
+
+func main() {}
+
+-- testonly/go.mod --
+module example.net/testonly
+
+go 1.15
+-- testonly/testonly_test.go --
+package testonly_test
+
+import _ "example.net/missing"
+
+func Test(t *testing.T) {}
+
+-- missing/go.mod --
+module example.net/missing
+
+go 1.15
+-- missing/README.txt --
+There are no Go source files here.
+-- missing/subdir/README.txt --
+There are no Go source files here either.