зеркало из https://github.com/golang/vgo.git
cmd/go: import from main repo at go1.11
One patch adjustment needed for CL 128735. Fixes golang/go#27530. Change-Id: I3884c2569e89754e31dd1a0ce53fad3b77e05c95 Reviewed-on: https://go-review.googlesource.com/134415 Run-TryBot: Bryan C. Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Родитель
045754d578
Коммит
9d567625ac
35
patch.txt
35
patch.txt
|
@ -434,19 +434,27 @@ diff -u -r ./internal/work/build.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/g
|
|||
|
||||
func runBuild(cmd *base.Command, args []string) {
|
||||
BuildInit()
|
||||
diff -u -r ./internal/work/buildid.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/work/buildid.go
|
||||
--- ./internal/work/buildid.go 2018-07-06 16:52:53.000000000 -0400
|
||||
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/work/buildid.go 2018-06-27 21:01:27.000000000 -0400
|
||||
@@ -134,6 +134,8 @@
|
||||
diff -u -r ./internal/work/buildid.go /home/bcmills/src/golang.org/x/vgo/vendor/cmd/go/internal/work/buildid.go
|
||||
--- ./internal/work/buildid.go 2018-09-10 17:07:58.954625955 -0400
|
||||
+++ /home/bcmills/src/golang.org/x/vgo/vendor/cmd/go/internal/work/buildid.go 2018-09-10 17:18:52.954844647 -0400
|
||||
@@ -18,7 +18,6 @@
|
||||
"cmd/go/internal/load"
|
||||
"cmd/go/internal/str"
|
||||
"cmd/internal/buildid"
|
||||
- "cmd/internal/objabi"
|
||||
)
|
||||
|
||||
// Build IDs
|
||||
@@ -135,6 +134,8 @@
|
||||
return string(dst[:])
|
||||
}
|
||||
|
||||
|
||||
+var oldVet = false
|
||||
+
|
||||
// toolID returns the unique ID to use for the current copy of the
|
||||
// named tool (asm, compile, cover, link).
|
||||
//
|
||||
@@ -166,6 +168,10 @@
|
||||
@@ -167,6 +168,10 @@
|
||||
// build setups agree on details like $GOROOT and file name paths, but at least the
|
||||
// tool IDs do not make it impossible.)
|
||||
func (b *Builder) toolID(name string) string {
|
||||
|
@ -457,7 +465,7 @@ diff -u -r ./internal/work/buildid.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd
|
|||
b.id.Lock()
|
||||
id := b.toolIDCache[name]
|
||||
b.id.Unlock()
|
||||
@@ -190,6 +196,10 @@
|
||||
@@ -191,6 +196,10 @@
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
|
@ -467,6 +475,19 @@ diff -u -r ./internal/work/buildid.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd
|
|||
+ }
|
||||
base.Fatalf("%s: %v\n%s%s", desc, err, stdout.Bytes(), stderr.Bytes())
|
||||
}
|
||||
|
||||
@@ -207,11 +216,6 @@
|
||||
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()
|
||||
|
||||
diff -u -r ./internal/work/exec.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/work/exec.go
|
||||
--- ./internal/work/exec.go 2018-07-12 00:17:57.000000000 -0400
|
||||
|
|
|
@ -1295,6 +1295,7 @@ func TestGetGitDefaultBranch(t *testing.T) {
|
|||
tg.grepStdout(`\* another-branch`, "not on correct default branch")
|
||||
}
|
||||
|
||||
// Security issue. Don't disable. See golang.org/issue/22125.
|
||||
func TestAccidentalGitCheckout(t *testing.T) {
|
||||
t.Skip("vgo") // Failing in main branch too: https://golang.org/issue/22983
|
||||
|
||||
|
@ -1307,13 +1308,17 @@ func TestAccidentalGitCheckout(t *testing.T) {
|
|||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.tempDir("src")
|
||||
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
|
||||
tg.runFail("get", "-u", "vcs-test.golang.org/go/test1-svn-git")
|
||||
tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
|
||||
|
||||
tg.runFail("get", "-u", "vcs-test.golang.org/go/test2-svn-git/test2main")
|
||||
tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
|
||||
if _, err := os.Stat(tg.path("SrC")); err == nil {
|
||||
// This case only triggers on a case-insensitive file system.
|
||||
tg.runFail("get", "-u", "vcs-test.golang.org/go/test2-svn-git/test2main")
|
||||
tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorMessageForSyntaxErrorInTestGoFileSaysFAIL(t *testing.T) {
|
||||
|
@ -3059,6 +3064,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()
|
||||
|
@ -3542,24 +3550,43 @@ func TestImportLocal(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGoGetInsecure(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
test := func(t *testing.T, modules bool) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.failSSH()
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.makeTempdir()
|
||||
tg.failSSH()
|
||||
|
||||
const repo = "insecure.go-get-issue-15410.appspot.com/pkg/p"
|
||||
if modules {
|
||||
tg.setenv("GOPATH", tg.path("gp"))
|
||||
tg.tempFile("go.mod", "module m")
|
||||
tg.cd(tg.path("."))
|
||||
tg.setenv("GO111MODULE", "on")
|
||||
} else {
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.setenv("GO111MODULE", "off")
|
||||
}
|
||||
|
||||
// Try go get -d of HTTP-only repo (should fail).
|
||||
tg.runFail("get", "-d", repo)
|
||||
const repo = "insecure.go-get-issue-15410.appspot.com/pkg/p"
|
||||
|
||||
// Try again with -insecure (should succeed).
|
||||
tg.run("get", "-d", "-insecure", repo)
|
||||
// Try go get -d of HTTP-only repo (should fail).
|
||||
tg.runFail("get", "-d", repo)
|
||||
|
||||
// Try updating without -insecure (should fail).
|
||||
tg.runFail("get", "-d", "-u", "-f", repo)
|
||||
// Try again with -insecure (should succeed).
|
||||
tg.run("get", "-d", "-insecure", repo)
|
||||
|
||||
// Try updating without -insecure (should fail).
|
||||
tg.runFail("get", "-d", "-u", "-f", repo)
|
||||
|
||||
if modules {
|
||||
tg.run("list", "-m", "...")
|
||||
tg.grepStdout("insecure.go-get-issue", "should find insecure module")
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("gopath", func(t *testing.T) { test(t, false) })
|
||||
t.Run("modules", func(t *testing.T) { test(t, true) })
|
||||
}
|
||||
|
||||
func TestGoGetUpdateInsecure(t *testing.T) {
|
||||
|
@ -4202,9 +4229,10 @@ func TestGoGetUpdateWithWildcard(t *testing.T) {
|
|||
tg.setenv("GOPATH", tg.path("."))
|
||||
const aPkgImportPath = "github.com/tmwh/go-get-issue-14450/a"
|
||||
tg.run("get", aPkgImportPath)
|
||||
tg.run("get", "-u", ".../")
|
||||
tg.grepStderrNot("cannot find package", "did not update packages given wildcard path")
|
||||
tg.runFail("get", "-u", ".../")
|
||||
tg.grepStderr("cannot find package.*d-dependency/e", "should have detected e missing")
|
||||
|
||||
// Even though get -u failed, the source for others should be downloaded.
|
||||
var expectedPkgPaths = []string{
|
||||
"src/github.com/tmwh/go-get-issue-14450/b",
|
||||
"src/github.com/tmwh/go-get-issue-14450-b-dependency/c",
|
||||
|
@ -5672,37 +5700,6 @@ func TestRelativePkgdir(t *testing.T) {
|
|||
tg.run("build", "-i", "-pkgdir=.", "runtime")
|
||||
}
|
||||
|
||||
func TestGcflagsPatterns(t *testing.T) {
|
||||
skipIfGccgo(t, "gccgo has no standard packages")
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.setenv("GOPATH", "")
|
||||
tg.setenv("GOCACHE", "off")
|
||||
|
||||
tg.run("build", "-n", "-v", "-gcflags= \t\r\n -e", "fmt")
|
||||
tg.grepStderr("^# fmt", "did not rebuild fmt")
|
||||
tg.grepStderrNot("^# reflect", "incorrectly rebuilt reflect")
|
||||
|
||||
tg.run("build", "-n", "-v", "-gcflags=-e", "fmt", "reflect")
|
||||
tg.grepStderr("^# fmt", "did not rebuild fmt")
|
||||
tg.grepStderr("^# reflect", "did not rebuild reflect")
|
||||
tg.grepStderrNot("^# runtime", "incorrectly rebuilt runtime")
|
||||
|
||||
tg.run("build", "-n", "-x", "-v", "-gcflags= \t\r\n reflect \t\r\n = \t\r\n -N", "fmt")
|
||||
tg.grepStderr("^# fmt", "did not rebuild fmt")
|
||||
tg.grepStderr("^# reflect", "did not rebuild reflect")
|
||||
tg.grepStderr("compile.* -N .*-p reflect", "did not build reflect with -N flag")
|
||||
tg.grepStderrNot("compile.* -N .*-p fmt", "incorrectly built fmt with -N flag")
|
||||
|
||||
tg.run("test", "-c", "-n", "-gcflags=-N", "-ldflags=-X=x.y=z", "strings")
|
||||
tg.grepStderr("compile.* -N .*compare_test.go", "did not compile strings_test package with -N flag")
|
||||
tg.grepStderr("link.* -X=x.y=z", "did not link strings.test binary with -X flag")
|
||||
|
||||
tg.run("test", "-c", "-n", "-gcflags=strings=-N", "-ldflags=strings=-X=x.y=z", "strings")
|
||||
tg.grepStderr("compile.* -N .*compare_test.go", "did not compile strings_test package with -N flag")
|
||||
tg.grepStderr("link.* -X=x.y=z", "did not link strings.test binary with -X flag")
|
||||
}
|
||||
|
||||
func TestGoTestMinusN(t *testing.T) {
|
||||
// Intent here is to verify that 'go test -n' works without crashing.
|
||||
// This reuses flag_test.go, but really any test would do.
|
||||
|
@ -5849,57 +5846,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()
|
||||
|
|
|
@ -7,10 +7,10 @@ const DefaultPkgConfig = `pkg-config`
|
|||
func DefaultCC(goos, goarch string) string {
|
||||
switch goos + `/` + goarch {
|
||||
}
|
||||
return "clang"
|
||||
return "gcc"
|
||||
}
|
||||
func DefaultCXX(goos, goarch string) string {
|
||||
switch goos + `/` + goarch {
|
||||
}
|
||||
return "clang++"
|
||||
return "c++"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -163,9 +163,8 @@ func runGet(cmd *base.Command, args []string) {
|
|||
if *getT {
|
||||
mode |= load.GetTestDeps
|
||||
}
|
||||
args = downloadPaths(args)
|
||||
for _, arg := range args {
|
||||
download(arg, nil, &stk, mode)
|
||||
for _, pkg := range downloadPaths(args) {
|
||||
download(pkg, nil, &stk, mode)
|
||||
}
|
||||
base.ExitIfErrors()
|
||||
|
||||
|
@ -184,8 +183,7 @@ func runGet(cmd *base.Command, args []string) {
|
|||
// This leads to duplicated loads of the standard packages.
|
||||
load.ClearCmdCache()
|
||||
|
||||
args = load.ImportPaths(args)
|
||||
load.PackagesForBuild(args)
|
||||
pkgs := load.PackagesForBuild(args)
|
||||
|
||||
// Phase 3. Install.
|
||||
if *getD {
|
||||
|
@ -195,7 +193,7 @@ func runGet(cmd *base.Command, args []string) {
|
|||
return
|
||||
}
|
||||
|
||||
work.InstallPackages(args)
|
||||
work.InstallPackages(args, pkgs)
|
||||
}
|
||||
|
||||
// downloadPaths prepares the list of paths to pass to download.
|
||||
|
@ -203,34 +201,21 @@ func runGet(cmd *base.Command, args []string) {
|
|||
// for a particular pattern, downloadPaths leaves it in the result list,
|
||||
// in the hope that we can figure out the repository from the
|
||||
// initial ...-free prefix.
|
||||
func downloadPaths(args []string) []string {
|
||||
for _, arg := range args {
|
||||
func downloadPaths(patterns []string) []string {
|
||||
for _, arg := range patterns {
|
||||
if strings.Contains(arg, "@") {
|
||||
base.Fatalf("go: cannot use path@version syntax in GOPATH mode")
|
||||
}
|
||||
}
|
||||
|
||||
args = load.ImportPathsForGoGet(args)
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
if strings.Contains(a, "...") {
|
||||
var expand []string
|
||||
// Use matchPackagesInFS to avoid printing
|
||||
// warnings. They will be printed by the
|
||||
// eventual call to importPaths instead.
|
||||
if build.IsLocalImport(a) {
|
||||
expand = search.MatchPackagesInFS(a)
|
||||
} else {
|
||||
expand = search.MatchPackages(a)
|
||||
}
|
||||
if len(expand) > 0 {
|
||||
out = append(out, expand...)
|
||||
continue
|
||||
}
|
||||
var pkgs []string
|
||||
for _, m := range search.ImportPathsQuiet(patterns) {
|
||||
if len(m.Pkgs) == 0 && strings.Contains(m.Pattern, "...") {
|
||||
pkgs = append(pkgs, m.Pattern)
|
||||
} else {
|
||||
pkgs = append(pkgs, m.Pkgs...)
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// downloadCache records the import paths we have already
|
||||
|
@ -255,7 +240,7 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int)
|
|||
}
|
||||
load1 := func(path string, mode int) *load.Package {
|
||||
if parent == nil {
|
||||
return load.LoadPackage(path, stk)
|
||||
return load.LoadPackageNoFlags(path, stk)
|
||||
}
|
||||
return load.LoadImport(path, parent.Dir, parent, stk, nil, mode|load.ResolveModule)
|
||||
}
|
||||
|
@ -311,9 +296,9 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int)
|
|||
// for p has been replaced in the package cache.
|
||||
if wildcardOkay && strings.Contains(arg, "...") {
|
||||
if build.IsLocalImport(arg) {
|
||||
args = search.MatchPackagesInFS(arg)
|
||||
args = search.MatchPackagesInFS(arg).Pkgs
|
||||
} else {
|
||||
args = search.MatchPackages(arg)
|
||||
args = search.MatchPackages(arg).Pkgs
|
||||
}
|
||||
isWildcard = true
|
||||
}
|
||||
|
@ -344,7 +329,7 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int)
|
|||
base.Run(cfg.BuildToolexec, str.StringList(base.Tool("fix"), files))
|
||||
|
||||
// The imports might have changed, so reload again.
|
||||
p = load.ReloadPackage(arg, stk)
|
||||
p = load.ReloadPackageNoFlags(arg, stk)
|
||||
if p.Error != nil {
|
||||
base.Errorf("%s", p.Error)
|
||||
return
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -37,6 +37,7 @@ func scanFiles(files []string, tags map[string]bool, explicitFiles bool) ([]stri
|
|||
imports := make(map[string]bool)
|
||||
testImports := make(map[string]bool)
|
||||
numFiles := 0
|
||||
Files:
|
||||
for _, name := range files {
|
||||
r, err := os.Open(name)
|
||||
if err != nil {
|
||||
|
@ -48,6 +49,19 @@ func scanFiles(files []string, tags map[string]bool, explicitFiles bool) ([]stri
|
|||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("reading %s: %v", name, err)
|
||||
}
|
||||
|
||||
// import "C" is implicit requirement of cgo tag.
|
||||
// When listing files on the command line (explicitFiles=true)
|
||||
// we do not apply build tag filtering but we still do apply
|
||||
// cgo filtering, so no explicitFiles check here.
|
||||
// Why? Because we always have, and it's not worth breaking
|
||||
// that behavior now.
|
||||
for _, path := range list {
|
||||
if path == `"C"` && !tags["cgo"] && !tags["*"] {
|
||||
continue Files
|
||||
}
|
||||
}
|
||||
|
||||
if !explicitFiles && !ShouldBuild(data, tags) {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
@ -46,24 +47,25 @@ syntax of package template. The default output is equivalent
|
|||
to -f '{{.ImportPath}}'. The struct being passed to the template is:
|
||||
|
||||
type Package struct {
|
||||
Dir string // directory containing package sources
|
||||
ImportPath string // import path of package in dir
|
||||
ImportComment string // path in import comment on package statement
|
||||
Name string // package name
|
||||
Doc string // package documentation string
|
||||
Target string // install path
|
||||
Shlib string // the shared library that contains this package (only set when -linkshared)
|
||||
Goroot bool // is this package in the Go root?
|
||||
Standard bool // is this package part of the standard Go library?
|
||||
Stale bool // would 'go install' do anything for this package?
|
||||
StaleReason string // explanation for Stale==true
|
||||
Root string // Go root or Go path dir containing this package
|
||||
ConflictDir string // this directory shadows Dir in $GOPATH
|
||||
BinaryOnly bool // binary-only package: cannot be recompiled from sources
|
||||
ForTest string // package is only for use in named test
|
||||
DepOnly bool // package is only a dependency, not explicitly listed
|
||||
Export string // file containing export data (when using -export)
|
||||
Module *Module // info about package's containing module, if any (can be nil)
|
||||
Dir string // directory containing package sources
|
||||
ImportPath string // import path of package in dir
|
||||
ImportComment string // path in import comment on package statement
|
||||
Name string // package name
|
||||
Doc string // package documentation string
|
||||
Target string // install path
|
||||
Shlib string // the shared library that contains this package (only set when -linkshared)
|
||||
Goroot bool // is this package in the Go root?
|
||||
Standard bool // is this package part of the standard Go library?
|
||||
Stale bool // would 'go install' do anything for this package?
|
||||
StaleReason string // explanation for Stale==true
|
||||
Root string // Go root or Go path dir containing this package
|
||||
ConflictDir string // this directory shadows Dir in $GOPATH
|
||||
BinaryOnly bool // binary-only package: cannot be recompiled from sources
|
||||
ForTest string // package is only for use in named test
|
||||
Export string // file containing export data (when using -export)
|
||||
Module *Module // info about package's containing module, if any (can be nil)
|
||||
Match []string // command-line patterns matching this package
|
||||
DepOnly bool // package is only a dependency, not explicitly listed
|
||||
|
||||
// Source files
|
||||
GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
|
||||
|
@ -107,7 +109,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 +148,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
|
||||
|
@ -266,7 +269,7 @@ A pattern containing "..." specifies the active modules whose
|
|||
module paths match the pattern.
|
||||
A query of the form path@version specifies the result of that query,
|
||||
which is not limited to active modules.
|
||||
See 'go help module' for more about module queries.
|
||||
See 'go help modules' for more about module queries.
|
||||
|
||||
The template function "module" takes a single string argument
|
||||
that must be a module path or query and returns the specified
|
||||
|
@ -303,6 +306,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()
|
||||
|
@ -506,7 +510,9 @@ func runList(cmd *base.Command, args []string) {
|
|||
a := &work.Action{}
|
||||
// TODO: Use pkgsFilter?
|
||||
for _, p := range pkgs {
|
||||
a.Deps = append(a.Deps, b.AutoAction(work.ModeInstall, work.ModeInstall, p))
|
||||
if len(p.GoFiles)+len(p.CgoFiles) > 0 {
|
||||
a.Deps = append(a.Deps, b.AutoAction(work.ModeInstall, work.ModeInstall, p))
|
||||
}
|
||||
}
|
||||
b.Do(a)
|
||||
}
|
||||
|
@ -516,6 +522,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 {
|
||||
|
|
|
@ -6,7 +6,6 @@ package load
|
|||
|
||||
import (
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/search"
|
||||
"cmd/go/internal/str"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
@ -92,52 +91,3 @@ func (f *PerPackageFlag) For(p *Package) []string {
|
|||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
var (
|
||||
cmdlineMatchers []func(*Package) bool
|
||||
cmdlineMatcherLiterals []func(*Package) bool
|
||||
)
|
||||
|
||||
// SetCmdlinePatterns records the set of patterns given on the command line,
|
||||
// for use by the PerPackageFlags.
|
||||
func SetCmdlinePatterns(args []string) {
|
||||
setCmdlinePatterns(args, base.Cwd)
|
||||
}
|
||||
|
||||
func setCmdlinePatterns(args []string, cwd string) {
|
||||
if len(args) == 0 {
|
||||
args = []string{"."}
|
||||
}
|
||||
cmdlineMatchers = nil // allow reset for testing
|
||||
cmdlineMatcherLiterals = nil
|
||||
for _, arg := range args {
|
||||
cmdlineMatchers = append(cmdlineMatchers, MatchPackage(arg, cwd))
|
||||
}
|
||||
for _, arg := range args {
|
||||
if !strings.Contains(arg, "...") && !search.IsMetaPackage(arg) {
|
||||
cmdlineMatcherLiterals = append(cmdlineMatcherLiterals, MatchPackage(arg, cwd))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// isCmdlinePkg reports whether p is a package listed on the command line.
|
||||
func isCmdlinePkg(p *Package) bool {
|
||||
for _, m := range cmdlineMatchers {
|
||||
if m(p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// isCmdlinePkgLiteral reports whether p is a package listed as
|
||||
// a literal package argument on the command line
|
||||
// (as opposed to being the result of expanding a wildcard).
|
||||
func isCmdlinePkgLiteral(p *Package) bool {
|
||||
for _, m := range cmdlineMatcherLiterals {
|
||||
if m(p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -32,13 +32,14 @@ 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) []*search.Match // 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
|
||||
ModDirImportPath func(string) string // return effective import path for directory
|
||||
)
|
||||
|
||||
var IgnoreImports bool // control whether we ignore imports in packages
|
||||
|
@ -60,15 +61,17 @@ type PackagePublic struct {
|
|||
Doc string `json:",omitempty"` // package documentation string
|
||||
Target string `json:",omitempty"` // installed target for this package (may be executable)
|
||||
Shlib string `json:",omitempty"` // the shared library that contains this package (only set when -linkshared)
|
||||
Goroot bool `json:",omitempty"` // is this package found in the Go root?
|
||||
Standard bool `json:",omitempty"` // is this package part of the standard Go library?
|
||||
Root string `json:",omitempty"` // Go root or Go path dir containing this package
|
||||
ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
|
||||
BinaryOnly bool `json:",omitempty"` // package cannot be recompiled
|
||||
ForTest string `json:",omitempty"` // package is only for use in named test
|
||||
DepOnly bool `json:",omitempty"` // package is only as a dependency, not explicitly listed
|
||||
Export string `json:",omitempty"` // file containing export data (set by go list -export)
|
||||
Module *modinfo.ModulePublic `json:",omitempty"` // info about package's module, if any
|
||||
Match []string `json:",omitempty"` // command-line patterns matching this package
|
||||
Goroot bool `json:",omitempty"` // is this package found in the Go root?
|
||||
Standard bool `json:",omitempty"` // is this package part of the standard Go library?
|
||||
DepOnly bool `json:",omitempty"` // package is only as a dependency, not explicitly listed
|
||||
BinaryOnly bool `json:",omitempty"` // package cannot be recompiled
|
||||
Incomplete bool `json:",omitempty"` // was there an error loading this package or dependencies?
|
||||
|
||||
// Stale and StaleReason remain here *only* for the list command.
|
||||
// They are only initialized in preparation for list execution.
|
||||
|
@ -107,7 +110,7 @@ type PackagePublic struct {
|
|||
Deps []string `json:",omitempty"` // all (recursively) imported dependencies
|
||||
|
||||
// Error information
|
||||
Incomplete bool `json:",omitempty"` // was there an error loading this package or dependencies?
|
||||
// Incomplete is above, packed into the other bools
|
||||
Error *PackageError `json:",omitempty"` // error loading this package (not dependencies)
|
||||
DepsErrors []*PackageError `json:",omitempty"` // errors loading dependencies
|
||||
|
||||
|
@ -157,6 +160,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 +323,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) {
|
||||
|
@ -372,15 +377,17 @@ func ClearPackageCachePartial(args []string) {
|
|||
}
|
||||
}
|
||||
|
||||
// reloadPackage is like loadPackage but makes sure
|
||||
// ReloadPackageNoFlags is like LoadPackageNoFlags but makes sure
|
||||
// not to use the package cache.
|
||||
func ReloadPackage(arg string, stk *ImportStack) *Package {
|
||||
// It is only for use by GOPATH-based "go get".
|
||||
// TODO(rsc): When GOPATH-based "go get" is removed, delete this function.
|
||||
func ReloadPackageNoFlags(arg string, stk *ImportStack) *Package {
|
||||
p := packageCache[arg]
|
||||
if p != nil {
|
||||
delete(packageCache, p.Dir)
|
||||
delete(packageCache, p.ImportPath)
|
||||
}
|
||||
return LoadPackage(arg, stk)
|
||||
return LoadPackageNoFlags(arg, stk)
|
||||
}
|
||||
|
||||
// dirToImportPath returns the pseudo-import path we use for a package
|
||||
|
@ -429,6 +436,9 @@ const (
|
|||
// but possibly a local import path (an absolute file system path or one beginning
|
||||
// with ./ or ../). A local relative path is interpreted relative to srcDir.
|
||||
// It returns a *Package describing the package found in that directory.
|
||||
// LoadImport does not set tool flags and should only be used by
|
||||
// this package, as part of a bigger load operation, and by GOPATH-based "go get".
|
||||
// TODO(rsc): When GOPATH-based "go get" is removed, unexport this function.
|
||||
func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package {
|
||||
stk.Push(path)
|
||||
defer stk.Pop()
|
||||
|
@ -468,6 +478,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 +496,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 +568,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, parent, 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, parent, parentPath, origPath, p, stk); perr != p {
|
||||
return setErrorPos(perr, importPos)
|
||||
}
|
||||
}
|
||||
|
@ -626,11 +637,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 +929,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 string, importer *Package, 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 +977,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)]
|
||||
|
||||
|
@ -984,21 +991,25 @@ func disallowInternal(srcDir string, p *Package, stk *ImportStack) *Package {
|
|||
return p
|
||||
}
|
||||
} else {
|
||||
// p is in a module, so make it available based on the import path instead
|
||||
// p is in a module, so make it available based on the importer's 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 importerPath == "." {
|
||||
// The importer is a list of command-line files.
|
||||
// Pretend that the import path is the import path of the
|
||||
// directory containing them.
|
||||
importerPath = ModDirImportPath(importer.Dir)
|
||||
}
|
||||
parentOfInternal := p.ImportPath[:i]
|
||||
if str.HasPathPrefix(importerPath, parentOfInternal) {
|
||||
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 +1034,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 string, importer *Package, 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,27 +1047,18 @@ func disallowVendor(srcDir, path string, p *Package, stk *ImportStack) *Package
|
|||
return p
|
||||
}
|
||||
|
||||
if p.Standard && ModPackageModuleInfo != nil {
|
||||
// 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 {
|
||||
dir := p.Dir
|
||||
if relDir, err := filepath.Rel(p.Root, p.Dir); err == nil {
|
||||
dir = relDir
|
||||
}
|
||||
if _, ok := FindVendor(filepath.ToSlash(dir)); ok {
|
||||
perr := *p
|
||||
perr.Error = &PackageError{
|
||||
ImportStack: stk.Copy(),
|
||||
Err: "use of vendored package " + path + " not allowed",
|
||||
}
|
||||
perr.Incomplete = true
|
||||
return &perr
|
||||
}
|
||||
// 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/".
|
||||
if p.Standard && !importer.Standard && strings.HasPrefix(p.ImportPath, "golang_org") {
|
||||
perr := *p
|
||||
perr.Error = &PackageError{
|
||||
ImportStack: stk.Copy(),
|
||||
Err: "use of vendored package " + path + " not allowed",
|
||||
}
|
||||
perr.Incomplete = true
|
||||
return &perr
|
||||
}
|
||||
|
||||
if perr := disallowVendorVisibility(srcDir, p, stk); perr != p {
|
||||
|
@ -1188,27 +1191,6 @@ var foldPath = make(map[string]string)
|
|||
func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
||||
p.copyBuild(bp)
|
||||
|
||||
// Decide whether p was listed on the command line.
|
||||
// Given that load is called while processing the command line,
|
||||
// you might think we could simply pass a flag down into load
|
||||
// saying whether we are loading something named on the command
|
||||
// line or something to satisfy an import. But the first load of a
|
||||
// package named on the command line may be as a dependency
|
||||
// of an earlier package named on the command line, not when we
|
||||
// get to that package during command line processing.
|
||||
// For example "go test fmt reflect" will load reflect as a dependency
|
||||
// of fmt before it attempts to load as a command-line argument.
|
||||
// Because loads are cached, the later load will be a no-op,
|
||||
// so it is important that the first load can fill in CmdlinePkg correctly.
|
||||
// Hence the call to a separate matching check here.
|
||||
p.Internal.CmdlinePkg = isCmdlinePkg(p)
|
||||
p.Internal.CmdlinePkgLiteral = isCmdlinePkgLiteral(p)
|
||||
|
||||
p.Internal.Asmflags = BuildAsmflags.For(p)
|
||||
p.Internal.Gcflags = BuildGcflags.For(p)
|
||||
p.Internal.Ldflags = BuildLdflags.For(p)
|
||||
p.Internal.Gccgoflags = BuildGccgoflags.For(p)
|
||||
|
||||
// The localPrefix is the path we interpret ./ imports relative to.
|
||||
// Synthesized main packages sometimes override this.
|
||||
if p.Internal.Local {
|
||||
|
@ -1245,6 +1227,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 +1313,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 +1352,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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1706,11 +1725,31 @@ func ClearCmdCache() {
|
|||
}
|
||||
}
|
||||
|
||||
// LoadPackage loads the package named by arg.
|
||||
func LoadPackage(arg string, stk *ImportStack) *Package {
|
||||
p := loadPackage(arg, stk)
|
||||
setToolFlags(p)
|
||||
return p
|
||||
}
|
||||
|
||||
// LoadPackageNoFlags is like LoadPackage
|
||||
// but does not guarantee that the build tool flags are set in the result.
|
||||
// It is only for use by GOPATH-based "go get"
|
||||
// and is only appropriate for preliminary loading of packages.
|
||||
// A real load using LoadPackage or (more likely)
|
||||
// Packages, PackageAndErrors, or PackagesForBuild
|
||||
// must be done before passing the package to any build
|
||||
// steps, so that the tool flags can be set properly.
|
||||
// TODO(rsc): When GOPATH-based "go get" is removed, delete this function.
|
||||
func LoadPackageNoFlags(arg string, stk *ImportStack) *Package {
|
||||
return loadPackage(arg, stk)
|
||||
}
|
||||
|
||||
// loadPackage is like loadImport but is used for command-line arguments,
|
||||
// not for paths found in import statements. In addition to ordinary import paths,
|
||||
// loadPackage accepts pseudo-paths beginning with cmd/ to denote commands
|
||||
// in the Go command directory, as well as paths to those directories.
|
||||
func LoadPackage(arg string, stk *ImportStack) *Package {
|
||||
func loadPackage(arg string, stk *ImportStack) *Package {
|
||||
if build.IsLocalImport(arg) {
|
||||
dir := arg
|
||||
if !filepath.IsAbs(dir) {
|
||||
|
@ -1771,7 +1810,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,58 +1830,68 @@ 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.
|
||||
func PackagesAndErrors(args []string) []*Package {
|
||||
if len(args) > 0 && strings.HasSuffix(args[0], ".go") {
|
||||
return []*Package{GoFilesPackage(args)}
|
||||
func PackagesAndErrors(patterns []string) []*Package {
|
||||
if len(patterns) > 0 && strings.HasSuffix(patterns[0], ".go") {
|
||||
return []*Package{GoFilesPackage(patterns)}
|
||||
}
|
||||
|
||||
args = ImportPaths(args)
|
||||
matches := ImportPaths(patterns)
|
||||
var (
|
||||
pkgs []*Package
|
||||
stk ImportStack
|
||||
seenArg = make(map[string]bool)
|
||||
seenPkg = make(map[*Package]bool)
|
||||
)
|
||||
|
||||
for _, arg := range args {
|
||||
if seenArg[arg] {
|
||||
continue
|
||||
for _, m := range matches {
|
||||
for _, pkg := range m.Pkgs {
|
||||
p := loadPackage(pkg, &stk)
|
||||
p.Match = append(p.Match, m.Pattern)
|
||||
p.Internal.CmdlinePkg = true
|
||||
if m.Literal {
|
||||
// Note: do not set = m.Literal unconditionally
|
||||
// because maybe we'll see p matching both
|
||||
// a literal and also a non-literal pattern.
|
||||
p.Internal.CmdlinePkgLiteral = true
|
||||
}
|
||||
if seenPkg[p] {
|
||||
continue
|
||||
}
|
||||
seenPkg[p] = true
|
||||
pkgs = append(pkgs, p)
|
||||
}
|
||||
seenArg[arg] = true
|
||||
pkg := LoadPackage(arg, &stk)
|
||||
if seenPkg[pkg] {
|
||||
continue
|
||||
}
|
||||
seenPkg[pkg] = true
|
||||
pkgs = append(pkgs, pkg)
|
||||
}
|
||||
|
||||
// Now that CmdlinePkg is set correctly,
|
||||
// compute the effective flags for all loaded packages
|
||||
// (not just the ones matching the patterns but also
|
||||
// their dependencies).
|
||||
setToolFlags(pkgs...)
|
||||
|
||||
return pkgs
|
||||
}
|
||||
|
||||
func ImportPaths(args []string) []string {
|
||||
if cmdlineMatchers == nil {
|
||||
SetCmdlinePatterns(search.CleanImportPaths(args))
|
||||
func setToolFlags(pkgs ...*Package) {
|
||||
for _, p := range PackageList(pkgs) {
|
||||
p.Internal.Asmflags = BuildAsmflags.For(p)
|
||||
p.Internal.Gcflags = BuildGcflags.For(p)
|
||||
p.Internal.Ldflags = BuildLdflags.For(p)
|
||||
p.Internal.Gccgoflags = BuildGccgoflags.For(p)
|
||||
}
|
||||
}
|
||||
|
||||
func ImportPaths(args []string) []*search.Match {
|
||||
if ModInit(); cfg.ModulesEnabled {
|
||||
return ModImportPaths(args)
|
||||
}
|
||||
return search.ImportPaths(args)
|
||||
}
|
||||
|
||||
func ImportPathsForGoGet(args []string) []string {
|
||||
if cmdlineMatchers == nil {
|
||||
SetCmdlinePatterns(search.CleanImportPaths(args))
|
||||
}
|
||||
return search.ImportPathsNoDotExpansion(args)
|
||||
}
|
||||
|
||||
// packagesForBuild is like 'packages' but fails if any of
|
||||
// the packages or their dependencies have errors
|
||||
// PackagesForBuild is like Packages but exits
|
||||
// if any of the packages or their dependencies have errors
|
||||
// (cannot be built).
|
||||
func PackagesForBuild(args []string) []*Package {
|
||||
pkgs := PackagesAndErrors(args)
|
||||
|
@ -1890,7 +1939,6 @@ func PackagesForBuild(args []string) []*Package {
|
|||
func GoFilesPackage(gofiles []string) *Package {
|
||||
ModInit()
|
||||
|
||||
// TODO: Remove this restriction.
|
||||
for _, f := range gofiles {
|
||||
if !strings.HasSuffix(f, ".go") {
|
||||
base.Fatalf("named files must be .go files")
|
||||
|
@ -1942,6 +1990,11 @@ func GoFilesPackage(gofiles []string) *Package {
|
|||
}
|
||||
|
||||
bp, err := ctxt.ImportDir(dir, 0)
|
||||
if ModDirImportPath != nil {
|
||||
// Use the effective import path of the directory
|
||||
// for deciding visibility during pkg.load.
|
||||
bp.ImportPath = ModDirImportPath(dir)
|
||||
}
|
||||
pkg := new(Package)
|
||||
pkg.Internal.Local = true
|
||||
pkg.Internal.CmdlineFiles = true
|
||||
|
@ -1951,6 +2004,7 @@ func GoFilesPackage(gofiles []string) *Package {
|
|||
pkg.Internal.LocalPrefix = dirToImportPath(dir)
|
||||
pkg.ImportPath = "command-line-arguments"
|
||||
pkg.Target = ""
|
||||
pkg.Match = gofiles
|
||||
|
||||
if pkg.Name == "main" {
|
||||
_, elem := filepath.Split(gofiles[0])
|
||||
|
@ -1965,5 +2019,7 @@ func GoFilesPackage(gofiles []string) *Package {
|
|||
}
|
||||
}
|
||||
|
||||
setToolFlags(pkg)
|
||||
|
||||
return pkg
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ package load
|
|||
|
||||
import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"cmd/go/internal/search"
|
||||
|
@ -28,13 +27,7 @@ func MatchPackage(pattern, cwd string) func(*Package) bool {
|
|||
}
|
||||
dir = filepath.Join(cwd, dir)
|
||||
if pattern == "" {
|
||||
return func(p *Package) bool {
|
||||
// TODO(rsc): This is wrong. See golang.org/issue/25878.
|
||||
if runtime.GOOS != "windows" {
|
||||
return p.Dir == dir
|
||||
}
|
||||
return strings.EqualFold(p.Dir, dir)
|
||||
}
|
||||
return func(p *Package) bool { return p.Dir == dir }
|
||||
}
|
||||
matchPath := search.MatchPattern(pattern)
|
||||
return func(p *Package) bool {
|
||||
|
|
|
@ -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 = ""
|
||||
}
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
// 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
|
||||
Sum string // checksum for path, version (as in go.sum)
|
||||
GoModSum string // checksum for go.mod (as in go.sum)
|
||||
}
|
||||
|
||||
See 'go help modules' 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"`
|
||||
Sum string `json:",omitempty"`
|
||||
GoModSum 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
|
||||
}
|
||||
m.GoModSum, err = modfetch.GoModSum(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.Sum = modfetch.Sum(mod)
|
||||
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'))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
// 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.
|
||||
|
||||
// go mod fix
|
||||
|
||||
package modcmd
|
||||
|
||||
import (
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/modload"
|
||||
)
|
||||
|
||||
var cmdFix = &base.Command{
|
||||
UsageLine: "go mod fix",
|
||||
Short: "make go.mod semantically consistent",
|
||||
Long: `
|
||||
Fix updates go.mod to use canonical version identifiers and
|
||||
to be semantically consistent. For example, consider this go.mod file:
|
||||
|
||||
module M
|
||||
|
||||
require (
|
||||
A v1
|
||||
B v1.0.0
|
||||
C v1.0.0
|
||||
D v1.2.3
|
||||
E dev
|
||||
)
|
||||
|
||||
exclude D v1.2.3
|
||||
|
||||
First, fix rewrites non-canonical version identifiers to semver form, so
|
||||
A's v1 becomes v1.0.0 and E's dev becomes the pseudo-version for the latest
|
||||
commit on the dev branch, perhaps v0.0.0-20180523231146-b3f5c0f6e5f1.
|
||||
|
||||
Next, fix updates requirements to respect exclusions, so the requirement
|
||||
on the excluded D v1.2.3 is updated to use the next available version of D,
|
||||
perhaps D v1.2.4 or D v1.3.0.
|
||||
|
||||
Finally, fix removes redundant or misleading requirements.
|
||||
For example, if A v1.0.0 itself requires B v1.2.0 and C v1.0.0, then go.mod's
|
||||
requirement of B v1.0.0 is misleading (superseded by A's need for v1.2.0),
|
||||
and its requirement of C v1.0.0 is redundant (implied by A's need for the
|
||||
same version), so both will be removed. If module M contains packages
|
||||
that directly import packages from B or C, then the requirements will be
|
||||
kept but updated to the actual versions being used.
|
||||
|
||||
Although fix runs the fix-up operation in isolation, the fix-up also
|
||||
runs automatically any time a go command uses the module graph,
|
||||
to update go.mod to reflect reality. Because the module graph defines
|
||||
the meaning of import statements, any commands that load packages
|
||||
also use and therefore fix the module graph. For example,
|
||||
go build, go get, go install, go list, go test, go mod graph, go mod tidy,
|
||||
and other commands all effectively imply go mod fix.
|
||||
`,
|
||||
Run: runFix,
|
||||
}
|
||||
|
||||
func runFix(cmd *base.Command, args []string) {
|
||||
if len(args) != 0 {
|
||||
base.Fatalf("go mod fix: fix takes no arguments")
|
||||
}
|
||||
modload.LoadBuildList() // writes go.mod
|
||||
}
|
|
@ -19,12 +19,13 @@ See 'go help modules' for an overview of module functionality.
|
|||
`,
|
||||
|
||||
Commands: []*base.Command{
|
||||
cmdDownload,
|
||||
cmdEdit,
|
||||
cmdFix,
|
||||
cmdGraph,
|
||||
cmdInit,
|
||||
cmdTidy,
|
||||
cmdVendor,
|
||||
cmdVerify,
|
||||
cmdWhy,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -44,10 +44,11 @@ func runTidy(cmd *base.Command, args []string) {
|
|||
|
||||
// LoadALL adds missing modules.
|
||||
// Remove unused modules.
|
||||
used := map[module.Version]bool{modload.Target: true}
|
||||
used := make(map[module.Version]bool)
|
||||
for _, pkg := range modload.LoadALL() {
|
||||
used[modload.PackageModule(pkg)] = true
|
||||
}
|
||||
used[modload.Target] = true // note: LoadALL initializes Target
|
||||
|
||||
inGoMod := make(map[string]bool)
|
||||
for _, r := range modload.ModFile().Require {
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
// 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 {
|
||||
matches := modload.ImportPaths(args) // resolve to packages
|
||||
loadALL() // rebuild graph, from main module (not from named packages)
|
||||
sep := ""
|
||||
for _, m := range matches {
|
||||
for _, path := range m.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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -61,28 +61,36 @@ func TestConvertLegacyConfig(t *testing.T) {
|
|||
vers string
|
||||
gomod string
|
||||
}{
|
||||
{
|
||||
// Gopkg.lock parsing.
|
||||
"github.com/golang/dep", "v0.4.0",
|
||||
`module github.com/golang/dep
|
||||
/*
|
||||
Different versions of git seem to find or not find
|
||||
github.com/Masterminds/semver's a93e51b5a57e,
|
||||
which is an unmerged pull request.
|
||||
We'd rather not provide access to unmerged pull requests,
|
||||
so the line is removed from the golden file here,
|
||||
but some git commands still find it somehow.
|
||||
|
||||
require (
|
||||
github.com/Masterminds/semver v0.0.0-20170726230514-a93e51b5a57e
|
||||
github.com/Masterminds/vcs v1.11.1
|
||||
github.com/armon/go-radix v0.0.0-20160115234725-4239b77079c7
|
||||
github.com/boltdb/bolt v1.3.1
|
||||
github.com/go-yaml/yaml v0.0.0-20170407172122-cd8b52f8269e
|
||||
github.com/golang/protobuf v0.0.0-20170901042739-5afd06f9d81a
|
||||
github.com/jmank88/nuts v0.3.0
|
||||
github.com/nightlyone/lockfile v0.0.0-20170707060451-e83dc5e7bba0
|
||||
github.com/pelletier/go-toml v0.0.0-20171218135716-b8b5e7696574
|
||||
github.com/pkg/errors v0.8.0
|
||||
github.com/sdboyer/constext v0.0.0-20170321163424-836a14457353
|
||||
golang.org/x/net v0.0.0-20170828231752-66aacef3dd8a
|
||||
golang.org/x/sync v0.0.0-20170517211232-f52d1811a629
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea
|
||||
)`,
|
||||
},
|
||||
{
|
||||
// Gopkg.lock parsing.
|
||||
"github.com/golang/dep", "v0.4.0",
|
||||
`module github.com/golang/dep
|
||||
|
||||
require (
|
||||
github.com/Masterminds/vcs v1.11.1
|
||||
github.com/armon/go-radix v0.0.0-20160115234725-4239b77079c7
|
||||
github.com/boltdb/bolt v1.3.1
|
||||
github.com/go-yaml/yaml v0.0.0-20170407172122-cd8b52f8269e
|
||||
github.com/golang/protobuf v0.0.0-20170901042739-5afd06f9d81a
|
||||
github.com/jmank88/nuts v0.3.0
|
||||
github.com/nightlyone/lockfile v0.0.0-20170707060451-e83dc5e7bba0
|
||||
github.com/pelletier/go-toml v0.0.0-20171218135716-b8b5e7696574
|
||||
github.com/pkg/errors v0.8.0
|
||||
github.com/sdboyer/constext v0.0.0-20170321163424-836a14457353
|
||||
golang.org/x/net v0.0.0-20170828231752-66aacef3dd8a
|
||||
golang.org/x/sync v0.0.0-20170517211232-f52d1811a629
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea
|
||||
)`,
|
||||
},
|
||||
*/
|
||||
|
||||
// TODO: https://github.com/docker/distribution uses vendor.conf
|
||||
|
||||
|
|
|
@ -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,40 @@ 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
|
||||
}
|
||||
|
||||
// GoModSum returns the go.sum entry for the module version's go.mod file.
|
||||
// (That is, it returns the entry listed in go.sum as "path version/go.mod".)
|
||||
func GoModSum(path, version string) (string, error) {
|
||||
if !semver.IsValid(version) {
|
||||
return "", fmt.Errorf("invalid version %q", version)
|
||||
}
|
||||
data, err := GoMod(path, version)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
sum, err := goModSum(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
var errNotCached = fmt.Errorf("not in cache")
|
||||
|
||||
// readDiskStat reads a cached stat result from disk,
|
||||
|
@ -274,6 +325,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
|
||||
}
|
||||
|
||||
|
|
|
@ -347,27 +347,19 @@ 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
|
||||
}
|
||||
}
|
||||
|
@ -375,6 +367,21 @@ func (r *gitRepo) stat(rev string) (*RevInfo, error) {
|
|||
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) {
|
||||
|
|
Двоичный файл не отображается.
|
@ -22,6 +22,17 @@ import (
|
|||
"cmd/go/internal/str"
|
||||
)
|
||||
|
||||
// A VCSError indicates an error using a version control system.
|
||||
// The implication of a VCSError is that we know definitively where
|
||||
// to get the code, but we can't access it due to the error.
|
||||
// The caller should report this error instead of continuing to probe
|
||||
// other possible module paths.
|
||||
type VCSError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *VCSError) Error() string { return e.Err.Error() }
|
||||
|
||||
func NewRepo(vcs, remote string) (Repo, error) {
|
||||
type key struct {
|
||||
vcs string
|
||||
|
@ -33,6 +44,9 @@ func NewRepo(vcs, remote string) (Repo, error) {
|
|||
}
|
||||
c := vcsRepoCache.Do(key{vcs, remote}, func() interface{} {
|
||||
repo, err := newVCSRepo(vcs, remote)
|
||||
if err != nil {
|
||||
err = &VCSError{err}
|
||||
}
|
||||
return cached{repo, err}
|
||||
}).(cached)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -228,10 +228,9 @@ var codeRepoTests = []struct {
|
|||
path: "swtch.com/testmod",
|
||||
rev: "v1.0.0",
|
||||
version: "v1.0.0",
|
||||
name: "v1.0.0",
|
||||
short: "v1.0.0",
|
||||
time: time.Date(1972, 7, 18, 12, 34, 56, 0, time.UTC),
|
||||
gomod: "module \"swtch.com/testmod\"\n",
|
||||
// NO name or short - we intentionally ignore those in the proxy protocol
|
||||
time: time.Date(1972, 7, 18, 12, 34, 56, 0, time.UTC),
|
||||
gomod: "module \"swtch.com/testmod\"\n",
|
||||
},
|
||||
{
|
||||
// redirect to googlesource
|
||||
|
|
|
@ -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 {
|
||||
|
@ -226,12 +253,17 @@ func checkSum(mod module.Version) {
|
|||
checkOneSum(mod, h)
|
||||
}
|
||||
|
||||
// goModSum returns the checksum for the go.mod contents.
|
||||
func goModSum(data []byte) (string, error) {
|
||||
return dirhash.Hash1([]string{"go.mod"}, func(string) (io.ReadCloser, error) {
|
||||
return ioutil.NopCloser(bytes.NewReader(data)), nil
|
||||
})
|
||||
}
|
||||
|
||||
// checkGoMod checks the given module's go.mod checksum;
|
||||
// data is the go.mod content.
|
||||
func checkGoMod(path, version string, data []byte) {
|
||||
h, err := dirhash.Hash1([]string{"go.mod"}, func(string) (io.ReadCloser, error) {
|
||||
return ioutil.NopCloser(bytes.NewReader(data)), nil
|
||||
})
|
||||
h, err := goModSum(data)
|
||||
if err != nil {
|
||||
base.Fatalf("go: verifying %s %s go.mod: %v", path, version, err)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
@ -213,7 +216,11 @@ func lookup(path string) (r Repo, err error) {
|
|||
return lookupProxy(path)
|
||||
}
|
||||
|
||||
rr, err := get.RepoRootForImportPath(path, get.PreferMod, web.Secure)
|
||||
security := web.Secure
|
||||
if get.Insecure {
|
||||
security = web.Insecure
|
||||
}
|
||||
rr, err := get.RepoRootForImportPath(path, get.PreferMod, security)
|
||||
if err != nil {
|
||||
// We don't know where to find code for a module with this path.
|
||||
return nil, err
|
||||
|
@ -234,6 +241,9 @@ func lookup(path string) (r Repo, err error) {
|
|||
func lookupCodeRepo(rr *get.RepoRoot) (codehost.Repo, error) {
|
||||
code, err := codehost.NewRepo(rr.VCS, rr.Repo)
|
||||
if err != nil {
|
||||
if _, ok := err.(*codehost.VCSError); ok {
|
||||
return nil, err
|
||||
}
|
||||
return nil, fmt.Errorf("lookup %s: %v", rr.Root, err)
|
||||
}
|
||||
return code, nil
|
||||
|
@ -251,7 +261,11 @@ func ImportRepoRev(path, rev string) (Repo, *RevInfo, error) {
|
|||
// Note: Because we are converting a code reference from a legacy
|
||||
// version control system, we ignore meta tags about modules
|
||||
// and use only direct source control entries (get.IgnoreMod).
|
||||
rr, err := get.RepoRootForImportPath(path, get.IgnoreMod, web.Secure)
|
||||
security := web.Secure
|
||||
if get.Insecure {
|
||||
security = web.Insecure
|
||||
}
|
||||
rr, err := get.RepoRootForImportPath(path, get.IgnoreMod, security)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
|
@ -250,7 +250,7 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f
|
|||
arrow = 1
|
||||
}
|
||||
if len(args) < arrow+2 || len(args) > arrow+3 || args[arrow] != "=>" {
|
||||
fmt.Fprintf(errs, "%s:%d: usage: %s module/path [v1.2.3] => other/module v1.4\n\t or %s module/path [v1.2.3] => ../local/directory", f.Syntax.Name, line.Start.Line, verb, verb)
|
||||
fmt.Fprintf(errs, "%s:%d: usage: %s module/path [v1.2.3] => other/module v1.4\n\t or %s module/path [v1.2.3] => ../local/directory\n", f.Syntax.Name, line.Start.Line, verb, verb)
|
||||
return
|
||||
}
|
||||
s, err := parseString(&args[0])
|
||||
|
@ -287,11 +287,11 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f
|
|||
nv := ""
|
||||
if len(args) == arrow+2 {
|
||||
if !IsDirectoryPath(ns) {
|
||||
fmt.Fprintf(errs, "%s:%d: replacement module without version must be directory path (rooted or starting with ./ or ../)", f.Syntax.Name, line.Start.Line)
|
||||
fmt.Fprintf(errs, "%s:%d: replacement module without version must be directory path (rooted or starting with ./ or ../)\n", f.Syntax.Name, line.Start.Line)
|
||||
return
|
||||
}
|
||||
if filepath.Separator == '/' && strings.Contains(ns, `\`) {
|
||||
fmt.Fprintf(errs, "%s:%d: replacement directory appears to be Windows path (on a non-windows system)", f.Syntax.Name, line.Start.Line)
|
||||
fmt.Fprintf(errs, "%s:%d: replacement directory appears to be Windows path (on a non-windows system)\n", f.Syntax.Name, line.Start.Line)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -303,7 +303,7 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f
|
|||
return
|
||||
}
|
||||
if IsDirectoryPath(ns) {
|
||||
fmt.Fprintf(errs, "%s:%d: replacement module directory path %q cannot have version", f.Syntax.Name, line.Start.Line, ns)
|
||||
fmt.Fprintf(errs, "%s:%d: replacement module directory path %q cannot have version\n", f.Syntax.Name, line.Start.Line, ns)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ func runGet(cmd *base.Command, args []string) {
|
|||
// and a list of install targets (for the "go install" at the end).
|
||||
var tasks []*task
|
||||
var install []string
|
||||
for _, arg := range search.CleanImportPaths(args) {
|
||||
for _, arg := range search.CleanPatterns(args) {
|
||||
// Argument is module query path@vers, or else path with implicit @latest.
|
||||
path := arg
|
||||
vers := ""
|
||||
|
@ -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,18 +515,34 @@ 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)
|
||||
pkgs := load.PackagesAndErrors(install)
|
||||
var todo []*load.Package
|
||||
for _, p := range pkgs {
|
||||
// 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
|
||||
}
|
||||
}
|
||||
todo = append(todo, p)
|
||||
}
|
||||
|
||||
// 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.)
|
||||
if len(pkgs) > 0 && !*getD {
|
||||
work.InstallPackages(pkgs)
|
||||
if len(todo) > 0 && !*getD {
|
||||
work.InstallPackages(install, todo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -534,13 +552,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 +563,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
|
||||
|
|
|
@ -25,15 +25,21 @@ var (
|
|||
)
|
||||
|
||||
func isStandardImportPath(path string) bool {
|
||||
return findStandardImportPath(path) != ""
|
||||
}
|
||||
|
||||
func findStandardImportPath(path string) string {
|
||||
if search.IsStandardImportPath(path) {
|
||||
if _, err := os.Stat(filepath.Join(cfg.GOROOT, "src", path)); err == nil {
|
||||
return true
|
||||
dir := filepath.Join(cfg.GOROOT, "src", path)
|
||||
if _, err := os.Stat(dir); err == nil {
|
||||
return dir
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(cfg.GOROOT, "src/vendor", path)); err == nil {
|
||||
return true
|
||||
dir = filepath.Join(cfg.GOROOT, "src/vendor", path)
|
||||
if _, err := os.Stat(dir); err == nil {
|
||||
return dir
|
||||
}
|
||||
}
|
||||
return false
|
||||
return ""
|
||||
}
|
||||
|
||||
func PackageModuleInfo(pkgpath string) *modinfo.ModulePublic {
|
||||
|
@ -144,23 +150,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
|
||||
|
|
|
@ -6,8 +6,7 @@ package modload
|
|||
|
||||
import "cmd/go/internal/base"
|
||||
|
||||
// TODO(rsc): The links out to research.swtch.com here should all be
|
||||
// replaced eventually with links to proper documentation.
|
||||
// TODO(rsc): The "module code layout" section needs to be written.
|
||||
|
||||
var HelpModules = &base.Command{
|
||||
UsageLine: "modules",
|
||||
|
@ -81,7 +80,7 @@ depends on specific versions of golang.org/x/text and gopkg.in/yaml.v2:
|
|||
The go.mod file can also specify replacements and excluded versions
|
||||
that only apply when building the module directly; they are ignored
|
||||
when the module is incorporated into a larger build.
|
||||
For more about the go.mod file, see https://research.swtch.com/vgo-module.
|
||||
For more about the go.mod file, see 'go help go.mod'.
|
||||
|
||||
To start a new module, simply create a go.mod file in the root of the
|
||||
module's directory tree, containing only a module statement.
|
||||
|
@ -336,8 +335,6 @@ For now, see https://research.swtch.com/vgo-module for information
|
|||
about how source code in version control systems is mapped to
|
||||
module file trees.
|
||||
|
||||
TODO: Add documentation to go command.
|
||||
|
||||
Module downloading and verification
|
||||
|
||||
The go command maintains, in the main module's root directory alongside
|
||||
|
@ -381,3 +378,85 @@ top-level vendor directory is used; vendor directories in other locations
|
|||
are still ignored.
|
||||
`,
|
||||
}
|
||||
|
||||
var HelpGoMod = &base.Command{
|
||||
UsageLine: "go.mod",
|
||||
Short: "the go.mod file",
|
||||
Long: `
|
||||
A module version is defined by a tree of source files, with a go.mod
|
||||
file in its root. When the go command is run, it looks in the current
|
||||
directory and then successive parent directories to find the go.mod
|
||||
marking the root of the main (current) module.
|
||||
|
||||
The go.mod file itself is line-oriented, with // comments but
|
||||
no /* */ comments. Each line holds a single directive, made up of a
|
||||
verb followed by arguments. For example:
|
||||
|
||||
module my/thing
|
||||
require other/thing v1.0.2
|
||||
require new/thing v2.3.4
|
||||
exclude old/thing v1.2.3
|
||||
replace bad/thing v1.4.5 => good/thing v1.4.5
|
||||
|
||||
The verbs are module, to define the module path; require, to require
|
||||
a particular module at a given version or later; exclude, to exclude
|
||||
a particular module version from use; and replace, to replace a module
|
||||
version with a different module version. Exclude and replace apply only
|
||||
in the main module's go.mod and are ignored in dependencies.
|
||||
See https://research.swtch.com/vgo-mvs for details.
|
||||
|
||||
The leading verb can be factored out of adjacent lines to create a block,
|
||||
like in Go imports:
|
||||
|
||||
require (
|
||||
new/thing v2.3.4
|
||||
old/thing v1.2.3
|
||||
)
|
||||
|
||||
The go.mod file is designed both to be edited directly and to be
|
||||
easily updated by tools. The 'go mod edit' command can be used to
|
||||
parse and edit the go.mod file from programs and tools.
|
||||
See 'go help mod edit'.
|
||||
|
||||
The go command automatically updates go.mod each time it uses the
|
||||
module graph, to make sure go.mod always accurately reflects reality
|
||||
and is properly formatted. For example, consider this go.mod file:
|
||||
|
||||
module M
|
||||
|
||||
require (
|
||||
A v1
|
||||
B v1.0.0
|
||||
C v1.0.0
|
||||
D v1.2.3
|
||||
E dev
|
||||
)
|
||||
|
||||
exclude D v1.2.3
|
||||
|
||||
The update rewrites non-canonical version identifiers to semver form,
|
||||
so A's v1 becomes v1.0.0 and E's dev becomes the pseudo-version for the
|
||||
latest commit on the dev branch, perhaps v0.0.0-20180523231146-b3f5c0f6e5f1.
|
||||
|
||||
The update modifies requirements to respect exclusions, so the
|
||||
requirement on the excluded D v1.2.3 is updated to use the next
|
||||
available version of D, perhaps D v1.2.4 or D v1.3.0.
|
||||
|
||||
The update removes redundant or misleading requirements.
|
||||
For example, if A v1.0.0 itself requires B v1.2.0 and C v1.0.0,
|
||||
then go.mod's requirement of B v1.0.0 is misleading (superseded by
|
||||
A's need for v1.2.0), and its requirement of C v1.0.0 is redundant
|
||||
(implied by A's need for the same version), so both will be removed.
|
||||
If module M contains packages that directly import packages from B or
|
||||
C, then the requirements will be kept but updated to the actual
|
||||
versions being used.
|
||||
|
||||
Finally, the update reformats the go.mod in a canonical formatting, so
|
||||
that future mechanical changes will result in minimal diffs.
|
||||
|
||||
Because the module graph defines the meaning of import statements, any
|
||||
commands that load packages also use and therefore update go.mod,
|
||||
including go build, go get, go install, go list, go test, go mod graph,
|
||||
go mod tidy, and go mod why.
|
||||
`,
|
||||
}
|
||||
|
|
|
@ -10,11 +10,11 @@ import (
|
|||
"fmt"
|
||||
"go/build"
|
||||
"os"
|
||||
pathpkg "path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"cmd/go/internal/cfg"
|
||||
"cmd/go/internal/modfetch/codehost"
|
||||
"cmd/go/internal/module"
|
||||
"cmd/go/internal/par"
|
||||
"cmd/go/internal/search"
|
||||
|
@ -42,7 +42,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 +124,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 +132,14 @@ 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 {
|
||||
if _, ok := err.(*codehost.VCSError); ok {
|
||||
return module.Version{}, "", err
|
||||
}
|
||||
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,
|
||||
|
@ -228,7 +181,7 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile
|
|||
// So we only check local module trees
|
||||
// (the main module, and any directory trees pointed at by replace directives).
|
||||
if isLocal {
|
||||
for d := dir; d != mdir && len(d) > len(mdir); d = filepath.Dir(d) {
|
||||
for d := dir; d != mdir && len(d) > len(mdir); {
|
||||
haveGoMod := haveGoModCache.Do(d, func() interface{} {
|
||||
_, err := os.Stat(filepath.Join(d, "go.mod"))
|
||||
return err == nil
|
||||
|
@ -237,6 +190,13 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile
|
|||
if haveGoMod {
|
||||
return "", false
|
||||
}
|
||||
parent := filepath.Dir(d)
|
||||
if parent == d {
|
||||
// Break the loop, as otherwise we'd loop
|
||||
// forever if d=="." and mdir=="".
|
||||
break
|
||||
}
|
||||
d = parent
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ var importTests = []struct {
|
|||
},
|
||||
{
|
||||
path: "golang.org/x/net",
|
||||
err: "missing module for import: golang.org/x/net@.* provides golang.org/x/net",
|
||||
err: "cannot find module providing package golang.org/x/net",
|
||||
},
|
||||
{
|
||||
path: "golang.org/x/text",
|
||||
|
|
|
@ -150,8 +150,20 @@ func Init() {
|
|||
ModRoot = cwd
|
||||
} else {
|
||||
ModRoot, _ = FindModuleRoot(cwd, "", MustUseModules)
|
||||
if ModRoot == "" && !MustUseModules {
|
||||
return
|
||||
if !MustUseModules {
|
||||
if ModRoot == "" {
|
||||
return
|
||||
}
|
||||
if search.InDir(ModRoot, os.TempDir()) == "." {
|
||||
// If you create /tmp/go.mod for experimenting,
|
||||
// then any tests that create work directories under /tmp
|
||||
// will find it and get modules when they're not expecting them.
|
||||
// It's a bit of a peculiar thing to disallow but quite mysterious
|
||||
// when it happens. See golang.org/issue/26708.
|
||||
ModRoot = ""
|
||||
fmt.Fprintf(os.Stderr, "go: warning: ignoring go.mod in system temp root %v\n", os.TempDir())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,6 +175,7 @@ func Init() {
|
|||
load.ModPackageBuildInfo = PackageBuildInfo
|
||||
load.ModInfoProg = ModInfoProg
|
||||
load.ModImportFromFiles = ImportFromFiles
|
||||
load.ModDirImportPath = DirImportPath
|
||||
|
||||
search.SetModRoot(ModRoot)
|
||||
}
|
||||
|
@ -521,7 +534,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
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
"cmd/go/internal/par"
|
||||
"cmd/go/internal/search"
|
||||
"cmd/go/internal/semver"
|
||||
"cmd/go/internal/str"
|
||||
)
|
||||
|
||||
// buildList is the list of modules to use for building packages.
|
||||
|
@ -50,24 +51,46 @@ var loaded *loader
|
|||
|
||||
// ImportPaths returns the set of packages matching the args (patterns),
|
||||
// adding modules to the build list as needed to satisfy new imports.
|
||||
func ImportPaths(args []string) []string {
|
||||
func ImportPaths(patterns []string) []*search.Match {
|
||||
InitMod()
|
||||
|
||||
cleaned := search.CleanImportPaths(args)
|
||||
var matches []*search.Match
|
||||
for _, pattern := range search.CleanPatterns(patterns) {
|
||||
m := &search.Match{
|
||||
Pattern: pattern,
|
||||
Literal: !strings.Contains(pattern, "...") && !search.IsMetaPackage(pattern),
|
||||
}
|
||||
if m.Literal {
|
||||
m.Pkgs = []string{pattern}
|
||||
}
|
||||
matches = append(matches, m)
|
||||
}
|
||||
|
||||
fsDirs := make([][]string, len(matches))
|
||||
loaded = newLoader()
|
||||
var paths []string
|
||||
loaded.load(func() []string {
|
||||
var roots []string
|
||||
paths = nil
|
||||
for _, pkg := range cleaned {
|
||||
updateMatches := func(iterating bool) {
|
||||
for i, m := range matches {
|
||||
switch {
|
||||
case build.IsLocalImport(pkg) || filepath.IsAbs(pkg):
|
||||
list := []string{pkg}
|
||||
if strings.Contains(pkg, "...") {
|
||||
// TODO: Where is the go.mod cutoff?
|
||||
list = warnPattern(pkg, search.AllPackagesInFS(pkg))
|
||||
case build.IsLocalImport(m.Pattern) || filepath.IsAbs(m.Pattern):
|
||||
// Evaluate list of file system directories on first iteration.
|
||||
if fsDirs[i] == nil {
|
||||
var dirs []string
|
||||
if m.Literal {
|
||||
dirs = []string{m.Pattern}
|
||||
} else {
|
||||
dirs = search.MatchPackagesInFS(m.Pattern).Pkgs
|
||||
}
|
||||
fsDirs[i] = dirs
|
||||
}
|
||||
for _, pkg := range list {
|
||||
|
||||
// Make a copy of the directory list and translate to import paths.
|
||||
// Note that whether a directory corresponds to an import path
|
||||
// changes as the build list is updated, and a directory can change
|
||||
// from not being in the build list to being in it and back as
|
||||
// the exact version of a particular module increases during
|
||||
// the loader iterations.
|
||||
m.Pkgs = str.StringList(fsDirs[i])
|
||||
for i, pkg := range m.Pkgs {
|
||||
dir := pkg
|
||||
if !filepath.IsAbs(dir) {
|
||||
dir = filepath.Join(cwd, pkg)
|
||||
|
@ -93,40 +116,67 @@ func ImportPaths(args []string) []string {
|
|||
} else if path := pathInModuleCache(dir); path != "" {
|
||||
pkg = path
|
||||
} else {
|
||||
base.Errorf("go: directory %s outside available modules", base.ShortPath(dir))
|
||||
continue
|
||||
pkg = ""
|
||||
if !iterating {
|
||||
base.Errorf("go: directory %s outside available modules", base.ShortPath(dir))
|
||||
}
|
||||
}
|
||||
info, err := os.Stat(dir)
|
||||
if err != nil || !info.IsDir() {
|
||||
// If the directory does not exist,
|
||||
// don't turn it into an import path
|
||||
// that will trigger a lookup.
|
||||
pkg = ""
|
||||
if !iterating {
|
||||
if err != nil {
|
||||
base.Errorf("go: no such directory %v", m.Pattern)
|
||||
} else {
|
||||
base.Errorf("go: %s is not a directory", m.Pattern)
|
||||
}
|
||||
}
|
||||
}
|
||||
m.Pkgs[i] = pkg
|
||||
}
|
||||
|
||||
case strings.Contains(m.Pattern, "..."):
|
||||
m.Pkgs = matchPackages(m.Pattern, loaded.tags, true, buildList)
|
||||
|
||||
case m.Pattern == "all":
|
||||
loaded.testAll = true
|
||||
if iterating {
|
||||
// Enumerate the packages in the main module.
|
||||
// We'll load the dependencies as we find them.
|
||||
m.Pkgs = matchPackages("...", loaded.tags, false, []module.Version{Target})
|
||||
} else {
|
||||
// Starting with the packages in the main module,
|
||||
// enumerate the full list of "all".
|
||||
m.Pkgs = loaded.computePatternAll(m.Pkgs)
|
||||
}
|
||||
|
||||
case search.IsMetaPackage(m.Pattern): // std, cmd
|
||||
if len(m.Pkgs) == 0 {
|
||||
m.Pkgs = search.MatchPackages(m.Pattern).Pkgs
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loaded.load(func() []string {
|
||||
var roots []string
|
||||
updateMatches(true)
|
||||
for _, m := range matches {
|
||||
for _, pkg := range m.Pkgs {
|
||||
if pkg != "" {
|
||||
roots = append(roots, pkg)
|
||||
paths = append(paths, pkg)
|
||||
}
|
||||
|
||||
case pkg == "all":
|
||||
if loaded.testRoots {
|
||||
loaded.testAll = true
|
||||
}
|
||||
// TODO: Don't print warnings multiple times.
|
||||
roots = append(roots, warnPattern("all", matchPackages("...", loaded.tags, []module.Version{Target}))...)
|
||||
paths = append(paths, "all") // will expand after load completes
|
||||
|
||||
case search.IsMetaPackage(pkg): // std, cmd
|
||||
list := search.AllPackages(pkg)
|
||||
roots = append(roots, list...)
|
||||
paths = append(paths, list...)
|
||||
|
||||
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))
|
||||
roots = append(roots, list...)
|
||||
paths = append(paths, list...)
|
||||
|
||||
default:
|
||||
roots = append(roots, pkg)
|
||||
paths = append(paths, pkg)
|
||||
}
|
||||
}
|
||||
return roots
|
||||
})
|
||||
|
||||
// One last pass to finalize wildcards.
|
||||
updateMatches(false)
|
||||
|
||||
// A given module path may be used as itself or as a replacement for another
|
||||
// module, but not both at the same time. Otherwise, the aliasing behavior is
|
||||
// too subtle (see https://golang.org/issue/26607), and we don't want to
|
||||
|
@ -140,34 +190,14 @@ 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()
|
||||
|
||||
WriteGoMod()
|
||||
|
||||
// Process paths to produce final paths list.
|
||||
// Remove duplicates and expand "all".
|
||||
have := make(map[string]bool)
|
||||
var final []string
|
||||
for _, path := range paths {
|
||||
if have[path] {
|
||||
continue
|
||||
}
|
||||
have[path] = true
|
||||
if path == "all" {
|
||||
for _, pkg := range loaded.pkgs {
|
||||
if !have[pkg.path] {
|
||||
have[pkg.path] = true
|
||||
final = append(final, pkg.path)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
final = append(final, path)
|
||||
}
|
||||
return final
|
||||
search.WarnUnmatched(matches)
|
||||
return matches
|
||||
}
|
||||
|
||||
// pathInModuleCache returns the import path of the directory dir,
|
||||
|
@ -218,6 +248,28 @@ func ImportFromFiles(gofiles []string) {
|
|||
WriteGoMod()
|
||||
}
|
||||
|
||||
// DirImportPath returns the effective import path for dir,
|
||||
// provided it is within the main module, or else returns ".".
|
||||
func DirImportPath(dir string) string {
|
||||
if !filepath.IsAbs(dir) {
|
||||
dir = filepath.Join(cwd, dir)
|
||||
} else {
|
||||
dir = filepath.Clean(dir)
|
||||
}
|
||||
|
||||
if dir == ModRoot {
|
||||
return Target.Path
|
||||
}
|
||||
if strings.HasPrefix(dir, ModRoot+string(filepath.Separator)) {
|
||||
suffix := filepath.ToSlash(dir[len(ModRoot):])
|
||||
if strings.HasPrefix(suffix, "/vendor/") {
|
||||
return strings.TrimPrefix(suffix, "/vendor/")
|
||||
}
|
||||
return Target.Path + suffix
|
||||
}
|
||||
return "."
|
||||
}
|
||||
|
||||
// LoadBuildList loads and returns the build list from go.mod.
|
||||
// The loading of the build list happens automatically in ImportPaths:
|
||||
// LoadBuildList need only be called if ImportPaths is not
|
||||
|
@ -270,6 +322,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 +337,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 +392,28 @@ 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 == "" {
|
||||
if isStandardImportPath(path) {
|
||||
dir := filepath.Join(cfg.GOROOT, "src", path)
|
||||
if _, err := os.Stat(dir); err == nil {
|
||||
return dir, path, nil
|
||||
}
|
||||
// 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 {
|
||||
// The loader should have found all the relevant paths.
|
||||
// There are a few exceptions, though:
|
||||
// - during go list without -test, the p.Resolve calls to process p.TestImports and p.XTestImports
|
||||
// end up here to canonicalize the import paths.
|
||||
// - during any load, non-loaded packages like "unsafe" end up here.
|
||||
// - during any load, build-injected dependencies like "runtime/cgo" end up here.
|
||||
// - because we ignore appengine/* in the module loader,
|
||||
// the dependencies of any actual appengine/* library end up here.
|
||||
dir := findStandardImportPath(path)
|
||||
if dir != "" {
|
||||
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 +446,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 +520,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 +565,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 +619,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
|
||||
}
|
||||
|
@ -585,6 +638,35 @@ func (ld *loader) doPkg(item interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
// computePatternAll returns the list of packages matching pattern "all",
|
||||
// starting with a list of the import paths for the packages in the main module.
|
||||
func (ld *loader) computePatternAll(paths []string) []string {
|
||||
seen := make(map[*loadPkg]bool)
|
||||
var all []string
|
||||
var walk func(*loadPkg)
|
||||
walk = func(pkg *loadPkg) {
|
||||
if seen[pkg] {
|
||||
return
|
||||
}
|
||||
seen[pkg] = true
|
||||
if pkg.testOf == nil {
|
||||
all = append(all, pkg.path)
|
||||
}
|
||||
for _, p := range pkg.imports {
|
||||
walk(p)
|
||||
}
|
||||
if p := pkg.test; p != nil {
|
||||
walk(p)
|
||||
}
|
||||
}
|
||||
for _, path := range paths {
|
||||
walk(ld.pkg(path, false))
|
||||
}
|
||||
sort.Strings(all)
|
||||
|
||||
return all
|
||||
}
|
||||
|
||||
// scanDir is like imports.ScanDir but elides known magic imports from the list,
|
||||
// so that we do not go looking for packages that don't really exist.
|
||||
//
|
||||
|
@ -675,6 +757,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 == "".
|
||||
|
|
|
@ -6,9 +6,11 @@ package modload
|
|||
|
||||
import (
|
||||
"cmd/go/internal/modfetch"
|
||||
"cmd/go/internal/modfetch/codehost"
|
||||
"cmd/go/internal/module"
|
||||
"cmd/go/internal/semver"
|
||||
"fmt"
|
||||
pathpkg "path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -29,6 +31,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 +121,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 +201,49 @@ 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 _, ok := err.(*codehost.VCSError); ok {
|
||||
// A VCSError means we know where to find the code,
|
||||
// we just can't. Abort search.
|
||||
return module.Version{}, nil, err
|
||||
}
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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,28 +35,30 @@ func matchPackages(pattern string, tags map[string]bool, modules []module.Versio
|
|||
}
|
||||
var pkgs []string
|
||||
|
||||
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 := func(root, importPathRoot string) {
|
||||
root = filepath.Clean(root)
|
||||
|
||||
var cmd string
|
||||
if root == cfg.GOROOTsrc {
|
||||
cmd = filepath.Join(root, "cmd")
|
||||
}
|
||||
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return 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)
|
||||
|
@ -64,7 +66,10 @@ func matchPackages(pattern string, tags map[string]bool, modules []module.Versio
|
|||
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
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -17,32 +17,22 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// AllPackages returns all the packages that can be found
|
||||
// A Match represents the result of matching a single package pattern.
|
||||
type Match struct {
|
||||
Pattern string // the pattern itself
|
||||
Literal bool // whether it is a literal (no wildcards)
|
||||
Pkgs []string // matching packages (dirs or import paths)
|
||||
}
|
||||
|
||||
// MatchPackages returns all the packages that can be found
|
||||
// under the $GOPATH directories and $GOROOT matching pattern.
|
||||
// The pattern is either "all" (all packages), "std" (standard packages),
|
||||
// "cmd" (standard commands), or a path including "...".
|
||||
func AllPackages(pattern string) []string {
|
||||
pkgs := MatchPackages(pattern)
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
|
||||
func MatchPackages(pattern string) *Match {
|
||||
m := &Match{
|
||||
Pattern: pattern,
|
||||
Literal: false,
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// AllPackagesInFS is like allPackages but is passed a pattern
|
||||
// beginning ./ or ../, meaning it should scan the tree rooted
|
||||
// at the given directory. There are ... in the pattern too.
|
||||
func AllPackagesInFS(pattern string) []string {
|
||||
pkgs := MatchPackagesInFS(pattern)
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// MatchPackages returns a list of package paths matching pattern
|
||||
// (see go help packages for pattern syntax).
|
||||
func MatchPackages(pattern string) []string {
|
||||
match := func(string) bool { return true }
|
||||
treeCanMatch := func(string) bool { return true }
|
||||
if !IsMetaPackage(pattern) {
|
||||
|
@ -56,7 +46,6 @@ func MatchPackages(pattern string) []string {
|
|||
if !cfg.BuildContext.CgoEnabled {
|
||||
have["runtime/cgo"] = true // ignore during walk
|
||||
}
|
||||
var pkgs []string
|
||||
|
||||
for _, src := range cfg.BuildContext.SrcDirs() {
|
||||
if (pattern == "std" || pattern == "cmd") && src != cfg.GOROOTsrc {
|
||||
|
@ -123,11 +112,11 @@ func MatchPackages(pattern string) []string {
|
|||
return nil
|
||||
}
|
||||
|
||||
pkgs = append(pkgs, name)
|
||||
m.Pkgs = append(m.Pkgs, name)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return pkgs
|
||||
return m
|
||||
}
|
||||
|
||||
var modRoot string
|
||||
|
@ -136,10 +125,16 @@ func SetModRoot(dir string) {
|
|||
modRoot = dir
|
||||
}
|
||||
|
||||
// MatchPackagesInFS returns a list of package paths matching pattern,
|
||||
// which must begin with ./ or ../
|
||||
// (see go help packages for pattern syntax).
|
||||
func MatchPackagesInFS(pattern string) []string {
|
||||
// MatchPackagesInFS is like allPackages but is passed a pattern
|
||||
// beginning ./ or ../, meaning it should scan the tree rooted
|
||||
// at the given directory. There are ... in the pattern too.
|
||||
// (See go help packages for pattern syntax.)
|
||||
func MatchPackagesInFS(pattern string) *Match {
|
||||
m := &Match{
|
||||
Pattern: pattern,
|
||||
Literal: false,
|
||||
}
|
||||
|
||||
// Find directory to begin the scan.
|
||||
// Could be smarter but this one optimization
|
||||
// is enough for now, since ... is usually at the
|
||||
|
@ -168,7 +163,6 @@ func MatchPackagesInFS(pattern string) []string {
|
|||
}
|
||||
}
|
||||
|
||||
var pkgs []string
|
||||
filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || !fi.IsDir() {
|
||||
return nil
|
||||
|
@ -218,10 +212,10 @@ func MatchPackagesInFS(pattern string) []string {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
pkgs = append(pkgs, name)
|
||||
m.Pkgs = append(m.Pkgs, name)
|
||||
return nil
|
||||
})
|
||||
return pkgs
|
||||
return m
|
||||
}
|
||||
|
||||
// TreeCanMatchPattern(pattern)(name) reports whether
|
||||
|
@ -308,36 +302,53 @@ func replaceVendor(x, repl string) string {
|
|||
return strings.Join(elem, "/")
|
||||
}
|
||||
|
||||
// ImportPaths returns the import paths to use for the given command line.
|
||||
func ImportPaths(args []string) []string {
|
||||
args = CleanImportPaths(args)
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
// WarnUnmatched warns about patterns that didn't match any packages.
|
||||
func WarnUnmatched(matches []*Match) {
|
||||
for _, m := range matches {
|
||||
if len(m.Pkgs) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "go: warning: %q matched no packages\n", m.Pattern)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ImportPaths returns the matching paths to use for the given command line.
|
||||
// It calls ImportPathsQuiet and then WarnUnmatched.
|
||||
func ImportPaths(patterns []string) []*Match {
|
||||
matches := ImportPathsQuiet(patterns)
|
||||
WarnUnmatched(matches)
|
||||
return matches
|
||||
}
|
||||
|
||||
// ImportPathsQuiet is like ImportPaths but does not warn about patterns with no matches.
|
||||
func ImportPathsQuiet(patterns []string) []*Match {
|
||||
var out []*Match
|
||||
for _, a := range CleanPatterns(patterns) {
|
||||
if IsMetaPackage(a) {
|
||||
out = append(out, AllPackages(a)...)
|
||||
out = append(out, MatchPackages(a))
|
||||
continue
|
||||
}
|
||||
if strings.Contains(a, "...") {
|
||||
if build.IsLocalImport(a) {
|
||||
out = append(out, AllPackagesInFS(a)...)
|
||||
out = append(out, MatchPackagesInFS(a))
|
||||
} else {
|
||||
out = append(out, AllPackages(a)...)
|
||||
out = append(out, MatchPackages(a))
|
||||
}
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
out = append(out, &Match{Pattern: a, Literal: true, Pkgs: []string{a}})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// CleanImportPaths returns the import paths to use for the given
|
||||
// command line, but it does no wildcard expansion.
|
||||
func CleanImportPaths(args []string) []string {
|
||||
if len(args) == 0 {
|
||||
// CleanPatterns returns the patterns to use for the given
|
||||
// command line. It canonicalizes the patterns but does not
|
||||
// evaluate any matches.
|
||||
func CleanPatterns(patterns []string) []string {
|
||||
if len(patterns) == 0 {
|
||||
return []string{"."}
|
||||
}
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
for _, a := range patterns {
|
||||
// Arguments are supposed to be import paths, but
|
||||
// as a courtesy to Windows developers, rewrite \ to /
|
||||
// in command-line arguments. Handles .\... and so on.
|
||||
|
@ -359,22 +370,6 @@ func CleanImportPaths(args []string) []string {
|
|||
return out
|
||||
}
|
||||
|
||||
// ImportPathsNoDotExpansion returns the import paths to use for the given
|
||||
// command line, but it does no ... expansion.
|
||||
// TODO(rsc): Delete once old go get is gone.
|
||||
func ImportPathsNoDotExpansion(args []string) []string {
|
||||
args = CleanImportPaths(args)
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
if IsMetaPackage(a) {
|
||||
out = append(out, AllPackages(a)...)
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// IsMetaPackage checks if name is a reserved package name that expands to multiple packages.
|
||||
func IsMetaPackage(name string) bool {
|
||||
return name == "std" || name == "cmd" || name == "all"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
package version
|
||||
|
||||
const version = "devel +1b870077c8"
|
||||
const version = "devel +b0a1c5df98"
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -434,7 +434,7 @@ func libname(args []string, pkgs []*load.Package) (string, error) {
|
|||
|
||||
func runInstall(cmd *base.Command, args []string) {
|
||||
BuildInit()
|
||||
InstallPackages(args)
|
||||
InstallPackages(args, load.PackagesForBuild(args))
|
||||
}
|
||||
|
||||
// omitTestOnly returns pkgs with test-only packages removed.
|
||||
|
@ -454,12 +454,12 @@ func omitTestOnly(pkgs []*load.Package) []*load.Package {
|
|||
return list
|
||||
}
|
||||
|
||||
func InstallPackages(args []string) {
|
||||
func InstallPackages(patterns []string, pkgs []*load.Package) {
|
||||
if cfg.GOBIN != "" && !filepath.IsAbs(cfg.GOBIN) {
|
||||
base.Fatalf("cannot install, GOBIN must be an absolute path")
|
||||
}
|
||||
|
||||
pkgs := omitTestOnly(pkgsFilter(load.PackagesForBuild(args)))
|
||||
pkgs = omitTestOnly(pkgsFilter(pkgs))
|
||||
for _, p := range pkgs {
|
||||
if p.Target == "" {
|
||||
switch {
|
||||
|
@ -520,7 +520,7 @@ func InstallPackages(args []string) {
|
|||
// tools above did not apply, and a is just a simple Action
|
||||
// with a list of Deps, one per package named in pkgs,
|
||||
// the same as in runBuild.
|
||||
a = b.buildmodeShared(ModeInstall, ModeInstall, args, pkgs, a)
|
||||
a = b.buildmodeShared(ModeInstall, ModeInstall, patterns, pkgs, a)
|
||||
}
|
||||
|
||||
b.Do(a)
|
||||
|
@ -535,7 +535,7 @@ func InstallPackages(args []string) {
|
|||
// One way to view this behavior is that it is as if 'go install' first
|
||||
// runs 'go build' and the moves the generated file to the install dir.
|
||||
// See issue 9645.
|
||||
if len(args) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" {
|
||||
if len(patterns) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" {
|
||||
// Compute file 'go build' would have created.
|
||||
// If it exists and is an executable file, remove it.
|
||||
_, targ := filepath.Split(pkgs[0].ImportPath)
|
||||
|
|
|
@ -473,6 +473,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"
|
||||
|
@ -490,6 +498,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
|
||||
|
@ -530,15 +547,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
|
||||
|
@ -559,6 +568,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))
|
||||
|
@ -583,6 +609,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 {
|
||||
|
@ -650,7 +696,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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ func init() {
|
|||
help.HelpCache,
|
||||
help.HelpEnvironment,
|
||||
help.HelpFileType,
|
||||
modload.HelpGoMod,
|
||||
help.HelpGopath,
|
||||
get.HelpGopathGet,
|
||||
modfetch.HelpGoproxy,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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"}
|
|
@ -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"}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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"}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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())
|
||||
}
|
|
@ -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())
|
||||
}
|
|
@ -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())
|
||||
}
|
|
@ -36,6 +36,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
_ "rsc.io/testonly"
|
||||
)
|
||||
|
||||
var glassTests = []struct {
|
||||
|
|
|
@ -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
|
|
@ -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")}
|
||||
|
|
|
@ -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() }
|
|
@ -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() }
|
|
@ -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)
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
[!gc] skip 'using -gcflags and -ldflags'
|
||||
|
||||
# -gcflags=-e applies to named packages, not dependencies
|
||||
go build -n -v -gcflags=-e z1 z2
|
||||
stderr 'compile.* -e .*-p z1'
|
||||
stderr 'compile.* -e .*-p z2'
|
||||
stderr 'compile.* -p y'
|
||||
! stderr 'compile.* -e .*-p [^z]'
|
||||
|
||||
# -gcflags can specify package=flags, and can be repeated; last match wins
|
||||
go build -n -v -gcflags=-e -gcflags=z1=-N z1 z2
|
||||
stderr 'compile.* -N .*-p z1'
|
||||
! stderr 'compile.* -e .*-p z1'
|
||||
! stderr 'compile.* -N .*-p z2'
|
||||
stderr 'compile.* -e .*-p z2'
|
||||
stderr 'compile.* -p y'
|
||||
! stderr 'compile.* -e .*-p [^z]'
|
||||
! stderr 'compile.* -N .*-p [^z]'
|
||||
|
||||
# -gcflags can have arbitrary spaces around the flags
|
||||
go build -n -v -gcflags=' z1 = -e ' z1
|
||||
stderr 'compile.* -e .*-p z1'
|
||||
|
||||
# -ldflags for implicit test package applies to test binary
|
||||
go test -c -n -gcflags=-N -ldflags=-X=x.y=z z1
|
||||
stderr 'compile.* -N .*z_test.go'
|
||||
stderr 'link.* -X=x.y=z'
|
||||
|
||||
# -ldflags for explicit test package applies to test binary
|
||||
go test -c -n -gcflags=z1=-N -ldflags=z1=-X=x.y=z z1
|
||||
stderr 'compile.* -N .*z_test.go'
|
||||
stderr 'link.* -X=x.y=z'
|
||||
|
||||
# -ldflags applies to link of command
|
||||
go build -n -ldflags=-X=math.pi=3 my/cmd/prog
|
||||
stderr 'link.* -X=math.pi=3'
|
||||
|
||||
# -ldflags applies to link of command even with strange directory name
|
||||
go build -n -ldflags=-X=math.pi=3 my/cmd/prog/
|
||||
stderr 'link.* -X=math.pi=3'
|
||||
|
||||
# -ldflags applies to current directory
|
||||
cd my/cmd/prog
|
||||
go build -n -ldflags=-X=math.pi=3
|
||||
stderr 'link.* -X=math.pi=3'
|
||||
|
||||
# -ldflags applies to current directory even if GOPATH is funny
|
||||
[windows] cd $WORK/GoPath/src/my/cmd/prog
|
||||
[darwin] cd $WORK/GoPath/src/my/cmd/prog
|
||||
go build -n -ldflags=-X=math.pi=3
|
||||
stderr 'link.* -X=math.pi=3'
|
||||
|
||||
-- z1/z.go --
|
||||
package z1
|
||||
import _ "y"
|
||||
import _ "z2"
|
||||
|
||||
-- z1/z_test.go --
|
||||
package z1_test
|
||||
import "testing"
|
||||
func Test(t *testing.T) {}
|
||||
|
||||
-- z2/z.go --
|
||||
package z2
|
||||
|
||||
-- y/y.go --
|
||||
package y
|
||||
|
||||
-- my/cmd/prog/prog.go --
|
||||
package main
|
||||
func main() {}
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
|
@ -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]
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
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 '^\t"Sum": "h1:6fJa6E\+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE="' # hash of testdata/mod version, not real version!
|
||||
stdout '^\t"GoModSum": "h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe\+TKr0="'
|
||||
! stdout '"Error"'
|
||||
|
||||
# download queries above should not have added to go.mod.
|
||||
go list -m all
|
||||
! stdout rsc.io
|
||||
|
||||
# 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
|
|
@ -65,6 +65,15 @@ cd $GOPATH/foo/bar/baz
|
|||
go env GOMOD
|
||||
! stdout .+
|
||||
|
||||
# GO111MODULE=auto should ignore and warn about /tmp/go.mod
|
||||
env GO111MODULE=auto
|
||||
cp $GOPATH/src/x/y/z/go.mod $WORK/tmp/go.mod
|
||||
mkdir $WORK/tmp/mydir
|
||||
cd $WORK/tmp/mydir
|
||||
go env GOMOD
|
||||
! stdout .+
|
||||
stderr '^go: warning: ignoring go.mod in system temp root '
|
||||
|
||||
-- $GOPATH/src/x/y/z/go.mod --
|
||||
module x/y/z
|
||||
-- $GOPATH/src/x/y/z/w/w.txt --
|
||||
|
|
|
@ -28,6 +28,18 @@ stdout ^m/vendor$
|
|||
stdout ^m/y$
|
||||
! stdout ^m/y/z
|
||||
|
||||
# non-existent directory should not prompt lookups
|
||||
! go build -mod=readonly example.com/nonexist
|
||||
stderr 'import lookup disabled'
|
||||
|
||||
! go build -mod=readonly ./nonexist
|
||||
! stderr 'import lookup disabled'
|
||||
stderr '^go: no such directory ./nonexist'
|
||||
|
||||
! go build -mod=readonly ./go.mod
|
||||
! stderr 'import lookup disabled'
|
||||
stderr '^go: ./go.mod is not a directory'
|
||||
|
||||
-- x/go.mod --
|
||||
module m
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -36,8 +45,8 @@ grep 'rsc.io/quote v1.5.1' go.mod
|
|||
go mod edit -require rsc.io/quote@23179ee
|
||||
grep 'rsc.io/quote 23179ee' go.mod
|
||||
|
||||
# but go mod fix fixes them
|
||||
go mod fix
|
||||
# but other commands fix them
|
||||
go mod graph
|
||||
grep 'rsc.io/quote v1.5.1' go.mod
|
||||
|
||||
-- go.mod --
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
|
@ -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'
|
|
@ -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
|
|
@ -5,66 +5,74 @@ 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
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v0\.0\.0-\d{14}-52853eb7b552$'
|
||||
|
||||
# v1.0.0
|
||||
go get -m ...test@7fff7f3
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v1\.0\.0$'
|
||||
|
||||
# v1.0.1-0.pseudo
|
||||
go get -m ...test@fa4f5d6
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v1\.0\.1-0\.\d{14}-fa4f5d6a71c6$'
|
||||
|
||||
# v1.1.0-pre (no longer on master)
|
||||
go get -m ...test@731e3b1
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v1\.1\.0-pre$'
|
||||
|
||||
# v1.1.0-pre.0.pseudo
|
||||
go get -m ...test@fb3c628
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v1\.1\.0-pre\.0\.\d{14}-fb3c628075e3$'
|
||||
|
||||
# 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
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v1\.2\.1-0\.\d{14}-d2d4c3ea6623$'
|
||||
|
||||
# v2.0.0+incompatible by hash (back on master)
|
||||
go get -m ...test@d7ae1e4
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
|
||||
|
||||
# v2.0.0+incompatible by tag
|
||||
go get -m ...test@v2.0.0
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
|
||||
|
||||
# v2.0.0+incompatible by tag+incompatible
|
||||
go get -m ...test@v2.0.0+incompatible
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
|
||||
|
||||
# v2.0.1-0.pseudo+incompatible
|
||||
go get -m ...test@7303f77
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v2\.0\.1-0\.\d{14}-7303f7796364\+incompatible$'
|
||||
|
||||
# v2.0.0+incompatible by tag+incompatible
|
||||
go get -m ...test@v2.0.0+incompatible
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
|
||||
|
||||
# v2.0.0+incompatible by tag
|
||||
go get -m ...test@v2.0.0
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
|
||||
|
||||
# v2.0.0+incompatible by hash (back on master)
|
||||
go get -m ...test@d7ae1e4
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$'
|
||||
|
||||
# v1.2.1-0.pseudo
|
||||
go get -m ...test@d2d4c3e
|
||||
go list -m all
|
||||
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.1.0-pre.0.pseudo
|
||||
go get -m ...test@fb3c628
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v1\.1\.0-pre\.0\.\d{14}-fb3c628075e3$'
|
||||
|
||||
# v1.1.0-pre (no longer on master)
|
||||
go get -m ...test@731e3b1
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v1\.1\.0-pre$'
|
||||
|
||||
# v1.0.1-0.pseudo
|
||||
go get -m ...test@fa4f5d6
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v1\.0\.1-0\.\d{14}-fa4f5d6a71c6$'
|
||||
|
||||
# v1.0.0
|
||||
go get -m ...test@7fff7f3
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v1\.0\.0$'
|
||||
|
||||
# v0.0.0-pseudo
|
||||
go get -m ...test@52853eb
|
||||
go list -m all
|
||||
stdout '^github.com/rsc/legacytest v0\.0\.0-\d{14}-52853eb7b552$'
|
||||
|
||||
-- go.mod --
|
||||
module x
|
||||
-- x.go --
|
||||
|
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
|
@ -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"
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
# This test matches list_bad_import, but in module mode.
|
||||
# Please keep them in sync.
|
||||
|
||||
env GO111MODULE=on
|
||||
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 'cannot find module providing package 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}} {{.Error}}' all
|
||||
stdout example.com/direct
|
||||
stdout example.com/indirect
|
||||
# TODO: go list creates a dummy package with the import-not-found
|
||||
# but really the Error belongs on example.com/direct, and this package
|
||||
# should not be printed.
|
||||
# ! stdout example.com/notfound
|
||||
|
||||
|
||||
-- example.com/go.mod --
|
||||
module example.com
|
||||
|
||||
-- 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.
|
|
@ -9,11 +9,14 @@ go list -f '{{.ImportPath}}' $GOROOT/src/math
|
|||
stdout ^math$
|
||||
go list -f '{{.ImportPath}}' .
|
||||
stdout ^x$
|
||||
! go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
|
||||
stderr '^go: no such directory.*quote@v1.5.2'
|
||||
go mod download rsc.io/quote@v1.5.2
|
||||
go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
|
||||
stdout '^rsc.io/quote$'
|
||||
go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.0
|
||||
stdout '^rsc.io/sampler$'
|
||||
go get rsc.io/sampler@v1.3.1
|
||||
go get -d rsc.io/sampler@v1.3.1
|
||||
go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.1
|
||||
stdout '^rsc.io/sampler$'
|
||||
! go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.0
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
env GO111MODULE=on
|
||||
|
||||
# go list -compiled -test must handle test-only packages
|
||||
# golang.org/issue/27097.
|
||||
go list -compiled -test
|
||||
stdout '^m$'
|
||||
stdout '^m\.test$'
|
||||
stdout '^m \[m\.test\]$'
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
||||
-- x_test.go --
|
||||
package x
|
||||
import "testing"
|
||||
func Test(t *testing.T) {}
|
|
@ -0,0 +1,66 @@
|
|||
env GO111MODULE=on
|
||||
|
||||
cd m
|
||||
|
||||
# 'go list all' should list all of the packages used (directly or indirectly) by
|
||||
# the packages in the main module, but no other packages from the standard
|
||||
# library or active modules.
|
||||
#
|
||||
# 'go list ...' should list packages in all active modules and the standard library.
|
||||
# But not cmd/* - see golang.org/issue/26924.
|
||||
#
|
||||
# 'go list example.com/m/...' should list packages in all modules that begin with 'example.com/m/'.
|
||||
#
|
||||
# 'go list ./...' should list only packages in the current module, not other active modules.
|
||||
#
|
||||
# Warnings about unmatched patterns should only be printed once.
|
||||
#
|
||||
# And the go command should be able to keep track of all this!
|
||||
go list -f '{{.ImportPath}}: {{.Match}}' all ... example.com/m/... ./... ./xyz...
|
||||
stdout 'example.com/m/useunicode: \[all \.\.\. example.com/m/... ./...\]'
|
||||
stdout 'example.com/m/useunsafe: \[all \.\.\. example.com/m/... ./...\]'
|
||||
[cgo] stdout 'example.com/m/useC: \[all \.\.\. example.com/m/... ./...\]'
|
||||
[!cgo] ! stdout example.com/m/useC
|
||||
stdout 'example.com/unused/useerrors: \[\.\.\.\]' # but not "all"
|
||||
stdout 'example.com/m/nested/useencoding: \[\.\.\. example.com/m/...\]' # but NOT "all" or "./..."
|
||||
stdout '^unicode: \[all \.\.\.\]'
|
||||
stdout '^unsafe: \[all \.\.\.\]'
|
||||
stdout 'index/suffixarray: \[\.\.\.\]'
|
||||
! stdout cmd/pprof # golang.org/issue/26924
|
||||
|
||||
stderr -count=1 '^go: warning: "./xyz..." matched no packages$'
|
||||
|
||||
env CGO_ENABLED=0
|
||||
go list -f '{{.ImportPath}}: {{.Match}}' all ... example.com/m/... ./... ./xyz...
|
||||
! stdout example.com/m/useC
|
||||
|
||||
-- m/go.mod --
|
||||
module example.com/m
|
||||
|
||||
require example.com/unused v0.0.0 // indirect
|
||||
replace example.com/unused => ../unused
|
||||
|
||||
require example.com/m/nested v0.0.0 // indirect
|
||||
replace example.com/m/nested => ../nested
|
||||
|
||||
-- m/useC/useC.go --
|
||||
package useC
|
||||
import _ "C" // "C" is a pseudo-package, not an actual one
|
||||
-- m/useunicode/useunicode.go --
|
||||
package useunicode
|
||||
import _ "unicode"
|
||||
-- m/useunsafe/useunsafe.go --
|
||||
package useunsafe
|
||||
import _ "unsafe"
|
||||
|
||||
-- unused/go.mod --
|
||||
module example.com/unused
|
||||
-- unused/useerrors/useerrors.go --
|
||||
package useerrors
|
||||
import _ "errors"
|
||||
|
||||
-- nested/go.mod --
|
||||
module example.com/m/nested
|
||||
-- nested/useencoding/useencoding.go --
|
||||
package useencoding
|
||||
import _ "encoding"
|
|
@ -1,10 +1,13 @@
|
|||
env GO111MODULE=on
|
||||
|
||||
# -mod=readonly must not resolve missing modules nor update go.mod
|
||||
#
|
||||
# TODO(bcmills): 'go list' should suffice, but today it does not fail due to
|
||||
# unresolved imports. When that is fixed, use 'go list' instead of 'go list all'.
|
||||
env GOFLAGS=-mod=readonly
|
||||
go mod edit -fmt
|
||||
cp go.mod go.mod.empty
|
||||
! go list
|
||||
! go list all
|
||||
stderr 'import lookup disabled by -mod=readonly'
|
||||
cmp go.mod go.mod.empty
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ stdout 'Clear is better than clever.'
|
|||
# However, the same module can't be used as two different paths.
|
||||
go mod edit -dropreplace=rsc.io/quote/v3 -replace=not-rsc.io/quote/v3@v3.0.0=rsc.io/quote/v3@v3.0.0 -require=not-rsc.io/quote/v3@v3.0.0
|
||||
! go build -o a4.exe .
|
||||
|
||||
stderr 'rsc.io/quote/v3@v3.0.0 used for two different module paths \(not-rsc.io/quote/v3 and rsc.io/quote/v3\)'
|
||||
|
||||
-- go.mod --
|
||||
module quoter
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
env GO111MODULE=on
|
||||
|
||||
go list -e -f '{{.Incomplete}}' runbad1.go
|
||||
stdout true
|
||||
! go run runbad1.go
|
||||
stderr 'use of internal package m/x/internal not allowed'
|
||||
|
||||
go list -e -f '{{.Incomplete}}' runbad2.go
|
||||
stdout true
|
||||
! go run runbad2.go
|
||||
stderr 'use of internal package m/x/internal/y not allowed'
|
||||
|
||||
go list -e -f '{{.Incomplete}}' runok.go
|
||||
stdout false
|
||||
go run runok.go
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
||||
-- x/internal/internal.go --
|
||||
package internal
|
||||
|
||||
-- x/internal/y/y.go --
|
||||
package y
|
||||
|
||||
-- internal/internal.go --
|
||||
package internal
|
||||
|
||||
-- internal/z/z.go --
|
||||
package z
|
||||
|
||||
-- runbad1.go --
|
||||
package main
|
||||
import _ "m/x/internal"
|
||||
func main() {}
|
||||
|
||||
-- runbad2.go --
|
||||
package main
|
||||
import _ "m/x/internal/y"
|
||||
func main() {}
|
||||
|
||||
-- runok.go --
|
||||
package main
|
||||
import _ "m/internal"
|
||||
import _ "m/internal/z"
|
||||
func main() {}
|
|
@ -0,0 +1,15 @@
|
|||
# Test that go run does not get confused by conflict
|
||||
# between go.mod's module path and what you'd
|
||||
# expect from GOPATH. golang.org/issue/26046.
|
||||
|
||||
env GO111MODULE=on
|
||||
|
||||
cd $GOPATH/src/example.com/hello
|
||||
go run main.go
|
||||
|
||||
-- $GOPATH/src/example.com/hello/go.mod --
|
||||
module example.com/hello/v2
|
||||
|
||||
-- $GOPATH/src/example.com/hello/main.go --
|
||||
package main
|
||||
func main() {}
|
|
@ -0,0 +1,19 @@
|
|||
env GO111MODULE=on
|
||||
|
||||
go list -f '{{.TestImports}}'
|
||||
stdout net/http # from .TestImports
|
||||
|
||||
go list -test -f '{{.Deps}}'
|
||||
stdout golang_org/x/crypto # dep of .TestImports
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
||||
-- x.go --
|
||||
package x
|
||||
|
||||
-- x_test.go --
|
||||
package x
|
||||
import "testing"
|
||||
import _ "net/http"
|
||||
func Test(t *testing.T) {}
|
|
@ -1,11 +1,55 @@
|
|||
env GO111MODULE=on
|
||||
|
||||
# A test in the module's root package should work.
|
||||
cd a/
|
||||
cp go.mod.empty go.mod
|
||||
go test
|
||||
stdout PASS
|
||||
|
||||
-- a/go.mod --
|
||||
module github.com/user/a
|
||||
cp go.mod.empty go.mod
|
||||
go list -deps
|
||||
! stdout ^testing$
|
||||
|
||||
# list all should include test dependencies, like testing
|
||||
cp go.mod.empty go.mod
|
||||
go list all
|
||||
stdout ^testing$
|
||||
stdout ^rsc.io/quote$
|
||||
stdout ^rsc.io/testonly$
|
||||
|
||||
# list -deps -tests should also include testing
|
||||
# but not deps of tests of deps (rsc.io/testonly).
|
||||
go list -deps -test
|
||||
stdout ^testing$
|
||||
stdout ^rsc.io/quote$
|
||||
! stdout ^rsc.io/testonly$
|
||||
|
||||
# list -test all should succeed
|
||||
cp go.mod.empty go.mod
|
||||
go list -test all
|
||||
stdout '^testing'
|
||||
|
||||
cp go.mod.empty go.mod
|
||||
go test
|
||||
stdout PASS
|
||||
|
||||
# A test with the "_test" suffix in the module root should also work.
|
||||
cd ../b/
|
||||
go test
|
||||
stdout PASS
|
||||
|
||||
# A test with the "_test" suffix of a *package* with a "_test" suffix should
|
||||
# even work (not that you should ever do that).
|
||||
cd ../c_test
|
||||
go test
|
||||
stdout PASS
|
||||
|
||||
cd ../d_test
|
||||
go test
|
||||
stdout PASS
|
||||
|
||||
-- a/go.mod.empty --
|
||||
module example.com/user/a
|
||||
|
||||
-- a/a.go --
|
||||
package a
|
||||
|
@ -13,6 +57,63 @@ package a
|
|||
-- a/a_test.go --
|
||||
package a
|
||||
|
||||
import "testing"
|
||||
import _ "rsc.io/quote"
|
||||
|
||||
func Test(t *testing.T) {}
|
||||
|
||||
-- b/go.mod --
|
||||
module example.com/user/b
|
||||
|
||||
-- b/b.go --
|
||||
package b
|
||||
|
||||
-- b/b_test.go --
|
||||
package b_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func Test(t *testing.T) {}
|
||||
|
||||
-- c_test/go.mod --
|
||||
module example.com/c_test
|
||||
|
||||
-- c_test/umm.go --
|
||||
// Package c_test is the non-test package for its import path!
|
||||
package c_test
|
||||
|
||||
-- c_test/c_test_test.go --
|
||||
package c_test_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func Test(t *testing.T) {}
|
||||
|
||||
-- d_test/go.mod --
|
||||
// Package d is an ordinary package in a deceptively-named directory.
|
||||
module example.com/d
|
||||
|
||||
-- d_test/d.go --
|
||||
package d
|
||||
|
||||
-- d_test/d_test.go --
|
||||
package d_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func Test(t *testing.T) {}
|
||||
|
||||
-- e/go.mod --
|
||||
module example.com/e_test
|
||||
|
||||
-- e/wat.go --
|
||||
// Package e_test is the non-test package for its import path,
|
||||
// in a deceptively-named directory!
|
||||
package e_test
|
||||
|
||||
-- e/e_test.go --
|
||||
package e_test_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func Test(t *testing.T) {}
|
||||
|
|
|
@ -10,6 +10,10 @@ go list -m all
|
|||
stdout '^w.1 v1.2.0'
|
||||
stdout '^z.1 v1.2.0'
|
||||
|
||||
# empty tidy should not crash
|
||||
cd triv
|
||||
go mod tidy
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
||||
|
@ -55,3 +59,6 @@ module z
|
|||
|
||||
-- z/sub/sub.go --
|
||||
package sub
|
||||
|
||||
-- triv/go.mod --
|
||||
module triv
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
[exec:bzr] skip 'tests NOT having bzr'
|
||||
[!net] skip
|
||||
|
||||
env GO111MODULE=on
|
||||
env GOPROXY=
|
||||
|
||||
! go list launchpad.net/gocheck
|
||||
stderr '"bzr": executable file not found'
|
||||
|
||||
-- go.mod --
|
||||
module m
|
|
@ -155,6 +155,12 @@ package m
|
|||
|
||||
import _ "appengine"
|
||||
import _ "appengine/datastore"
|
||||
-- nonexistent.go --
|
||||
// +build alternatereality
|
||||
|
||||
package m
|
||||
|
||||
import _ "nonexistent.rsc.io"
|
||||
-- mypkg/go.mod --
|
||||
module me
|
||||
-- mypkg/mydir/d.go --
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
env GO111MODULE=on
|
||||
|
||||
# initial conditions: using sampler v1.3.0, not listed in go.mod.
|
||||
go list -deps
|
||||
stdout rsc.io/sampler
|
||||
! grep 'rsc.io/sampler v1.3.0' go.mod
|
||||
|
||||
# update to v1.3.1, now indirect in go.mod.
|
||||
go get rsc.io/sampler@v1.3.1
|
||||
grep 'rsc.io/sampler v1.3.1 // indirect' go.mod
|
||||
cp go.mod go.mod.good
|
||||
|
||||
# vendoring can but should not need to make changes.
|
||||
go mod vendor
|
||||
cmp go.mod go.mod.good
|
||||
|
||||
# go list -mod=vendor (or go build -mod=vendor) must not modify go.mod.
|
||||
# golang.org/issue/26704
|
||||
go list -mod=vendor
|
||||
cmp go.mod go.mod.good
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
||||
-- x.go --
|
||||
package x
|
||||
import _ "rsc.io/quote"
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче