Skip to content

Commit

Permalink
cmd/go: suppress errors from 'go get -d' for packages that only condi…
Browse files Browse the repository at this point in the history
…tionally exist

Fixes golang#44106
Fixes golang#29268

Change-Id: Id113f2ced274d43fbf66cb804581448218996f81
Reviewed-on: https://go-review.googlesource.com/c/go/+/289769
TryBot-Result: Go Bot <[email protected]>
Reviewed-by: Jay Conrod <[email protected]>
Trust: Bryan C. Mills <[email protected]>
Run-TryBot: Bryan C. Mills <[email protected]>
  • Loading branch information
Bryan C. Mills committed Feb 9, 2021
1 parent e0ac989 commit e9c9683
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 5 deletions.
20 changes: 15 additions & 5 deletions src/cmd/go/internal/modget/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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 {
Expand Down
116 changes: 116 additions & 0 deletions src/cmd/go/testdata/script/mod_get_pkgtags.txt
Original file line number Diff line number Diff line change
@@ -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/[email protected]
! 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/[email protected]

! 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/[email protected]

# With the -t flag, the test dependencies must resolve successfully.
! go get -d -t example.net/[email protected]
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/[email protected]
stderr '^go get: module example.net/[email protected] found \(replaced by ./missing\), but does not contain package example.net/missing/subdir$'

go get -d example.net/[email protected]


# 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/[email protected]
stderr '^go get: module example.net/[email protected] 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.

0 comments on commit e9c9683

Please sign in to comment.