env GO111MODULE=on

# Without vendoring, a build should succeed unless -mod=vendor is set.
[!short] go build
[!short] ! go build -mod=vendor

# Without vendoring, 'go list' should report the replacement directory for
# a package in a replaced module.
go list -f {{.Dir}} x
stdout 'src[\\/]x'

# 'go mod vendor' should copy all replaced modules to the vendor directory.
go mod vendor -v
stderr '^# x v1.0.0 => ./x'
stderr '^x'
stderr '^# y v1.0.0 => ./y'
stderr '^y'
stderr '^# z v1.0.0 => ./z'
stderr '^z'
! stderr '^w'
grep 'a/foo/bar/b\na/foo/bar/c' vendor/modules.txt # must be sorted

# An explicit '-mod=mod' should ignore the vendor directory.
go list -mod=mod -f {{.Dir}} x
stdout 'src[\\/]x'

go list -mod=mod -f {{.Dir}} -m x
stdout 'src[\\/]x'

# An explicit '-mod=vendor' should report package directories within
# the vendor directory.
go list -mod=vendor -f {{.Dir}} x
stdout 'src[\\/]vendor[\\/]x'

# 'go list -mod=vendor -m' should successfully list vendored modules,
# but should not provide a module directory because no directory contains
# the complete module.
go list -mod=vendor -f '{{.Version}} {{.Dir}}' -m x
stdout '^v1.0.0 $'

# -mod=vendor should cause 'go list' flags that look up versions to fail.
! go list -mod=vendor -versions -m x
stderr '^go: can''t determine available versions using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)$'
! go list -mod=vendor -u -m x
stderr '^go: can''t determine available upgrades using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)$'

# 'go list -mod=vendor -m' on a transitive dependency that does not
# provide vendored packages should give a helpful error rather than
# 'not a known dependency'.
! go list -mod=vendor -f '{{.Version}} {{.Dir}}' -m diamondright
stderr 'go: module diamondright: can''t resolve module using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)'

# 'go list -mod=mod' should report packages outside the import graph,
# but 'go list -mod=vendor' should error out for them.
go list -mod=mod -f {{.Dir}} w
stdout 'src[\\/]w'
! go list -mod=vendor -f {{.Dir}} w
stderr 'package w is not in GOROOT'

go list -mod=mod -f {{.Dir}} diamondright
stdout 'src[\\/]diamondright'

# Test dependencies should not be copied.
! exists vendor/x/testdata
! exists vendor/a/foo/bar/b/ignored.go
! exists vendor/a/foo/bar/b/main_test.go

# Licenses and other metadata for each module should be copied
# if any package within their module is copied.
exists vendor/a/foo/AUTHORS.txt
exists vendor/a/foo/CONTRIBUTORS
exists vendor/a/foo/LICENSE
exists vendor/a/foo/PATENTS
exists vendor/a/foo/COPYING
exists vendor/a/foo/COPYLEFT
exists vendor/x/NOTICE!
exists vendor/mysite/myname/mypkg/LICENSE.txt

! exists vendor/a/foo/licensed-to-kill
! exists vendor/w
! exists vendor/w/LICENSE
! exists vendor/x/x2
! exists vendor/x/x2/LICENSE

# 'go mod vendor' should work with an alternative vendor directory if the -o flag is provided.
go mod vendor -v -o alternative-vendor-dir
exists alternative-vendor-dir/modules.txt
exists alternative-vendor-dir/a/foo/LICENSE

# 'go mod vendor' should interpret paths relative to the current working directory when the -o flag is provided.
mkdir dir1
mkdir dir2

cd dir1
go mod vendor -v -o relative-vendor-dir

go mod vendor -v -o ../dir2/relative-vendor-dir

cd ..
exists dir1/relative-vendor-dir/modules.txt
exists dir1/relative-vendor-dir/a/foo/LICENSE
exists dir2/relative-vendor-dir/modules.txt
exists dir2/relative-vendor-dir/a/foo/LICENSE

# 'go mod vendor' should fall back to the default 'vendor' directory when an empty argument is passed to the -o flag
# the same behavior should be exhibited both on the module root directory, as well as nested subdirectories

go mod vendor -v -o ''
exists vendor/modules.txt

env GOFLAGS=-o=foo
go mod vendor -v -o ''
exists vendor/modules.txt
env GOFLAGS=''

mkdir -p nested/dir
cd nested/dir
go mod vendor -v -o ''
! exists vendor/
exists ../../vendor/modules.txt
cd ../..

# 'go mod vendor' should work with absolute paths as well
go mod vendor -v -o $WORK/tmp/absolute-vendor-dir
exists $WORK/tmp/absolute-vendor-dir/modules.txt

[short] stop

# 'go build' and 'go test' using vendored packages should succeed.
go build -mod=mod
go build -mod=vendor
go test -mod=vendor . ./subdir
go test -mod=vendor ./...
go fmt -mod=vendor ./...

-- go.mod --
module m

go 1.13

require (
	a v1.0.0
	diamondroot v0.0.0
	mysite/myname/mypkg v1.0.0
	w v1.0.0 // indirect
	x v1.0.0
	y v1.0.0
	z v1.0.0
)

replace (
	a v1.0.0 => ./a
	diamondleft => ./diamondleft
	diamondpoint => ./diamondpoint
	diamondright => ./diamondright
	diamondroot => ./diamondroot
	mysite/myname/mypkg v1.0.0 => ./mypkg
	w v1.0.0 => ./w
	x v1.0.0 => ./x
	y v1.0.0 => ./y
	z v1.0.0 => ./z
)

-- a/foo/AUTHORS.txt --
-- a/foo/CONTRIBUTORS --
-- a/foo/LICENSE --
-- a/foo/PATENTS --
-- a/foo/COPYING --
-- a/foo/COPYLEFT --
-- a/foo/licensed-to-kill --
-- w/LICENSE --
-- x/NOTICE! --
-- x/x2/LICENSE --
-- mypkg/LICENSE.txt --

-- a/foo/bar/b/main.go --
package b
-- a/foo/bar/b/ignored.go --
// This file is intended for use with "go run"; it isn't really part of the package.

// +build ignore

package main

func main() {}
-- a/foo/bar/b/main_test.go --
package b

import (
	"os"
	"testing"
)

func TestDir(t *testing.T) {
	if _, err := os.Stat("../testdata/1"); err != nil {
		t.Fatalf("testdata: %v", err)
	}
}
-- a/foo/bar/c/main.go --
package c
import _ "a/foo/bar/b"
-- a/foo/bar/c/main_test.go --
package c

import (
	"os"
	"testing"
)

func TestDir(t *testing.T) {
	if _, err := os.Stat("../../../testdata/1"); err != nil {
		t.Fatalf("testdata: %v", err)
	}
	if _, err := os.Stat("./testdata/1"); err != nil {
		t.Fatalf("testdata: %v", err)
	}
}
-- a/foo/bar/c/testdata/1 --
-- a/foo/bar/testdata/1 --
-- a/go.mod --
module a
-- a/main.go --
package a
-- a/main_test.go --
package a

import (
	"os"
	"testing"
)

func TestDir(t *testing.T) {
	if _, err := os.Stat("./testdata/1"); err != nil {
		t.Fatalf("testdata: %v", err)
	}
}
-- a/testdata/1 --
-- appengine.go --
// +build appengine

package m

import _ "appengine"
import _ "appengine/datastore"
-- mypkg/go.mod --
module me
-- mypkg/mydir/d.go --
package mydir
-- subdir/v1_test.go --
package m

import _ "mysite/myname/mypkg/mydir"
-- testdata1.go --
package m

import _ "a"
-- testdata2.go --
package m

import _ "a/foo/bar/c"
-- v1.go --
package m

import _ "x"
-- v2.go --
// +build abc

package mMmMmMm

import _ "y"
-- v3.go --
// +build !abc

package m

import _ "z"
-- v4.go --
// +build notmytag

package m

import _ "x/x1"
-- importdiamond.go --
package m

import _ "diamondroot"
-- w/go.mod --
module w
-- w/w.go --
package w
-- x/go.mod --
module x
-- x/testdata/x.txt --
placeholder - want directory with no go files
-- x/x.go --
package x
-- x/x1/x1.go --
// +build notmytag

package x1
-- x/x2/dummy.txt --
dummy
-- x/x_test.go --
package x

import _ "w"
-- y/go.mod --
module y
-- y/y.go --
package y
-- z/go.mod --
module z
-- z/z.go --
package z

-- diamondroot/go.mod --
module diamondroot

require (
	diamondleft v0.0.0
	diamondright v0.0.0
)
-- diamondroot/x.go --
package diamondroot

import _ "diamondleft"
-- diamondroot/unused/unused.go --
package unused

import _ "diamondright"
-- diamondleft/go.mod --
module diamondleft

require (
	diamondpoint v0.0.0
)
-- diamondleft/x.go --
package diamondleft

import _ "diamondpoint"
-- diamondright/go.mod --
module diamondright

require (
	diamondpoint v0.0.0
)
-- diamondright/x.go --
package diamondright

import _ "diamondpoint"
-- diamondpoint/go.mod --
module diamondpoint
-- diamondpoint/x.go --
package diamondpoint
