env GO111MODULE=on

# download with version should print nothing.
# It should not load retractions from the .mod file from the latest version.
go mod download rsc.io/quote@v1.5.0
! stdout .
! stderr .
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.info
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.mod
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.zip
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod

# download of an invalid path should report the error
[short] skip
! go mod download this.domain.is.invalid/somemodule@v1.0.0
stderr 'this.domain.is.invalid'
! go mod download -json this.domain.is.invalid/somemodule@v1.0.0
stdout '"Error": ".*this.domain.is.invalid.*"'

# download -json with version should print JSON
go mod download -json 'rsc.io/quote@<=v1.5.0'
stdout '^\t"Path": "rsc.io/quote"'
stdout '^\t"Version": "v1.5.0"'
stdout '^\t"Info": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.0.info"'
stdout '^\t"GoMod": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.0.mod"'
stdout '^\t"Zip": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.0.zip"'
stdout '^\t"Sum": "h1:6fJa6E\+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE="'  # hash of testdata/mod version, not real version!
stdout '^\t"GoModSum": "h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe\+TKr0="'
! stdout '"Error"'

# download queries above should not have added to go.mod.
go list -m all
! stdout rsc.io

# download query should have downloaded go.mod for the highest release version
# in order to find retractions when resolving the query '@<=v1.5.0'.
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip

# add to go.mod so we can test non-query downloads
go mod edit -require rsc.io/quote@v1.5.3-pre1
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.info
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.mod
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.zip

# module loading will page in the info and mod files
go list -m -mod=mod all
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.info
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.mod
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.zip

# download will fetch and unpack the zip file
go mod download
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.info
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.mod
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.zip
exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.3-pre1

# download repopulates deleted files and directories independently.
rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.info
go mod download
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.info
rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.mod
go mod download
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.mod
rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.zip
go mod download
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.zip
rm -r $GOPATH/pkg/mod/rsc.io/quote@v1.5.3-pre1
go mod download
exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.3-pre1

# download reports the locations of downloaded files
go mod download -json
stdout '^\t"Path": "rsc.io/quote"'
stdout '^\t"Version": "v1.5.3-pre1"'
stdout '^\t"Info": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.3-pre1.info"'
stdout '^\t"GoMod": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.3-pre1.mod"'
stdout '^\t"Zip": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.3-pre1.zip"'
stdout '^\t"Dir": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)rsc.io(\\\\|/)quote@v1.5.3-pre1"'

# download will follow replacements
go mod edit -require rsc.io/quote@v1.5.1 -replace rsc.io/quote@v1.5.1=rsc.io/quote@v1.5.2
go mod download
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.1.zip
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip

# download will not follow replacements for explicit module queries
go mod download -json rsc.io/quote@v1.5.1
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.1.zip

# download reports errors encountered when locating modules
! go mod download bad/path
stderr '^go: module bad/path: not a known dependency$'
! go mod download bad/path@latest
stderr '^go: bad/path@latest: malformed module path "bad/path": missing dot in first path element$'
! go mod download rsc.io/quote@v1.999.999
stderr '^go: rsc.io/quote@v1.999.999: reading .*/v1.999.999.info: 404 Not Found$'
! go mod download -json bad/path
stdout '^\t"Error": "module bad/path: not a known dependency"'

# download main module produces a warning or error
go mod download m
stderr '^go: skipping download of m that resolves to the main module\n'
! go mod download m@latest
stderr '^go: m@latest: malformed module path "m": missing dot in first path element$'

# download without arguments updates go.mod and go.sum after loading the
# build list, but does not save sums for downloaded zips.
cd update
cp go.mod.orig go.mod
! exists go.sum
go mod download
cmp go.mod.update go.mod
cmp go.sum.update go.sum
cp go.mod.orig go.mod
rm go.sum

# download with arguments (even "all") does update go.mod and go.sum.
go mod download rsc.io/sampler
cmp go.mod.update go.mod
grep '^rsc.io/sampler v1.3.0 ' go.sum
cp go.mod.orig go.mod
rm go.sum

go mod download all
cmp go.mod.update go.mod
grep '^rsc.io/sampler v1.3.0 ' go.sum

# https://golang.org/issue/44435: At go 1.17 or higher, 'go mod download'
# (without arguments) should only download the modules explicitly required in
# the go.mod file, not (presumed-irrelevant) transitive dependencies.
#
# (If the go.mod file is inconsistent, the version downloaded should be the
# selected version from the broader graph, but the go.mod file will also be
# updated to list the correct versions. If at some point we change 'go mod
# download' to stop updating for consistency, then it should fail if the
# requirements are inconsistent.)

rm go.sum
cp go.mod.orig go.mod
go mod edit -go=1.17
cp go.mod.update go.mod.go117
go mod edit -go=1.17 go.mod.go117

go clean -modcache
go mod download
cmp go.mod go.mod.go117

go list -e -m all
stdout '^rsc.io/quote v1.5.2$'
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
stdout '^rsc.io/sampler v1.3.0$'
! exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.2.1.zip
exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.3.0.zip
stdout '^golang\.org/x/text v0.0.0-20170915032832-14c0d48ead0c$'
! exists $GOPATH/pkg/mod/cache/download/golang.org/x/text/@v/v0.0.0-20170915032832-14c0d48ead0c.zip
cmp go.mod go.mod.go117

# However, 'go mod download all' continues to download the selected version
# of every module reported by 'go list -m all'.

cp go.mod.orig go.mod
go mod edit -go=1.17
go clean -modcache
go mod download all
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
! exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.2.1.zip
exists $GOPATH/pkg/mod/cache/download/rsc.io/sampler/@v/v1.3.0.zip
exists $GOPATH/pkg/mod/cache/download/golang.org/x/text/@v/v0.0.0-20170915032832-14c0d48ead0c.zip
cmp go.mod go.mod.go117

cd ..

# allow go mod download without go.mod
env GO111MODULE=auto
rm go.mod
rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.2.1.zip
go mod download rsc.io/quote@v1.2.1
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.2.1.zip

# download -x with version should print
# the underlying commands such as contacting GOPROXY.
go mod download -x rsc.io/quote@v1.0.0
! stdout .
stderr 'get '$GOPROXY

-- go.mod --
module m

-- update/go.mod.orig --
module m

go 1.16

require (
	rsc.io/quote v1.5.2
	rsc.io/sampler v1.2.1 // older version than in build list
)
-- update/go.mod.update --
module m

go 1.16

require (
	rsc.io/quote v1.5.2
	rsc.io/sampler v1.3.0 // older version than in build list
)
-- update/go.sum.update --
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
