View
@@ -683,7 +683,7 @@
// path to the vendor directory (for example, "d/vendor/p" instead of "p"),
// so that the ImportPath uniquely identifies a given copy of a package.
// The Imports, Deps, TestImports, and XTestImports lists also contain these
// expanded imports paths. See golang.org/s/go15vendor for more about vendoring.
// expanded import paths. See golang.org/s/go15vendor for more about vendoring.
//
// The error information, if any, is
//
@@ -871,16 +871,50 @@
//
// The commands are:
//
// download download modules to local cache
// edit edit go.mod from tools or scripts
// fix make go.mod semantically consistent
// graph print module requirement graph
// init initialize new module in current directory
// tidy add missing and remove unused modules
// vendor make vendored copy of dependencies
// verify verify dependencies have expected content
// why explain why packages or modules are needed
//
// Use "go help mod <command>" for more information about a command.
//
// Download modules to local cache
//
// Usage:
//
// go mod download [-dir] [-json] [modules]
//
// Download downloads the named modules, which can be module patterns selecting
// dependencies of the main module or module queries of the form path@version.
// With no arguments, download applies to all dependencies of the main module.
//
// The go command will automatically download modules as needed during ordinary
// execution. The "go mod download" command is useful mainly for pre-filling
// the local cache or to compute the answers for a Go module proxy.
//
// By default, download reports errors to standard error but is otherwise silent.
// The -json flag causes download to print a sequence of JSON objects
// to standard output, describing each downloaded module (or failure),
// corresponding to this Go struct:
//
// type Module struct {
// Path string // module path
// Version string // module version
// Error string // error loading module
// Info string // absolute path to cached .info file
// GoMod string // absolute path to cached .mod file
// Zip string // absolute path to cached .zip file
// Dir string // absolute path to cached source root directory
// }
//
// See 'go help module' for more about module queries.
//
//
// Edit go.mod from tools or scripts
//
// Usage:
@@ -1079,6 +1113,42 @@
// non-zero status.
//
//
// Explain why packages or modules are needed
//
// Usage:
//
// go mod why [-m] [-vendor] packages...
//
// Why shows a shortest path in the import graph from the main module to
// each of the listed packages. If the -m flag is given, why treats the
// arguments as a list of modules and finds a path to any package in each
// of the modules.
//
// By default, why queries the graph of packages matched by "go list all",
// which includes tests for reachable packages. The -vendor flag causes why
// to exclude tests of dependencies.
//
// The output is a sequence of stanzas, one for each package or module
// name on the command line, separated by blank lines. Each stanza begins
// with a comment line "# package" or "# module" giving the target
// package or module. Subsequent lines give a path through the import
// graph, one package per line. If the package or module is not
// referenced from the main module, the stanza will display a single
// parenthesized note indicating that fact.
//
// For example:
//
// $ go mod why golang.org/x/text/language golang.org/x/text/encoding
// # golang.org/x/text/language
// rsc.io/quote
// rsc.io/sampler
// golang.org/x/text/language
//
// # golang.org/x/text/encoding
// (main module does not need package golang.org/x/text/encoding)
// $
//
//
// Compile and run Go program
//
// Usage:
@@ -1708,10 +1778,10 @@
//
// The go command by default downloads modules from version control systems
// directly, just as 'go get' always has. The GOPROXY environment variable allows
// further control over the download source. GOPROXY being unset, the empty string,
// or the string "direct" corresponds to the default direct connection to version
// further control over the download source. If GOPROXY is unset, is the empty string,
// or is the string "direct", downloads use the default direct connection to version
// control systems. Setting GOPROXY to "off" disallows downloading modules from
// any source. Otherwise, if GOPROXY is expected to be the URL of a module proxy,
// any source. Otherwise, GOPROXY is expected to be the URL of a module proxy,
// in which case the go command will fetch all modules from that proxy.
// No matter the source of the modules, downloaded modules must match existing
// entries in go.sum (see 'go help modules' for discussion of verification).
@@ -1737,7 +1807,7 @@
//
// To avoid problems when serving from case-sensitive file systems,
// the <module> and <version> elements are case-encoded, replacing every
// uppercase letter with an exclamation mark followed by the correponding
// uppercase letter with an exclamation mark followed by the corresponding
// lower-case letter: github.com/Azure encodes as github.com/!azure.
//
// The JSON-formatted metadata about a given module corresponds to
@@ -2117,10 +2187,14 @@
// and understanding modules and go.mod files. See 'go help mod'.
//
// The -mod build flag provides additional control over updating and use of go.mod.
// If invoked with -mod=readonly, the go command disables its automatic updates
// of go.mod as described above and fails if any changes are needed. This setting
// is most useful to check that go.mod does not need any updates, such as in a
// continuous integration and testing system.
//
// If invoked with -mod=readonly, the go command is disallowed from the implicit
// automatic updating of go.mod described above. Instead, it fails when any changes
// to go.mod are needed. This setting is most useful to check that go.mod does
// not need updates, such as in a continuous integration and testing system.
// The "go get" command remains permitted to update go.mod even with -mod=readonly,
// and the "go mod" commands do not take the -mod flag (or any other build flags).
//
// If invoked with -mod=vendor, the go command assumes that the vendor
// directory holds the correct copies of dependencies and ignores
// the dependency descriptions in go.mod.
View
@@ -3047,6 +3047,9 @@ func TestGoTestMainAsNormalTest(t *testing.T) {
}
func TestGoTestMainTwice(t *testing.T) {
if testing.Short() {
t.Skip("Skipping in short mode")
}
tg := testgo(t)
defer tg.cleanup()
tg.makeTempdir()
@@ -5817,57 +5820,6 @@ func init() {}
tg.run("test", "a")
}
// Issue 23150.
func TestCpuprofileTwice(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempFile("prof/src/x/x_test.go", `
package x_test
import (
"testing"
"time"
)
func TestSleep(t *testing.T) { time.Sleep(10 * time.Millisecond) }`)
tg.setenv("GOPATH", tg.path("prof"))
bin := tg.path("x.test")
out := tg.path("cpu.out")
tg.run("test", "-o="+bin, "-cpuprofile="+out, "x")
tg.must(os.Remove(out))
tg.run("test", "-o="+bin, "-cpuprofile="+out, "x")
tg.mustExist(out)
}
// Issue 23694.
func TestAtomicCoverpkgAll(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempFile("src/x/x.go", `package x; import _ "sync/atomic"; func F() {}`)
tg.tempFile("src/x/x_test.go", `package x; import "testing"; func TestF(t *testing.T) { F() }`)
tg.setenv("GOPATH", tg.path("."))
tg.run("test", "-coverpkg=all", "-covermode=atomic", "x")
if canRace {
tg.run("test", "-coverpkg=all", "-race", "x")
}
}
// Issue 23882.
func TestCoverpkgAllRuntime(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempFile("src/x/x.go", `package x; import _ "runtime"; func F() {}`)
tg.tempFile("src/x/x_test.go", `package x; import "testing"; func TestF(t *testing.T) { F() }`)
tg.setenv("GOPATH", tg.path("."))
tg.run("test", "-coverpkg=all", "x")
if canRace {
tg.run("test", "-coverpkg=all", "-race", "x")
}
}
func TestBadCommandLines(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
View
@@ -60,7 +60,7 @@ func runFmt(cmd *base.Command, args []string) {
}()
}
for _, pkg := range load.PackagesAndErrors(args) {
if modload.Enabled() && !pkg.Module.Main {
if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main {
if !printed {
fmt.Fprintf(os.Stderr, "go: not formatting packages in dependency modules\n")
printed = true
View
@@ -5,7 +5,6 @@
package get
import (
"bytes"
"encoding/json"
"errors"
"fmt"
@@ -428,19 +427,18 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
fmt.Printf("cd %s\n", dir)
fmt.Printf("%s %s\n", v.cmd, strings.Join(args, " "))
}
var buf bytes.Buffer
cmd.Stdout = &buf
cmd.Stderr = &buf
err = cmd.Run()
out := buf.Bytes()
out, err := cmd.Output()
if err != nil {
if verbose || cfg.BuildV {
fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " "))
os.Stderr.Write(out)
if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
os.Stderr.Write(ee.Stderr)
} else {
fmt.Fprintf(os.Stderr, err.Error())
}
}
return out, err
}
return out, nil
return out, err
}
// ping pings to determine scheme to use.
View
@@ -20,6 +20,7 @@ import (
"cmd/go/internal/cfg"
"cmd/go/internal/load"
"cmd/go/internal/modload"
"cmd/go/internal/str"
"cmd/go/internal/work"
)
@@ -107,7 +108,7 @@ Packages stored in vendor directories report an ImportPath that includes the
path to the vendor directory (for example, "d/vendor/p" instead of "p"),
so that the ImportPath uniquely identifies a given copy of a package.
The Imports, Deps, TestImports, and XTestImports lists also contain these
expanded imports paths. See golang.org/s/go15vendor for more about vendoring.
expanded import paths. See golang.org/s/go15vendor for more about vendoring.
The error information, if any, is
@@ -146,7 +147,8 @@ instead of using the template format.
The -compiled flag causes list to set CompiledGoFiles to the Go source
files presented to the compiler. Typically this means that it repeats
the files listed in GoFiles and then also adds the Go code generated
by processing CgoFiles and SwigFiles.
by processing CgoFiles and SwigFiles. The Imports list contains the
union of all imports from both GoFiles and CompiledGoFiles.
The -deps flag causes list to iterate over not just the named packages
but also all their dependencies. It visits them in a depth-first post-order
@@ -303,6 +305,7 @@ var (
var nl = []byte{'\n'}
func runList(cmd *base.Command, args []string) {
modload.LoadTests = *listTest
work.BuildInit()
out := newTrackingWriter(os.Stdout)
defer out.w.Flush()
@@ -516,6 +519,10 @@ func runList(cmd *base.Command, args []string) {
p.TestImports = p.Resolve(p.TestImports)
p.XTestImports = p.Resolve(p.XTestImports)
p.DepOnly = !cmdline[p]
if *listCompiled {
p.Imports = str.StringList(p.Imports, p.Internal.CompiledImports)
}
}
if *listTest {
View
@@ -32,13 +32,13 @@ var (
ModInit func()
// module hooks; nil if module use is disabled
ModBinDir func() string // return effective bin directory
ModLookup func(parentPath, path string) (dir, realPath string, err error) // lookup effective meaning of import
ModPackageModuleInfo func(path string) *modinfo.ModulePublic // return module info for Package struct
ModImportPaths func(args []string) []string // expand import paths
ModPackageBuildInfo func(main string, deps []string) string // return module info to embed in binary
ModInfoProg func(info string) []byte // wrap module info in .go code for binary
ModImportFromFiles func([]string) // update go.mod to add modules for imports in these files
ModBinDir func() string // return effective bin directory
ModLookup func(path string) (dir, realPath string, err error) // lookup effective meaning of import
ModPackageModuleInfo func(path string) *modinfo.ModulePublic // return module info for Package struct
ModImportPaths func(args []string) []string // expand import paths
ModPackageBuildInfo func(main string, deps []string) string // return module info to embed in binary
ModInfoProg func(info string) []byte // wrap module info in .go code for binary
ModImportFromFiles func([]string) // update go.mod to add modules for imports in these files
)
var IgnoreImports bool // control whether we ignore imports in packages
@@ -157,6 +157,7 @@ type PackageInternal struct {
// Unexported fields are not part of the public API.
Build *build.Package
Imports []*Package // this package's direct imports
CompiledImports []string // additional Imports necessary when using CompiledGoFiles (all from standard library)
RawImports []string // this package's original imports as they appear in the text of the program
ForceLibrary bool // this package is a library (even if named "main")
CmdlineFiles bool // package built from files listed on command line
@@ -319,7 +320,8 @@ func (p *PackageError) Error() string {
}
// An ImportStack is a stack of import paths, possibly with the suffix " (test)" appended.
// TODO(bcmills): When the tree opens for 1.12, replace the suffixed string with a struct.
// The import path of a test package is the import path of the corresponding
// non-test package with the suffix "_test" added.
type ImportStack []string
func (s *ImportStack) Push(p string) {
@@ -468,6 +470,11 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo
}
}
parentPath := ""
if parent != nil {
parentPath = parent.ImportPath
}
// Determine canonical identifier for this package.
// For a local import the identifier is the pseudo-import path
// we create from the full directory to the package.
@@ -481,12 +488,8 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo
if isLocal {
importPath = dirToImportPath(filepath.Join(srcDir, path))
} else if cfg.ModulesEnabled {
parentPath := ""
if parent != nil {
parentPath = parent.ImportPath
}
var p string
modDir, p, modErr = ModLookup(parentPath, path)
modDir, p, modErr = ModLookup(path)
if modErr == nil {
importPath = p
}
@@ -557,11 +560,11 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo
}
// Checked on every import because the rules depend on the code doing the importing.
if perr := disallowInternal(srcDir, p, stk); perr != p {
if perr := disallowInternal(srcDir, parentPath, p, stk); perr != p {
return setErrorPos(perr, importPos)
}
if mode&ResolveImport != 0 {
if perr := disallowVendor(srcDir, origPath, p, stk); perr != p {
if perr := disallowVendor(srcDir, parentPath, origPath, p, stk); perr != p {
return setErrorPos(perr, importPos)
}
}
@@ -626,11 +629,7 @@ func isDir(path string) bool {
// Go 1.11 module legacy conversion (golang.org/issue/25069).
func ResolveImportPath(parent *Package, path string) (found string) {
if cfg.ModulesEnabled {
parentPath := ""
if parent != nil {
parentPath = parent.ImportPath
}
if _, p, e := ModLookup(parentPath, path); e == nil {
if _, p, e := ModLookup(path); e == nil {
return p
}
return path
@@ -922,10 +921,11 @@ func reusePackage(p *Package, stk *ImportStack) *Package {
return p
}
// disallowInternal checks that srcDir is allowed to import p.
// disallowInternal checks that srcDir (containing package importerPath, if non-empty)
// is allowed to import p.
// If the import is allowed, disallowInternal returns the original package p.
// If not, it returns a new package containing just an appropriate error.
func disallowInternal(srcDir string, p *Package, stk *ImportStack) *Package {
func disallowInternal(srcDir, importerPath string, p *Package, stk *ImportStack) *Package {
// golang.org/s/go14internal:
// An import of a path containing the element “internal”
// is disallowed if the importing code is outside the tree
@@ -969,7 +969,6 @@ func disallowInternal(srcDir string, p *Package, stk *ImportStack) *Package {
i-- // rewind over slash in ".../internal"
}
var where string
if p.Module == nil {
parent := p.Dir[:i+len(p.Dir)-len(p.ImportPath)]
@@ -987,18 +986,16 @@ func disallowInternal(srcDir string, p *Package, stk *ImportStack) *Package {
// p is in a module, so make it available based on the import path instead
// of the file path (https://golang.org/issue/23970).
parent := p.ImportPath[:i]
importer := strings.TrimSuffix((*stk)[len(*stk)-2], " (test)")
if str.HasPathPrefix(importer, parent) {
if str.HasPathPrefix(importerPath, parent) {
return p
}
where = " in " + importer
}
// Internal is present, and srcDir is outside parent's tree. Not allowed.
perr := *p
perr.Error = &PackageError{
ImportStack: stk.Copy(),
Err: "use of internal package " + p.ImportPath + " not allowed" + where,
Err: "use of internal package " + p.ImportPath + " not allowed",
}
perr.Incomplete = true
return &perr
@@ -1023,10 +1020,11 @@ func findInternal(path string) (index int, ok bool) {
return 0, false
}
// disallowVendor checks that srcDir is allowed to import p as path.
// disallowVendor checks that srcDir (containing package importerPath, if non-empty)
// is allowed to import p as path.
// If the import is allowed, disallowVendor returns the original package p.
// If not, it returns a new package containing just an appropriate error.
func disallowVendor(srcDir, path string, p *Package, stk *ImportStack) *Package {
func disallowVendor(srcDir, importerPath, path string, p *Package, stk *ImportStack) *Package {
// The stack includes p.ImportPath.
// If that's the only thing on the stack, we started
// with a name given on the command line, not an
@@ -1035,13 +1033,12 @@ func disallowVendor(srcDir, path string, p *Package, stk *ImportStack) *Package
return p
}
if p.Standard && ModPackageModuleInfo != nil {
if p.Standard && ModPackageModuleInfo != nil && importerPath != "" {
// Modules must not import vendor packages in the standard library,
// but the usual vendor visibility check will not catch them
// because the module loader presents them with an ImportPath starting
// with "golang_org/" instead of "vendor/".
importer := strings.TrimSuffix((*stk)[len(*stk)-2], " (test)")
if mod := ModPackageModuleInfo(importer); mod != nil {
if mod := ModPackageModuleInfo(importerPath); mod != nil {
dir := p.Dir
if relDir, err := filepath.Rel(p.Root, p.Dir); err == nil {
dir = relDir
@@ -1245,6 +1242,37 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
return
}
_, elem := filepath.Split(p.Dir)
if cfg.ModulesEnabled {
// NOTE(rsc): Using p.ImportPath instead of p.Dir
// makes sure we install a package in the root of a
// cached module directory as that package name
// not name@v1.2.3.
// Using p.ImportPath instead of p.Dir
// is probably correct all the time,
// even for non-module-enabled code,
// but I'm not brave enough to change the
// non-module behavior this late in the
// release cycle. Maybe for Go 1.12.
// See golang.org/issue/26869.
_, elem = pathpkg.Split(p.ImportPath)
// If this is example.com/mycmd/v2, it's more useful to install it as mycmd than as v2.
// See golang.org/issue/24667.
isVersion := func(v string) bool {
if len(v) < 2 || v[0] != 'v' || v[1] < '1' || '9' < v[1] {
return false
}
for i := 2; i < len(v); i++ {
if c := v[i]; c < '0' || '9' < c {
return false
}
}
return true
}
if isVersion(elem) {
_, elem = pathpkg.Split(pathpkg.Dir(p.ImportPath))
}
}
full := cfg.BuildContext.GOOS + "_" + cfg.BuildContext.GOARCH + "/" + elem
if cfg.BuildContext.GOOS != base.ToolGOOS || cfg.BuildContext.GOARCH != base.ToolGOARCH {
// Install cross-compiled binaries to subdirectories of bin.
@@ -1300,31 +1328,37 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
// Build augmented import list to add implicit dependencies.
// Be careful not to add imports twice, just to avoid confusion.
importPaths := p.Imports
addImport := func(path string) {
addImport := func(path string, forCompiler bool) {
for _, p := range importPaths {
if path == p {
return
}
}
importPaths = append(importPaths, path)
if forCompiler {
p.Internal.CompiledImports = append(p.Internal.CompiledImports, path)
}
}
// Cgo translation adds imports of "runtime/cgo" and "syscall",
// Cgo translation adds imports of "unsafe", "runtime/cgo" and "syscall",
// except for certain packages, to avoid circular dependencies.
if p.UsesCgo() {
addImport("unsafe", true)
}
if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) && cfg.BuildContext.Compiler != "gccgo" {
addImport("runtime/cgo")
addImport("runtime/cgo", true)
}
if p.UsesCgo() && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) {
addImport("syscall")
addImport("syscall", true)
}
// SWIG adds imports of some standard packages.
if p.UsesSwig() {
if cfg.BuildContext.Compiler != "gccgo" {
addImport("runtime/cgo")
addImport("runtime/cgo", true)
}
addImport("syscall")
addImport("sync")
addImport("syscall", true)
addImport("sync", true)
// TODO: The .swig and .swigcxx files can use
// %go_import directives to import other packages.
@@ -1333,7 +1367,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
// The linker loads implicit dependencies.
if p.Name == "main" && !p.Internal.ForceLibrary {
for _, dep := range LinkerDeps(p) {
addImport(dep)
addImport(dep, false)
}
}
@@ -1771,7 +1805,7 @@ func LoadPackage(arg string, stk *ImportStack) *Package {
return LoadImport(arg, base.Cwd, nil, stk, nil, 0)
}
// packages returns the packages named by the
// Packages returns the packages named by the
// command line arguments 'args'. If a named package
// cannot be loaded at all (for example, if the directory does not exist),
// then packages prints an error and does not include that
@@ -1791,7 +1825,7 @@ func Packages(args []string) []*Package {
return pkgs
}
// packagesAndErrors is like 'packages' but returns a
// PackagesAndErrors is like 'packages' but returns a
// *Package for every argument, even the ones that
// cannot be loaded at all.
// The packages that fail to load will have p.Error != nil.
View
@@ -342,6 +342,8 @@ func recompileForTest(pmain, preal, ptest, pxtest *Package) {
p1.ForTest = preal.ImportPath
p1.Internal.Imports = make([]*Package, len(p.Internal.Imports))
copy(p1.Internal.Imports, p.Internal.Imports)
p1.Imports = make([]string, len(p.Imports))
copy(p1.Imports, p.Imports)
p = p1
p.Target = ""
}
View
@@ -0,0 +1,123 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package modcmd
import (
"cmd/go/internal/base"
"cmd/go/internal/modfetch"
"cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/par"
"encoding/json"
"os"
)
var cmdDownload = &base.Command{
UsageLine: "go mod download [-dir] [-json] [modules]",
Short: "download modules to local cache",
Long: `
Download downloads the named modules, which can be module patterns selecting
dependencies of the main module or module queries of the form path@version.
With no arguments, download applies to all dependencies of the main module.
The go command will automatically download modules as needed during ordinary
execution. The "go mod download" command is useful mainly for pre-filling
the local cache or to compute the answers for a Go module proxy.
By default, download reports errors to standard error but is otherwise silent.
The -json flag causes download to print a sequence of JSON objects
to standard output, describing each downloaded module (or failure),
corresponding to this Go struct:
type Module struct {
Path string // module path
Version string // module version
Error string // error loading module
Info string // absolute path to cached .info file
GoMod string // absolute path to cached .mod file
Zip string // absolute path to cached .zip file
Dir string // absolute path to cached source root directory
}
See 'go help module' for more about module queries.
`,
}
var downloadJSON = cmdDownload.Flag.Bool("json", false, "")
func init() {
cmdDownload.Run = runDownload // break init cycle
}
type moduleJSON struct {
Path string `json:",omitempty"`
Version string `json:",omitempty"`
Error string `json:",omitempty"`
Info string `json:",omitempty"`
GoMod string `json:",omitempty"`
Zip string `json:",omitempty"`
Dir string `json:",omitempty"`
}
func runDownload(cmd *base.Command, args []string) {
if len(args) == 0 {
args = []string{"all"}
}
var mods []*moduleJSON
var work par.Work
listU := false
listVersions := false
for _, info := range modload.ListModules(args, listU, listVersions) {
if info.Replace != nil {
info = info.Replace
}
if info.Version == "" {
continue
}
m := &moduleJSON{
Path: info.Path,
Version: info.Version,
}
mods = append(mods, m)
work.Add(m)
}
work.Do(10, func(item interface{}) {
m := item.(*moduleJSON)
var err error
m.Info, err = modfetch.InfoFile(m.Path, m.Version)
if err != nil {
m.Error = err.Error()
return
}
m.GoMod, err = modfetch.GoModFile(m.Path, m.Version)
if err != nil {
m.Error = err.Error()
return
}
mod := module.Version{Path: m.Path, Version: m.Version}
m.Zip, err = modfetch.DownloadZip(mod)
if err != nil {
m.Error = err.Error()
return
}
m.Dir, err = modfetch.Download(mod)
if err != nil {
m.Error = err.Error()
return
}
})
if *downloadJSON {
for _, m := range mods {
b, err := json.MarshalIndent(m, "", "\t")
if err != nil {
base.Fatalf("%v", err)
}
os.Stdout.Write(append(b, '\n'))
}
}
}
View
@@ -19,12 +19,14 @@ See 'go help modules' for an overview of module functionality.
`,
Commands: []*base.Command{
cmdDownload,
cmdEdit,
cmdFix,
cmdGraph,
cmdInit,
cmdTidy,
cmdVendor,
cmdVerify,
cmdWhy,
},
}
View
@@ -0,0 +1,119 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package modcmd
import (
"cmd/go/internal/base"
"cmd/go/internal/modload"
"cmd/go/internal/module"
"fmt"
"strings"
)
var cmdWhy = &base.Command{
UsageLine: "go mod why [-m] [-vendor] packages...",
Short: "explain why packages or modules are needed",
Long: `
Why shows a shortest path in the import graph from the main module to
each of the listed packages. If the -m flag is given, why treats the
arguments as a list of modules and finds a path to any package in each
of the modules.
By default, why queries the graph of packages matched by "go list all",
which includes tests for reachable packages. The -vendor flag causes why
to exclude tests of dependencies.
The output is a sequence of stanzas, one for each package or module
name on the command line, separated by blank lines. Each stanza begins
with a comment line "# package" or "# module" giving the target
package or module. Subsequent lines give a path through the import
graph, one package per line. If the package or module is not
referenced from the main module, the stanza will display a single
parenthesized note indicating that fact.
For example:
$ go mod why golang.org/x/text/language golang.org/x/text/encoding
# golang.org/x/text/language
rsc.io/quote
rsc.io/sampler
golang.org/x/text/language
# golang.org/x/text/encoding
(main module does not need package golang.org/x/text/encoding)
$
`,
}
var (
whyM = cmdWhy.Flag.Bool("m", false, "")
whyVendor = cmdWhy.Flag.Bool("vendor", false, "")
)
func init() {
cmdWhy.Run = runWhy // break init cycle
}
func runWhy(cmd *base.Command, args []string) {
loadALL := modload.LoadALL
if *whyVendor {
loadALL = modload.LoadVendor
}
if *whyM {
listU := false
listVersions := false
for _, arg := range args {
if strings.Contains(arg, "@") {
base.Fatalf("go mod why: module query not allowed")
}
}
mods := modload.ListModules(args, listU, listVersions)
byModule := make(map[module.Version][]string)
for _, path := range loadALL() {
m := modload.PackageModule(path)
if m.Path != "" {
byModule[m] = append(byModule[m], path)
}
}
sep := ""
for _, m := range mods {
best := ""
bestDepth := 1000000000
for _, path := range byModule[module.Version{Path: m.Path, Version: m.Version}] {
d := modload.WhyDepth(path)
if d > 0 && d < bestDepth {
best = path
bestDepth = d
}
}
why := modload.Why(best)
if why == "" {
vendoring := ""
if *whyVendor {
vendoring = " to vendor"
}
why = "(main module does not need" + vendoring + " module " + m.Path + ")\n"
}
fmt.Printf("%s# %s\n%s", sep, m.Path, why)
sep = "\n"
}
} else {
pkgs := modload.ImportPaths(args) // resolve to packages
loadALL() // rebuild graph, from main module (not from named packages)
sep := ""
for _, path := range pkgs {
why := modload.Why(path)
if why == "" {
vendoring := ""
if *whyVendor {
vendoring = " to vendor"
}
why = "(main module does not need" + vendoring + " package " + path + ")\n"
}
fmt.Printf("%s# %s\n%s", sep, path, why)
sep = "\n"
}
}
}
View
@@ -232,6 +232,23 @@ func Stat(path, rev string) (*RevInfo, error) {
return repo.Stat(rev)
}
// InfoFile is like Stat but returns the name of the file containing
// the cached information.
func InfoFile(path, version string) (string, error) {
if !semver.IsValid(version) {
return "", fmt.Errorf("invalid version %q", version)
}
if _, err := Stat(path, version); err != nil {
return "", err
}
// Stat should have populated the disk cache for us.
file, _, err := readDiskStat(path, version)
if err != nil {
return "", err
}
return file, nil
}
// GoMod is like Lookup(path).GoMod(rev) but avoids the
// repository path resolution in Lookup if the result is
// already cached on local disk.
@@ -256,6 +273,23 @@ func GoMod(path, rev string) ([]byte, error) {
return repo.GoMod(rev)
}
// GoModFile is like GoMod but returns the name of the file containing
// the cached information.
func GoModFile(path, version string) (string, error) {
if !semver.IsValid(version) {
return "", fmt.Errorf("invalid version %q", version)
}
if _, err := GoMod(path, version); err != nil {
return "", err
}
// GoMod should have populated the disk cache for us.
file, _, err := readDiskGoMod(path, version)
if err != nil {
return "", err
}
return file, nil
}
var errNotCached = fmt.Errorf("not in cache")
// readDiskStat reads a cached stat result from disk,
@@ -274,6 +308,13 @@ func readDiskStat(path, rev string) (file string, info *RevInfo, err error) {
if err := json.Unmarshal(data, info); err != nil {
return file, nil, errNotCached
}
// The disk might have stale .info files that have Name and Short fields set.
// We want to canonicalize to .info files with those fields omitted.
// Remarshal and update the cache file if needed.
data2, err := json.Marshal(info)
if err == nil && !bytes.Equal(data2, data) {
writeDiskCache(file, data)
}
return file, info, nil
}
View
@@ -347,34 +347,41 @@ func (r *gitRepo) stat(rev string) (*RevInfo, error) {
if err == nil {
return r.statLocal(rev, ref)
}
if !strings.Contains(err.Error(), "unadvertised object") && !strings.Contains(err.Error(), "no such remote ref") && !strings.Contains(err.Error(), "does not support shallow") {
return nil, err
}
// Don't try to be smart about parsing the error.
// It's too complex and varies too much by git version.
// No matter what went wrong, fall back to a complete fetch.
}
// Last resort.
// Fetch all heads and tags and hope the hash we want is in the history.
if r.fetchLevel < fetchAll {
// TODO(bcmills): should we wait to upgrade fetchLevel until after we check
// err? If there is a temporary server error, we want subsequent fetches to
// try again instead of proceeding with an incomplete repo.
r.fetchLevel = fetchAll
// To work around a protocol version 2 bug that breaks --unshallow,
// add -c protocol.version=0.
// TODO(rsc): The bug is believed to be server-side, meaning only
// on Google's Git servers. Once the servers are fixed, drop the
// protocol.version=0. See Google-internal bug b/110495752.
var protoFlag []string
unshallowFlag := unshallow(r.dir)
if len(unshallowFlag) > 0 {
protoFlag = []string{"-c", "protocol.version=0"}
}
if _, err := Run(r.dir, "git", protoFlag, "fetch", unshallowFlag, "-f", r.remote, "refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"); err != nil {
if err := r.fetchUnshallow("refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"); err != nil {
return nil, err
}
}
return r.statLocal(rev, rev)
}
func (r *gitRepo) fetchUnshallow(refSpecs ...string) error {
// To work around a protocol version 2 bug that breaks --unshallow,
// add -c protocol.version=0.
// TODO(rsc): The bug is believed to be server-side, meaning only
// on Google's Git servers. Once the servers are fixed, drop the
// protocol.version=0. See Google-internal bug b/110495752.
var protoFlag []string
unshallowFlag := unshallow(r.dir)
if len(unshallowFlag) > 0 {
protoFlag = []string{"-c", "protocol.version=0"}
}
_, err := Run(r.dir, "git", protoFlag, "fetch", unshallowFlag, "-f", r.remote, refSpecs)
return err
}
// statLocal returns a RevInfo describing rev in the local git repository.
// It uses version as info.Version.
func (r *gitRepo) statLocal(version, rev string) (*RevInfo, error) {
@@ -512,6 +519,18 @@ func (r *gitRepo) ReadFileRevs(revs []string, file string, maxSize int64) (map[s
return nil, err
}
// TODO(bcmills): after the 1.11 freeze, replace the block above with:
// if r.fetchLevel <= fetchSome {
// r.fetchLevel = fetchSome
// var refs []string
// for _, tag := range redo {
// refs = append(refs, "refs/tags/"+tag+":refs/tags/"+tag)
// }
// if _, err := Run(r.dir, "git", "fetch", "--update-shallow", "-f", r.remote, refs); err != nil {
// return nil, err
// }
// }
if _, err := r.readFileRevs(redo, file, files); err != nil {
return nil, err
}
@@ -603,15 +622,65 @@ func (r *gitRepo) readFileRevs(tags []string, file string, fileMap map[string]*F
}
func (r *gitRepo) RecentTag(rev, prefix string) (tag string, err error) {
_, err = r.Stat(rev)
info, err := r.Stat(rev)
if err != nil {
return "", err
}
out, err := Run(r.dir, "git", "describe", "--first-parent", "--tags", "--always", "--abbrev=0", "--match", prefix+"v[0-9]*.[0-9]*.[0-9]*", "--tags", rev)
rev = info.Name // expand hash prefixes
// describe sets tag and err using 'git describe' and reports whether the
// result is definitive.
describe := func() (definitive bool) {
var out []byte
out, err = Run(r.dir, "git", "describe", "--first-parent", "--always", "--abbrev=0", "--match", prefix+"v[0-9]*.[0-9]*.[0-9]*", "--tags", rev)
if err != nil {
return true // Because we use "--always", describe should never fail.
}
tag = string(bytes.TrimSpace(out))
return tag != "" && !AllHex(tag)
}
if describe() {
return tag, err
}
// Git didn't find a version tag preceding the requested rev.
// See whether any plausible tag exists.
tags, err := r.Tags(prefix + "v")
if err != nil {
return "", err
}
return strings.TrimSpace(string(out)), nil
if len(tags) == 0 {
return "", nil
}
// There are plausible tags, but we don't know if rev is a descendent of any of them.
// Fetch the history to find out.
r.mu.Lock()
defer r.mu.Unlock()
if r.fetchLevel < fetchAll {
// Fetch all heads and tags and see if that gives us enough history.
if err := r.fetchUnshallow("refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"); err != nil {
return "", err
}
r.fetchLevel = fetchAll
}
// If we've reached this point, we have all of the commits that are reachable
// from all heads and tags.
//
// The only refs we should be missing are those that are no longer reachable
// (or never were reachable) from any branch or tag, including the master
// branch, and we don't want to resolve them anyway (they're probably
// unreachable for a reason).
//
// Try one last time in case some other goroutine fetched rev while we were
// waiting on r.mu.
describe()
return tag, err
}
func (r *gitRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser, actualSubdir string, err error) {
View
@@ -86,6 +86,13 @@ func (r *codeRepo) ModulePath() string {
}
func (r *codeRepo) Versions(prefix string) ([]string, error) {
// Special case: gopkg.in/macaroon-bakery.v2-unstable
// does not use the v2 tags (those are for macaroon-bakery.v2).
// It has no possible tags at all.
if strings.HasPrefix(r.modPath, "gopkg.in/") && strings.HasSuffix(r.modPath, "-unstable") {
return nil, nil
}
p := prefix
if r.codeDir != "" {
p = r.codeDir + "/" + p
View
@@ -17,6 +17,7 @@ import (
"sync"
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/dirhash"
"cmd/go/internal/module"
"cmd/go/internal/par"
@@ -46,24 +47,10 @@ func Download(mod module.Version) (dir string, err error) {
return cached{"", err}
}
if files, _ := ioutil.ReadDir(dir); len(files) == 0 {
zipfile, err := CachePath(mod, "zip")
zipfile, err := DownloadZip(mod)
if err != nil {
return cached{"", err}
}
if _, err := os.Stat(zipfile); err == nil {
// Use it.
// This should only happen if the mod/cache directory is preinitialized
// or if pkg/mod/path was removed but not pkg/mod/cache/download.
fmt.Fprintf(os.Stderr, "go: extracting %s %s\n", mod.Path, mod.Version)
} else {
if err := os.MkdirAll(filepath.Dir(zipfile), 0777); err != nil {
return cached{"", err}
}
fmt.Fprintf(os.Stderr, "go: downloading %s %s\n", mod.Path, mod.Version)
if err := downloadZip(mod, zipfile); err != nil {
return cached{"", err}
}
}
modpath := mod.Path + "@" + mod.Version
if err := Unzip(dir, zipfile, modpath, 0); err != nil {
fmt.Fprintf(os.Stderr, "-> %s\n", err)
@@ -76,6 +63,46 @@ func Download(mod module.Version) (dir string, err error) {
return c.dir, c.err
}
var downloadZipCache par.Cache
// DownloadZip downloads the specific module version to the
// local zip cache and returns the name of the zip file.
func DownloadZip(mod module.Version) (zipfile string, err error) {
// The par.Cache here avoids duplicate work but also
// avoids conflicts from simultaneous calls by multiple goroutines
// for the same version.
type cached struct {
zipfile string
err error
}
c := downloadZipCache.Do(mod, func() interface{} {
zipfile, err := CachePath(mod, "zip")
if err != nil {
return cached{"", err}
}
if _, err := os.Stat(zipfile); err == nil {
// Use it.
// This should only happen if the mod/cache directory is preinitialized
// or if pkg/mod/path was removed but not pkg/mod/cache/download.
if cfg.CmdName != "mod download" {
fmt.Fprintf(os.Stderr, "go: extracting %s %s\n", mod.Path, mod.Version)
}
} else {
if err := os.MkdirAll(filepath.Dir(zipfile), 0777); err != nil {
return cached{"", err}
}
if cfg.CmdName != "mod download" {
fmt.Fprintf(os.Stderr, "go: downloading %s %s\n", mod.Path, mod.Version)
}
if err := downloadZip(mod, zipfile); err != nil {
return cached{"", err}
}
}
return cached{zipfile, nil}
}).(cached)
return c.zipfile, c.err
}
func downloadZip(mod module.Version, target string) error {
repo, err := Lookup(mod.Path)
if err != nil {
View
@@ -55,7 +55,7 @@ for that version of the given module.
To avoid problems when serving from case-sensitive file systems,
the <module> and <version> elements are case-encoded, replacing every
uppercase letter with an exclamation mark followed by the correponding
uppercase letter with an exclamation mark followed by the corresponding
lower-case letter: github.com/Azure encodes as github.com/!azure.
The JSON-formatted metadata about a given module corresponds to
View
@@ -49,6 +49,7 @@ func PseudoVersion(major, older string, t time.Time, rev string) string {
if major == "" {
major = "v0"
}
major = strings.TrimSuffix(major, "-unstable") // make gopkg.in/macaroon-bakery.v2-unstable use "v2"
segment := fmt.Sprintf("%s-%s", t.UTC().Format("20060102150405"), rev)
build := semver.Build(older)
older = semver.Canonical(older)
View
@@ -55,9 +55,12 @@ type Repo interface {
// A Rev describes a single revision in a module repository.
type RevInfo struct {
Version string // version string
Name string // complete ID in underlying repository
Short string // shortened ID, for use in pseudo-version
Time time.Time // commit time
// These fields are used for Stat of arbitrary rev,
// but they are not recorded when talking about module versions.
Name string `json:"-"` // complete ID in underlying repository
Short string `json:"-"` // shortened ID, for use in pseudo-version
}
// Re: module paths, import paths, repository roots, and lookups
View
@@ -374,7 +374,7 @@ func runGet(cmd *base.Command, args []string) {
// Now we know the specific version of each path@vers.
// The final build list will be the union of three build lists:
// 1. the original build list
// 2. the modules named on the command line
// 2. the modules named on the command line (other than @none)
// 3. the upgraded requirements of those modules (if upgrading)
// Start building those lists.
// This loop collects (2).
@@ -395,7 +395,9 @@ func runGet(cmd *base.Command, args []string) {
continue // already added
}
byPath[t.m.Path] = t
named = append(named, t.m)
if t.m.Version != "none" {
named = append(named, t.m)
}
}
base.ExitIfErrors()
@@ -513,13 +515,28 @@ func runGet(cmd *base.Command, args []string) {
}
if len(install) > 0 {
// All requested versions were explicitly @none.
// Note that 'go get -u' without any arguments results in len(install) == 1:
// search.CleanImportPaths returns "." for empty args.
work.BuildInit()
var pkgs []string
for _, p := range load.PackagesAndErrors(install) {
if p.Error == nil || !strings.HasPrefix(p.Error.Err, "no Go files") {
pkgs = append(pkgs, p.ImportPath)
// Ignore "no Go source files" errors for 'go get' operations on modules.
if p.Error != nil {
if len(args) == 0 && getU != "" && strings.HasPrefix(p.Error.Err, "no Go files") {
// Upgrading modules: skip the implicitly-requested package at the
// current directory, even if it is not tho module root.
continue
}
if strings.Contains(p.Error.Err, "cannot find module providing") && modload.ModuleInfo(p.ImportPath) != nil {
// Explicitly-requested module, but it doesn't contain a package at the
// module root.
continue
}
}
pkgs = append(pkgs, p.ImportPath)
}
// If -d was specified, we're done after the download: no build.
// (The load.PackagesAndErrors is what did the download
// of the named packages and their dependencies.)
@@ -534,13 +551,6 @@ func runGet(cmd *base.Command, args []string) {
// If forceModulePath is set, getQuery must interpret path
// as a module path.
func getQuery(path, vers string, forceModulePath bool) (module.Version, error) {
if path == modload.Target.Path {
if vers != "" {
return module.Version{}, fmt.Errorf("cannot update main module to explicit version")
}
return modload.Target, nil
}
if vers == "" {
vers = "latest"
}
@@ -552,34 +562,14 @@ func getQuery(path, vers string, forceModulePath bool) (module.Version, error) {
return module.Version{Path: path, Version: info.Version}, nil
}
// Even if the query fails, if the path is (or must be) a real module, then report the query error.
if forceModulePath || *getM || isModulePath(path) {
// Even if the query fails, if the path must be a real module, then report the query error.
if forceModulePath || *getM {
return module.Version{}, err
}
// Otherwise, interpret the package path as an import
// and determine what module that import would address
// if found in the current source code.
// Then apply the version to that module.
m, _, err := modload.Import(path)
if err != nil {
return module.Version{}, err
}
if m.Path == "" {
return module.Version{}, fmt.Errorf("package %q is not in a module", path)
}
info, err = modload.Query(m.Path, vers, modload.Allowed)
if err != nil {
return module.Version{}, err
}
return module.Version{Path: m.Path, Version: info.Version}, nil
}
// isModulePath reports whether path names an actual module,
// defined as one with an accessible latest version.
func isModulePath(path string) bool {
_, err := modload.Query(path, "latest", modload.Allowed)
return err == nil
// Otherwise, try a package path.
m, _, err := modload.QueryPackage(path, vers, modload.Allowed)
return m, err
}
// An upgrader adapts an underlying mvs.Reqs to apply an
View
@@ -144,23 +144,25 @@ func moduleInfo(m module.Version, fromBuildList bool) *modinfo.ModulePublic {
complete(info)
if r := Replacement(m); r.Path != "" {
info.Replace = &modinfo.ModulePublic{
Path: r.Path,
Version: r.Version,
GoVersion: info.GoVersion,
}
if r.Version == "" {
if filepath.IsAbs(r.Path) {
info.Replace.Dir = r.Path
} else {
info.Replace.Dir = filepath.Join(ModRoot, r.Path)
if fromBuildList {
if r := Replacement(m); r.Path != "" {
info.Replace = &modinfo.ModulePublic{
Path: r.Path,
Version: r.Version,
GoVersion: info.GoVersion,
}
if r.Version == "" {
if filepath.IsAbs(r.Path) {
info.Replace.Dir = r.Path
} else {
info.Replace.Dir = filepath.Join(ModRoot, r.Path)
}
}
complete(info.Replace)
info.Dir = info.Replace.Dir
info.GoMod = filepath.Join(info.Dir, "go.mod")
info.Error = nil // ignore error loading original module version (it has been replaced)
}
complete(info.Replace)
info.Dir = info.Replace.Dir
info.GoMod = filepath.Join(info.Dir, "go.mod")
info.Error = nil // ignore error loading original module version (it has been replaced)
}
return info
View
@@ -10,7 +10,6 @@ import (
"fmt"
"go/build"
"os"
pathpkg "path"
"path/filepath"
"strings"
@@ -42,7 +41,7 @@ func (e *ImportMissingError) Error() string {
// If the package cannot be found in the current build list,
// Import returns an ImportMissingError as the error.
// If Import can identify a module that could be added to supply the package,
// the ImportMissingErr records that module.
// the ImportMissingError records that module.
func Import(path string) (m module.Version, dir string, err error) {
if strings.Contains(path, "@") {
return module.Version{}, "", fmt.Errorf("import path should not have @version")
@@ -124,24 +123,6 @@ func Import(path string) (m module.Version, dir string, err error) {
return module.Version{}, "", errors.New(buf.String())
}
// Special case: if the path matches a module path,
// and we haven't found code in any module on the build list
// (since we haven't returned yet),
// force the use of the current module instead of
// looking for an alternate one.
// This helps "go get golang.org/x/net" even though
// there is no code in x/net.
for _, m := range buildList {
if m.Path == path {
root, isLocal, err := fetch(m)
if err != nil {
return module.Version{}, "", err
}
dir, _ := dirInModule(path, m.Path, root, isLocal)
return m, dir, nil
}
}
// Not on build list.
// Look up module containing the package, for addition to the build list.
@@ -150,43 +131,11 @@ func Import(path string) (m module.Version, dir string, err error) {
return module.Version{}, "", fmt.Errorf("import lookup disabled by -mod=%s", cfg.BuildMod)
}
for p := path; p != "."; p = pathpkg.Dir(p) {
// We can't upgrade the main module.
// Note that this loop does consider upgrading other modules on the build list.
// If that's too aggressive we can skip all paths already on the build list,
// not just Target.Path, but for now let's try being aggressive.
if p == Target.Path {
// Can't move to a new version of main module.
continue
}
info, err := Query(p, "latest", Allowed)
if err != nil {
continue
}
m := module.Version{Path: p, Version: info.Version}
root, isLocal, err := fetch(m)
if err != nil {
continue
}
_, ok := dirInModule(path, m.Path, root, isLocal)
if ok {
return module.Version{}, "", &ImportMissingError{ImportPath: path, Module: m}
}
// Special case matching the one above:
// if m.Path matches path, assume adding it to the build list
// will either add the right code or the right code doesn't exist.
if m.Path == path {
return module.Version{}, "", &ImportMissingError{ImportPath: path, Module: m}
}
m, _, err = QueryPackage(path, "latest", Allowed)
if err != nil {
return module.Version{}, "", &ImportMissingError{ImportPath: path}
}
// Did not resolve import to any module.
// TODO(rsc): It would be nice to return a specific error encountered
// during the loop above if possible, but it's not clear how to pick
// out the right one.
return module.Version{}, "", &ImportMissingError{ImportPath: path}
return m, "", &ImportMissingError{ImportPath: path, Module: m}
}
// maybeInModule reports whether, syntactically,
View
@@ -521,7 +521,10 @@ func MinReqs() mvs.Reqs {
// WriteGoMod writes the current build list back to go.mod.
func WriteGoMod() {
if !allowWriteGoMod {
// If we're using -mod=vendor we basically ignored
// go.mod, so definitely don't try to write back our
// incomplete view of the world.
if !allowWriteGoMod || cfg.BuildMod == "vendor" {
return
}
View
@@ -101,11 +101,9 @@ func ImportPaths(args []string) []string {
}
case pkg == "all":
if loaded.testRoots {
loaded.testAll = true
}
loaded.testAll = true
// TODO: Don't print warnings multiple times.
roots = append(roots, warnPattern("all", matchPackages("...", loaded.tags, []module.Version{Target}))...)
roots = append(roots, warnPattern("all", matchPackages("...", loaded.tags, false, []module.Version{Target}))...)
paths = append(paths, "all") // will expand after load completes
case search.IsMetaPackage(pkg): // std, cmd
@@ -115,7 +113,7 @@ func ImportPaths(args []string) []string {
case strings.Contains(pkg, "..."):
// TODO: Don't we need to reevaluate this one last time once the build list stops changing?
list := warnPattern(pkg, matchPackages(pkg, loaded.tags, buildList))
list := warnPattern(pkg, matchPackages(pkg, loaded.tags, true, buildList))
roots = append(roots, list...)
paths = append(paths, list...)
@@ -140,7 +138,7 @@ func ImportPaths(args []string) []string {
if prev, ok := firstPath[src]; !ok {
firstPath[src] = mod.Path
} else if prev != mod.Path {
base.Errorf("go: %s@%s used for two different module paths (%s and %s)", mod.Path, mod.Version, prev, mod.Path)
base.Errorf("go: %s@%s used for two different module paths (%s and %s)", src.Path, src.Version, prev, mod.Path)
}
}
base.ExitIfErrors()
@@ -158,6 +156,9 @@ func ImportPaths(args []string) []string {
have[path] = true
if path == "all" {
for _, pkg := range loaded.pkgs {
if e, ok := pkg.err.(*ImportMissingError); ok && e.Module.Path == "" {
continue // Package doesn't actually exist, so don't report it.
}
if !have[pkg.path] {
have[pkg.path] = true
final = append(final, pkg.path)
@@ -270,6 +271,9 @@ func loadAll(testAll bool) []string {
var paths []string
for _, pkg := range loaded.pkgs {
if e, ok := pkg.err.(*ImportMissingError); ok && e.Module.Path == "" {
continue // Package doesn't actually exist.
}
paths = append(paths, pkg.path)
}
return paths
@@ -282,7 +286,7 @@ var anyTags = map[string]bool{"*": true}
// TargetPackages returns the list of packages in the target (top-level) module,
// under all build tag settings.
func TargetPackages() []string {
return matchPackages("...", anyTags, []module.Version{Target})
return matchPackages("...", anyTags, false, []module.Version{Target})
}
// BuildList returns the module build list,
@@ -337,19 +341,22 @@ func ModuleUsedDirectly(path string) bool {
return loaded.direct[path]
}
// Lookup XXX TODO.
func Lookup(parentPath, path string) (dir, realPath string, err error) {
realPath = ImportMap(path)
if realPath == "" {
// Lookup returns the source directory, import path, and any loading error for
// the package at path.
// Lookup requires that one of the Load functions in this package has already
// been called.
func Lookup(path string) (dir, realPath string, err error) {
pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
if !ok {
if isStandardImportPath(path) {
dir := filepath.Join(cfg.GOROOT, "src", path)
if _, err := os.Stat(dir); err == nil {
return dir, path, nil
}
}
return "", "", fmt.Errorf("no such package in module")
return "", "", errMissing
}
return PackageDir(realPath), realPath, nil
return pkg.dir, pkg.path, pkg.err
}
// A loader manages the process of loading information about
@@ -382,14 +389,13 @@ type loader struct {
goVersion map[string]string // go version recorded in each module
}
// LoadTests controls whether the loaders load tests of the root packages.
var LoadTests bool
func newLoader() *loader {
ld := new(loader)
ld.tags = imports.Tags()
switch cfg.CmdName {
case "test", "vet":
ld.testRoots = true
}
ld.testRoots = LoadTests
return ld
}
@@ -457,9 +463,7 @@ func (ld *loader) load(roots func() []string) {
}
continue
}
if pkg.err != nil {
base.Errorf("go: %s: %s", pkg.stackText(), pkg.err)
}
// Leave other errors for Import or load.Packages to report.
}
base.ExitIfErrors()
if numAdded == 0 {
@@ -504,9 +508,6 @@ func (ld *loader) load(roots func() []string) {
}
}
}
// Check for visibility violations.
// TODO!
}
// pkg returns the *loadPkg for path, creating and queuing it if needed.
@@ -561,11 +562,6 @@ func (ld *loader) doPkg(item interface{}) {
var err error
imports, testImports, err = scanDir(pkg.dir, ld.tags)
if err != nil {
if strings.HasPrefix(err.Error(), "no Go ") {
// Don't print about directories with no Go source files.
// Let the eventual real package load do that.
return
}
pkg.err = err
return
}
@@ -675,6 +671,51 @@ func (pkg *loadPkg) stackText() string {
return buf.String()
}
// why returns the text to use in "go mod why" output about the given package.
// It is less ornate than the stackText but conatins the same information.
func (pkg *loadPkg) why() string {
var buf strings.Builder
var stack []*loadPkg
for p := pkg; p != nil; p = p.stack {
stack = append(stack, p)
}
for i := len(stack) - 1; i >= 0; i-- {
p := stack[i]
if p.testOf != nil {
fmt.Fprintf(&buf, "%s.test\n", p.testOf.path)
} else {
fmt.Fprintf(&buf, "%s\n", p.path)
}
}
return buf.String()
}
// Why returns the "go mod why" output stanza for the given package,
// without the leading # comment.
// The package graph must have been loaded already, usually by LoadALL.
// If there is no reason for the package to be in the current build,
// Why returns an empty string.
func Why(path string) string {
pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
if !ok {
return ""
}
return pkg.why()
}
// WhyDepth returns the number of steps in the Why listing.
// If there is no reason for the package to be in the current build,
// WhyDepth returns 0.
func WhyDepth(path string) int {
n := 0
pkg, _ := loaded.pkgCache.Get(path).(*loadPkg)
for p := pkg; p != nil; p = p.stack {
n++
}
return n
}
// Replacement returns the replacement for mod, if any, from go.mod.
// If there is no replacement for mod, Replacement returns
// a module.Version with Path == "".
View
@@ -9,6 +9,7 @@ import (
"cmd/go/internal/module"
"cmd/go/internal/semver"
"fmt"
pathpkg "path"
"strings"
)
@@ -29,6 +30,8 @@ import (
//
// If the allowed function is non-nil, Query excludes any versions for which allowed returns false.
//
// If path is the path of the main module and the query is "latest",
// Query returns Target.Version as the version.
func Query(path, query string, allowed func(module.Version) bool) (*modfetch.RevInfo, error) {
if allowed == nil {
allowed = func(module.Version) bool { return true }
@@ -117,6 +120,16 @@ func Query(path, query string, allowed func(module.Version) bool) (*modfetch.Rev
return info, nil
}
if path == Target.Path {
if query != "latest" {
return nil, fmt.Errorf("can't query specific version (%q) for the main module (%s)", query, path)
}
if !allowed(Target) {
return nil, fmt.Errorf("internal error: main module version is not allowed")
}
return &modfetch.RevInfo{Version: Target.Version}, nil
}
// Load versions and execute query.
repo, err := modfetch.Lookup(path)
if err != nil {
@@ -187,3 +200,44 @@ func isSemverPrefix(v string) bool {
func matchSemverPrefix(p, v string) bool {
return len(v) > len(p) && v[len(p)] == '.' && v[:len(p)] == p
}
// QueryPackage looks up a revision of a module containing path.
//
// If multiple modules with revisions matching the query provide the requested
// package, QueryPackage picks the one with the longest module path.
//
// If the path is in the the main module and the query is "latest",
// QueryPackage returns Target as the version.
func QueryPackage(path, query string, allowed func(module.Version) bool) (module.Version, *modfetch.RevInfo, error) {
if _, ok := dirInModule(path, Target.Path, ModRoot, true); ok {
if query != "latest" {
return module.Version{}, nil, fmt.Errorf("can't query specific version (%q) for package %s in the main module (%s)", query, path, Target.Path)
}
if !allowed(Target) {
return module.Version{}, nil, fmt.Errorf("internal error: package %s is in the main module (%s), but version is not allowed", path, Target.Path)
}
return Target, &modfetch.RevInfo{Version: Target.Version}, nil
}
finalErr := errMissing
for p := path; p != "."; p = pathpkg.Dir(p) {
info, err := Query(p, query, allowed)
if err != nil {
if finalErr == errMissing {
finalErr = err
}
continue
}
m := module.Version{Path: p, Version: info.Version}
root, isLocal, err := fetch(m)
if err != nil {
return module.Version{}, nil, err
}
_, ok := dirInModule(path, m.Path, root, isLocal)
if ok {
return m, info, nil
}
}
return module.Version{}, nil, finalErr
}
View
@@ -19,7 +19,7 @@ import (
// matchPackages returns a list of packages in the list of modules
// matching the pattern. Package loading assumes the given set of tags.
func matchPackages(pattern string, tags map[string]bool, modules []module.Version) []string {
func matchPackages(pattern string, tags map[string]bool, useStd bool, modules []module.Version) []string {
match := func(string) bool { return true }
treeCanMatch := func(string) bool { return true }
if !search.IsMetaPackage(pattern) {
@@ -35,36 +35,41 @@ func matchPackages(pattern string, tags map[string]bool, modules []module.Versio
}
var pkgs []string
for _, mod := range modules {
if !treeCanMatch(mod.Path) {
continue
walkPkgs := func(root, importPathRoot string) {
root = filepath.Clean(root)
var cmd string
if root == cfg.GOROOTsrc {
cmd = filepath.Join(root, "cmd")
}
var root string
if mod.Version == "" {
root = ModRoot
} else {
var err error
root, _, err = fetch(mod)
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
if err != nil {
base.Errorf("go: %v", err)
continue
return nil
}
}
root = filepath.Clean(root)
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
if err != nil {
// Don't use GOROOT/src but do walk down into it.
if path == root && importPathRoot == "" {
return nil
}
// GOROOT/src/cmd makes use of GOROOT/src/cmd/vendor,
// which module mode can't deal with. Eventually we'll stop using
// that vendor directory, and then we can remove this exclusion.
// golang.org/issue/26924.
if path == cmd {
return filepath.SkipDir
}
want := true
// Avoid .foo, _foo, and testdata directory trees.
_, elem := filepath.Split(path)
if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
want = false
}
name := mod.Path + filepath.ToSlash(path[len(root):])
name := importPathRoot + filepath.ToSlash(path[len(root):])
if importPathRoot == "" {
name = name[1:] // cut leading slash
}
if !treeCanMatch(name) {
want = false
}
@@ -102,5 +107,28 @@ func matchPackages(pattern string, tags map[string]bool, modules []module.Versio
return nil
})
}
if useStd {
walkPkgs(cfg.GOROOTsrc, "")
}
for _, mod := range modules {
if !treeCanMatch(mod.Path) {
continue
}
var root string
if mod.Version == "" {
root = ModRoot
} else {
var err error
root, _, err = fetch(mod)
if err != nil {
base.Errorf("go: %v", err)
continue
}
}
walkPkgs(root, mod.Path)
}
return pkgs
}
View
@@ -143,7 +143,7 @@ func CheckPath(path string) error {
}
}
if _, _, ok := SplitPathVersion(path); !ok {
return fmt.Errorf("malformed module path %q: invalid version %s", path, path[strings.LastIndex(path, "/")+1:])
return fmt.Errorf("malformed module path %q: invalid version", path)
}
return nil
}
@@ -300,6 +300,9 @@ func splitGopkgIn(path string) (prefix, pathMajor string, ok bool) {
return path, "", false
}
i := len(path)
if strings.HasSuffix(path, "-unstable") {
i -= len("-unstable")
}
for i > 0 && ('0' <= path[i-1] && path[i-1] <= '9') {
i--
}
@@ -317,6 +320,9 @@ func splitGopkgIn(path string) (prefix, pathMajor string, ok bool) {
// MatchPathMajor reports whether the semantic version v
// matches the path major version pathMajor.
func MatchPathMajor(v, pathMajor string) bool {
if strings.HasPrefix(pathMajor, ".v") && strings.HasSuffix(pathMajor, "-unstable") {
pathMajor = strings.TrimSuffix(pathMajor, "-unstable")
}
if strings.HasPrefix(v, "v0.0.0-") && pathMajor == ".v1" {
// Allow old bug in pseudo-versions that generated v0.0.0- pseudoversion for gopkg .v1.
// For example, gopkg.in/yaml.v2@v2.2.1's go.mod requires gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405.
View
@@ -27,6 +27,7 @@ import (
"cmd/go/internal/cache"
"cmd/go/internal/cfg"
"cmd/go/internal/load"
"cmd/go/internal/modload"
"cmd/go/internal/str"
"cmd/go/internal/work"
"cmd/internal/test2json"
@@ -527,6 +528,8 @@ var testVetFlags = []string{
}
func runTest(cmd *base.Command, args []string) {
modload.LoadTests = true
pkgArgs, testArgs = testFlags(args)
work.FindExecCmd() // initialize cached result
View
@@ -8,6 +8,7 @@ package vet
import (
"cmd/go/internal/base"
"cmd/go/internal/load"
"cmd/go/internal/modload"
"cmd/go/internal/work"
"path/filepath"
)
@@ -35,6 +36,8 @@ See also: go fmt, go fix.
}
func runVet(cmd *base.Command, args []string) {
modload.LoadTests = true
vetFlags, pkgArgs := vetFlags(args)
work.BuildInit()
View
@@ -18,6 +18,7 @@ import (
"cmd/go/internal/load"
"cmd/go/internal/str"
"cmd/internal/buildid"
"cmd/internal/objabi"
)
// Build IDs
@@ -206,6 +207,11 @@ func (b *Builder) toolID(name string) string {
id = f[2]
}
// For the compiler, add any experiments.
if name == "compile" {
id += " " + objabi.Expstring()
}
b.id.Lock()
b.toolIDCache[name] = id
b.id.Unlock()
@@ -463,6 +469,14 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID
a.buildID = id[1] + buildIDSeparator + id[2]
linkID := hashToString(b.linkActionID(a.triggers[0]))
if id[0] == linkID {
// Best effort attempt to display output from the compile and link steps.
// If it doesn't work, it doesn't work: reusing the cached binary is more
// important than reprinting diagnostic information.
if c := cache.Default(); c != nil {
showStdout(b, c, a.actionID, "stdout") // compile output
showStdout(b, c, a.actionID, "link-stdout") // link output
}
// Poison a.Target to catch uses later in the build.
a.Target = "DO NOT USE - main build pseudo-cache Target"
a.built = "DO NOT USE - main build pseudo-cache built"
@@ -480,6 +494,15 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID
// We avoid the nested build ID problem in the previous special case
// by recording the test results in the cache under the action ID half.
if !cfg.BuildA && len(a.triggers) == 1 && a.triggers[0].TryCache != nil && a.triggers[0].TryCache(b, a.triggers[0]) {
// Best effort attempt to display output from the compile and link steps.
// If it doesn't work, it doesn't work: reusing the test result is more
// important than reprinting diagnostic information.
if c := cache.Default(); c != nil {
showStdout(b, c, a.Deps[0].actionID, "stdout") // compile output
showStdout(b, c, a.Deps[0].actionID, "link-stdout") // link output
}
// Poison a.Target to catch uses later in the build.
a.Target = "DO NOT USE - pseudo-cache Target"
a.built = "DO NOT USE - pseudo-cache built"
return true
@@ -520,15 +543,7 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID
if !cfg.BuildA {
if file, _, err := c.GetFile(actionHash); err == nil {
if buildID, err := buildid.ReadFile(file); err == nil {
if stdout, stdoutEntry, err := c.GetBytes(cache.Subkey(a.actionID, "stdout")); err == nil {
if len(stdout) > 0 {
if cfg.BuildX || cfg.BuildN {
b.Showcmd("", "%s # internal", joinUnambiguously(str.StringList("cat", c.OutputFile(stdoutEntry.OutputID))))
}
if !cfg.BuildN {
b.Print(string(stdout))
}
}
if err := showStdout(b, c, a.actionID, "stdout"); err == nil {
a.built = file
a.Target = "DO NOT USE - using cache"
a.buildID = buildID
@@ -549,6 +564,23 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID
return false
}
func showStdout(b *Builder, c *cache.Cache, actionID cache.ActionID, key string) error {
stdout, stdoutEntry, err := c.GetBytes(cache.Subkey(actionID, key))
if err != nil {
return err
}
if len(stdout) > 0 {
if cfg.BuildX || cfg.BuildN {
b.Showcmd("", "%s # internal", joinUnambiguously(str.StringList("cat", c.OutputFile(stdoutEntry.OutputID))))
}
if !cfg.BuildN {
b.Print(string(stdout))
}
}
return nil
}
// flushOutput flushes the output being queued in a.
func (b *Builder) flushOutput(a *Action) {
b.Print(string(a.output))
@@ -573,6 +605,26 @@ func (b *Builder) updateBuildID(a *Action, target string, rewrite bool) error {
}
}
// Cache output from compile/link, even if we don't do the rest.
if c := cache.Default(); c != nil {
switch a.Mode {
case "build":
c.PutBytes(cache.Subkey(a.actionID, "stdout"), a.output)
case "link":
// Even though we don't cache the binary, cache the linker text output.
// We might notice that an installed binary is up-to-date but still
// want to pretend to have run the linker.
// Store it under the main package's action ID
// to make it easier to find when that's all we have.
for _, a1 := range a.Deps {
if p1 := a1.Package; p1 != nil && p1.Name == "main" {
c.PutBytes(cache.Subkey(a1.actionID, "link-stdout"), a.output)
break
}
}
}
}
// Find occurrences of old ID and compute new content-based ID.
r, err := os.Open(target)
if err != nil {
@@ -640,7 +692,6 @@ func (b *Builder) updateBuildID(a *Action, target string, rewrite bool) error {
}
a.Package.Export = c.OutputFile(outputID)
}
c.PutBytes(cache.Subkey(a.actionID, "stdout"), a.output)
}
}
View
@@ -1155,11 +1155,11 @@ func (b *Builder) link(a *Action) (err error) {
// We still call updateBuildID to update a.buildID, which is important
// for test result caching, but passing rewrite=false (final arg)
// means we don't actually rewrite the binary, nor store the
// result into the cache.
// Not calling updateBuildID means we also don't insert these
// binaries into the build object cache. That's probably a net win:
// result into the cache. That's probably a net win:
// less cache space wasted on large binaries we are not likely to
// need again. (On the other hand it does make repeated go test slower.)
// It also makes repeated go run slower, which is a win in itself:
// we don't want people to treat go run like a scripting environment.
if err := b.updateBuildID(a, a.Target, !a.Package.Internal.OmitDebug); err != nil {
return err
}
View
@@ -81,13 +81,13 @@ func readModList() {
encPath := strings.Replace(name[:i], "_", "/", -1)
path, err := module.DecodePath(encPath)
if err != nil {
fmt.Fprintf(os.Stderr, "go proxy_test: %v", err)
fmt.Fprintf(os.Stderr, "go proxy_test: %v\n", err)
continue
}
encVers := name[i+1:]
vers, err := module.DecodeVersion(encVers)
if err != nil {
fmt.Fprintf(os.Stderr, "go proxy_test: %v", err)
fmt.Fprintf(os.Stderr, "go proxy_test: %v\n", err)
continue
}
modList = append(modList, module.Version{Path: path, Version: vers})
@@ -140,7 +140,7 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
encVers, ext := file[:i], file[i+1:]
vers, err := module.DecodeVersion(encVers)
if err != nil {
fmt.Fprintf(os.Stderr, "go proxy_test: %v", err)
fmt.Fprintf(os.Stderr, "go proxy_test: %v\n", err)
http.NotFound(w, r)
return
}
View
@@ -0,0 +1,9 @@
Written by hand.
Test case for package moved into a parent module.
-- .mod --
module example.com/join/subpkg
-- .info --
{"Version": "v1.0.0"}
-- x.go --
package subpkg
View
@@ -0,0 +1,9 @@
Written by hand.
Test case for package moved into a parent module.
-- .mod --
module example.com/join/subpkg
require example.com/join v1.1.0
-- .info --
{"Version": "v1.1.0"}
View
@@ -0,0 +1,7 @@
Written by hand.
Test case for package moved into a parent module.
-- .mod --
module example.com/join
-- .info --
{"Version": "v1.0.0"}
View
@@ -0,0 +1,9 @@
Written by hand.
Test case for package moved into a parent module.
-- .mod --
module example.com/join
-- .info --
{"Version": "v1.1.0"}
-- subpkg/x.go --
package subpkg
View
@@ -0,0 +1,11 @@
Written by hand.
Test case for getting a package that has been moved to a different module.
-- .mod --
module example.com/split/subpkg
require example.com/split v1.1.0
-- .info --
{"Version": "v1.1.0"}
-- x.go --
package subpkg
View
@@ -0,0 +1,9 @@
Written by hand.
Test case for getting a package that has been moved to a different module.
-- .mod --
module example.com/split
-- .info --
{"Version": "v1.0.0"}
-- subpkg/x.go --
package subpkg
View
@@ -0,0 +1,9 @@
Written by hand.
Test case for getting a package that has been moved to a different module.
-- .mod --
module example.com/split
require example.com/split/subpkg v1.1.0
-- .info --
{"Version": "v1.1.0"}
View
@@ -6,6 +6,8 @@ module golang.org/x/text
{"Version":"v0.0.0-20170915032832-14c0d48ead0c","Name":"v0.0.0-20170915032832-14c0d48ead0c","Short":"14c0d48ead0c","Time":"2017-09-15T03:28:32Z"}
-- go.mod --
module golang.org/x/text
-- unused/unused.go --
package unused
-- language/lang.go --
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
View
@@ -6,6 +6,8 @@ module golang.org/x/text
{"Version":"v0.3.0","Name":"","Short":"","Time":"2017-09-16T03:28:32Z"}
-- go.mod --
module golang.org/x/text
-- unused/unused.go --
package unused
-- language/lang.go --
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
View
@@ -0,0 +1,9 @@
gopkg.in/dummy.v2-unstable v2.0.0
written by hand
-- .mod --
module gopkg.in/dummy.v2-unstable
-- .info --
{"Version":"v2.0.0"}
-- dummy.go --
package dummy
View
@@ -0,0 +1,23 @@
research.swtch.com/vgo-tour@v1.0.0
-- .mod --
module "research.swtch.com/vgo-tour"
-- .info --
{"Version":"v1.0.0","Name":"84de74b35823c1e49634f2262f1a58cfc951ebae","Short":"84de74b35823","Time":"2018-02-20T00:04:00Z"}
-- go.mod --
module "research.swtch.com/vgo-tour"
-- hello.go --
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"rsc.io/quote"
)
func main() {
fmt.Println(quote.Hello())
}
View
@@ -0,0 +1,15 @@
rsc.io/fortune v1.0.0
written by hand
-- .mod --
module rsc.io/fortune
-- .info --
{"Version":"v1.0.0"}
-- fortune.go --
package main
import "rsc.io/quote"
func main() {
println(quote.Hello())
}
View
@@ -0,0 +1,15 @@
rsc.io/fortune v2.0.0
written by hand
-- .mod --
module rsc.io/fortune/v2
-- .info --
{"Version":"v2.0.0"}
-- fortune.go --
package main
import "rsc.io/quote"
func main() {
println(quote.Hello())
}
View
@@ -36,6 +36,7 @@ import (
"testing"
"golang.org/x/text/language"
_ "rsc.io/testonly"
)
var glassTests = []struct {
View
@@ -0,0 +1,9 @@
rsc.io/testonly v1.0.0
written by hand
-- .mod --
module rsc.io/testonly
-- .info --
{"Version":"v1.0.0"}
-- testonly.go --
package testonly
View
@@ -6,14 +6,58 @@ mkdir $GOCACHE
# Building a trivial non-main package should run compiler the first time.
go build -x -gcflags=-m lib.go
stderr 'compile( |\.exe)'
stderr 'compile( |\.exe"?)'
stderr 'lib.go:2.* can inline f'
# ... but not the second, even though it still prints the compiler output.
go build -x -gcflags=-m lib.go
! stderr 'compile( |\.exe)'
! stderr 'compile( |\.exe"?)'
stderr 'lib.go:2.* can inline f'
# Building a trivial main package should run the compiler and linker the first time.
go build -x -gcflags=-m -ldflags='-v -w' main.go
stderr 'compile( |\.exe"?)'
stderr 'main.go:2.* can inline main' # from compiler
stderr 'link(\.exe"?)? -'
stderr '\d+ symbols' # from linker
# ... but not the second, even though it still prints the compiler and linker output.
go build -x -gcflags=-m -ldflags='-v -w' main.go
! stderr 'compile( |\.exe"?)'
stderr 'main.go:2.* can inline main' # from compiler
! stderr 'link(\.exe"?)? -'
stderr '\d+ symbols' # from linker
# Running a test should run the compiler, linker, and the test the first time.
go test -v -x -gcflags=-m -ldflags=-v p_test.go
stderr 'compile( |\.exe"?)'
stderr 'p_test.go:.*can inline Test' # from compile of p_test
stderr 'testmain\.go:.*inlin' # from compile of testmain
stderr 'link(\.exe"?)? -'
stderr '\d+ symbols' # from linker
stderr 'p\.test( |\.exe"?)'
stdout 'TEST' # from test
# ... but not the second, even though it still prints the compiler, linker, and test output.
go test -v -x -gcflags=-m -ldflags=-v p_test.go
! stderr 'compile( |\.exe"?)'
stderr 'p_test.go:.*can inline Test' # from compile of p_test
stderr 'testmain\.go:.*inlin' # from compile of testmain
! stderr 'link(\.exe"?)? -'
stderr '\d+ symbols' # from linker
! stderr 'p\.test( |\.exe"?)'
stdout 'TEST' # from test
-- lib.go --
package p
func f(x *int) *int { return x }
-- main.go --
package main
func main() {}
-- p_test.go --
package p
import "testing"
func Test(t *testing.T) {println("TEST")}
View
@@ -0,0 +1,23 @@
[short] skip
go test -coverpkg=all -covermode=atomic x
stdout ok[\s\S]+?coverage
[!race] stop
go test -coverpkg=all -race x
stdout ok[\s\S]+?coverage
-- x/x.go --
package x
import _ "sync/atomic"
func F() {}
-- x/x_test.go --
package x
import "testing"
func TestF(t *testing.T) { F() }
View
@@ -0,0 +1,21 @@
# Issue 23882
[short] skip
go test -coverpkg=all x
stdout ok[\s\S]+?coverage
[!race] stop
go test -coverpkg=all -race x
stdout ok[\s\S]+?coverage
-- x/x.go --
package x
import _ "runtime"
func F() {}
-- x/x_test.go --
package x
import "testing"
func TestF(t *testing.T) { F() }
View
@@ -0,0 +1,20 @@
# Issue 23150
[short] skip
go test -o=$WORK/x.test -cpuprofile=$WORK/cpu_profile_twice.out x
rm $WORK/cpu_profile_twice.out
go test -o=$WORK/x.test -cpuprofile=$WORK/cpu_profile_twice.out x
exists $WORK/cpu_profile_twice.out
-- x/x_test.go --
package x_test
import (
"testing"
"time"
)
func TestSleep(t *testing.T) {
time.Sleep(10 * time.Millisecond)
}
View
@@ -0,0 +1,7 @@
env GIT_TRACE=1
[!net] skip
[!exec:git] skip
# go get should be success when GIT_TRACE set
go get golang.org/x/text
View
@@ -0,0 +1,67 @@
# This test matches mod_list_bad_import, but in GOPATH mode.
# Please keep them in sync.
env GO111MODULE=off
cd example.com
# Without -e, listing an otherwise-valid package with an unsatisfied direct import should fail.
# BUG: Today it succeeds.
go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}} {{range .DepsErrors}}bad dep: {{.Err}}{{end}}' example.com/direct
! stdout ^error
stdout 'incomplete'
stdout 'bad dep: .*example.com[/\\]notfound'
# Listing with -deps should also fail.
# BUG: Today, it does not.
# ! go list -deps example.com/direct
# stderr example.com[/\\]notfound
go list -deps example.com/direct
stdout example.com/notfound
# Listing an otherwise-valid package that imports some *other* package with an
# unsatisfied import should also fail.
# BUG: Today, it succeeds.
go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}} {{range .DepsErrors}}bad dep: {{.Err}}{{end}}' example.com/indirect
! stdout ^error
stdout incomplete
stdout 'bad dep: .*example.com[/\\]notfound'
# Again, -deps should fail.
# BUG: Again, it does not.
# ! go list -deps example.com/indirect
# stderr example.com[/\\]notfound
go list -deps example.com/indirect
stdout example.com/notfound
# Listing the missing dependency directly should fail outright...
! go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}}' example.com/notfound
stderr 'no Go files in .*example.com[/\\]notfound'
! stdout error
! stdout incomplete
# ...but listing with -e should succeed.
go list -e -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}}' example.com/notfound
stdout error
stdout incomplete
# The pattern "all" should match only packages that acutally exist,
# ignoring those whose existence is merely implied by imports.
go list -e -f '{{.ImportPath}}' all
stdout example.com/direct
stdout example.com/indirect
! stdout example.com/notfound
-- example.com/direct/direct.go --
package direct
import _ "example.com/notfound"
-- example.com/indirect/indirect.go --
package indirect
import _ "example.com/direct"
-- example.com/notfound/README --
This directory intentionally left blank.
View
@@ -0,0 +1,29 @@
[!cgo] skip
# go list should report import "C"
cd x
go list -f '{{.Imports}}'
! stdout runtime/cgo
! stdout unsafe
! stdout syscall
stdout C
stdout unicode
stdout unicode/utf16
# go list -compiled should report imports in compiled files as well,
# adding "runtime/cgo", "unsafe", and "syscall" but not dropping "C".
go list -compiled -f '{{.Imports}}'
stdout runtime/cgo
stdout unsafe
stdout syscall
stdout C
stdout unicode
stdout unicode/utf16
-- x/x.go --
package x
import "C"
import "unicode" // does not use unsafe, syscall, runtime/cgo, unicode/utf16
-- x/x1.go --
package x
import "unicode/utf16" // does not use unsafe, syscall, runtime/cgo, unicode
View
@@ -0,0 +1,19 @@
# issue 26880: list with tests has wrong variant in imports
go list -test -f '{{.ImportPath}}:{{with .Imports}} {{join . ", "}}{{end}}' a b
cmp stdout imports.txt
-- a/a.go --
package a; import _ "b"
-- b/b.go --
package b
-- b/b_test.go --
package b
-- b/b_x_test.go --
package b_test; import _ "a"
-- imports.txt --
a: b
b:
b.test: b [b.test], b_test [b.test], os, testing, testing/internal/testdeps
b [b.test]:
b_test [b.test]: a [b.test]
View
@@ -2,20 +2,28 @@ env GO111MODULE=on
# explicit get should report errors about bad names
! go get appengine
stderr 'cannot find module providing package appengine'
stderr 'malformed module path "appengine": missing dot in first path element'
! go get x/y.z
stderr 'cannot find module providing package x/y.z'
stderr 'malformed module path "x/y.z": missing dot in first path element'
# build should skip over appengine imports
! go build
! stderr appengine
# build should report all unsatisfied imports,
# but should be more definitive about non-module import paths
! go build ./useappengine
stderr 'cannot find package'
! go build ./usenonexistent
stderr 'cannot find module providing package nonexistent.rsc.io'
# go mod vendor and go mod tidy should ignore appengine imports.
rm usenonexistent/x.go
go mod tidy
go mod vendor
-- go.mod --
module x
-- x.go --
package x
import _ "appengine"
-- useappengine/x.go --
package useappengine
import _ "appengine" // package does not exist
-- usenonexistent/x.go --
package usenonexistent
import _ "nonexistent.rsc.io" // domain does not exist
View
@@ -0,0 +1,62 @@
env GO111MODULE=on
# download with version should print nothing
go mod download rsc.io/quote@v1.5.0
! stdout .
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
# 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 '"Error"'
# download queries above should not have added to go.mod.
go list -m all
! stdout rsc.io
# add to go.mod so we can test non-query downloads
go mod edit -require rsc.io/quote@v1.5.2
! 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
# module loading will page in the info and mod files
go list -m all
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
# download will fetch and unpack the zip file
go mod download
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
exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
go mod download -json
stdout '^\t"Path": "rsc.io/quote"'
stdout '^\t"Version": "v1.5.2"'
stdout '^\t"Info": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.2.info"'
stdout '^\t"GoMod": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.2.mod"'
stdout '^\t"Zip": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.2.zip"'
stdout '^\t"Dir": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)rsc.io(\\\\|/)quote@v1.5.2"'
# 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.3-pre1
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.3-pre1.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
-- go.mod --
module m
View
@@ -2,12 +2,6 @@ env GO111MODULE=on
# @commit should resolve
# go get should skip build with no Go files in root
go get golang.org/x/text@14c0d48
# ... and go get should skip build with -m
go get -m golang.org/x/text@14c0d48
# golang.org/x/text/language@commit should not resolve with -m,
# because that's not a module path.
! go get -m golang.org/x/text/language@14c0d48
@@ -17,10 +11,25 @@ go get -m golang.org/x/text@14c0d48
go get -d -x golang.org/x/text/language@14c0d48
! stderr 'compile|cp|gccgo .*language\.a$'
# go get should skip build with no Go files in root
go get golang.org/x/text@14c0d48
# ... and go get should skip build with -m
go get -m golang.org/x/text@14c0d48
# dropping -d, we should see a build.
go get -x golang.org/x/text/language@14c0d48
stderr 'compile|cp|gccgo .*language\.a$'
# BUG: after the build, the package should not be stale, as 'go install' would
# not do anything further.
go list -f '{{.Stale}}' golang.org/x/text/language
stdout ^true
# install after get should not run the compiler again.
go install -x golang.org/x/text/language
! stderr 'compile|cp|gccgo .*language\.a$'
# even with -d, we should see an error for unknown packages.
! go get -d -x golang.org/x/text/foo@14c0d48
View
@@ -11,8 +11,14 @@ go list -m -f '{{.Path}} {{.Version}}{{if .Indirect}} // indirect{{end}}' all
stdout '^golang.org/x/text [v0-9a-f\.-]+ // indirect'
grep 'golang.org/x/text [v0-9a-f\.-]+ // indirect' go.mod
# indirect tag should be removed upon seeing direct import
# importing an empty module root as a package makes it direct.
# TODO(bcmills): This doesn't seem correct. Fix is in the next change.
cp $WORK/tmp/usetext.go x.go
go list -e
grep 'golang.org/x/text [v0-9a-f\.-]+ // indirect' go.mod
# indirect tag should be removed upon seeing direct import.
cp $WORK/tmp/uselang.go x.go
go list
grep 'rsc.io/quote v1.5.2$' go.mod
grep 'golang.org/x/text [v0-9a-f\.-]+$' go.mod
@@ -24,7 +30,7 @@ grep 'rsc.io/quote v1.5.2$' go.mod
grep 'golang.org/x/text [v0-9a-f\.-]+ // indirect' go.mod
# requirement should be dropped entirely if not needed
cp $WORK/tmp/usetext.go x.go
cp $WORK/tmp/uselang.go x.go
go mod tidy
! grep rsc.io/quote go.mod
grep 'golang.org/x/text [v0-9a-f\.-]+$' go.mod
@@ -37,6 +43,9 @@ package x
-- $WORK/tmp/usetext.go --
package x
import _ "golang.org/x/text"
-- $WORK/tmp/uselang.go --
package x
import _ "golang.org/x/text/language"
-- $WORK/tmp/usequote.go --
package x
import _ "rsc.io/quote"
View
@@ -0,0 +1,61 @@
# Test 'go get' with a local module with a name that is not valid for network lookup.
env GO111MODULE=on
go mod edit -fmt
cp go.mod go.mod.orig
# 'go get -u -m' within the main module should work, even if it has a local-only name.
cp go.mod.orig go.mod
go get -u -m
grep 'rsc.io/quote.*v1.5.2' go.mod
grep 'golang.org/x/text.*v0.3.0' go.mod
cp go.mod go.mod.implicitmod
# 'go get -u -m' with the name of the main module should be equivalent to
# 'go get -u -m' without any further arguments.
cp go.mod.orig go.mod
go get -u -m local
cmp go.mod go.mod.implicitmod
# 'go get -u -d' in the empty root of the main module should update the
# dependencies of all packages in the module.
cp go.mod.orig go.mod
go get -u -d
cmp go.mod go.mod.implicitmod
# 'go get -u -d .' within a package in the main module updates all dependencies
# of the main module.
# TODO: Determine whether that behavior is a bug.
# (https://golang.org/issue/26902)
cp go.mod.orig go.mod
cd uselang
go get -u -d .
cd ..
grep 'rsc.io/quote.*v1.5.2' go.mod
grep 'golang.org/x/text.*v0.3.0' go.mod
cp go.mod go.mod.dotpkg
# 'go get -u -d' with an explicit package in the main module updates
# all dependencies of the main module.
# TODO: Determine whether that behavior is a bug.
# (https://golang.org/issue/26902)
cp go.mod.orig go.mod
go get -u -d local/uselang
cmp go.mod go.mod.dotpkg
-- go.mod --
module local
require (
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
rsc.io/quote v1.3.0
)
-- uselang/uselang.go --
package uselang
import _ "golang.org/x/text/language"
-- usequote/usequote.go --
package usequote
import _ "rsc.io/quote"
View
@@ -0,0 +1,37 @@
env GO111MODULE=on
# A 'go get' that worked at a previous version should continue to work at that version,
# even if the package was subsequently moved into a submodule.
go mod init example.com/foo
go get -d example.com/split/subpkg@v1.0.0
go list -m all
stdout 'example.com/split v1.0.0'
# A 'go get' that simultaneously upgrades away conflicting package defitions is not ambiguous.
go get example.com/split/subpkg@v1.1.0
# A 'go get' without an upgrade should find the package.
rm go.mod
go mod init example.com/foo
go get -d example.com/split/subpkg
go list -m all
stdout 'example.com/split/subpkg v1.1.0'
# A 'go get' that worked at a previous version should continue to work at that version,
# even if the package was subsequently moved into a parent module.
rm go.mod
go mod init example.com/foo
go get -d example.com/join/subpkg@v1.0.0
go list -m all
stdout 'example.com/join/subpkg v1.0.0'
# A 'go get' that simultaneously upgrades away conflicting package definitions is not ambiguous.
go get example.com/join/subpkg@v1.1.0
# A 'go get' without an upgrade should find the package.
rm go.mod
go mod init example.com/foo
go get -d example.com/join/subpkg@v1.1.0
go list -m all
stdout 'example.com/join v1.1.0'
View
@@ -0,0 +1,12 @@
env GO111MODULE=on
go mod init example.com/foo
# 'go get bar@none' should be a no-op if module bar is not active.
go get example.com/bar@none
go list -m all
! stdout example.com/bar
go get example.com/bar@none
go list -m all
! stdout example.com/bar
View
@@ -5,65 +5,73 @@ env GO111MODULE=on
[!exec:git] skip
env GOPROXY=
# We can resolve the @master branch without unshallowing the local repository
# (even with older gits), so try that before we do anything else.
# (This replicates https://golang.org/issue/26713 with git 2.7.4.)
go get -m github.com/rsc/legacytest@master
go list -m all
stdout '^github.com/rsc/legacytest v2\.0\.1-0\.\d{14}-7303f7796364\+incompatible$'
# get should include incompatible tags in "latest" calculation.
go get -m github.com/rsc/legacytest@latest
go list
go list -m all
stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
# v0.0.0-pseudo
go get -m ...test@52853eb
# v2.0.1-0.pseudo+incompatible
go get -m ...test@7303f77
go list -m all
stdout '^github.com/rsc/legacytest v0\.0\.0-\d{14}-52853eb7b552$'
stdout '^github.com/rsc/legacytest v2\.0\.1-0\.\d{14}-7303f7796364\+incompatible$'
# v1.0.0
go get -m ...test@7fff7f3
# v2.0.0+incompatible by tag+incompatible
go get -m ...test@v2.0.0+incompatible
go list -m all
stdout '^github.com/rsc/legacytest v1\.0\.0$'
stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
# v1.0.1-0.pseudo
go get -m ...test@fa4f5d6
# v2.0.0+incompatible by tag
go get -m ...test@v2.0.0
go list -m all
stdout '^github.com/rsc/legacytest v1\.0\.1-0\.\d{14}-fa4f5d6a71c6$'
stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
# v1.1.0-pre (no longer on master)
go get -m ...test@731e3b1
# v2.0.0+incompatible by hash (back on master)
go get -m ...test@d7ae1e4
go list -m all
stdout '^github.com/rsc/legacytest v1\.1\.0-pre$'
stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
# v1.1.0-pre.0.pseudo
go get -m ...test@fb3c628
# v1.2.1-0.pseudo
go get -m ...test@d2d4c3e
go list -m all
stdout '^github.com/rsc/legacytest v1\.1\.0-pre\.0\.\d{14}-fb3c628075e3$'
stdout '^github.com/rsc/legacytest v1\.2\.1-0\.\d{14}-d2d4c3ea6623$'
# v1.2.0
go get -m ...test@9f6f860
go list -m all
stdout '^github.com/rsc/legacytest v1\.2\.0$'
# v1.2.1-0.pseudo
go get -m ...test@d2d4c3e
# v1.1.0-pre.0.pseudo
go get -m ...test@fb3c628
go list -m all
stdout '^github.com/rsc/legacytest v1\.2\.1-0\.\d{14}-d2d4c3ea6623$'
stdout '^github.com/rsc/legacytest v1\.1\.0-pre\.0\.\d{14}-fb3c628075e3$'
# v2.0.0+incompatible by hash (back on master)
go get -m ...test@d7ae1e4
# v1.1.0-pre (no longer on master)
go get -m ...test@731e3b1
go list -m all
stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
stdout '^github.com/rsc/legacytest v1\.1\.0-pre$'
# v2.0.0+incompatible by tag
go get -m ...test@v2.0.0
# v1.0.1-0.pseudo
go get -m ...test@fa4f5d6
go list -m all
stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
stdout '^github.com/rsc/legacytest v1\.0\.1-0\.\d{14}-fa4f5d6a71c6$'
# v2.0.0+incompatible by tag+incompatible
go get -m ...test@v2.0.0+incompatible
# v1.0.0
go get -m ...test@7fff7f3
go list -m all
stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
stdout '^github.com/rsc/legacytest v1\.0\.0$'
# v2.0.1-0.pseudo+incompatible
go get -m ...test@7303f77
# v0.0.0-pseudo
go get -m ...test@52853eb
go list -m all
stdout '^github.com/rsc/legacytest v2\.0\.1-0\.\d{14}-7303f7796364\+incompatible$'
stdout '^github.com/rsc/legacytest v0\.0\.0-\d{14}-52853eb7b552$'
-- go.mod --
module x
View
@@ -0,0 +1,13 @@
# Test for a crash in go fmt on invalid input when using modules.
# Issue 26792.
env GO111MODULE=on
! go fmt x.go
! stderr panic
-- go.mod --
module x
-- x.go --
// Missing package declaration.
var V int
View
@@ -0,0 +1,22 @@
env GO111MODULE=on
cp go.mod.empty go.mod
go get -d gopkg.in/dummy.v2-unstable
cp x.go.txt x.go
cp go.mod.empty go.mod
go list
[!net] skip
env GOPROXY=
go get gopkg.in/macaroon-bakery.v2-unstable/bakery
go list -m all
stdout 'gopkg.in/macaroon-bakery.v2-unstable v2.0.0-[0-9]+-[0-9a-f]+$'
-- go.mod.empty --
module m
-- x.go.txt --
package x
import _ "gopkg.in/dummy.v2-unstable"
View
@@ -0,0 +1,12 @@
env GO111MODULE=on
go list -f '{{.Target}}' rsc.io/fortune
! stdout fortune@v1
stdout 'fortune(\.exe)?$'
go list -f '{{.Target}}' rsc.io/fortune/v2
! stdout v2
stdout 'fortune(\.exe)?$'
-- go.mod --
module m
View
@@ -5,18 +5,27 @@ rm go.mod
go mod init golang.org/x/anything
go build .
# ...and their tests...
go test
stdout PASS
# ...but that should not leak into other modules.
! go build ./baddep
stderr 'use of internal package golang.org/x/.* not allowed in golang.org/notx/useinternal$'
stderr golang.org[/\\]notx[/\\]useinternal
stderr 'use of internal package golang.org/x/.* not allowed'
# Internal packages in the standard library should not leak into modules.
! go build ./fromstd
stderr 'use of internal package internal/testenv not allowed$'
stderr 'use of internal package internal/testenv not allowed'
# Packages found via standard-library vendoring should not leak.
! go build ./fromstdvendor
stderr 'use of vendored package golang_org/x/net/http/httpguts not allowed$'
stderr 'use of vendored package golang_org/x/net/http/httpguts not allowed'
env GO111MODULE=off
! go build ./fromstdvendor
stderr 'cannot find package "golang_org/x/net/http/httpguts" in any of:'
env GO111MODULE=on
# Dependencies should be able to use their own internal modules...
rm go.mod
@@ -25,12 +34,12 @@ go build ./throughdep
# ... but other modules should not, even if they have transitive dependencies.
! go build .
stderr 'use of internal package golang.org/x/.* not allowed in golang.org/notx$'
stderr 'use of internal package golang.org/x/.* not allowed'
# And transitive dependencies still should not leak.
! go build ./baddep
stderr 'use of internal package golang.org/x/.* not allowed in golang.org/notx/useinternal$'
stderr golang.org[/\\]notx[/\\]useinternal
stderr 'use of internal package golang.org/x/.* not allowed'
# Replacing an internal module should keep it internal to the same paths.
rm go.mod
@@ -39,18 +48,29 @@ go mod edit -replace golang.org/x/internal=./replace/golang.org/notx/internal
go build ./throughdep
! go build ./baddep
stderr 'use of internal package golang.org/x/.* not allowed in golang.org/notx/useinternal$'
stderr golang.org[/\\]notx[/\\]useinternal
stderr 'use of internal package golang.org/x/.* not allowed'
go mod edit -replace golang.org/x/internal=./vendor/golang.org/x/internal
go build ./throughdep
! go build ./baddep
stderr 'use of internal package golang.org/x/.* not allowed in golang.org/notx/useinternal$'
stderr golang.org[/\\]notx[/\\]useinternal
stderr 'use of internal package golang.org/x/.* not allowed'
-- useinternal.go --
package useinternal
import _ "golang.org/x/internal/subtle"
-- useinternal_test.go --
package useinternal_test
import (
"testing"
_ "golang.org/x/internal/subtle"
)
func Test(*testing.T) {}
-- throughdep/useinternal.go --
package throughdep
import _ "golang.org/x/useinternal"
Oops, something went wrong.