cp go.mod go.mod.orig

env oldGOPROXY=$GOPROXY

# If a wildcard replacement exists for an otherwise-nonexistent module,
# 'go get' should resolve it to the minimum valid pseudo-version.

go mod edit -replace=example.com/x=./x
go get example.com/x

go list -m example.com/x
stdout '^example.com/x v0.0.0-00010101000000-000000000000 '

# If specific-version replacements exist, the highest matching version should be used.
go mod edit -replace=example.com/x@v0.1.0=./x
go mod edit -replace=example.com/x@v0.2.0=./x

go get example.com/x
go list -m example.com/x
stdout '^example.com/x v0.2.0 '

go get example.com/x@<v0.2.0
go list -m example.com/x
stdout '^example.com/x v0.1.0 '


# The same should work with GOPROXY=off.

env GOPROXY=off
cp go.mod.orig go.mod

go mod edit -replace=example.com/x=./x
go get example.com/x

go list -m example.com/x
stdout '^example.com/x v0.0.0-00010101000000-000000000000 '

# If specific-version replacements exist, the highest matching version should be used.
go mod edit -replace=example.com/x@v0.1.0=./x
go mod edit -replace=example.com/x@v0.2.0=./x

go get example.com/x
go list -m example.com/x
stdout '^example.com/x v0.2.0 '

go get example.com/x@<v0.2.0
go list -m example.com/x
stdout '^example.com/x v0.1.0 '


# Replacements should also be listed as known versions, and 'go get' should sort
# them in with ordinary versions.

env GOPROXY=$oldGOPROXY

cp go.mod.orig go.mod
go list -versions -m rsc.io/quote
stdout 'v1.3.0 v1.4.0'

go get rsc.io/quote@v1.3
go list -m rsc.io/quote
stdout '^rsc.io/quote v1.3.0'

go mod edit -replace rsc.io/quote@v1.3.1=rsc.io/quote@v1.4.0

go list -versions -m rsc.io/quote
stdout 'v1.3.0 v1.3.1 v1.4.0'

go get rsc.io/quote@v1.3
go list -m rsc.io/quote
stdout '^rsc.io/quote v1.3.1 '

go get rsc.io/quote@>v1.3.1
go list -m rsc.io/quote
stdout '^rsc.io/quote v1.4.0'


# Replacements should allow 'go get' to work even with dotless module paths.

cp go.mod.orig go.mod

! go list example
stderr '^package example is not in std \(.*\)$'
! go get example
stderr '^go: malformed module path "example": missing dot in first path element$'

go mod edit -replace example@v0.1.0=./example

! go list example
stderr '^module example provides package example and is replaced but not required; to add it:\n\tgo get example@v0.1.0$'

go get example
go list -m example
stdout '^example v0.1.0 '


-- go.mod --
module example.com

go 1.16
-- x/go.mod --
module example.com/x

go 1.16
-- x/x.go --
package x
-- example/go.mod --
module example
go 1.16
-- example/example.go --
package example
