cp go.mod go.mod.orig


# 'go get' on a package already provided by the build list should update
# the module already in the build list, not fail with an ambiguous import error.

go get example.net/split/nested@patch
go list -m all
stdout '^example.net/split v0.2.1 '
! stdout '^example.net/split/nested'

# We should get the same behavior if we use a pattern that matches only that package.

cp go.mod.orig go.mod

go get example.net/split/nested/...@patch
go list -m all
stdout '^example.net/split v0.2.1 '
! stdout '^example.net/split/nested'


# If we request a version for which the package only exists in one particular module,
# we should add that one particular module but not resolve import ambiguities.
#
# In particular, if the module that previously provided the package has a
# matching version, but does not itself match the pattern and contains no
# matching packages, we should not change its version. (We should *not* downgrade
# module example.net/split to v0.1.0, despite the fact that
# example.net/split v0.2.0 currently provides the package with the requested path.)
#
# TODO(#27899): Maybe we should resolve the ambiguities by upgrading.

cp go.mod.orig go.mod

! go get example.net/split/nested@v0.1.0
stderr '^go: example.net/split/nested: ambiguous import: found package example.net/split/nested in multiple modules:\n\texample.net/split v0.2.0 \(.*split.2[/\\]nested\)\n\texample.net/split/nested v0.1.0 \(.*nested.1\)$'

# A wildcard that matches packages in some module at its selected version
# but not at the requested version should fail.
#
# We can't set the module to the selected version, because that version doesn't
# even match the query: if we ran the same query twice, we wouldn't consider the
# module to match the wildcard during the second call, so why should we consider
# it to match during the first one?  ('go get' should be idempotent, and if we
# did that then it would not be.)
#
# But we also can't leave it where it is: the user requested that we set everything
# matching the pattern to the given version, and right now we have packages
# that match the pattern but *not* the version.
#
# That only leaves two options: we can set the module to an arbitrary version
# (perhaps 'latest' or 'none'), or we can report an error and the let the user
# disambiguate. We would rather not choose arbitrarily, so we do the latter.
#
# TODO(#27899): Should we instead upgrade or downgrade to an arbitrary version?

! go get example.net/split/nested/...@v0.1.0
stderr '^go: example.net/split/nested/\.\.\.@v0.1.0 matches packages in example.net/split@v0.2.0 but not example.net/split@v0.1.0: specify a different version for module example.net/split$'

cmp go.mod go.mod.orig


# If another argument resolves the ambiguity, we should be ok again.

go get example.net/split@none example.net/split/nested@v0.1.0
go list -m all
! stdout '^example.net/split '
stdout '^example.net/split/nested v0.1.0 '

cp go.mod.orig go.mod

go get example.net/split@v0.3.0 example.net/split/nested@v0.1.0
go list -m all
stdout '^example.net/split v0.3.0 '
stdout '^example.net/split/nested v0.1.0 '


# If a pattern applies to modules and to packages, we should set all matching
# modules to the version indicated by the pattern, and also resolve packages
# to match the pattern if possible.

cp go.mod.orig go.mod
go get example.net/split/nested@v0.0.0

go get example.net/...@v0.1.0
go list -m all
stdout '^example.net/split v0.1.0 '
stdout '^example.net/split/nested v0.1.0 '

go get example.net/...
go list -m all
stdout '^example.net/split v0.3.0 '
stdout '^example.net/split/nested v0.2.0 '


# @none applies to all matching module paths,
# regardless of whether they contain any packages.

go get example.net/...@none
go list -m all
! stdout '^example.net'

# Starting from no dependencies, a wildcard can resolve to an empty module with
# the same prefix even if it contains no packages.

go get example.net/...@none
go get example.net/split/...@v0.1.0
go list -m all
stdout '^example.net/split v0.1.0 '


-- go.mod --
module m

go 1.16

require example.net/split v0.2.0

replace (
	example.net/split v0.1.0 => ./split.1
	example.net/split v0.2.0 => ./split.2
	example.net/split v0.2.1 => ./split.2
	example.net/split v0.3.0 => ./split.3
	example.net/split/nested v0.0.0 => ./nested.0
	example.net/split/nested v0.1.0 => ./nested.1
	example.net/split/nested v0.2.0 => ./nested.2
)
-- split.1/go.mod --
module example.net/split

go 1.16
-- split.2/go.mod --
module example.net/split

go 1.16
-- split.2/nested/nested.go --
package nested
-- split.3/go.mod --
module example.net/split

go 1.16
-- nested.0/go.mod --
module example.net/split/nested

go 1.16
-- nested.1/go.mod --
module example.net/split/nested

go 1.16
-- nested.1/nested.go --
package nested
-- nested.2/go.mod --
module example.net/split/nested

go 1.16
-- nested.2/nested.go --
package nested
