The files update.bash and patch.txt are new.
Running update.bash made the other changes.

Fixes golang/go#25514 (version now auto-inserted).
Fixes golang/go#26434.

Change-Id: Ied836ab8c1ddfea0a3158b2e4d84fbc787140e66
Reviewed-on: https://go-review.googlesource.com/123579
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
Russ Cox 2018-07-12 00:12:11 -04:00
Родитель cc75ec08d5
Коммит 2093985079
162 изменённых файлов: 5967 добавлений и 4990 удалений

1
go.mod Normal file
Просмотреть файл

@ -0,0 +1 @@
module golang.org/x/vgo

568
patch.txt Normal file
Просмотреть файл

@ -0,0 +1,568 @@
diff -u -r ./go11.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/go11.go
--- ./go11.go 2018-05-30 20:46:08.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/go11.go 2018-02-20 12:11:43.000000000 -0500
@@ -4,7 +4,7 @@
// +build go1.1
-package main
+package Main
// Test that go1.1 tag above is included in builds. main.go refers to this definition.
const go11tag = true
diff -u -r ./go_test.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/go_test.go
--- ./go_test.go 2018-07-12 00:17:57.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/go_test.go 2018-07-12 00:09:46.000000000 -0400
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main_test
+package Main_test
import (
"bytes"
@@ -120,8 +120,8 @@
}
if canRun {
testGo = filepath.Join(testTmpDir, "testgo"+exeSuffix)
- args := []string{"build", "-tags", "testgo", "-o", testGo}
+ args := []string{"build", "-tags", "testgo", "-o", testGo, "../../.."}
if race.Enabled {
args = append(args, "-race")
}
@@ -867,7 +870,9 @@
tg.grepBoth("FAIL.*badtest/badvar", "test did not run everything")
}
func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
+ t.Skip("vgo")
+
if testing.Short() {
t.Skip("don't rebuild the standard library in short mode")
}
@@ -1342,6 +1389,8 @@
}
func TestMoveHG(t *testing.T) {
+ t.Skip("vgo") // Failing in main branch too: non-hermetic hg configuration?
+
testMove(t, "hg", "vcs-test.golang.org/go/custom-hg-hello", "custom-hg-hello", "vcs-test.golang.org/go/custom-hg-hello/.hg/hgrc")
}
@@ -1507,6 +1556,8 @@
}
func TestAccidentalGitCheckout(t *testing.T) {
+ t.Skip("vgo") // Failing in main branch too: https://golang.org/issue/22983
+
testenv.MustHaveExternalNetwork(t)
if _, err := exec.LookPath("git"); err != nil {
t.Skip("skipping because git binary not found")
@@ -2114,6 +2165,8 @@
}
func TestDefaultGOPATH(t *testing.T) {
+ t.Skip("vgo") // Needs a more realistic GOROOT; see RuntimeGoroot below.
+
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
@@ -2172,6 +2225,8 @@
// Issue 4186. go get cannot be used to download packages to $GOROOT.
// Test that without GOPATH set, go get should fail.
func TestGoGetIntoGOROOT(t *testing.T) {
+ t.Skip("vgo")
+
testenv.MustHaveExternalNetwork(t)
tg := testgo(t)
@@ -2771,6 +2771,8 @@ func TestTestBuildFailureOutput(t *testing.T) {
}
func TestCoverageFunc(t *testing.T) {
+ t.Skip("vgo")
+
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
@@ -3395,6 +3450,8 @@
}
func TestGoVetWithExternalTests(t *testing.T) {
+ t.Skip("vgo")
+
tg := testgo(t)
defer tg.cleanup()
tg.makeTempdir()
@@ -3404,6 +3461,8 @@
}
func TestGoVetWithTags(t *testing.T) {
+ t.Skip("vgo")
+
tg := testgo(t)
defer tg.cleanup()
tg.makeTempdir()
@@ -3413,6 +3472,8 @@
}
func TestGoVetWithFlagsOn(t *testing.T) {
+ t.Skip("vgo")
+
tg := testgo(t)
defer tg.cleanup()
tg.makeTempdir()
@@ -4754,6 +4815,8 @@
}
func TestExecutableGOROOT(t *testing.T) {
+ t.Skip("vgo")
+
skipIfGccgo(t, "gccgo has no GOROOT")
if runtime.GOOS == "openbsd" {
t.Skipf("test case does not work on %s, missing os.Executable", runtime.GOOS)
@@ -4829,6 +4892,8 @@
// Binaries built in the new tree should report the
// new tree when they call runtime.GOROOT.
t.Run("RuntimeGoroot", func(t *testing.T) {
+ t.Skip("vgo") // Needs "new/api" in GOROOT.
+
// Build a working GOROOT the easy way, with symlinks.
testenv.MustHaveSymlink(t)
if err := os.Symlink(filepath.Join(testGOROOT, "src"), tg.path("new/src")); err != nil {
@@ -4984,6 +5049,8 @@
}
func TestTestRegexps(t *testing.T) {
+ t.Skip("vgo") // fails with Go 1.10 testing package
+
tg := testgo(t)
defer tg.cleanup()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
@@ -5119,6 +5186,8 @@
}
func TestExecBuildX(t *testing.T) {
+ t.Skip("vgo")
+
tooSlow(t)
if !canCgo {
t.Skip("skipping because cgo not enabled")
@@ -5761,6 +5830,8 @@
}
func TestTestVet(t *testing.T) {
+ t.Skip("vgo")
+
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
@@ -5945,6 +6011,8 @@
}
func TestGoTestJSON(t *testing.T) {
+ t.Skip("vgo") // "did not see skip"
+
skipIfGccgo(t, "gccgo does not have standard packages")
tooSlow(t)
@@ -5983,6 +6051,8 @@
}
func TestFailFast(t *testing.T) {
+ t.Skip("vgo") // fails with Go 1.10 testing package
+
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
diff -u -r ./go_unix_test.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/go_unix_test.go
--- ./go_unix_test.go 2018-06-04 09:24:18.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/go_unix_test.go 2018-02-20 12:11:43.000000000 -0500
@@ -4,6 +4,6 @@
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
-package main_test
+package Main_test
import (
diff -u -r ./go_windows_test.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/go_windows_test.go
--- ./go_windows_test.go 2018-06-04 09:24:18.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/go_windows_test.go 2018-02-20 12:11:43.000000000 -0500
@@ -2,6 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package Main
import (
diff -u -r ./script_test.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/script_test.go
--- ./script_test.go 2018-06-04 09:24:18.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/script_test.go 2018-02-20 12:11:43.000000000 -0500
@@ -5,6 +5,6 @@
// Script-driven tests.
// See testdata/script/README for an overview.
-package main_test
+package Main_test
import (
diff -u -r ./internal/base/base.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/base/base.go
--- ./internal/base/base.go 2018-06-04 09:24:18.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/base/base.go 2018-02-23 16:13:50.000000000 -0500
@@ -15,6 +15,7 @@
"log"
"os"
"os/exec"
+ "runtime/debug"
"strings"
"sync"
@@ -86,13 +87,20 @@
os.Exit(exitStatus)
}
+var et = flag.Bool("et", false, "print stack traces with errors")
+
func Fatalf(format string, args ...interface{}) {
Errorf(format, args...)
Exit()
}
func Errorf(format string, args ...interface{}) {
- log.Printf(format, args...)
+ if *et {
+ stack := debug.Stack()
+ log.Printf("%s\n%s", fmt.Sprintf(format, args...), stack)
+ } else {
+ log.Printf(format, args...)
+ }
SetExitStatus(1)
}
diff -u -r ./internal/cfg/cfg.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/cfg/cfg.go
--- ./internal/cfg/cfg.go 2018-07-12 00:17:57.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/cfg/cfg.go 2018-07-12 00:03:05.000000000 -0400
@@ -7,13 +7,14 @@
package cfg
import (
+ "bytes"
"fmt"
"go/build"
+ "io/ioutil"
+ "log"
"os"
"path/filepath"
"runtime"
-
- "cmd/internal/objabi"
)
// These are general "build flags" used by build and other commands.
@@ -90,10 +91,10 @@
GOROOT_FINAL = findGOROOT_FINAL()
// Used in envcmd.MkEnv and build ID computations.
- GOARM = fmt.Sprint(objabi.GOARM)
- GO386 = objabi.GO386
- GOMIPS = objabi.GOMIPS
- GOMIPS64 = objabi.GOMIPS64
+ GOARM, GO386, GOMIPS, GOMIPS64 = objabi()
+
+ // C and C++ compilers
+ CC, CXX = compilers()
)
// Update build context to use our computed GOROOT.
@@ -109,18 +110,75 @@
}
}
-// There is a copy of findGOROOT, isSameDir, and isGOROOT in
-// x/tools/cmd/godoc/goroot.go.
-// Try to keep them in sync for now.
-
-// findGOROOT returns the GOROOT value, using either an explicitly
-// provided environment variable, a GOROOT that contains the current
-// os.Executable value, or else the GOROOT that the binary was built
-// with from runtime.GOROOT().
-//
-// There is a copy of this code in x/tools/cmd/godoc/goroot.go.
+func objabi() (GOARM, GO386, GOMIPS, GOMIPS64 string) {
+ data, err := ioutil.ReadFile(filepath.Join(GOROOT, "src/cmd/internal/objabi/zbootstrap.go"))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "go objabi: %v\n", err)
+ }
+
+ find := func(key string) string {
+ if env := os.Getenv(key); env != "" {
+ return env
+ }
+ i := bytes.Index(data, []byte("default"+key+" = `"))
+ if i < 0 {
+ if key == "GOMIPS64" { // new in Go 1.11
+ return ""
+ }
+ fmt.Fprintf(os.Stderr, "go objabi: cannot find %s\n", key)
+ os.Exit(2)
+ }
+ line := data[i:]
+ line = line[bytes.IndexByte(line, '`')+1:]
+ return string(line[:bytes.IndexByte(line, '`')])
+ }
+
+ return find("GOARM"), find("GO386"), find("GOMIPS"), find("GOMIPS64")
+}
+
+func compilers() (CC, CXX string) {
+ data, err := ioutil.ReadFile(filepath.Join(GOROOT, "src/cmd/go/internal/cfg/zdefaultcc.go"))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "go compilers: %v\n", err)
+ }
+
+ find := func(key string) string {
+ if env := os.Getenv(key); env != "" {
+ return env
+ }
+ fi := bytes.Index(data, []byte("Default"+key+"(goos, goarch string)"))
+ if fi < 0 {
+ fmt.Fprintf(os.Stderr, "go compilers: cannot find %s\n", key)
+ os.Exit(2)
+ }
+ i := bytes.Index(data[fi:], []byte("\treturn "))
+ if i < 0 {
+ fmt.Fprintf(os.Stderr, "go compilers: cannot find %s\n", key)
+ os.Exit(2)
+ }
+ line := data[fi+i:]
+ line = line[bytes.IndexByte(line, '"')+1:]
+ return string(line[:bytes.IndexByte(line, '"')])
+ }
+
+ return find("CC"), find("CXX")
+}
+
func findGOROOT() string {
+ goroot := findGOROOT1()
+ _, err := os.Stat(filepath.Join(goroot, "api/go1.10.txt"))
+ if err != nil {
+ log.SetFlags(0)
+ log.Fatalf("go requires Go 1.10 but VGOROOT=%s is not a Go 1.10 source tree", goroot)
+ }
+ return goroot
+}
+
+func findGOROOT1() string {
+ if env := os.Getenv("VGOROOT"); env != "" {
+ return filepath.Clean(env)
+ }
if env := os.Getenv("GOROOT"); env != "" {
return filepath.Clean(env)
}
def := filepath.Clean(runtime.GOROOT())
diff -u -r ./internal/help/help.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/help/help.go
--- ./internal/help/help.go 2018-07-12 00:17:57.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/help/help.go 2018-07-12 00:03:05.000000000 -0400
@@ -72,6 +72,10 @@
var usageTemplate = `Go is a tool for managing Go source code.
+This is vgo, an experimental go command with support for package versioning.
+Even though you are invoking it as vgo, most of the messages printed will
+still say "go", not "vgo". Sorry.
+
Usage:
go command [arguments]
diff -u -r ./internal/version/version.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/version/version.go
--- ./internal/version/version.go 2018-06-04 09:24:18.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/version/version.go 2018-07-10 16:04:55.000000000 -0400
@@ -10,8 +10,9 @@
"runtime"
"cmd/go/internal/base"
+ "cmd/go/internal/work"
)
var CmdVersion = &base.Command{
Run: runVersion,
UsageLine: "version",
@@ -24,5 +27,5 @@
cmd.Usage()
}
- fmt.Printf("go version %s %s/%s\n", runtime.Version(), runtime.GOOS, runtime.GOARCH)
+ fmt.Printf("go version %s %s/%s vgo:%s\n", work.RuntimeVersion, runtime.GOOS, runtime.GOARCH, version)
}
diff -u -r ./internal/work/build.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/work/build.go
--- ./internal/work/build.go 2018-07-12 00:17:57.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/work/build.go 2018-07-10 17:04:18.000000000 -0400
@@ -5,9 +5,11 @@
package work
import (
+ "bytes"
"errors"
"fmt"
"go/build"
+ "io/ioutil"
"os"
"os/exec"
"path"
@@ -274,7 +276,25 @@
var pkgsFilter = func(pkgs []*load.Package) []*load.Package { return pkgs }
-var runtimeVersion = runtime.Version()
+var runtimeVersion = getRuntimeVersion()
+var RuntimeVersion = runtimeVersion
+
+func getRuntimeVersion() string {
+ data, err := ioutil.ReadFile(filepath.Join(cfg.GOROOT, "src/runtime/internal/sys/zversion.go"))
+ if err != nil {
+ base.Fatalf("go: %v", err)
+ }
+ i := bytes.Index(data, []byte("TheVersion = `"))
+ if i < 0 {
+ base.Fatalf("go: cannot find TheVersion")
+ }
+ data = data[i+len("TheVersion = `"):]
+ j := bytes.IndexByte(data, '`')
+ if j < 0 {
+ base.Fatalf("go: cannot find TheVersion")
+ }
+ return string(data[:j])
+}
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 @@
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 @@
// 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 {
+ if name == "vet" && oldVet {
+ return ""
+ }
+
b.id.Lock()
id := b.toolIDCache[name]
b.id.Unlock()
@@ -190,6 +196,10 @@
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
+ if name == "vet" {
+ oldVet = true
+ return ""
+ }
base.Fatalf("%s: %v\n%s%s", desc, err, stdout.Bytes(), stderr.Bytes())
}
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
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/work/exec.go 2018-07-12 00:03:05.000000000 -0400
@@ -972,7 +972,7 @@
// TODO(rsc,gri): Try to remove this for Go 1.11.
//
// Disabled 2018-04-20. Let's see if we can do without it.
- // vcfg.SucceedOnTypecheckFailure = cfg.CmdName == "test"
+ vcfg.SucceedOnTypecheckFailure = cfg.CmdName == "test"
js, err := json.MarshalIndent(vcfg, "", "\t")
if err != nil {
diff -u -r ./internal/work/gc.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/work/gc.go
--- ./internal/work/gc.go 2018-07-06 16:52:53.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/internal/work/gc.go 2018-06-27 21:01:27.000000000 -0400
@@ -20,7 +20,6 @@
"cmd/go/internal/cfg"
"cmd/go/internal/load"
"cmd/go/internal/str"
- "cmd/internal/objabi"
"crypto/sha1"
)
@@ -167,11 +166,6 @@
}
}
- // TODO: Test and delete these conditions.
- if objabi.Fieldtrack_enabled != 0 || objabi.Preemptibleloops_enabled != 0 || objabi.Clobberdead_enabled != 0 {
- canDashC = false
- }
-
if !canDashC {
return 1
}
diff -u -r ./main.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/main.go
--- ./main.go 2018-07-12 00:17:57.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/main.go 2018-07-10 16:04:55.000000000 -0400
@@ -4,7 +4,7 @@
//go:generate ./mkalldocs.sh
-package main
+package Main
import (
"flag"
@@ -74,7 +74,7 @@
}
}
-func main() {
+func Main() {
_ = go11tag
flag.Usage = base.Usage
flag.Parse()
diff -u -r ./note_test.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/note_test.go
--- ./note_test.go 2018-07-12 00:14:08.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/note_test.go 2018-07-11 23:25:10.000000000 -0400
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main_test
+package Main_test
import (
"bytes"
diff -u -r ./proxy_test.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/proxy_test.go
--- ./proxy_test.go 2018-07-12 00:14:08.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/proxy_test.go 2018-07-11 23:25:10.000000000 -0400
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main_test
+package Main_test
import (
"bytes"
diff -u -r ./vendor_test.go /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/vendor_test.go
--- ./vendor_test.go 2018-07-12 00:14:08.000000000 -0400
+++ /Users/rsc/src/golang.org/x/vgo/vendor/cmd/go/vendor_test.go 2018-07-11 23:25:10.000000000 -0400
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main_test
+package Main_test
import (
"bytes"

17
update.bash Executable file
Просмотреть файл

@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -e
rm -rf ./vendor/cmd/go
cp -a $(go env GOROOT)/src/cmd/go vendor/cmd/go
rm -f vendor/cmd/go/alldocs.go vendor/cmd/go/mkalldocs.sh # docs are in wrong place and describe wrong command
cd vendor/cmd/go
patch -p0 < ../../../patch.txt
vers=$(go version | sed 's/^go version //; s/ [A-Z][a-z][a-z].*//')
echo "package version; const version = \"$vers\"" > internal/version/vgo.go
gofmt -w internal
cd ../../..
rm $(find . -name '*.orig')
go build
./vgo version
rm vgo
git add .

1925
vendor/cmd/go/alldocs.go поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

548
vendor/cmd/go/go_test.go поставляемый
Просмотреть файл

@ -15,6 +15,7 @@ import (
"internal/testenv"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
@ -102,6 +103,9 @@ var testGOROOT string
var testCC string
var testGOCACHE string
var testGo string
var testTmpDir string
// The TestMain function creates a go command for testing purposes and
// deletes it after the tests have been run.
func TestMain(m *testing.M) {
@ -119,8 +123,18 @@ func TestMain(m *testing.M) {
select {}
}
dir, err := ioutil.TempDir(os.Getenv("GOTMPDIR"), "cmd-go-test-")
if err != nil {
log.Fatal(err)
}
testTmpDir = dir
if !*testWork {
defer removeAll(testTmpDir)
}
if canRun {
args := []string{"build", "-tags", "testgo", "-o", "testgo" + exeSuffix, "../../.."}
testGo = filepath.Join(testTmpDir, "testgo"+exeSuffix)
args := []string{"build", "-tags", "testgo", "-o", testGo, "../../.."}
if race.Enabled {
args = append(args, "-race")
}
@ -173,7 +187,7 @@ func TestMain(m *testing.M) {
}
testCC = strings.TrimSpace(string(out))
if out, err := exec.Command("./testgo"+exeSuffix, "env", "CGO_ENABLED").Output(); err != nil {
if out, err := exec.Command(testGo, "env", "CGO_ENABLED").Output(); err != nil {
fmt.Fprintf(os.Stderr, "running testgo failed: %v\n", err)
canRun = false
} else {
@ -217,9 +231,8 @@ func TestMain(m *testing.M) {
}
r := m.Run()
if canRun {
os.Remove("testgo" + exeSuffix)
if !*testWork {
removeAll(testTmpDir) // os.Exit won't run defer
}
os.Exit(r)
@ -249,6 +262,7 @@ type testgoData struct {
ran bool
inParallel bool
stdout, stderr bytes.Buffer
execDir string // dir for tg.run
}
// skipIfGccgo skips the test if using gccgo.
@ -367,10 +381,7 @@ func (tg *testgoData) unsetenv(name string) {
}
func (tg *testgoData) goTool() string {
if tg.wd == "" {
return "./testgo" + exeSuffix
}
return filepath.Join(tg.wd, "testgo"+exeSuffix)
return testGo
}
// doRun runs the test go command, recording stdout and stderr and
@ -404,6 +415,7 @@ func (tg *testgoData) doRun(args []string) error {
cmd := exec.Command(prog, args...)
tg.stdout.Reset()
tg.stderr.Reset()
cmd.Dir = tg.execDir
cmd.Stdout = &tg.stdout
cmd.Stderr = &tg.stderr
cmd.Env = tg.env
@ -751,7 +763,11 @@ func (tg *testgoData) wantStale(pkg, reason, msg string) {
if !stale {
tg.t.Fatal(msg)
}
if reason == "" && why != "" || !strings.Contains(why, reason) {
// We always accept the reason as being "not installed but
// available in build cache", because when that is the case go
// list doesn't try to sort out the underlying reason why the
// package is not installed.
if reason == "" && why != "" || !strings.Contains(why, reason) && !strings.Contains(why, "not installed but available in build cache") {
tg.t.Errorf("wrong reason for Stale=true: %q, want %q", why, reason)
}
}
@ -802,6 +818,9 @@ func removeAll(dir string) error {
// module cache has 0444 directories;
// make them writable in order to remove content.
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return nil // ignore errors walking in file system
}
if info.IsDir() {
os.Chmod(path, 0777)
}
@ -822,97 +841,6 @@ func (tg *testgoData) failSSH() {
tg.setenv("PATH", fmt.Sprintf("%v%c%v", fail, filepath.ListSeparator, os.Getenv("PATH")))
}
func TestBuildComplex(t *testing.T) {
// Simple smoke test for build configuration.
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.run("build", "-x", "-o", os.DevNull, "complex")
if _, err := exec.LookPath("gccgo"); err == nil {
t.Skip("golang.org/issue/22472")
tg.run("build", "-x", "-o", os.DevNull, "-compiler=gccgo", "complex")
}
}
func TestFileLineInErrorMessages(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempFile("err.go", `package main; import "bar"`)
path := tg.path("err.go")
tg.runFail("run", path)
shortPath := path
if rel, err := filepath.Rel(tg.pwd(), path); err == nil && len(rel) < len(path) {
shortPath = rel
}
tg.grepStderr("^"+regexp.QuoteMeta(shortPath)+":", "missing file:line in error message")
}
func TestProgramNameInCrashMessages(t *testing.T) {
skipIfGccgo(t, "gccgo does not use cmd/link")
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempFile("triv.go", `package main; func main() {}`)
tg.runFail("build", "-ldflags", "-crash_for_testing", tg.path("triv.go"))
tg.grepStderr(`[/\\]tool[/\\].*[/\\]link`, "missing linker name in error message")
}
func TestBrokenTestsWithoutTestFunctionsAllFail(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
// TODO: tg.parallel()
tg.runFail("test", "./testdata/src/badtest/...")
tg.grepBothNot("^ok", "test passed unexpectedly")
tg.grepBoth("FAIL.*badtest/badexec", "test did not run everything")
tg.grepBoth("FAIL.*badtest/badsyntax", "test did not run everything")
tg.grepBoth("FAIL.*badtest/badvar", "test did not run everything")
}
func TestGoBuildDashAInDevBranch(t *testing.T) {
t.Skip("vgo")
if testing.Short() {
t.Skip("don't rebuild the standard library in short mode")
}
tg := testgo(t)
defer tg.cleanup()
tg.run("install", "math") // should be up to date already but just in case
tg.setenv("TESTGO_IS_GO_RELEASE", "0")
tg.run("build", "-v", "-a", "math")
tg.grepStderr("runtime", "testgo build -a math in dev branch DID NOT build runtime, but should have")
// Everything is out of date. Rebuild to leave things in a better state.
tg.run("install", "std")
}
func TestGoBuildDashAInReleaseBranch(t *testing.T) {
t.Skip("vgo")
if testing.Short() {
t.Skip("don't rebuild the standard library in short mode")
}
tg := testgo(t)
defer tg.cleanup()
tg.run("install", "math", "net/http") // should be up to date already but just in case
tg.setenv("TESTGO_IS_GO_RELEASE", "1")
tg.run("install", "-v", "-a", "math")
tg.grepStderr("runtime", "testgo build -a math in release branch DID NOT build runtime, but should have")
// Now runtime.a is updated (newer mtime), so everything would look stale if not for being a release.
tg.run("build", "-v", "net/http")
tg.grepStderrNot("strconv", "testgo build -v net/http in release branch with newer runtime.a DID build strconv but should not have")
tg.grepStderrNot("golang.org/x/net/http2/hpack", "testgo build -v net/http in release branch with newer runtime.a DID build .../golang.org/x/net/http2/hpack but should not have")
tg.grepStderrNot("net/http", "testgo build -v net/http in release branch with newer runtime.a DID build net/http but should not have")
// Everything is out of date. Rebuild to leave things in a better state.
tg.run("install", "std")
}
func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
t.Skip("vgo")
@ -923,13 +851,13 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
addNL := func(name string) (restore func()) {
addVar := func(name string, idx int) (restore func()) {
data, err := ioutil.ReadFile(name)
if err != nil {
t.Fatal(err)
}
old := data
data = append(data, '\n')
data = append(data, fmt.Sprintf("var DummyUnusedVar%d bool\n", idx)...)
if err := ioutil.WriteFile(name, append(data, '\n'), 0666); err != nil {
t.Fatal(err)
}
@ -953,19 +881,19 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
// In fact this should be true even outside a release branch.
sys := runtime.GOROOT() + "/src/runtime/internal/sys/sys.go"
tg.sleep()
restore := addNL(sys)
restore := addVar(sys, 0)
restore()
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after updating mtime of runtime/internal/sys/sys.go")
// But changing content of any file should have an effect.
// Previously zversion.go was the only one that mattered;
// now they all matter, so keep using sys.go.
restore = addNL(sys)
restore = addVar(sys, 1)
defer restore()
tg.wantStale("p1", "stale dependency: runtime/internal/sys", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go")
restore()
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after changing back to old release")
addNL(sys)
addVar(sys, 2)
tg.wantStale("p1", "stale dependency: runtime/internal/sys", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go again")
tg.run("install", "-i", "p1")
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with new release")
@ -980,198 +908,6 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
tg.run("install", "std")
}
func TestGoListStandard(t *testing.T) {
skipIfGccgo(t, "gccgo does not have GOROOT")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
// TODO: tg.parallel()
tg.cd(runtime.GOROOT() + "/src")
tg.run("list", "-f", "{{if not .Standard}}{{.ImportPath}}{{end}}", "./...")
stdout := tg.getStdout()
for _, line := range strings.Split(stdout, "\n") {
if strings.HasPrefix(line, "_/") && strings.HasSuffix(line, "/src") {
// $GOROOT/src shows up if there are any .go files there.
// We don't care.
continue
}
if line == "" {
continue
}
t.Errorf("package in GOROOT not listed as standard: %v", line)
}
// Similarly, expanding std should include some of our vendored code.
tg.run("list", "std", "cmd")
tg.grepStdout("golang.org/x/net/http2/hpack", "list std cmd did not mention vendored hpack")
tg.grepStdout("golang.org/x/arch/x86/x86asm", "list std cmd did not mention vendored x86asm")
}
func TestGoInstallCleansUpAfterGoBuild(t *testing.T) {
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
// TODO: tg.parallel()
tg.tempFile("src/mycmd/main.go", `package main; func main(){}`)
tg.setenv("GOPATH", tg.path("."))
tg.cd(tg.path("src/mycmd"))
doesNotExist := func(file, msg string) {
if _, err := os.Stat(file); err == nil {
t.Fatal(msg)
} else if !os.IsNotExist(err) {
t.Fatal(msg, "error:", err)
}
}
tg.run("build")
tg.wantExecutable("mycmd"+exeSuffix, "testgo build did not write command binary")
tg.run("install")
doesNotExist("mycmd"+exeSuffix, "testgo install did not remove command binary")
tg.run("build")
tg.wantExecutable("mycmd"+exeSuffix, "testgo build did not write command binary (second time)")
// Running install with arguments does not remove the target,
// even in the same directory.
tg.run("install", "mycmd")
tg.wantExecutable("mycmd"+exeSuffix, "testgo install mycmd removed command binary when run in mycmd")
tg.run("build")
tg.wantExecutable("mycmd"+exeSuffix, "testgo build did not write command binary (third time)")
// And especially not outside the directory.
tg.cd(tg.path("."))
if data, err := ioutil.ReadFile("src/mycmd/mycmd" + exeSuffix); err != nil {
t.Fatal("could not read file:", err)
} else {
if err := ioutil.WriteFile("mycmd"+exeSuffix, data, 0555); err != nil {
t.Fatal("could not write file:", err)
}
}
tg.run("install", "mycmd")
tg.wantExecutable("src/mycmd/mycmd"+exeSuffix, "testgo install mycmd removed command binary from its source dir when run outside mycmd")
tg.wantExecutable("mycmd"+exeSuffix, "testgo install mycmd removed command binary from current dir when run outside mycmd")
}
func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) {
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempFile("d1/src/p1/p1.go", `package p1
import "p2"
func F() { p2.F() }`)
tg.tempFile("d2/src/p2/p2.go", `package p2
func F() {}`)
sep := string(filepath.ListSeparator)
tg.setenv("GOPATH", tg.path("d1")+sep+tg.path("d2"))
tg.run("install", "-i", "p1")
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly")
tg.wantNotStale("p2", "", "./testgo list claims p2 is stale, incorrectly")
tg.sleep()
if f, err := os.OpenFile(tg.path("d2/src/p2/p2.go"), os.O_WRONLY|os.O_APPEND, 0); err != nil {
t.Fatal(err)
} else if _, err = f.WriteString(`func G() {}`); err != nil {
t.Fatal(err)
} else {
tg.must(f.Close())
}
tg.wantStale("p2", "build ID mismatch", "./testgo list claims p2 is NOT stale, incorrectly")
tg.wantStale("p1", "stale dependency: p2", "./testgo list claims p1 is NOT stale, incorrectly")
tg.run("install", "-i", "p1")
tg.wantNotStale("p2", "", "./testgo list claims p2 is stale after reinstall, incorrectly")
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after reinstall, incorrectly")
}
func TestGoInstallDetectsRemovedFiles(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempFile("src/mypkg/x.go", `package mypkg`)
tg.tempFile("src/mypkg/y.go", `package mypkg`)
tg.tempFile("src/mypkg/z.go", `// +build missingtag
package mypkg`)
tg.setenv("GOPATH", tg.path("."))
tg.run("install", "mypkg")
tg.wantNotStale("mypkg", "", "./testgo list mypkg claims mypkg is stale, incorrectly")
// z.go was not part of the build; removing it is okay.
tg.must(os.Remove(tg.path("src/mypkg/z.go")))
tg.wantNotStale("mypkg", "", "./testgo list mypkg claims mypkg is stale after removing z.go; should not be stale")
// y.go was part of the package; removing it should be detected.
tg.must(os.Remove(tg.path("src/mypkg/y.go")))
tg.wantStale("mypkg", "build ID mismatch", "./testgo list mypkg claims mypkg is NOT stale after removing y.go; should be stale")
}
func TestWildcardMatchesSyntaxErrorDirs(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
// TODO: tg.parallel()
tg.tempFile("src/mypkg/x.go", `package mypkg`)
tg.tempFile("src/mypkg/y.go", `pkg mypackage`)
tg.setenv("GOPATH", tg.path("."))
tg.cd(tg.path("src/mypkg"))
tg.runFail("list", "./...")
tg.runFail("build", "./...")
tg.runFail("install", "./...")
}
func TestGoListWithTags(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.tempFile("src/mypkg/x.go", "// +build thetag\n\npackage mypkg\n")
tg.setenv("GOPATH", tg.path("."))
tg.cd(tg.path("./src"))
tg.run("list", "-tags=thetag", "./my...")
tg.grepStdout("mypkg", "did not find mypkg")
}
func TestGoInstallErrorOnCrossCompileToBin(t *testing.T) {
if testing.Short() {
t.Skip("don't install into GOROOT in short mode")
}
tg := testgo(t)
defer tg.cleanup()
tg.tempFile("src/mycmd/x.go", `package main
func main() {}`)
tg.setenv("GOPATH", tg.path("."))
tg.cd(tg.path("src/mycmd"))
tg.run("build", "mycmd")
goarch := "386"
if runtime.GOARCH == "386" {
goarch = "amd64"
}
tg.setenv("GOOS", "linux")
tg.setenv("GOARCH", goarch)
tg.run("install", "mycmd")
tg.setenv("GOBIN", tg.path("."))
tg.runFail("install", "mycmd")
tg.run("install", "cmd/pack")
}
func TestGoInstallDetectsRemovedFilesInPackageMain(t *testing.T) {
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempFile("src/mycmd/x.go", `package main
func main() {}`)
tg.tempFile("src/mycmd/y.go", `package main`)
tg.tempFile("src/mycmd/z.go", `// +build missingtag
package main`)
tg.setenv("GOPATH", tg.path("."))
tg.run("install", "mycmd")
tg.wantNotStale("mycmd", "", "./testgo list mypkg claims mycmd is stale, incorrectly")
// z.go was not part of the build; removing it is okay.
tg.must(os.Remove(tg.path("src/mycmd/z.go")))
tg.wantNotStale("mycmd", "", "./testgo list mycmd claims mycmd is stale after removing z.go; should not be stale")
// y.go was part of the package; removing it should be detected.
tg.must(os.Remove(tg.path("src/mycmd/y.go")))
tg.wantStale("mycmd", "build ID mismatch", "./testgo list mycmd claims mycmd is NOT stale after removing y.go; should be stale")
}
func testLocalRun(tg *testgoData, exepath, local, match string) {
tg.t.Helper()
out, err := exec.Command(exepath).Output()
@ -1450,6 +1186,21 @@ func TestImportCycle(t *testing.T) {
tg.run("list", "-e", "-json", "selfimport")
}
func TestListImportMap(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.run("list", "-f", "{{.ImportPath}}: {{.ImportMap}}", "net", "fmt")
tg.grepStdout(`^net: map\[(.* )?golang_org/x/net/dns/dnsmessage:vendor/golang_org/x/net/dns/dnsmessage.*\]`, "net/http should have rewritten dnsmessage import")
tg.grepStdout(`^fmt: map\[\]`, "fmt should have no rewritten imports")
tg.run("list", "-deps", "-test", "-f", "{{.ImportPath}} MAP: {{.ImportMap}}\n{{.ImportPath}} IMPORT: {{.Imports}}", "fmt")
tg.grepStdout(`^flag \[fmt\.test\] MAP: map\[fmt:fmt \[fmt\.test\]\]`, "flag [fmt.test] should import fmt [fmt.test] as fmt")
tg.grepStdout(`^fmt\.test MAP: map\[(.* )?testing:testing \[fmt\.test\]`, "fmt.test should import testing [fmt.test] as testing")
tg.grepStdout(`^fmt\.test MAP: map\[(.* )?testing:testing \[fmt\.test\]`, "fmt.test should import testing [fmt.test] as testing")
tg.grepStdoutNot(`^fmt\.test MAP: map\[(.* )?os:`, "fmt.test should not import a modified os")
tg.grepStdout(`^fmt\.test IMPORT: \[fmt \[fmt\.test\] fmt_test \[fmt\.test\] os testing \[fmt\.test\] testing/internal/testdeps \[fmt\.test\]\]`, "wrong imports for fmt.test")
}
// cmd/go: custom import path checking should not apply to Go packages without import comment.
func TestIssue10952(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
@ -1567,7 +1318,8 @@ func TestErrorMessageForSyntaxErrorInTestGoFileSaysFAIL(t *testing.T) {
defer tg.cleanup()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.runFail("test", "syntaxerror")
tg.grepStderr("FAIL", "go test did not say FAIL")
tg.grepStderr("x_test.go:", "did not diagnose error")
tg.grepStdout("FAIL", "go test did not say FAIL")
}
func TestWildcardsDoNotLookInUselessDirectories(t *testing.T) {
@ -2150,6 +1902,17 @@ func homeEnvName() string {
}
}
func tempEnvName() string {
switch runtime.GOOS {
case "windows":
return "TMP"
case "plan9":
return "TMPDIR" // actually plan 9 doesn't have one at all but this is fine
default:
return "TMPDIR"
}
}
func TestDefaultGOPATH(t *testing.T) {
t.Skip("vgo") // Needs a more realistic GOROOT; see RuntimeGoroot below.
@ -2799,6 +2562,8 @@ func TestTestBuildFailureOutput(t *testing.T) {
}
func TestCoverageFunc(t *testing.T) {
t.Skip("vgo")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
@ -3130,7 +2895,6 @@ func TestIssue7573(t *testing.T) {
if _, err := exec.LookPath("gccgo"); err != nil {
t.Skip("skipping because no gccgo compiler found")
}
t.Skip("golang.org/issue/22472")
tg := testgo(t)
defer tg.cleanup()
@ -3324,43 +3088,6 @@ func TestGoTestBuildsAnXtestContainingOnlyNonRunnableExamples(t *testing.T) {
tg.grepStdout("File with non-runnable example was built.", "file with non-runnable example was not built")
}
// issue 24570
func TestGoTestCoverMultiPackage(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.run("test", "-cover", "./testdata/testcover/...")
tg.grepStdout(`\?.*testdata/testcover/pkg1.*(\d\.\d\d\ds|cached).*coverage:.*0\.0% of statements \[no test files\]`, "expected [no test files] for pkg1")
tg.grepStdout(`ok.*testdata/testcover/pkg2.*(\d\.\d\d\ds|cached).*coverage:.*0\.0% of statements \[no tests to run\]`, "expected [no tests to run] for pkg2")
tg.grepStdout(`ok.*testdata/testcover/pkg3.*(\d\.\d\d\ds|cached).*coverage:.*100\.0% of statements`, "expected 100% coverage for pkg3")
}
// issue 24570
func TestGoTestCoverprofileMultiPackage(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.creatingTemp("testdata/cover.out")
tg.run("test", "-coverprofile=testdata/cover.out", "./testdata/testcover/...")
tg.grepStdout(`\?.*testdata/testcover/pkg1.*(\d\.\d\d\ds|cached).*coverage:.*0\.0% of statements \[no test files\]`, "expected [no test files] for pkg1")
tg.grepStdout(`ok.*testdata/testcover/pkg2.*(\d\.\d\d\ds|cached).*coverage:.*0\.0% of statements \[no tests to run\]`, "expected [no tests to run] for pkg2")
tg.grepStdout(`ok.*testdata/testcover/pkg3.*(\d\.\d\d\ds|cached).*coverage:.*100\.0% of statements`, "expected 100% coverage for pkg3")
if out, err := ioutil.ReadFile("testdata/cover.out"); err != nil {
t.Error(err)
} else {
if !bytes.Contains(out, []byte("mode: set")) {
t.Errorf(`missing "mode: set" in %s`, out)
}
if !bytes.Contains(out, []byte(`pkg1/a.go:5.10,7.2 1 0`)) && !bytes.Contains(out, []byte(`pkg1\a.go:5.10,7.2 1 0`)) {
t.Errorf(`missing "pkg1/a.go:5.10,7.2 1 0" in %s`, out)
}
if !bytes.Contains(out, []byte(`pkg2/a.go:5.10,7.2 1 0`)) && !bytes.Contains(out, []byte(`pkg2\a.go:5.10,7.2 1 0`)) {
t.Errorf(`missing "pkg2/a.go:5.10,7.2 1 0" in %s`, out)
}
if !bytes.Contains(out, []byte(`pkg3/a.go:5.10,7.2 1 1`)) && !bytes.Contains(out, []byte(`pkg3\a.go:5.10,7.2 1 1`)) {
t.Errorf(`missing "pkg3/a.go:5.10,7.2 1 1" in %s`, out)
}
}
}
func TestGoGenerateHandlesSimpleCommand(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("skipping because windows has no echo command")
@ -5384,81 +5111,6 @@ func TestQEMUUserMode(t *testing.T) {
}
func TestGOTMPDIR(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.makeTempdir()
tg.setenv("GOTMPDIR", tg.tempdir)
tg.setenv("GOCACHE", "off")
// complex/x is a trivial non-main package.
tg.run("build", "-work", "-x", "complex/w")
tg.grepStderr("WORK="+regexp.QuoteMeta(tg.tempdir), "did not work in $GOTMPDIR")
}
func TestBuildCache(t *testing.T) {
tooSlow(t)
if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") {
t.Skip("GODEBUG gocacheverify")
}
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.makeTempdir()
tg.setenv("GOCACHE", tg.tempdir)
// complex/w is a trivial non-main package.
// It imports nothing, so there should be no Deps.
tg.run("list", "-f={{join .Deps \" \"}}", "complex/w")
tg.grepStdoutNot(".+", "complex/w depends on unexpected packages")
tg.run("build", "-x", "complex/w")
tg.grepStderr(`[\\/]compile|gccgo`, "did not run compiler")
tg.run("build", "-x", "complex/w")
tg.grepStderrNot(`[\\/]compile|gccgo`, "ran compiler incorrectly")
tg.run("build", "-a", "-x", "complex/w")
tg.grepStderr(`[\\/]compile|gccgo`, "did not run compiler with -a")
// complex is a non-trivial main package.
// the link step should not be cached.
tg.run("build", "-o", os.DevNull, "-x", "complex")
tg.grepStderr(`[\\/]link|gccgo`, "did not run linker")
tg.run("build", "-o", os.DevNull, "-x", "complex")
tg.grepStderr(`[\\/]link|gccgo`, "did not run linker")
}
func TestCacheOutput(t *testing.T) {
// Test that command output is cached and replayed too.
if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") {
t.Skip("GODEBUG gocacheverify")
}
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.makeTempdir()
tg.setenv("GOCACHE", tg.tempdir)
tg.run("build", "-gcflags=-m", "errors")
stdout1 := tg.getStdout()
stderr1 := tg.getStderr()
tg.run("build", "-gcflags=-m", "errors")
stdout2 := tg.getStdout()
stderr2 := tg.getStderr()
if stdout2 != stdout1 || stderr2 != stderr1 {
t.Errorf("cache did not reproduce output:\n\nstdout1:\n%s\n\nstdout2:\n%s\n\nstderr1:\n%s\n\nstderr2:\n%s",
stdout1, stdout2, stderr1, stderr2)
}
}
func TestCacheListStale(t *testing.T) {
tooSlow(t)
if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") {
@ -5895,6 +5547,11 @@ func TestTestVet(t *testing.T) {
tg.runFail("test", "vetfail/...")
tg.grepStderr(`Printf format %d`, "did not diagnose bad Printf")
tg.grepStdout(`ok\s+vetfail/p2`, "did not run vetfail/p2")
// Use -a so that we need to recompute the vet-specific export data for
// vetfail/p1.
tg.run("test", "-a", "vetfail/p2")
tg.grepStderrNot(`invalid.*constraint`, "did diagnose bad build constraint in vetxonly mode")
}
func TestTestVetRebuild(t *testing.T) {
@ -6414,6 +6071,30 @@ echo $* >>`+tg.path("pkg-config.out"))
}
}
func TestCgoCache(t *testing.T) {
if !canCgo {
t.Skip("no cgo")
}
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempFile("src/x/a.go", `package main
// #ifndef VAL
// #define VAL 0
// #endif
// int val = VAL;
import "C"
import "fmt"
func main() { fmt.Println(C.val) }
`)
tg.setenv("GOPATH", tg.path("."))
exe := tg.path("x.exe")
tg.run("build", "-o", exe, "x")
tg.setenv("CGO_LDFLAGS", "-lnosuchlibraryexists")
tg.runFail("build", "-o", exe, "x")
tg.grepStderr(`nosuchlibraryexists`, "did not run linker with changed CGO_LDFLAGS")
}
// Issue 23982
func TestFilepathUnderCwdFormat(t *testing.T) {
tg := testgo(t)
@ -6450,15 +6131,14 @@ func TestNoRelativeTmpdir(t *testing.T) {
tg.setenv("GOCACHE", "off")
tg.setenv("GOPATH", tg.path("."))
tg.setenv("GOTMPDIR", "tmp")
tg.runFail("build", "a")
tg.grepStderr("relative tmpdir", "wrong error")
tg.run("build", "-work", "a")
tg.grepStderr("WORK=[^t]", "work should be absolute path")
if runtime.GOOS != "windows" && runtime.GOOS != "plan9" {
tg.unsetenv("GOTMPDIR")
tg.setenv("TMPDIR", "tmp")
tg.runFail("build", "a")
tg.grepStderr("relative tmpdir", "wrong error")
}
tg.setenv("TMP", "tmp") // windows
tg.setenv("TMPDIR", "tmp") // unix
tg.run("build", "-work", "a")
tg.grepStderr("WORK=[^t]", "work should be absolute path")
}
// Issue 24704.
@ -6542,6 +6222,16 @@ func TestCDAndGOPATHAreDifferent(t *testing.T) {
}
}
// Issue 26242.
func TestGoTestWithoutTests(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.run("test", "testnorun")
tg.grepStdout(`testnorun\t\[no test files\]`, "do not want test to run")
}
// Issue 25579.
func TestGoBuildDashODevNull(t *testing.T) {
tg := testgo(t)
@ -6552,3 +6242,23 @@ func TestGoBuildDashODevNull(t *testing.T) {
tg.mustNotExist("hello")
tg.mustNotExist("hello.exe")
}
// Issue 25093.
func TestCoverpkgTestOnly(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempFile("src/a/a.go", `package a
func F(i int) int {
return i*i
}`)
tg.tempFile("src/atest/a_test.go", `
package a_test
import ( "a"; "testing" )
func TestF(t *testing.T) { a.F(2) }
`)
tg.setenv("GOPATH", tg.path("."))
tg.run("test", "-coverpkg=a", "atest")
tg.grepStderrNot("no packages being tested depend on matches", "bad match message")
tg.grepStdout("coverage: 100", "no coverage")
}

33
vendor/cmd/go/internal/cache/default.go поставляемый
Просмотреть файл

@ -35,12 +35,14 @@ See golang.org to learn more about Go.
// initDefaultCache does the work of finding the default cache
// the first time Default is called.
func initDefaultCache() {
dir := DefaultDir()
dir, showWarnings := defaultDir()
if dir == "off" {
return
}
if err := os.MkdirAll(dir, 0777); err != nil {
if showWarnings {
fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err)
}
return
}
if _, err := os.Stat(filepath.Join(dir, "README")); err != nil {
@ -50,7 +52,9 @@ func initDefaultCache() {
c, err := Open(dir)
if err != nil {
if showWarnings {
fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err)
}
return
}
defaultCache = c
@ -59,14 +63,24 @@ func initDefaultCache() {
// DefaultDir returns the effective GOCACHE setting.
// It returns "off" if the cache is disabled.
func DefaultDir() string {
dir, _ := defaultDir()
return dir
}
// defaultDir returns the effective GOCACHE setting.
// It returns "off" if the cache is disabled.
// The second return value reports whether warnings should
// be shown if the cache fails to initialize.
func defaultDir() (string, bool) {
dir := os.Getenv("GOCACHE")
if dir != "" {
return dir
return dir, true
}
// Compute default location.
// TODO(rsc): This code belongs somewhere else,
// like maybe ioutil.CacheDir or os.CacheDir.
showWarnings := true
switch runtime.GOOS {
case "windows":
dir = os.Getenv("LocalAppData")
@ -76,20 +90,20 @@ func DefaultDir() string {
dir = os.Getenv("AppData")
}
if dir == "" {
return "off"
return "off", true
}
case "darwin":
dir = os.Getenv("HOME")
if dir == "" {
return "off"
return "off", true
}
dir += "/Library/Caches"
case "plan9":
dir = os.Getenv("home")
if dir == "" {
return "off"
return "off", true
}
// Plan 9 has no established per-user cache directory,
// but $home/lib/xyz is the usual equivalent of $HOME/.xyz on Unix.
@ -101,10 +115,15 @@ func DefaultDir() string {
if dir == "" {
dir = os.Getenv("HOME")
if dir == "" {
return "off"
return "off", true
}
if dir == "/" {
// probably docker run with -u flag
// https://golang.org/issue/26280
showWarnings = false
}
dir += "/.cache"
}
}
return filepath.Join(dir, "go-build")
return filepath.Join(dir, "go-build"), showWarnings
}

67
vendor/cmd/go/internal/cache/default_unix_test.go поставляемый Normal file
Просмотреть файл

@ -0,0 +1,67 @@
// 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.
// +build !windows,!darwin,!plan9
package cache
import (
"os"
"strings"
"testing"
)
func TestDefaultDir(t *testing.T) {
goCacheDir := "/tmp/test-go-cache"
xdgCacheDir := "/tmp/test-xdg-cache"
homeDir := "/tmp/test-home"
// undo env changes when finished
defer func(GOCACHE, XDG_CACHE_HOME, HOME string) {
os.Setenv("GOCACHE", GOCACHE)
os.Setenv("XDG_CACHE_HOME", XDG_CACHE_HOME)
os.Setenv("HOME", HOME)
}(os.Getenv("GOCACHE"), os.Getenv("XDG_CACHE_HOME"), os.Getenv("HOME"))
os.Setenv("GOCACHE", goCacheDir)
os.Setenv("XDG_CACHE_HOME", xdgCacheDir)
os.Setenv("HOME", homeDir)
dir, showWarnings := defaultDir()
if dir != goCacheDir {
t.Errorf("Cache DefaultDir %q should be $GOCACHE %q", dir, goCacheDir)
}
if !showWarnings {
t.Error("Warnings should be shown when $GOCACHE is set")
}
os.Unsetenv("GOCACHE")
dir, showWarnings = defaultDir()
if !strings.HasPrefix(dir, xdgCacheDir+"/") {
t.Errorf("Cache DefaultDir %q should be under $XDG_CACHE_HOME %q when $GOCACHE is unset", dir, xdgCacheDir)
}
if !showWarnings {
t.Error("Warnings should be shown when $XDG_CACHE_HOME is set")
}
os.Unsetenv("XDG_CACHE_HOME")
dir, showWarnings = defaultDir()
if !strings.HasPrefix(dir, homeDir+"/.cache/") {
t.Errorf("Cache DefaultDir %q should be under $HOME/.cache %q when $GOCACHE and $XDG_CACHE_HOME are unset", dir, homeDir+"/.cache")
}
if !showWarnings {
t.Error("Warnings should be shown when $HOME is not /")
}
os.Unsetenv("HOME")
if dir, _ := defaultDir(); dir != "off" {
t.Error("Cache not disabled when $GOCACHE, $XDG_CACHE_HOME, and $HOME are unset")
}
os.Setenv("HOME", "/")
if _, showWarnings := defaultDir(); showWarnings {
// https://golang.org/issue/26280
t.Error("Cache initalization warnings should be squelched when $GOCACHE and $XDG_CACHE_HOME are unset and $HOME is /")
}
}

12
vendor/cmd/go/internal/cfg/cfg.go поставляемый
Просмотреть файл

@ -74,6 +74,11 @@ var (
// in module-aware mode (as opposed to GOPATH mode).
// It is equal to modload.Enabled, but not all packages can import modload.
ModulesEnabled bool
// GoModInGOPATH records whether we've found a go.mod in GOPATH/src
// in GO111MODULE=auto mode. In that case, we don't use modules
// but people might expect us to, so 'go get' warns.
GoModInGOPATH string
)
func init() {
@ -182,6 +187,11 @@ func findGOROOT1() string {
return filepath.Clean(env)
}
def := filepath.Clean(runtime.GOROOT())
if runtime.Compiler == "gccgo" {
// gccgo has no real GOROOT, and it certainly doesn't
// depend on the executable's location.
return def
}
exe, err := os.Executable()
if err == nil {
exe, err = filepath.Abs(exe)
@ -231,6 +241,8 @@ func isSameDir(dir1, dir2 string) bool {
// It does this by looking for the path/pkg/tool directory,
// which is necessary for useful operation of the cmd/go tool,
// and is not typically present in a GOPATH.
//
// There is a copy of this code in x/tools/cmd/godoc/goroot.go.
func isGOROOT(path string) bool {
stat, err := os.Stat(filepath.Join(path, "pkg", "tool"))
if err != nil {

4
vendor/cmd/go/internal/cfg/zdefaultcc.go поставляемый
Просмотреть файл

@ -7,10 +7,10 @@ const DefaultPkgConfig = `pkg-config`
func DefaultCC(goos, goarch string) string {
switch goos + `/` + goarch {
}
return CC
return "clang"
}
func DefaultCXX(goos, goarch string) string {
switch goos + `/` + goarch {
}
return CXX
return "clang++"
}

1
vendor/cmd/go/internal/cfg/zosarch.go поставляемый
Просмотреть файл

@ -26,6 +26,7 @@ var OSArchSupportsCgo = map[string]bool{
"linux/mipsle": true,
"linux/ppc64": false,
"linux/ppc64le": true,
"linux/riscv64": true,
"linux/s390x": true,
"nacl/386": false,
"nacl/amd64p32": false,

32
vendor/cmd/go/internal/clean/clean.go поставляемый
Просмотреть файл

@ -17,11 +17,12 @@ import (
"cmd/go/internal/cache"
"cmd/go/internal/cfg"
"cmd/go/internal/load"
"cmd/go/internal/modfetch"
"cmd/go/internal/work"
)
var CmdClean = &base.Command{
UsageLine: "clean [-i] [-r] [-n] [-x] [-cache] [-testcache] [build flags] [packages]",
UsageLine: "clean [clean flags] [build flags] [packages]",
Short: "remove object files and cached files",
Long: `
Clean removes object files from package source directories.
@ -65,6 +66,10 @@ The -cache flag causes clean to remove the entire go build cache.
The -testcache flag causes clean to expire all test results in the
go build cache.
The -modcache flag causes clean to remove the entire module
download cache, including unpacked source code of versioned
dependencies.
For more about build flags, see 'go help build'.
For more about specifying packages, see 'go help packages'.
@ -75,6 +80,7 @@ var (
cleanI bool // clean -i flag
cleanR bool // clean -r flag
cleanCache bool // clean -cache flag
cleanModcache bool // clean -modcache flag
cleanTestcache bool // clean -testcache flag
)
@ -85,6 +91,7 @@ func init() {
CmdClean.Flag.BoolVar(&cleanI, "i", false, "")
CmdClean.Flag.BoolVar(&cleanR, "r", false, "")
CmdClean.Flag.BoolVar(&cleanCache, "cache", false, "")
CmdClean.Flag.BoolVar(&cleanModcache, "modcache", false, "")
CmdClean.Flag.BoolVar(&cleanTestcache, "testcache", false, "")
// -n and -x are important enough to be
@ -138,6 +145,29 @@ func runClean(cmd *base.Command, args []string) {
}
}
}
if cleanModcache {
if modfetch.SrcMod == "" {
base.Fatalf("go clean -modcache: no module cache")
}
if err := removeAll(modfetch.SrcMod); err != nil {
base.Errorf("go clean -modcache: %v", err)
}
}
}
func removeAll(dir string) error {
// Module cache has 0555 directories; make them writable in order to remove content.
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return nil // ignore errors walking in file system
}
if info.IsDir() {
os.Chmod(path, 0777)
}
return nil
})
return os.RemoveAll(dir)
}
var cleaned = map[*load.Package]bool{}

3
vendor/cmd/go/internal/envcmd/env.go поставляемый
Просмотреть файл

@ -63,9 +63,6 @@ func MkEnv() []cfg.EnvVar {
{Name: "GOROOT", Value: cfg.GOROOT},
{Name: "GOTMPDIR", Value: os.Getenv("GOTMPDIR")},
{Name: "GOTOOLDIR", Value: base.ToolDir},
// disable escape codes in clang errors
{Name: "TERM", Value: "dumb"},
}
if work.GccgoBin != "" {

6
vendor/cmd/go/internal/generate/generate.go поставляемый
Просмотреть файл

@ -48,6 +48,12 @@ that can be run locally. It must either be in the shell path
(gofmt), a fully qualified path (/usr/you/bin/mytool), or a
command alias, described below.
To convey to humans and machine tools that code is generated,
generated source should have a line early in the file that
matches the following regular expression (in Go syntax):
^// Code generated .* DO NOT EDIT\.$
Note that go generate does not parse the file, so lines that look
like directives in comments or multiline strings will be treated
as directives.

5
vendor/cmd/go/internal/get/get.go поставляемый
Просмотреть файл

@ -118,6 +118,11 @@ func runGet(cmd *base.Command, args []string) {
// Should not happen: main.go should install the separate module-enabled get code.
base.Fatalf("go get: modules not implemented")
}
if cfg.GoModInGOPATH != "" {
// Warn about not using modules with GO111MODULE=auto when go.mod exists.
// To silence the warning, users can set GO111MODULE=off.
fmt.Fprintf(os.Stderr, "go get: warning: modules disabled by GO111MODULE=auto in GOPATH/src;\n\tignoring %s;\n\tsee 'go help modules'\n", base.ShortPath(cfg.GoModInGOPATH))
}
work.BuildInit()

17
vendor/cmd/go/internal/get/pkg_test.go поставляемый
Просмотреть файл

@ -98,6 +98,23 @@ var parseMetaGoImportsTests = []struct {
IgnoreMod,
[]metaImport{{"chitin.io/chitin", "git", "https://github.com/chitin-io/chitin"}},
},
{
`<meta name="go-import" content="myitcv.io git https://github.com/myitcv/x">
<meta name="go-import" content="myitcv.io/blah2 mod https://raw.githubusercontent.com/myitcv/pubx/master">
`,
IgnoreMod,
[]metaImport{{"myitcv.io", "git", "https://github.com/myitcv/x"}},
},
{
`<meta name="go-import" content="myitcv.io git https://github.com/myitcv/x">
<meta name="go-import" content="myitcv.io/blah2 mod https://raw.githubusercontent.com/myitcv/pubx/master">
`,
PreferMod,
[]metaImport{
{"myitcv.io/blah2", "mod", "https://raw.githubusercontent.com/myitcv/pubx/master"},
{"myitcv.io", "git", "https://github.com/myitcv/x"},
},
},
}
func TestParseMetaGoImports(t *testing.T) {

8
vendor/cmd/go/internal/get/vcs.go поставляемый
Просмотреть файл

@ -948,7 +948,13 @@ func matchGoImport(imports []metaImport, importPath string) (metaImport, error)
continue
}
if match != -1 {
if match >= 0 {
if imports[match].VCS == "mod" && im.VCS != "mod" {
// All the mod entries precede all the non-mod entries.
// We have a mod entry and don't care about the rest,
// matching or not.
break
}
return metaImport{}, fmt.Errorf("multiple meta tags match import path %q", importPath)
}
match = i

16
vendor/cmd/go/internal/get/vcs_test.go поставляемый
Просмотреть файл

@ -401,6 +401,22 @@ func TestMatchGoImport(t *testing.T) {
path: "different.example.com/user/foo",
err: errors.New("meta tags do not match import path"),
},
{
imports: []metaImport{
{Prefix: "myitcv.io/blah2", VCS: "mod", RepoRoot: "https://raw.githubusercontent.com/myitcv/pubx/master"},
{Prefix: "myitcv.io", VCS: "git", RepoRoot: "https://github.com/myitcv/x"},
},
path: "myitcv.io/blah2/foo",
mi: metaImport{Prefix: "myitcv.io/blah2", VCS: "mod", RepoRoot: "https://raw.githubusercontent.com/myitcv/pubx/master"},
},
{
imports: []metaImport{
{Prefix: "myitcv.io/blah2", VCS: "mod", RepoRoot: "https://raw.githubusercontent.com/myitcv/pubx/master"},
{Prefix: "myitcv.io", VCS: "git", RepoRoot: "https://github.com/myitcv/x"},
},
path: "myitcv.io/other",
mi: metaImport{Prefix: "myitcv.io", VCS: "git", RepoRoot: "https://github.com/myitcv/x"},
},
}
for _, test := range tests {

2
vendor/cmd/go/internal/help/help.go поставляемый
Просмотреть файл

@ -39,7 +39,7 @@ func Help(args []string) {
fmt.Println("// Use of this source code is governed by a BSD-style")
fmt.Println("// license that can be found in the LICENSE file.")
fmt.Println()
fmt.Println("// DO NOT EDIT THIS FILE. GENERATED BY mkalldocs.sh.")
fmt.Println("// Code generated by mkalldocs.sh; DO NOT EDIT.")
fmt.Println("// Edit the documentation in other files and rerun mkalldocs.sh to generate this one.")
fmt.Println()
buf := new(bytes.Buffer)

35
vendor/cmd/go/internal/help/helpdoc.go поставляемый
Просмотреть файл

@ -195,6 +195,7 @@ using the named version control system, and then the path inside
that repository. The supported version control systems are:
Bazaar .bzr
Fossil .fossil
Git .git
Mercurial .hg
Subversion .svn
@ -238,7 +239,7 @@ The meta tag should appear as early in the file as possible.
In particular, it should appear before any raw JavaScript or CSS,
to avoid confusing the go command's restricted parser.
The vcs is one of "git", "hg", "svn", etc,
The vcs is one of "bzr", "fossil", "git", "hg", "svn".
The repo-root is the root of the version control system
containing a scheme and not containing a .vcs qualifier.
@ -260,12 +261,22 @@ the go tool will verify that https://example.org/?go-get=1 contains the
same meta tag and then git clone https://code.org/r/p/exproj into
GOPATH/src/example.org.
New downloaded packages are written to the first directory listed in the GOPATH
environment variable (For more details see: 'go help gopath').
When using GOPATH, downloaded packages are written to the first directory
listed in the GOPATH environment variable.
(See 'go help gopath-get' and 'go help gopath'.)
The go command attempts to download the version of the
package appropriate for the Go release being used.
Run 'go help get' for more.
When using modules, downloaded packages are stored in the module cache.
(See 'go help modules-get' and 'go help goproxy'.)
When using modules, an additional variant of the go-import meta tag is
recognized and is preferred over those listing version control systems.
That variant uses "mod" as the vcs in the content value, as in:
<meta name="go-import" content="example.org mod https://code.org/moduleproxy">
This tag means to fetch modules with paths beginning with example.org
from the module proxy available at the URL https://code.org/moduleproxy.
See 'go help goproxy' for details about the proxy protocol.
Import path checking
@ -288,6 +299,9 @@ Import path checking is disabled for code found within vendor trees.
This makes it possible to copy code into alternate locations in vendor trees
without needing to update import comments.
Import path checking is also disabled when using modules.
Import path comments are obsoleted by the go.mod file's module statement.
See https://golang.org/s/go14customimport for details.
`,
}
@ -360,6 +374,12 @@ in the list.
See https://golang.org/doc/code.html for an example.
GOPATH and Modules
When using modules, GOPATH is no longer used for resolving imports.
However, it is still used to store downloaded source code (in GOPATH/src/mod)
and compiled commands (in GOPATH/bin).
Internal Directories
Code in or below a directory named "internal" is importable only
@ -471,6 +491,8 @@ General-purpose environment variables:
Examples are linux, darwin, windows, netbsd.
GOPATH
For more details see: 'go help gopath'.
GOPROXY
URL of Go module proxy. See 'go help goproxy'.
GORACE
Options for the race detector.
See https://golang.org/doc/articles/race_detector.html.
@ -660,6 +682,7 @@ The default location for cache data is a subdirectory named go-build
in the standard user cache directory for the current operating system.
Setting the GOCACHE environment variable overrides this default,
and running 'go env GOCACHE' prints the current cache directory.
You can set the variable to 'off' to disable the cache.
The go command periodically deletes cached data that has not been
used recently. Running 'go clean -cache' deletes all cached data.

14
vendor/cmd/go/internal/imports/build.go поставляемый
Просмотреть файл

@ -183,27 +183,27 @@ func MatchFile(name string, tags map[string]bool) bool {
l = l[:n-1]
}
n := len(l)
if n >= 2 && knownOS[l[n-2]] && knownArch[l[n-1]] {
if n >= 2 && KnownOS[l[n-2]] && KnownArch[l[n-1]] {
return tags[l[n-2]] && tags[l[n-1]]
}
if n >= 1 && knownOS[l[n-1]] {
if n >= 1 && KnownOS[l[n-1]] {
return tags[l[n-1]]
}
if n >= 1 && knownArch[l[n-1]] {
if n >= 1 && KnownArch[l[n-1]] {
return tags[l[n-1]]
}
return true
}
var knownOS = make(map[string]bool)
var knownArch = make(map[string]bool)
var KnownOS = make(map[string]bool)
var KnownArch = make(map[string]bool)
func init() {
for _, v := range strings.Fields(goosList) {
knownOS[v] = true
KnownOS[v] = true
}
for _, v := range strings.Fields(goarchList) {
knownArch[v] = true
KnownArch[v] = true
}
}

5
vendor/cmd/go/internal/imports/scan_test.go поставляемый
Просмотреть файл

@ -5,6 +5,7 @@
package imports
import (
"internal/testenv"
"path/filepath"
"reflect"
"runtime"
@ -12,6 +13,8 @@ import (
)
func TestScan(t *testing.T) {
testenv.MustHaveGoBuild(t)
imports, testImports, err := ScanDir(filepath.Join(runtime.GOROOT(), "src/encoding/json"), Tags())
if err != nil {
t.Fatal(err)
@ -50,6 +53,8 @@ func TestScan(t *testing.T) {
}
func TestScanStar(t *testing.T) {
testenv.MustHaveGoBuild(t)
imports, _, err := ScanDir("testdata/import1", map[string]bool{"*": true})
if err != nil {
t.Fatal(err)

38
vendor/cmd/go/internal/list/list.go поставляемый
Просмотреть файл

@ -91,6 +91,7 @@ to -f '{{.ImportPath}}'. The struct being passed to the template is:
// Dependency information
Imports []string // import paths used by this package
ImportMap map[string]string // map from source import to ImportPath (identity entries omitted)
Deps []string // all (recursively) imported dependencies
TestImports []string // imports from TestGoFiles
XTestImports []string // imports from XTestGoFiles
@ -501,22 +502,30 @@ func runList(cmd *base.Command, args []string) {
// This must happen only once the build code is done
// looking at import paths, because it will get very confused
// if it sees these.
old := make(map[string]string)
for _, p := range all {
if p.ForTest != "" {
p.ImportPath += " [" + p.ForTest + ".test]"
new := p.ImportPath + " [" + p.ForTest + ".test]"
old[new] = p.ImportPath
p.ImportPath = new
}
p.DepOnly = !cmdline[p]
}
// Update import path lists to use new strings.
m := make(map[string]string)
for _, p := range all {
j := 0
for i := range p.Imports {
// Internal skips "C"
if p.Imports[i] == "C" {
continue
for _, p1 := range p.Internal.Imports {
if p1.ForTest != "" {
m[old[p1.ImportPath]] = p1.ImportPath
}
p.Imports[i] = p.Internal.Imports[j].ImportPath
j++
}
for i, old := range p.Imports {
if new := m[old]; new != "" {
p.Imports[i] = new
}
}
for old := range m {
delete(m, old)
}
}
// Recompute deps lists using new strings, from the leaves up.
@ -536,6 +545,19 @@ func runList(cmd *base.Command, args []string) {
}
}
// Record non-identity import mappings in p.ImportMap.
for _, p := range pkgs {
for i, srcPath := range p.Internal.RawImports {
path := p.Imports[i]
if path != srcPath {
if p.ImportMap == nil {
p.ImportMap = make(map[string]string)
}
p.ImportMap[srcPath] = path
}
}
}
for _, p := range pkgs {
do(&p.PackagePublic)
}

39
vendor/cmd/go/internal/load/pkg.go поставляемый
Просмотреть файл

@ -99,6 +99,7 @@ type PackagePublic struct {
// Dependency information
Imports []string `json:",omitempty"` // import paths used by this package
ImportMap map[string]string `json:",omitempty"` // map from source import to ImportPath (identity entries omitted)
Deps []string `json:",omitempty"` // all (recursively) imported dependencies
// Error information
@ -1595,7 +1596,7 @@ func (p *Package) UsesCgo() bool {
return len(p.CgoFiles) > 0
}
// packageList returns the list of packages in the dag rooted at roots
// PackageList returns the list of packages in the dag rooted at roots
// as visited in a depth-first post-order traversal.
func PackageList(roots []*Package) []*Package {
seen := map[*Package]bool{}
@ -1617,6 +1618,42 @@ func PackageList(roots []*Package) []*Package {
return all
}
// TestPackageList returns the list of packages in the dag rooted at roots
// as visited in a depth-first post-order traversal, including the test
// imports of the roots. This ignores errors in test packages.
func TestPackageList(roots []*Package) []*Package {
seen := map[*Package]bool{}
all := []*Package{}
var walk func(*Package)
walk = func(p *Package) {
if seen[p] {
return
}
seen[p] = true
for _, p1 := range p.Internal.Imports {
walk(p1)
}
all = append(all, p)
}
walkTest := func(root *Package, path string) {
var stk ImportStack
p1 := LoadImport(path, root.Dir, root, &stk, root.Internal.Build.TestImportPos[path], ResolveImport)
if p1.Error == nil {
walk(p1)
}
}
for _, root := range roots {
walk(root)
for _, path := range root.TestImports {
walkTest(root, path)
}
for _, path := range root.XTestImports {
walkTest(root, path)
}
}
return all
}
var cmdCache = map[string]*Package{}
func ClearCmdCache() {

9
vendor/cmd/go/internal/load/search.go поставляемый
Просмотреть файл

@ -6,6 +6,7 @@ package load
import (
"path/filepath"
"runtime"
"strings"
"cmd/go/internal/search"
@ -27,7 +28,13 @@ func MatchPackage(pattern, cwd string) func(*Package) bool {
}
dir = filepath.Join(cwd, dir)
if pattern == "" {
return func(p *Package) bool { return p.Dir == dir }
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)
}
}
matchPath := search.MatchPattern(pattern)
return func(p *Package) bool {

32
vendor/cmd/go/internal/load/test.go поставляемый
Просмотреть файл

@ -36,7 +36,7 @@ type TestCover struct {
Pkgs []*Package
Paths []string
Vars []coverInfo
DeclVars func(string, ...string) map[string]*CoverVar
DeclVars func(*Package, ...string) map[string]*CoverVar
}
// TestPackagesFor returns three packages:
@ -49,6 +49,9 @@ type TestCover struct {
// (for example, if there are no "package p" test files and
// package p need not be instrumented for coverage or any other reason),
// then the returned ptest == p.
//
// The caller is expected to have checked that len(p.TestGoFiles)+len(p.XTestGoFiles) > 0,
// or else there's no point in any of this.
func TestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Package, err error) {
var imports, ximports []*Package
var stk ImportStack
@ -111,16 +114,17 @@ func TestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Packag
ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
ptest.Target = ""
// Note: The preparation of the vet config requires that common
// indexes in ptest.Imports, ptest.Internal.Imports, and ptest.Internal.RawImports
// indexes in ptest.Imports and ptest.Internal.RawImports
// all line up (but RawImports can be shorter than the others).
// That is, for 0 ≤ i < len(RawImports),
// RawImports[i] is the import string in the program text,
// Imports[i] is the expanded import string (vendoring applied or relative path expanded away),
// and Internal.Imports[i] is the corresponding *Package.
// RawImports[i] is the import string in the program text, and
// Imports[i] is the expanded import string (vendoring applied or relative path expanded away).
// Any implicitly added imports appear in Imports and Internal.Imports
// but not RawImports (because they were not in the source code).
// We insert TestImports, imports, and rawTestImports at the start of
// these lists to preserve the alignment.
// Note that p.Internal.Imports may not be aligned with p.Imports/p.Internal.RawImports,
// but we insert at the beginning there too just for consistency.
ptest.Imports = str.StringList(p.TestImports, p.Imports)
ptest.Internal.Imports = append(imports, p.Internal.Imports...)
ptest.Internal.RawImports = str.StringList(rawTestImports, p.Internal.RawImports)
@ -178,6 +182,7 @@ func TestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Packag
GoFiles: []string{"_testmain.go"},
ImportPath: p.ImportPath + ".test",
Root: p.Root,
Imports: str.StringList(TestMainDeps),
},
Internal: PackageInternal{
Build: &build.Package{Name: "main"},
@ -233,13 +238,28 @@ func TestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Packag
t.Cover = cover
if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 {
pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
pmain.Imports = append(pmain.Imports, ptest.ImportPath)
t.ImportTest = true
}
if pxtest != nil {
pmain.Internal.Imports = append(pmain.Internal.Imports, pxtest)
pmain.Imports = append(pmain.Imports, pxtest.ImportPath)
t.ImportXtest = true
}
// Sort and dedup pmain.Imports.
// Only matters for go list -test output.
sort.Strings(pmain.Imports)
w := 0
for _, path := range pmain.Imports {
if w == 0 || path != pmain.Imports[w-1] {
pmain.Imports[w] = path
w++
}
}
pmain.Imports = pmain.Imports[:w]
pmain.Internal.RawImports = str.StringList(pmain.Imports)
if ptest != p {
// We have made modifications to the package p being tested
// and are rebuilding p (as ptest).
@ -261,7 +281,7 @@ func TestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Packag
var coverFiles []string
coverFiles = append(coverFiles, ptest.GoFiles...)
coverFiles = append(coverFiles, ptest.CgoFiles...)
ptest.Internal.CoverVars = cover.DeclVars(ptest.ImportPath, coverFiles...)
ptest.Internal.CoverVars = cover.DeclVars(ptest, coverFiles...)
}
for _, cp := range pmain.Internal.Imports {

30
vendor/cmd/go/internal/modcmd/mod.go поставляемый
Просмотреть файл

@ -14,6 +14,7 @@ import (
"strings"
"cmd/go/internal/base"
"cmd/go/internal/modfetch"
"cmd/go/internal/modfile"
"cmd/go/internal/modload"
"cmd/go/internal/module"
@ -154,7 +155,8 @@ effectively imply 'go mod -fix'.
The -sync flag synchronizes go.mod with the source code in the module.
It adds any missing modules necessary to build the current module's
packages and dependencies, and it removes unused modules that
don't provide any relevant packages.
don't provide any relevant packages. It also adds any missing entries
to go.sum and removes any unnecessary ones.
The -vendor flag resets the module's vendor directory to include all
packages needed to build and test all the module's packages.
@ -207,7 +209,7 @@ func init() {
func runMod(cmd *base.Command, args []string) {
if modload.Init(); !modload.Enabled() {
base.Fatalf("go mod: cannot use outside module")
base.Fatalf("go mod: cannot use outside module; see 'go help modules'")
}
if len(args) != 0 {
base.Fatalf("go mod: mod takes no arguments")
@ -291,6 +293,7 @@ func runMod(cmd *base.Command, args []string) {
}
}
modload.SetBuildList(keep)
modSyncGoSum() // updates memory copy; WriteGoMod on next line flushes it out
}
modload.WriteGoMod()
if *modVendor {
@ -400,7 +403,7 @@ func flagReplace(arg string) {
if i = strings.Index(arg, "="); i < 0 {
base.Fatalf("go mod: -replace=%s: need old@v=new[@v] (missing =)", arg)
}
old, new := strings.TrimSpace(arg[:i]), strings.TrimSpace(arg[i+2:])
old, new := strings.TrimSpace(arg[:i]), strings.TrimSpace(arg[i+1:])
if strings.HasPrefix(new, ">") {
base.Fatalf("go mod: -replace=%s: separator between old and new is =, not =>", arg)
}
@ -530,3 +533,24 @@ func modPrintGraph() {
}
w.Flush()
}
// modSyncGoSum resets the go.sum file content
// to be exactly what's needed for the current go.mod.
func modSyncGoSum() {
// Assuming go.sum already has at least enough from the successful load,
// we only have to tell modfetch what needs keeping.
reqs := modload.Reqs()
keep := make(map[module.Version]bool)
var walk func(module.Version)
walk = func(m module.Version) {
keep[m] = true
list, _ := reqs.Required(m)
for _, r := range list {
if !keep[r] {
walk(r)
}
}
}
walk(modload.Target)
modfetch.TrimGoSum(keep)
}

13
vendor/cmd/go/internal/modcmd/verify.go поставляемый
Просмотреть файл

@ -9,7 +9,6 @@ import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"cmd/go/internal/base"
"cmd/go/internal/dirhash"
@ -30,10 +29,14 @@ func runVerify() {
func verifyMod(mod module.Version) bool {
ok := true
zip := filepath.Join(modfetch.SrcMod, "cache/download", mod.Path, "/@v/", mod.Version+".zip")
_, zipErr := os.Stat(zip)
dir := filepath.Join(modfetch.SrcMod, mod.Path+"@"+mod.Version)
_, dirErr := os.Stat(dir)
zip, zipErr := modfetch.CachePath(mod, "zip")
if zipErr == nil {
_, zipErr = os.Stat(zip)
}
dir, dirErr := modfetch.DownloadDir(mod)
if dirErr == nil {
_, dirErr = os.Stat(dir)
}
data, err := ioutil.ReadFile(zip + "hash")
if err != nil {
if zipErr != nil && os.IsNotExist(zipErr) && dirErr != nil && os.IsNotExist(dirErr) {

5
vendor/cmd/go/internal/modconv/convert.go поставляемый
Просмотреть файл

@ -63,7 +63,10 @@ func ConvertLegacyConfig(f *modfile.File, file string, data []byte) error {
}
mu.Lock()
path := repo.ModulePath()
need[path] = semver.Max(need[path], info.Version)
// Don't use semver.Max here; need to preserve +incompatible suffix.
if v, ok := need[path]; !ok || semver.Compare(v, info.Version) < 0 {
need[path] = info.Version
}
mu.Unlock()
})

Просмотреть файл

@ -125,7 +125,7 @@ func TestConvertLegacyConfig(t *testing.T) {
cloud.google.com/go v0.18.0
github.com/fishy/fsdb v0.0.0-20180217030800-5527ded01371
github.com/golang/protobuf v1.0.0
github.com/googleapis/gax-go v0.0.0-20170915024731-317e0006254c
github.com/googleapis/gax-go v2.0.0+incompatible
golang.org/x/net v0.0.0-20180216171745-136a25c244d3
golang.org/x/oauth2 v0.0.0-20180207181906-543e37812f10
golang.org/x/text v0.0.0-20180208041248-4e4a3210bb54

55
vendor/cmd/go/internal/modfetch/cache.go поставляемый
Просмотреть файл

@ -15,6 +15,7 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/module"
"cmd/go/internal/par"
"cmd/go/internal/semver"
)
@ -23,6 +24,48 @@ var QuietLookup bool // do not print about lookups
var SrcMod string // $GOPATH/src/mod; set by package modload
func cacheDir(path string) (string, error) {
if SrcMod == "" {
return "", fmt.Errorf("internal error: modfetch.SrcMod not set")
}
enc, err := module.EncodePath(path)
if err != nil {
return "", err
}
return filepath.Join(SrcMod, "cache/download", enc, "/@v"), nil
}
func CachePath(m module.Version, suffix string) (string, error) {
dir, err := cacheDir(m.Path)
if err != nil {
return "", err
}
if !semver.IsValid(m.Version) {
return "", fmt.Errorf("non-semver module version %q", m.Version)
}
if module.CanonicalVersion(m.Version) != m.Version {
return "", fmt.Errorf("non-canonical module version %q", m.Version)
}
return filepath.Join(dir, m.Version+"."+suffix), nil
}
func DownloadDir(m module.Version) (string, error) {
if SrcMod == "" {
return "", fmt.Errorf("internal error: modfetch.SrcMod not set")
}
enc, err := module.EncodePath(m.Path)
if err != nil {
return "", err
}
if !semver.IsValid(m.Version) {
return "", fmt.Errorf("non-semver module version %q", m.Version)
}
if module.CanonicalVersion(m.Version) != m.Version {
return "", fmt.Errorf("non-canonical module version %q", m.Version)
}
return filepath.Join(SrcMod, enc+"@"+m.Version), nil
}
// A cachingRepo is a cache around an underlying Repo,
// avoiding redundant calls to ModulePath, Versions, Stat, Latest, and GoMod (but not Zip).
// It is also safe for simultaneous use by multiple goroutines
@ -245,7 +288,11 @@ func readDiskStatByHash(path, rev string) (file string, info *RevInfo, err error
return "", nil, errNotCached
}
rev = rev[:12]
dir, err := os.Open(filepath.Join(SrcMod, "cache/download", path, "@v"))
cdir, err := cacheDir(path)
if err != nil {
return "", nil, errNotCached
}
dir, err := os.Open(cdir)
if err != nil {
return "", nil, errNotCached
}
@ -296,10 +343,10 @@ func readDiskGoMod(path, rev string) (file string, data []byte, err error) {
// If the read fails, the caller can use
// writeDiskCache(file, data) to write a new cache entry.
func readDiskCache(path, rev, suffix string) (file string, data []byte, err error) {
if !semver.IsValid(rev) || SrcMod == "" {
file, err = CachePath(module.Version{Path: path, Version: rev}, suffix)
if err != nil {
return "", nil, errNotCached
}
file = filepath.Join(SrcMod, "cache/download", path, "@v", rev+"."+suffix)
data, err = ioutil.ReadFile(file)
if err != nil {
return file, nil, errNotCached
@ -386,7 +433,7 @@ func rewriteVersionList(dir string) {
name := info.Name()
if strings.HasSuffix(name, ".mod") {
v := strings.TrimSuffix(name, ".mod")
if semver.IsValid(v) && semver.Canonical(v) == v {
if v != "" && module.CanonicalVersion(v) == v {
list = append(list, v)
}
}

Просмотреть файл

@ -54,6 +54,21 @@ type Repo interface {
// os.IsNotExist(err) returns true.
ReadFile(rev, file string, maxSize int64) (data []byte, err error)
// ReadFileRevs reads a single file at multiple versions.
// It should refuse to read more than maxSize bytes.
// The result is a map from each requested rev strings
// to the associated FileRev. The map must have a non-nil
// entry for every requested rev (unless ReadFileRevs returned an error).
// A file simply being missing or even corrupted in revs[i]
// should be reported only in files[revs[i]].Err, not in the error result
// from ReadFileRevs.
// The overall call should return an error (and no map) only
// in the case of a problem with obtaining the data, such as
// a network failure.
// Implementations may assume that revs only contain tags,
// not direct commit hashes.
ReadFileRevs(revs []string, file string, maxSize int64) (files map[string]*FileRev, err error)
// ReadZip downloads a zip file for the subdir subdirectory
// of the given revision to a new file in a given temporary directory.
// It should refuse to read more than maxSize bytes.
@ -62,6 +77,15 @@ type Repo interface {
// contained in the zip file. All files in the zip file are expected to be
// nested in a single top-level directory, whose name is not specified.
ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser, actualSubdir string, err error)
// RecentTag returns the most recent tag at or before the given rev
// with the given prefix. It should make a best-effort attempt to
// find a tag that is a valid semantic version (following the prefix),
// or else the result is not useful to the caller, but it need not
// incur great expense in doing so. For example, the git implementation
// of RecentTag limits git's search to tags matching the glob expression
// "v[0-9]*.[0-9]*.[0-9]*" (after the prefix).
RecentTag(rev, prefix string) (tag string, err error)
}
// A Rev describes a single revision in a source code repository.
@ -73,6 +97,13 @@ type RevInfo struct {
Tags []string // known tags for commit
}
// A FileRev describes the result of reading a file at a given revision.
type FileRev struct {
Rev string // requested revision
Data []byte // file data
Err error // error if any; os.IsNotExist(Err)==true if rev exists but file does not exist in that rev
}
// AllHex reports whether the revision rev is entirely lower-case hexadecimal digits.
func AllHex(rev string) bool {
for i := 0; i < len(rev); i++ {
@ -167,6 +198,10 @@ var dirLock sync.Map
// a *RunError indicating the command, exit status, and standard error.
// Standard error is unavailable for commands that exit successfully.
func Run(dir string, cmdline ...interface{}) ([]byte, error) {
return RunWithStdin(dir, nil, cmdline...)
}
func RunWithStdin(dir string, stdin io.Reader, cmdline ...interface{}) ([]byte, error) {
if dir != "" {
muIface, ok := dirLock.Load(dir)
if !ok {
@ -196,6 +231,7 @@ func Run(dir string, cmdline ...interface{}) ([]byte, error) {
var stdout bytes.Buffer
c := exec.Command(cmd[0], cmd[1:]...)
c.Dir = dir
c.Stdin = stdin
c.Stderr = &stderr
c.Stdout = &stdout
err := c.Run()

Просмотреть файл

@ -245,10 +245,12 @@ func (r *gitRepo) stat(rev string) (*RevInfo, error) {
}
// Fast path: maybe rev is a hash we already have locally.
didStatLocal := false
if len(rev) >= minHashDigits && len(rev) <= 40 && AllHex(rev) {
if info, err := r.statLocal(rev, rev); err == nil {
return info, nil
}
didStatLocal = true
}
// Maybe rev is a tag we already have locally.
@ -308,11 +310,25 @@ func (r *gitRepo) stat(rev string) (*RevInfo, error) {
r.mu.Lock()
defer r.mu.Unlock()
// Perhaps r.localTags did not have the ref when we loaded local tags,
// but we've since done fetches that pulled down the hash we need
// (or already have the hash we need, just without its tag).
// Either way, try a local stat before falling back to network I/O.
if !didStatLocal {
if info, err := r.statLocal(rev, hash); err == nil {
if strings.HasPrefix(ref, "refs/tags/") {
// Make sure tag exists, so it will be in localTags next time the go command is run.
Run(r.dir, "git", "tag", strings.TrimPrefix(ref, "refs/tags/"), hash)
}
return info, nil
}
}
// If we know a specific commit we need, fetch it.
if r.fetchLevel <= fetchSome && hash != "" && !r.local {
r.fetchLevel = fetchSome
var refspec string
if ref != "" && ref != "head" {
if ref != "" && ref != "HEAD" {
// If we do know the ref name, save the mapping locally
// so that (if it is a tag) it can show up in localTags
// on a future call. Also, some servers refuse to allow
@ -362,7 +378,7 @@ func (r *gitRepo) stat(rev string) (*RevInfo, error) {
// 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) {
out, err := Run(r.dir, "git", "log", "-n1", "--format=format:%H %ct %D", rev)
out, err := Run(r.dir, "git", "log", "-n1", "--format=format:%H %ct %D", "--no-show-signature", rev)
if err != nil {
return nil, fmt.Errorf("unknown revision %s", rev)
}
@ -438,6 +454,166 @@ func (r *gitRepo) ReadFile(rev, file string, maxSize int64) ([]byte, error) {
return out, nil
}
func (r *gitRepo) ReadFileRevs(revs []string, file string, maxSize int64) (map[string]*FileRev, error) {
// Create space to hold results.
files := make(map[string]*FileRev)
for _, rev := range revs {
f := &FileRev{Rev: rev}
files[rev] = f
}
// Collect locally-known revs.
need, err := r.readFileRevs(revs, file, files)
if err != nil {
return nil, err
}
if len(need) == 0 {
return files, nil
}
// Build list of known remote refs that might help.
var redo []string
r.refsOnce.Do(r.loadRefs)
if r.refsErr != nil {
return nil, r.refsErr
}
for _, tag := range need {
if r.refs["refs/tags/"+tag] != "" {
redo = append(redo, tag)
}
}
if len(redo) == 0 {
return files, nil
}
// Protect r.fetchLevel and the "fetch more and more" sequence.
// See stat method above.
r.mu.Lock()
defer r.mu.Unlock()
var refs []string
var protoFlag []string
var unshallowFlag []string
for _, tag := range redo {
refs = append(refs, "refs/tags/"+tag+":refs/tags/"+tag)
}
if len(refs) > 1 {
unshallowFlag = unshallow(r.dir)
if len(unshallowFlag) > 0 {
// 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.
protoFlag = []string{"-c", "protocol.version=0"}
}
}
if _, err := Run(r.dir, "git", protoFlag, "fetch", unshallowFlag, "-f", r.remote, refs); err != nil {
return nil, err
}
if _, err := r.readFileRevs(redo, file, files); err != nil {
return nil, err
}
return files, nil
}
func (r *gitRepo) readFileRevs(tags []string, file string, fileMap map[string]*FileRev) (missing []string, err error) {
var stdin bytes.Buffer
for _, tag := range tags {
fmt.Fprintf(&stdin, "refs/tags/%s\n", tag)
fmt.Fprintf(&stdin, "refs/tags/%s:%s\n", tag, file)
}
data, err := RunWithStdin(r.dir, &stdin, "git", "cat-file", "--batch")
if err != nil {
return nil, err
}
next := func() (typ string, body []byte, ok bool) {
var line string
i := bytes.IndexByte(data, '\n')
if i < 0 {
return "", nil, false
}
line, data = string(bytes.TrimSpace(data[:i])), data[i+1:]
if strings.HasSuffix(line, " missing") {
return "missing", nil, true
}
f := strings.Fields(line)
if len(f) != 3 {
return "", nil, false
}
n, err := strconv.Atoi(f[2])
if err != nil || n > len(data) {
return "", nil, false
}
body, data = data[:n], data[n:]
if len(data) > 0 && data[0] == '\r' {
data = data[1:]
}
if len(data) > 0 && data[0] == '\n' {
data = data[1:]
}
return f[1], body, true
}
badGit := func() ([]string, error) {
return nil, fmt.Errorf("malformed output from git cat-file --batch")
}
for _, tag := range tags {
commitType, _, ok := next()
if !ok {
return badGit()
}
fileType, fileData, ok := next()
if !ok {
return badGit()
}
f := fileMap[tag]
f.Data = nil
f.Err = nil
switch commitType {
default:
f.Err = fmt.Errorf("unexpected non-commit type %q for rev %s", commitType, tag)
case "missing":
// Note: f.Err must not satisfy os.IsNotExist. That's reserved for the file not existing in a valid commit.
f.Err = fmt.Errorf("no such rev %s", tag)
missing = append(missing, tag)
case "tag", "commit":
switch fileType {
default:
f.Err = &os.PathError{Path: tag + ":" + file, Op: "read", Err: fmt.Errorf("unexpected non-blob type %q", fileType)}
case "missing":
f.Err = &os.PathError{Path: tag + ":" + file, Op: "read", Err: os.ErrNotExist}
case "blob":
f.Data = fileData
}
}
}
if len(bytes.TrimSpace(data)) != 0 {
return badGit()
}
return missing, nil
}
func (r *gitRepo) RecentTag(rev, prefix string) (tag string, err error) {
_, 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)
if err != nil {
return "", err
}
return strings.TrimSpace(string(out)), nil
}
func (r *gitRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser, actualSubdir string, err error) {
// TODO: Use maxSize or drop it.
args := []string{}

Просмотреть файл

@ -7,6 +7,7 @@ package codehost
import (
"archive/zip"
"bytes"
"flag"
"fmt"
"internal/testenv"
"io/ioutil"
@ -22,6 +23,9 @@ import (
)
func TestMain(m *testing.M) {
// needed for initializing the test environment variables as testing.Short
// and HasExternalNetwork
flag.Parse()
os.Exit(testMain(m))
}

Двоичные данные
vendor/cmd/go/internal/modfetch/codehost/shell поставляемый Executable file

Двоичный файл не отображается.

Просмотреть файл

@ -325,6 +325,14 @@ func (r *vcsRepo) ReadFile(rev, file string, maxSize int64) ([]byte, error) {
return out, nil
}
func (r *vcsRepo) ReadFileRevs(revs []string, file string, maxSize int64) (map[string]*FileRev, error) {
return nil, fmt.Errorf("ReadFileRevs not implemented")
}
func (r *vcsRepo) RecentTag(rev, prefix string) (tag string, err error) {
return "", fmt.Errorf("RecentTags not implemented")
}
func (r *vcsRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser, actualSubdir string, err error) {
if rev == "latest" {
rev = r.cmd.latest

148
vendor/cmd/go/internal/modfetch/coderepo.go поставляемый
Просмотреть файл

@ -6,15 +6,12 @@ package modfetch
import (
"archive/zip"
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"path"
"regexp"
"strings"
"time"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/modfile"
@ -97,7 +94,9 @@ func (r *codeRepo) Versions(prefix string) ([]string, error) {
if err != nil {
return nil, err
}
list := []string{}
var incompatible []string
for _, tag := range tags {
if !strings.HasPrefix(tag, p) {
continue
@ -106,11 +105,34 @@ func (r *codeRepo) Versions(prefix string) ([]string, error) {
if r.codeDir != "" {
v = v[len(r.codeDir)+1:]
}
if !semver.IsValid(v) || v != semver.Canonical(v) || IsPseudoVersion(v) || !module.MatchPathMajor(v, r.pathMajor) {
if v == "" || v != module.CanonicalVersion(v) || IsPseudoVersion(v) {
continue
}
if !module.MatchPathMajor(v, r.pathMajor) {
if r.codeDir == "" && r.pathMajor == "" && semver.Major(v) > "v1" {
incompatible = append(incompatible, v)
}
continue
}
list = append(list, v)
}
if len(incompatible) > 0 {
// Check for later versions that were created not following semantic import versioning,
// as indicated by the absence of a go.mod file. Those versions can be addressed
// by referring to them with a +incompatible suffix, as in v17.0.0+incompatible.
files, err := r.code.ReadFileRevs(incompatible, "go.mod", codehost.MaxGoMod)
if err != nil {
return nil, err
}
for _, rev := range incompatible {
f := files[rev]
if os.IsNotExist(f.Err) {
list = append(list, rev+"+incompatible")
}
}
}
SortVersions(list)
return list, nil
}
@ -146,7 +168,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
}
// Determine version.
if semver.IsValid(statVers) && statVers == semver.Canonical(statVers) && module.MatchPathMajor(statVers, r.pathMajor) {
if module.CanonicalVersion(statVers) == statVers && module.MatchPathMajor(statVers, r.pathMajor) {
// The original call was repo.Stat(statVers), and requestedVersion is OK, so use it.
info2.Version = statVers
} else {
@ -157,27 +179,51 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
p = r.codeDir + "/"
}
tagOK := func(v string) bool {
// If this is a plain tag (no dir/ prefix)
// and the module path is unversioned,
// and if the underlying file tree has no go.mod,
// then allow using the tag with a +incompatible suffix.
canUseIncompatible := false
if r.codeDir == "" && r.pathMajor == "" {
_, errGoMod := r.code.ReadFile(info.Name, "go.mod", codehost.MaxGoMod)
if errGoMod != nil {
canUseIncompatible = true
}
}
tagToVersion := func(v string) string {
if !strings.HasPrefix(v, p) {
return false
return ""
}
v = v[len(p):]
return semver.IsValid(v) && v == semver.Canonical(v) && module.MatchPathMajor(v, r.pathMajor) && !IsPseudoVersion(v)
if module.CanonicalVersion(v) != v || IsPseudoVersion(v) {
return ""
}
if module.MatchPathMajor(v, r.pathMajor) {
return v
}
if canUseIncompatible {
return v + "+incompatible"
}
return ""
}
// If info.Version is OK, use it.
if tagOK(info.Version) {
info2.Version = info.Version[len(p):]
if v := tagToVersion(info.Version); v != "" {
info2.Version = v
} else {
// Otherwise look through all known tags for latest in semver ordering.
for _, tag := range info.Tags {
if tagOK(tag) && semver.Compare(info2.Version, tag[len(p):]) < 0 {
info2.Version = tag[len(p):]
if v := tagToVersion(tag); v != "" && semver.Compare(info2.Version, v) < 0 {
info2.Version = v
}
}
// Otherwise make a pseudo-version.
if info2.Version == "" {
info2.Version = PseudoVersion(r.pseudoMajor, info.Time, info.Short)
tag, _ := r.code.RecentTag(statVers, p)
v = tagToVersion(tag)
// TODO: Check that v is OK for r.pseudoMajor or else is OK for incompatible.
info2.Version = PseudoVersion(r.pseudoMajor, v, info.Time, info.Short)
}
}
}
@ -199,9 +245,11 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
func (r *codeRepo) revToRev(rev string) string {
if semver.IsValid(rev) {
if IsPseudoVersion(rev) {
i := strings.Index(rev, "-")
j := strings.Index(rev[i+1:], "-")
return rev[i+1+j+1:]
r, _ := PseudoVersionRev(rev)
return r
}
if semver.Build(rev) == "+incompatible" {
rev = rev[:len(rev)-len("+incompatible")]
}
if r.codeDir == "" {
return rev
@ -548,71 +596,3 @@ func isVendoredPackage(name string) bool {
}
return strings.Contains(name[i:], "/")
}
func PseudoVersion(major string, t time.Time, rev string) string {
if major == "" {
major = "v0"
}
return fmt.Sprintf("%s.0.0-%s-%s", major, t.UTC().Format("20060102150405"), rev)
}
var ErrNotPseudoVersion = errors.New("not a pseudo-version")
/*
func ParsePseudoVersion(repo Repo, version string) (rev string, err error) {
major := semver.Major(version)
if major == "" {
return "", ErrNotPseudoVersion
}
majorPrefix := major + ".0.0-"
if !strings.HasPrefix(version, majorPrefix) || !strings.Contains(version[len(majorPrefix):], "-") {
return "", ErrNotPseudoVersion
}
versionSuffix := version[len(majorPrefix):]
for i := 0; versionSuffix[i] != '-'; i++ {
c := versionSuffix[i]
if c < '0' || '9' < c {
return "", ErrNotPseudoVersion
}
}
rev = versionSuffix[strings.Index(versionSuffix, "-")+1:]
if rev == "" {
return "", ErrNotPseudoVersion
}
if proxyURL != "" {
return version, nil
}
fullRev, t, err := repo.CommitInfo(rev)
if err != nil {
return "", fmt.Errorf("unknown pseudo-version %s: loading %v: %v", version, rev, err)
}
v := PseudoVersion(major, t, repo.ShortRev(fullRev))
if v != version {
return "", fmt.Errorf("unknown pseudo-version %s: %v is %v", version, rev, v)
}
return fullRev, nil
}
*/
var pseudoVersionRE = regexp.MustCompile(`^v[0-9]+\.0\.0-[0-9]{14}-[A-Za-z0-9]+$`)
// IsPseudoVersion reports whether v is a pseudo-version.
func IsPseudoVersion(v string) bool {
return pseudoVersionRE.MatchString(v)
}
// PseudoVersionTime returns the time stamp of the pseudo-version v.
// It returns an error if v is not a pseudo-version or if the time stamp
// embedded in the pseudo-version is not a valid time.
func PseudoVersionTime(v string) (time.Time, error) {
if !IsPseudoVersion(v) {
return time.Time{}, fmt.Errorf("not a pseudo-version")
}
i := strings.Index(v, "-") + 1
j := i + strings.Index(v[i:], "-")
t, err := time.Parse("20060102150405", v[i:j])
if err != nil {
return time.Time{}, fmt.Errorf("malformed pseudo-version %q", v)
}
return t, nil
}

Просмотреть файл

@ -88,9 +88,9 @@ var codeRepoTests = []struct {
path: "github.com/rsc/vgotest1/v2",
rev: "v2.0.0",
version: "v2.0.0",
name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
short: "80d85c5d4d17",
time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
name: "45f53230a74ad275c7127e117ac46914c8126160",
short: "45f53230a74a",
time: time.Date(2018, 7, 19, 1, 21, 27, 0, time.UTC),
ziperr: "missing github.com/rsc/vgotest1/go.mod and .../v2/go.mod at revision v2.0.0",
},
{
@ -121,11 +121,11 @@ var codeRepoTests = []struct {
},
{
path: "github.com/rsc/vgotest1/v2",
rev: "80d85c5",
rev: "45f53230a",
version: "v2.0.0",
name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
short: "80d85c5d4d17",
time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
name: "45f53230a74ad275c7127e117ac46914c8126160",
short: "45f53230a74a",
time: time.Date(2018, 7, 19, 1, 21, 27, 0, time.UTC),
gomoderr: "missing github.com/rsc/vgotest1/go.mod and .../v2/go.mod at revision v2.0.0",
ziperr: "missing github.com/rsc/vgotest1/go.mod and .../v2/go.mod at revision v2.0.0",
},
@ -237,7 +237,7 @@ var codeRepoTests = []struct {
// redirect to googlesource
path: "golang.org/x/text",
rev: "4e4a3210bb",
version: "v0.0.0-20180208041248-4e4a3210bb54",
version: "v0.3.1-0.20180208041248-4e4a3210bb54",
name: "4e4a3210bb54bb31f6ab2cdca2edcc0b50c420c1",
short: "4e4a3210bb54",
time: time.Date(2018, 2, 8, 4, 12, 48, 0, time.UTC),
@ -459,6 +459,7 @@ var hgmap = map[string]string{
"2f615117ce481c8efef46e0cc0b4b4dccfac8fea": "879ea98f7743c8eff54f59a918f3a24123d1cf46",
"80d85c5d4d17598a0e9055e7c175a32b415d6128": "e125018e286a4b09061079a81e7b537070b7ff71",
"1f863feb76bc7029b78b21c5375644838962f88d": "bf63880162304a9337477f3858f5b7e255c75459",
"45f53230a74ad275c7127e117ac46914c8126160": "814fce58e83abd5bf2a13892e0b0e1198abefcd4",
}
func remap(name string, m map[string]string) string {
@ -486,10 +487,9 @@ var codeRepoVersionsTests = []struct {
prefix string
versions []string
}{
// TODO: Why do we allow a prefix here at all?
{
path: "github.com/rsc/vgotest1",
versions: []string{"v0.0.0", "v0.0.1", "v1.0.0", "v1.0.1", "v1.0.2", "v1.0.3", "v1.1.0"},
versions: []string{"v0.0.0", "v0.0.1", "v1.0.0", "v1.0.1", "v1.0.2", "v1.0.3", "v1.1.0", "v2.0.0+incompatible"},
},
{
path: "github.com/rsc/vgotest1",
@ -605,9 +605,15 @@ type fixedTagsRepo struct {
func (ch *fixedTagsRepo) Tags(string) ([]string, error) { return ch.tags, nil }
func (ch *fixedTagsRepo) Latest() (*codehost.RevInfo, error) { panic("not impl") }
func (ch *fixedTagsRepo) ReadFile(string, string, int64) ([]byte, error) { panic("not impl") }
func (ch *fixedTagsRepo) ReadFileRevs([]string, string, int64) (map[string]*codehost.FileRev, error) {
panic("not impl")
}
func (ch *fixedTagsRepo) ReadZip(string, string, int64) (io.ReadCloser, string, error) {
panic("not impl")
}
func (ch *fixedTagsRepo) RecentTag(string, string) (string, error) {
panic("not impl")
}
func (ch *fixedTagsRepo) Stat(string) (*codehost.RevInfo, error) { panic("not impl") }
func TestNonCanonicalSemver(t *testing.T) {

44
vendor/cmd/go/internal/modfetch/fetch.go поставляемый
Просмотреть файл

@ -41,17 +41,22 @@ func Download(mod module.Version) (dir string, err error) {
err error
}
c := downloadCache.Do(mod, func() interface{} {
modpath := mod.Path + "@" + mod.Version
dir = filepath.Join(SrcMod, modpath)
dir, err := DownloadDir(mod)
if err != nil {
return cached{"", err}
}
if files, _ := ioutil.ReadDir(dir); len(files) == 0 {
zipfile := filepath.Join(SrcMod, "cache/download", mod.Path, "@v", mod.Version+".zip")
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 src/mod/path was removed but not src/mod/cache/download.
fmt.Fprintf(os.Stderr, "go: extracting %s %s\n", mod.Path, mod.Version)
} else {
if err := os.MkdirAll(filepath.Join(SrcMod, "cache/download", mod.Path, "@v"), 0777); err != nil {
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)
@ -59,6 +64,7 @@ func Download(mod module.Version) (dir string, err error) {
return cached{"", err}
}
}
modpath := mod.Path + "@" + mod.Version
if err := Unzip(dir, zipfile, modpath, 0); err != nil {
fmt.Fprintf(os.Stderr, "-> %s\n", err)
return cached{"", err}
@ -201,7 +207,11 @@ func checkSum(mod module.Version) {
}
// Do the file I/O before acquiring the go.sum lock.
data, err := ioutil.ReadFile(filepath.Join(SrcMod, "cache/download", mod.Path, "@v", mod.Version+".ziphash"))
ziphash, err := CachePath(mod, "ziphash")
if err != nil {
base.Fatalf("go: verifying %s@%s: %v", mod.Path, mod.Version, err)
}
data, err := ioutil.ReadFile(ziphash)
if err != nil {
if os.IsNotExist(err) {
// This can happen if someone does rm -rf GOPATH/src/cache/download. So it goes.
@ -260,7 +270,11 @@ func Sum(mod module.Version) string {
return ""
}
data, err := ioutil.ReadFile(filepath.Join(SrcMod, "cache/download", mod.Path, "@v", mod.Version+".ziphash"))
ziphash, err := CachePath(mod, "ziphash")
if err != nil {
return ""
}
data, err := ioutil.ReadFile(ziphash)
if err != nil {
return ""
}
@ -300,3 +314,21 @@ func WriteGoSum() {
os.Remove(goSum.modverify)
}
}
// TrimGoSum trims go.sum to contain only the modules for which keep[m] is true.
func TrimGoSum(keep map[module.Version]bool) {
goSum.mu.Lock()
defer goSum.mu.Unlock()
if !initGoSum() {
return
}
for m := range goSum.m {
// If we're keeping x@v we also keep x@v/go.mod.
// Map x@v/go.mod back to x@v for the keep lookup.
noGoMod := module.Version{Path: m.Path, Version: strings.TrimSuffix(m.Version, "/go.mod")}
if !keep[m] && !keep[noGoMod] {
delete(goSum.m, m)
}
}
}

80
vendor/cmd/go/internal/modfetch/proxy.go поставляемый
Просмотреть файл

@ -14,19 +14,87 @@ import (
"strings"
"time"
"cmd/go/internal/base"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/module"
"cmd/go/internal/semver"
)
var HelpGoproxy = &base.Command{
UsageLine: "goproxy",
Short: "module proxy protocol",
Long: `
The go command by default downloads modules from version control systems
directly, just as 'go get' always has. If the GOPROXY environment variable
is set to the URL of a module proxy, the go command will instead fetch
all modules from that proxy. No matter the source of the modules, downloaded
modules must match existing entries in go.sum (see 'go help modules' for
discussion of verification).
A Go module proxy is any web server that can respond to GET requests for
URLs of a specified form. The requests have no query parameters, so even
a site serving from a fixed file system (including a file:/// URL)
can be a module proxy.
The GET requests sent to a Go module proxy are:
GET $GOPROXY/<module>/@v/list returns a list of all known versions of the
given module, one per line.
GET $GOPROXY/<module>/@v/<version>.info returns JSON-formatted metadata
about that version of the given module.
GET $GOPROXY/<module>/@v/<version>.mod returns the go.mod file
for that version of the given module.
GET $GOPROXY/<module>/@v/<version>.zip returns the zip archive
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
lower-case letter: github.com/Azure encodes as github.com/!azure.
The JSON-formatted metadata about a given module corresponds to
this Go data structure, which may be expanded in the future:
type Info struct {
Version string // version string
Time time.Time // commit time
}
The zip archive for a specific version of a given module is a
standard zip file that contains the file tree corresponding
to the module's source code and related files. The archive uses
slash-separated paths, and every file path in the archive must
begin with <module>@<version>/, where the module and version are
substituted directly, not case-encoded. The root of the module
file tree corresponds to the <module>@<version>/ prefix in the
archive.
Even when downloading directly from version control systems,
the go command synthesizes explicit info, mod, and zip files
and stores them in its local cache, $GOPATH/src/mod/cache/download,
the same as if it had downloaded them directly from a proxy.
The cache layout is the same as the proxy URL space, so
serving $GOPATH/src/mod/cache/download at (or copying it to)
https://example.com/proxy would let other users access those
cached module versions with GOPROXY=https://example.com/proxy.
`,
}
var proxyURL = os.Getenv("GOPROXY")
func lookupProxy(path string) (Repo, error) {
if strings.Contains(proxyURL, ",") {
return nil, fmt.Errorf("invalid $GOPROXY setting: cannot have comma")
}
u, err := url.Parse(proxyURL)
if err != nil || u.Scheme != "http" && u.Scheme != "https" && u.Scheme != "file" {
// Don't echo $GOPROXY back in case it has user:password in it (sigh).
return nil, fmt.Errorf("invalid $GOPROXY setting")
return nil, fmt.Errorf("invalid $GOPROXY setting: malformed URL or invalid scheme (must be http, https, file)")
}
return newProxyRepo(u.String(), path), nil
return newProxyRepo(u.String(), path)
}
type proxyRepo struct {
@ -34,8 +102,12 @@ type proxyRepo struct {
path string
}
func newProxyRepo(baseURL, path string) Repo {
return &proxyRepo{strings.TrimSuffix(baseURL, "/") + "/" + pathEscape(path), path}
func newProxyRepo(baseURL, path string) (Repo, error) {
enc, err := module.EncodePath(path)
if err != nil {
return nil, err
}
return &proxyRepo{strings.TrimSuffix(baseURL, "/") + "/" + pathEscape(enc), path}, nil
}
func (p *proxyRepo) ModulePath() string {

128
vendor/cmd/go/internal/modfetch/pseudo.go поставляемый Normal file
Просмотреть файл

@ -0,0 +1,128 @@
// 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.
// Pseudo-versions
//
// Code authors are expected to tag the revisions they want users to use,
// including prereleases. However, not all authors tag versions at all,
// and not all commits a user might want to try will have tags.
// A pseudo-version is a version with a special form that allows us to
// address an untagged commit and order that version with respect to
// other versions we might encounter.
//
// A pseudo-version takes one of the general forms:
//
// (1) vX.0.0-yyyymmddhhmmss-abcdef123456
// (2) vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456
// (3) vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456+incompatible
// (4) vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456
// (5) vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456+incompatible
//
// If there is no recently tagged version with the right major version vX,
// then form (1) is used, creating a space of pseudo-versions at the bottom
// of the vX version range, less than any tagged version, including the unlikely v0.0.0.
//
// If the most recent tagged version before the target commit is vX.Y.Z or vX.Y.Z+incompatible,
// then the pseudo-version uses form (2) or (3), making it a prerelease for the next
// possible semantic version after vX.Y.Z. The leading 0 segment in the prerelease string
// ensures that the pseudo-version compares less than possible future explicit prereleases
// like vX.Y.(Z+1)-rc1 or vX.Y.(Z+1)-1.
//
// If the most recent tagged version before the target commit is vX.Y.Z-pre or vX.Y.Z-pre+incompatible,
// then the pseudo-version uses form (4) or (5), making it a slightly later prerelease.
package modfetch
import (
"cmd/go/internal/semver"
"fmt"
"regexp"
"strings"
"time"
)
// PseudoVersion returns a pseudo-version for the given major version ("v1")
// preexisting older tagged version ("" or "v1.2.3" or "v1.2.3-pre"), revision time,
// and revision identifier (usually a 12-byte commit hash prefix).
func PseudoVersion(major, older string, t time.Time, rev string) string {
if major == "" {
major = "v0"
}
segment := fmt.Sprintf("%s-%s", t.UTC().Format("20060102150405"), rev)
build := semver.Build(older)
older = semver.Canonical(older)
if older == "" {
return major + ".0.0-" + segment // form (1)
}
if semver.Prerelease(older) != "" {
return older + ".0." + segment + build // form (4), (5)
}
// Form (2), (3).
// Extract patch from vMAJOR.MINOR.PATCH
v := older[:len(older)]
i := strings.LastIndex(v, ".") + 1
v, patch := v[:i], v[i:]
// Increment PATCH by adding 1 to decimal:
// scan right to left turning 9s to 0s until you find a digit to increment.
// (Number might exceed int64, but math/big is overkill.)
digits := []byte(patch)
for i = len(digits) - 1; i >= 0 && digits[i] == '9'; i-- {
digits[i] = '0'
}
if i >= 0 {
digits[i]++
} else {
// digits is all zeros
digits[0] = '1'
digits = append(digits, '0')
}
patch = string(digits)
// Reassemble.
return v + patch + "-0." + segment + build
}
var pseudoVersionRE = regexp.MustCompile(`^v[0-9]+\.(0\.0-|\d+\.\d+-([^+]*\.)?0\.)\d{14}-[A-Za-z0-9]+(\+incompatible)?$`)
// IsPseudoVersion reports whether v is a pseudo-version.
func IsPseudoVersion(v string) bool {
return strings.Count(v, "-") >= 2 && semver.IsValid(v) && pseudoVersionRE.MatchString(v)
}
// PseudoVersionTime returns the time stamp of the pseudo-version v.
// It returns an error if v is not a pseudo-version or if the time stamp
// embedded in the pseudo-version is not a valid time.
func PseudoVersionTime(v string) (time.Time, error) {
timestamp, _, err := parsePseudoVersion(v)
t, err := time.Parse("20060102150405", timestamp)
if err != nil {
return time.Time{}, fmt.Errorf("pseudo-version with malformed time %s: %q", timestamp, v)
}
return t, nil
}
// PseudoVersionRev returns the revision identifier of the pseudo-version v.
// It returns an error if v is not a pseudo-version.
func PseudoVersionRev(v string) (rev string, err error) {
_, rev, err = parsePseudoVersion(v)
return
}
func parsePseudoVersion(v string) (timestamp, rev string, err error) {
if !IsPseudoVersion(v) {
return "", "", fmt.Errorf("malformed pseudo-version %q", v)
}
v = strings.TrimSuffix(v, "+incompatible")
j := strings.LastIndex(v, "-")
v, rev = v[:j], v[j+1:]
i := strings.LastIndex(v, "-")
if j := strings.LastIndex(v, "."); j > i {
timestamp = v[j+1:]
} else {
timestamp = v[i+1:]
}
return timestamp, rev, nil
}

74
vendor/cmd/go/internal/modfetch/pseudo_test.go поставляемый Normal file
Просмотреть файл

@ -0,0 +1,74 @@
// 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 modfetch
import (
"testing"
"time"
)
var pseudoTests = []struct {
major string
older string
version string
}{
{"", "", "v0.0.0-20060102150405-hash"},
{"v0", "", "v0.0.0-20060102150405-hash"},
{"v1", "", "v1.0.0-20060102150405-hash"},
{"v2", "", "v2.0.0-20060102150405-hash"},
{"unused", "v0.0.0", "v0.0.1-0.20060102150405-hash"},
{"unused", "v1.2.3", "v1.2.4-0.20060102150405-hash"},
{"unused", "v1.2.99999999999999999", "v1.2.100000000000000000-0.20060102150405-hash"},
{"unused", "v1.2.3-pre", "v1.2.3-pre.0.20060102150405-hash"},
{"unused", "v1.3.0-pre", "v1.3.0-pre.0.20060102150405-hash"},
}
var pseudoTime = time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC)
func TestPseudoVersion(t *testing.T) {
for _, tt := range pseudoTests {
v := PseudoVersion(tt.major, tt.older, pseudoTime, "hash")
if v != tt.version {
t.Errorf("PseudoVersion(%q, %q, ...) = %v, want %v", tt.major, tt.older, v, tt.version)
}
}
}
func TestIsPseudoVersion(t *testing.T) {
for _, tt := range pseudoTests {
if !IsPseudoVersion(tt.version) {
t.Errorf("IsPseudoVersion(%q) = false, want true", tt.version)
}
if IsPseudoVersion(tt.older) {
t.Errorf("IsPseudoVersion(%q) = true, want false", tt.older)
}
}
}
func TestPseudoVersionTime(t *testing.T) {
for _, tt := range pseudoTests {
tm, err := PseudoVersionTime(tt.version)
if tm != pseudoTime || err != nil {
t.Errorf("PseudoVersionTime(%q) = %v, %v, want %v, nil", tt.version, tm.Format(time.RFC3339), err, pseudoTime.Format(time.RFC3339))
}
tm, err = PseudoVersionTime(tt.older)
if tm != (time.Time{}) || err == nil {
t.Errorf("PseudoVersionTime(%q) = %v, %v, want %v, error", tt.older, tm.Format(time.RFC3339), err, time.Time{}.Format(time.RFC3339))
}
}
}
func TestPseudoVersionRev(t *testing.T) {
for _, tt := range pseudoTests {
rev, err := PseudoVersionRev(tt.version)
if rev != "hash" || err != nil {
t.Errorf("PseudoVersionRev(%q) = %q, %v, want %q, nil", tt.older, rev, err, "hash")
}
rev, err = PseudoVersionRev(tt.older)
if rev != "" || err == nil {
t.Errorf("PseudoVersionRev(%q) = %q, %v, want %q, error", tt.older, rev, err, "")
}
}
}

2
vendor/cmd/go/internal/modfetch/repo.go поставляемый
Просмотреть файл

@ -218,7 +218,7 @@ func lookup(path string) (r Repo, err error) {
if rr.VCS == "mod" {
// Fetch module from proxy with base URL rr.Repo.
return newProxyRepo(rr.Repo, path), nil
return newProxyRepo(rr.Repo, path)
}
code, err := lookupCodeRepo(rr)

36
vendor/cmd/go/internal/modfetch/unzip.go поставляемый
Просмотреть файл

@ -10,11 +10,13 @@ import (
"io"
"io/ioutil"
"os"
"path"
"path/filepath"
"sort"
"strings"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/module"
"cmd/go/internal/str"
)
@ -48,7 +50,28 @@ func Unzip(dir, zipfile, prefix string, maxSize int64) error {
return fmt.Errorf("unzip %v: %s", zipfile, err)
}
// Check total size.
foldPath := make(map[string]string)
var checkFold func(string) error
checkFold = func(name string) error {
fold := str.ToFold(name)
if foldPath[fold] == name {
return nil
}
dir := path.Dir(name)
if dir != "." {
if err := checkFold(dir); err != nil {
return err
}
}
if foldPath[fold] == "" {
foldPath[fold] = name
return nil
}
other := foldPath[fold]
return fmt.Errorf("unzip %v: case-insensitive file name collision: %q and %q", zipfile, other, name)
}
// Check total size, valid file names.
var size int64
for _, zf := range z.File {
if !str.HasPathPrefix(zf.Name, prefix) {
@ -57,7 +80,14 @@ func Unzip(dir, zipfile, prefix string, maxSize int64) error {
if zf.Name == prefix || strings.HasSuffix(zf.Name, "/") {
continue
}
if filepath.Clean(zf.Name) != zf.Name || strings.HasPrefix(zf.Name[len(prefix)+1:], "/") {
name := zf.Name[len(prefix)+1:]
if err := module.CheckFilePath(name); err != nil {
return fmt.Errorf("unzip %v: %v", zipfile, err)
}
if err := checkFold(name); err != nil {
return err
}
if path.Clean(zf.Name) != zf.Name || strings.HasPrefix(zf.Name[len(prefix)+1:], "/") {
return fmt.Errorf("unzip %v: invalid file name %s", zipfile, zf.Name)
}
s := int64(zf.UncompressedSize64)
@ -116,7 +146,7 @@ func Unzip(dir, zipfile, prefix string, maxSize int64) error {
// Run over list backward to chmod children before parents.
for i := len(dirlist) - 1; i >= 0; i-- {
os.Chmod(dir, 0555)
os.Chmod(dirlist[i], 0555)
}
return nil

52
vendor/cmd/go/internal/modfile/rule.go поставляемый
Просмотреть файл

@ -167,13 +167,16 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f
fmt.Fprintf(errs, "%s:%d: invalid module version %q: %v\n", f.Syntax.Name, line.Start.Line, old, err)
return
}
v1, err := moduleMajorVersion(s)
pathMajor, err := modulePathMajor(s)
if err != nil {
fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err)
return
}
if v2 := semver.Major(v); v1 != v2 && (v1 != "v1" || v2 != "v0") {
fmt.Fprintf(errs, "%s:%d: invalid module: %s should be %s, not %s (%s)\n", f.Syntax.Name, line.Start.Line, s, v1, v2, v)
if !module.MatchPathMajor(v, pathMajor) {
if pathMajor == "" {
pathMajor = "v0 or v1"
}
fmt.Fprintf(errs, "%s:%d: invalid module: %s should be %s, not %s (%s)\n", f.Syntax.Name, line.Start.Line, s, pathMajor, semver.Major(v), v)
return
}
if verb == "require" {
@ -202,7 +205,7 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f
fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err)
return
}
v1, err := moduleMajorVersion(s)
pathMajor, err := modulePathMajor(s)
if err != nil {
fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err)
return
@ -215,8 +218,11 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f
fmt.Fprintf(errs, "%s:%d: invalid module version %v: %v\n", f.Syntax.Name, line.Start.Line, old, err)
return
}
if v2 := semver.Major(v); v1 != v2 && (v1 != "v1" || v2 != "v0") {
fmt.Fprintf(errs, "%s:%d: invalid module: %s should be %s, not %s (%s)\n", f.Syntax.Name, line.Start.Line, s, v1, v2, v)
if !module.MatchPathMajor(v, pathMajor) {
if pathMajor == "" {
pathMajor = "v0 or v1"
}
fmt.Fprintf(errs, "%s:%d: invalid module: %s should be %s, not %s (%s)\n", f.Syntax.Name, line.Start.Line, s, pathMajor, semver.Major(v), v)
return
}
}
@ -364,41 +370,21 @@ func parseVersion(path string, s *string, fix VersionFixer) (string, error) {
return "", err
}
}
if semver.IsValid(t) {
*s = semver.Canonical(t)
if v := module.CanonicalVersion(t); v != "" {
*s = v
return *s, nil
}
return "", fmt.Errorf("version must be of the form v1.2.3")
}
func moduleMajorVersion(p string) (string, error) {
if _, _, major, _, ok := ParseGopkgIn(p); ok {
func modulePathMajor(path string) (string, error) {
_, major, ok := module.SplitPathVersion(path)
if !ok {
return "", fmt.Errorf("invalid module path")
}
return major, nil
}
start := strings.LastIndex(p, "/") + 1
v := p[start:]
if !isMajorVersion(v) {
return "v1", nil
}
if v[1] == '0' || v == "v1" {
return "", fmt.Errorf("module path has invalid version number %s", v)
}
return v, nil
}
func isMajorVersion(v string) bool {
if len(v) < 2 || v[0] != 'v' {
return false
}
for i := 1; i < len(v); i++ {
if v[i] < '0' || '9' < v[i] {
return false
}
}
return true
}
func (f *File) Format() ([]byte, error) {
return Format(f.Syntax), nil
}

9
vendor/cmd/go/internal/modget/get.go поставляемый
Просмотреть файл

@ -356,16 +356,17 @@ func runGet(cmd *base.Command, args []string) {
}
lookup.Do(10, func(item interface{}) {
t := item.(*task)
if t.vers == "none" {
// Wait for downgrade step.
t.m = module.Version{Path: t.path, Version: "none"}
return
}
m, err := getQuery(t.path, t.vers, t.forceModulePath)
if err != nil {
base.Errorf("go get %v: %v", t.arg, err)
return
}
t.m = m
if t.vers == "none" {
// Wait for downgrade step.
return
}
// If there is no -u, then we don't need to upgrade the
// collected requirements separately from the overall
// recalculation of the build list (modload.ReloadBuildList below),

8
vendor/cmd/go/internal/modload/build.go поставляемый
Просмотреть файл

@ -12,7 +12,6 @@ import (
"cmd/go/internal/modinfo"
"cmd/go/internal/module"
"cmd/go/internal/search"
"cmd/go/internal/semver"
"encoding/hex"
"fmt"
"os"
@ -115,10 +114,9 @@ func moduleInfo(m module.Version, fromBuildList bool) *modinfo.ModulePublic {
m.Version = q.Version
m.Time = &q.Time
}
if semver.IsValid(m.Version) {
dir := filepath.Join(modfetch.SrcMod, m.Path+"@"+m.Version)
if stat, err := os.Stat(dir); err == nil && stat.IsDir() {
dir, err := modfetch.DownloadDir(module.Version{Path: m.Path, Version: m.Version})
if err == nil {
if info, err := os.Stat(dir); err == nil && info.IsDir() {
m.Dir = dir
}
}

72
vendor/cmd/go/internal/modload/help.go поставляемый
Просмотреть файл

@ -49,6 +49,10 @@ Module support is enabled only when the current directory is outside
GOPATH/src and itself contains a go.mod file or is below a directory
containing a go.mod file.
In module-aware mode, GOPATH no longer defines the meaning of imports
during a build, but it still stores downloaded dependencies (in GOPATH/src/mod)
and installed commands (in GOPATH/bin, unless GOBIN is set).
Defining a module
A module is defined by a tree of Go source files with a go.mod file
@ -176,13 +180,25 @@ the standard form for describing module versions, so that versions can be
compared to determine which should be considered earlier or later than another.
A module version like v1.2.3 is introduced by tagging a revision in the
underlying source repository. Untagged revisions can be referred to
using a "pseudo-version" of the form v0.0.0-yyyymmddhhmmss-abcdefabcdef,
using a "pseudo-version" like v0.0.0-yyyymmddhhmmss-abcdefabcdef,
where the time is the commit time in UTC and the final suffix is the prefix
of the commit hash. The time portion ensures that two pseudo-versions can
be compared to determine which happened later, the commit hash identifes
the underlying commit, and the v0.0.0- prefix identifies the pseudo-version
as a pre-release before version v0.0.0, so that the go command prefers any
tagged release over any pseudo-version.
the underlying commit, and the prefix (v0.0.0- in this example) is derived from
the most recent tagged version in the commit graph before this commit.
There are three pseudo-version forms:
vX.0.0-yyyymmddhhmmss-abcdefabcdef is used when there is no earlier
versioned commit with an appropriate major version before the target commit.
(This was originally the only form, so some older go.mod files use this form
even for commits that do follow tags.)
vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef is used when the most
recent versioned commit before the target commit is vX.Y.Z-pre.
vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef is used when the most
recent versioned commit before the target commit is vX.Y.Z.
Pseudo-versions never need to be typed by hand: the go command will accept
the plain commit hash and translate it into a pseudo-version (or a tagged
@ -233,7 +249,6 @@ For example, these commands are all valid:
go get github.com/gorilla/mux@c856192 # records v0.0.0-20180517173623-c85619274f5d
go get github.com/gorilla/mux@master # records current meaning of master
Module compatibility and semantic versioning
The go command requires that modules use semantic versions and expects that
@ -265,6 +280,11 @@ called "semantic import versioning". Pseudo-versions for modules with major
version v2 and later begin with that major version instead of v0, as in
v2.0.0-20180326061214-4fc5987536ef.
As a special case, module paths beginning with gopkg.in/ continue to use the
conventions established on that system: the major version is always present,
and it is preceded by a dot instead of a slash: gopkg.in/yaml.v1
and gopkg.in/yaml.v2, not gopkg.in/yaml and gopkg.in/yaml/v2.
The go command treats modules with different module paths as unrelated:
it makes no connection between example.com/m and example.com/m/v2.
Modules with different major versions can be used together in a build
@ -277,16 +297,35 @@ Major version v0 does not appear in the module path, because those
versions are preparation for v1.0.0, and v1 does not appear in the
module path either.
As a special case, for historical reasons, module paths beginning with
gopkg.in/ continue to use the conventions established on that system:
the major version is always present, and it is preceded by a dot
instead of a slash: gopkg.in/yaml.v1 and gopkg.in/yaml.v2, not
gopkg.in/yaml and gopkg.in/yaml/v2.
Code written before the semantic import versioning convention
was introduced may use major versions v2 and later to describe
the same set of unversioned import paths as used in v0 and v1.
To accommodate such code, if a source code repository has a
v2.0.0 or later tag for a file tree with no go.mod, the version is
considered to be part of the v1 module's available versions
and is given an +incompatible suffix when converted to a module
version, as in v2.0.0+incompatible. The +incompatible tag is also
applied to pseudo-versions derived from such versions, as in
v2.0.1-0.yyyymmddhhmmss-abcdefabcdef+incompatible.
See https://research.swtch.com/vgo-import and https://semver.org/
for more information.
In general, having a dependency in the build list (as reported by 'go list -m all')
on a v0 version, pre-release version, pseudo-version, or +incompatible version
is an indication that problems are more likely when upgrading that
dependency, since there is no expectation of compatibility for those.
Module verification
See https://research.swtch.com/vgo-import for more information about
semantic import versioning, and see https://semver.org/ for more about
semantic versioning.
Module code layout
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
go.mod, a file named go.sum containing the expected cryptographic checksums
@ -302,6 +341,13 @@ each command invocation. The 'go mod -verify' command checks that
the cached copies of module downloads still match both their recorded
checksums and the entries in go.sum.
The go command can fetch modules from a proxy instead of connecting
to source control systems directly, according to the setting of the GOPROXY
environment variable.
See 'go help goproxy' for details about the proxy and also the format of
the cached downloaded packages.
Modules and vendoring
When using modules, the go command completely ignores vendor directories.

39
vendor/cmd/go/internal/modload/init.go поставляемый
Просмотреть файл

@ -17,8 +17,6 @@ import (
"cmd/go/internal/module"
"cmd/go/internal/mvs"
"cmd/go/internal/search"
"cmd/go/internal/semver"
"cmd/go/internal/str"
"encoding/json"
"fmt"
"io/ioutil"
@ -97,8 +95,8 @@ func Init() {
}
// If this is testgo - the test binary during cmd/go tests -
// then do not let it look for a go.mod unless GO111MODULE has an explicit setting.
if base := filepath.Base(os.Args[0]); (base == "testgo" || base == "testgo.exe") && env == "" {
// then do not let it look for a go.mod unless GO111MODULE has an explicit setting or this is 'go mod -init'.
if base := filepath.Base(os.Args[0]); (base == "testgo" || base == "testgo.exe") && env == "" && !CmdModInit {
return
}
@ -135,25 +133,30 @@ func Init() {
base.Fatalf("go: %v", err)
}
if CmdModInit {
// Running 'go mod -init': go.mod will be created in current directory.
ModRoot = cwd
} else {
inGOPATH := false
for _, gopath := range filepath.SplitList(cfg.BuildContext.GOPATH) {
if gopath == "" {
continue
}
if str.HasFilePathPrefix(cwd, filepath.Join(gopath, "src")) {
if search.InDir(cwd, filepath.Join(gopath, "src")) != "" {
inGOPATH = true
break
}
}
if inGOPATH {
if !MustUseModules {
// No automatic enabling in GOPATH.
return
if inGOPATH && !MustUseModules && cfg.CmdName == "mod" {
base.Fatalf("go: modules disabled inside GOPATH/src by GO111MODULE=auto; see 'go help modules'")
}
if CmdModInit {
// Running 'go mod -init': go.mod will be created in current directory.
ModRoot = cwd
} else {
if inGOPATH && !MustUseModules {
// No automatic enabling in GOPATH.
if root, _ := FindModuleRoot(cwd, "", false); root != "" {
cfg.GoModInGOPATH = filepath.Join(root, "go.mod")
}
return
}
root, _ := FindModuleRoot(cwd, "", MustUseModules)
if root == "" {
@ -424,9 +427,11 @@ func FindModulePath(dir string) (string, error) {
// Look for path in GOPATH.
for _, gpdir := range filepath.SplitList(cfg.BuildContext.GOPATH) {
src := filepath.Join(gpdir, "src") + string(filepath.Separator)
if strings.HasPrefix(dir, src) {
return filepath.ToSlash(dir[len(src):]), nil
if gpdir == "" {
continue
}
if rel := search.InDir(dir, filepath.Join(gpdir, "src")); rel != "" && rel != "." {
return filepath.ToSlash(rel), nil
}
}
@ -513,7 +518,7 @@ func fixVersion(path, vers string) (string, error) {
if !ok {
return "", fmt.Errorf("malformed module path: %s", path)
}
if semver.IsValid(vers) && vers == semver.Canonical(vers) && module.MatchPathMajor(vers, pathMajor) {
if vers != "" && module.CanonicalVersion(vers) == vers && module.MatchPathMajor(vers, pathMajor) {
return vers, nil
}

6
vendor/cmd/go/internal/modload/query.go поставляемый
Просмотреть файл

@ -40,6 +40,7 @@ func Query(path, query string, allowed func(module.Version) bool) (*modfetch.Rev
return nil, fmt.Errorf("invalid semantic version %q in range %q", v, query)
}
var ok func(module.Version) bool
var prefix string
var preferOlder bool
switch {
case query == "latest":
@ -95,9 +96,10 @@ func Query(path, query string, allowed func(module.Version) bool) (*modfetch.Rev
ok = func(m module.Version) bool {
return matchSemverPrefix(query, m.Version) && allowed(m)
}
prefix = query + "."
case semver.IsValid(query):
vers := semver.Canonical(query)
vers := module.CanonicalVersion(query)
if !allowed(module.Version{Path: path, Version: vers}) {
return nil, fmt.Errorf("%s@%s excluded", path, vers)
}
@ -120,7 +122,7 @@ func Query(path, query string, allowed func(module.Version) bool) (*modfetch.Rev
if err != nil {
return nil, err
}
versions, err := repo.Versions("")
versions, err := repo.Versions(prefix)
if err != nil {
return nil, err
}

Просмотреть файл

@ -102,7 +102,7 @@ var queryTests = []struct {
{path: queryRepo, query: ">v1.9.9", vers: "v1.9.10-pre1"},
{path: queryRepo, query: ">v1.10.0", err: `no matching versions for query ">v1.10.0"`},
{path: queryRepo, query: ">=v1.10.0", err: `no matching versions for query ">=v1.10.0"`},
{path: queryRepo, query: "6cf84eb", vers: "v0.0.0-20180704023347-6cf84ebaea54"},
{path: queryRepo, query: "6cf84eb", vers: "v0.0.2-0.20180704023347-6cf84ebaea54"},
{path: queryRepo, query: "start", vers: "v0.0.0-20180704023101-5e9e31667ddf"},
{path: queryRepo, query: "7a1b6bf", vers: "v0.1.0"},

387
vendor/cmd/go/internal/module/module.go поставляемый
Просмотреть файл

@ -6,6 +6,17 @@
// along with support code.
package module
// IMPORTANT NOTE
//
// This file essentially defines the set of valid import paths for the go command.
// There are many subtle considerations, including Unicode ambiguity,
// security, network, and file system representations.
//
// This file also defines the set of valid module path and version combinations,
// another topic with many subtle considerations.
//
// Changes to the semantics in this file require approval from rsc.
import (
"fmt"
"sort"
@ -42,65 +53,77 @@ func Check(path, version string) error {
if !semver.IsValid(version) {
return fmt.Errorf("malformed semantic version %v", version)
}
vm := semver.Major(version)
_, pathVersion, _ := SplitPathVersion(path)
if strings.HasPrefix(pathVersion, ".") {
// Special-case gopkg.in path requirements.
pathVersion = pathVersion[1:] // cut .
if vm == pathVersion {
_, pathMajor, _ := SplitPathVersion(path)
if !MatchPathMajor(version, pathMajor) {
if pathMajor == "" {
pathMajor = "v0 or v1"
}
if pathMajor[0] == '.' { // .v1
pathMajor = pathMajor[1:]
}
return fmt.Errorf("mismatched module path %v and version %v (want %v)", path, version, pathMajor)
}
return nil
}
} else {
// Standard path requirements.
if pathVersion != "" {
pathVersion = pathVersion[1:] // cut /
}
if vm == "v0" || vm == "v1" {
vm = ""
}
if vm == pathVersion {
return nil
}
if pathVersion == "" {
pathVersion = "v0 or v1"
}
}
return fmt.Errorf("mismatched module path %v and version %v (want %v)", path, version, pathVersion)
}
// firstPathOK reports whether r can appear in the first element of a module path.
// The first element of the path must be an LDH domain name, at least for now.
// To avoid case ambiguity, the domain name must be entirely lower case.
func firstPathOK(r rune) bool {
return r == '-' || r == '.' ||
'0' <= r && r <= '9' ||
'A' <= r && r <= 'Z' ||
'a' <= r && r <= 'z'
}
// pathOK reports whether r can appear in a module path.
// Paths must avoid potentially problematic ASCII punctuation
// and control characters but otherwise can be any Unicode printable character,
// as defined by Go's IsPrint.
// pathOK reports whether r can appear in an import path element.
// Paths can be ASCII letters, ASCII digits, and limited ASCII punctuation: + - . _ and ~.
// This matches what "go get" has historically recognized in import paths.
// TODO(rsc): We would like to allow Unicode letters, but that requires additional
// care in the safe encoding (see note below).
func pathOK(r rune) bool {
if r < utf8.RuneSelf {
return r == '+' || r == ',' || r == '-' || r == '.' || r == '/' || r == '_' || r == '~' ||
return r == '+' || r == '-' || r == '.' || r == '_' || r == '~' ||
'0' <= r && r <= '9' ||
'A' <= r && r <= 'Z' ||
'a' <= r && r <= 'z'
}
return unicode.IsPrint(r)
return false
}
// fileNameOK reports whether r can appear in a file name.
// For now we allow all Unicode letters but otherwise limit to pathOK plus a few more punctuation characters.
// If we expand the set of allowed characters here, we have to
// work harder at detecting potential case-folding and normalization collisions.
// See note about "safe encoding" below.
func fileNameOK(r rune) bool {
if r < utf8.RuneSelf {
// Entire set of ASCII punctuation, from which we remove characters:
// ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
// We disallow some shell special characters: " ' * < > ? ` |
// (Note that some of those are disallowed by the Windows file system as well.)
// We also disallow path separators / : and \ (fileNameOK is only called on path element characters).
// We allow spaces (U+0020) in file names.
const allowed = "!#$%&()+,-.=@[]^_{}~ "
if '0' <= r && r <= '9' || 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' {
return true
}
for i := 0; i < len(allowed); i++ {
if rune(allowed[i]) == r {
return true
}
}
return false
}
// It may be OK to add more ASCII punctuation here, but only carefully.
// For example Windows disallows < > \, and macOS disallows :, so we must not allow those.
return unicode.IsLetter(r)
}
// CheckPath checks that a module path is valid.
func CheckPath(path string) error {
if !utf8.ValidString(path) {
return fmt.Errorf("malformed module path %q: invalid UTF-8", path)
if err := checkPath(path, false); err != nil {
return fmt.Errorf("malformed module path %q: %v", path, err)
}
if path == "" {
return fmt.Errorf("malformed module path %q: empty string", path)
}
i := strings.Index(path, "/")
if i < 0 {
i = len(path)
@ -111,40 +134,139 @@ func CheckPath(path string) error {
if !strings.Contains(path[:i], ".") {
return fmt.Errorf("malformed module path %q: missing dot in first path element", path)
}
if path[i-1] == '.' {
return fmt.Errorf("malformed module path %q: trailing dot in first path element", path)
}
if path[0] == '.' {
return fmt.Errorf("malformed module path %q: leading dot in first path element", path)
}
if path[0] == '-' {
return fmt.Errorf("malformed module path %q: leading dash in first path element", path)
}
if strings.Contains(path, "..") {
return fmt.Errorf("malformed module path %q: double dot", path)
}
if strings.Contains(path, "//") {
return fmt.Errorf("malformed module path %q: double slash", path)
}
for _, r := range path[:i] {
if !firstPathOK(r) {
return fmt.Errorf("malformed module path %q: invalid char %q in first path element", path, r)
}
}
if path[len(path)-1] == '/' {
return fmt.Errorf("malformed module path %q: trailing slash", path)
}
for _, r := range path {
if !pathOK(r) {
return fmt.Errorf("malformed module path %q: invalid char %q", path, r)
}
}
if _, _, ok := SplitPathVersion(path); !ok {
return fmt.Errorf("malformed module path %q: invalid version %s", path, path[strings.LastIndex(path, "/")+1:])
}
return nil
}
// CheckImportPath checks that an import path is valid.
func CheckImportPath(path string) error {
if err := checkPath(path, false); err != nil {
return fmt.Errorf("malformed import path %q: %v", path, err)
}
return nil
}
// checkPath checks that a general path is valid.
// It returns an error describing why but not mentioning path.
// Because these checks apply to both module paths and import paths,
// the caller is expected to add the "malformed ___ path %q: " prefix.
// fileName indicates whether the final element of the path is a file name
// (as opposed to a directory name).
func checkPath(path string, fileName bool) error {
if !utf8.ValidString(path) {
return fmt.Errorf("invalid UTF-8")
}
if path == "" {
return fmt.Errorf("empty string")
}
if strings.Contains(path, "..") {
return fmt.Errorf("double dot")
}
if strings.Contains(path, "//") {
return fmt.Errorf("double slash")
}
if path[len(path)-1] == '/' {
return fmt.Errorf("trailing slash")
}
elemStart := 0
for i, r := range path {
if r == '/' {
if err := checkElem(path[elemStart:i], fileName); err != nil {
return err
}
elemStart = i + 1
}
}
if err := checkElem(path[elemStart:], fileName); err != nil {
return err
}
return nil
}
// checkElem checks whether an individual path element is valid.
// fileName indicates whether the element is a file name (not a directory name).
func checkElem(elem string, fileName bool) error {
if elem == "" {
return fmt.Errorf("empty path element")
}
if strings.Count(elem, ".") == len(elem) {
return fmt.Errorf("invalid path element %q", elem)
}
if elem[0] == '.' && !fileName {
return fmt.Errorf("leading dot in path element")
}
if elem[len(elem)-1] == '.' {
return fmt.Errorf("trailing dot in path element")
}
charOK := pathOK
if fileName {
charOK = fileNameOK
}
for _, r := range elem {
if !charOK(r) {
return fmt.Errorf("invalid char %q", r)
}
}
// Windows disallows a bunch of path elements, sadly.
// See https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file
short := elem
if i := strings.Index(short, "."); i >= 0 {
short = short[:i]
}
for _, bad := range badWindowsNames {
if strings.EqualFold(bad, short) {
return fmt.Errorf("disallowed path element %q", elem)
}
}
return nil
}
// CheckFilePath checks whether a slash-separated file path is valid.
func CheckFilePath(path string) error {
if err := checkPath(path, true); err != nil {
return fmt.Errorf("malformed file path %q: %v", path, err)
}
return nil
}
// badWindowsNames are the reserved file path elements on Windows.
// See https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file
var badWindowsNames = []string{
"CON",
"PRN",
"AUX",
"NUL",
"COM1",
"COM2",
"COM3",
"COM4",
"COM5",
"COM6",
"COM7",
"COM8",
"COM9",
"LPT1",
"LPT2",
"LPT3",
"LPT4",
"LPT5",
"LPT6",
"LPT7",
"LPT8",
"LPT9",
}
// SplitPathVersion returns prefix and major version such that prefix+pathMajor == path
// and version is either empty or "/vN" for N >= 2.
// As a special case, gopkg.in paths are recognized directly;
@ -195,13 +317,28 @@ 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(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.
return true
}
m := semver.Major(v)
if pathMajor == "" {
return m == "v0" || m == "v1"
return m == "v0" || m == "v1" || semver.Build(v) == "+incompatible"
}
return (pathMajor[0] == '/' || pathMajor[0] == '.') && m == pathMajor[1:]
}
// CanonicalVersion returns the canonical form of the version string v.
// It is the same as semver.Canonical(v) except that it preserves the special build suffix "+incompatible".
func CanonicalVersion(v string) string {
cv := semver.Canonical(v)
if semver.Build(v) == "+incompatible" {
cv += "+incompatible"
}
return cv
}
// Sort sorts the list by Path, breaking ties by comparing Versions.
func Sort(list []Version) {
sort.Slice(list, func(i, j int) bool {
@ -228,3 +365,137 @@ func Sort(list []Version) {
return fi < fj
})
}
// Safe encodings
//
// Module paths appear as substrings of file system paths
// (in the download cache) and of web server URLs in the proxy protocol.
// In general we cannot rely on file systems to be case-sensitive,
// nor can we rely on web servers, since they read from file systems.
// That is, we cannot rely on the file system to keep rsc.io/QUOTE
// and rsc.io/quote separate. Windows and macOS don't.
// Instead, we must never require two different casings of a file path.
// Because we want the download cache to match the proxy protocol,
// and because we want the proxy protocol to be possible to serve
// from a tree of static files (which might be stored on a case-insensitive
// file system), the proxy protocol must never require two different casings
// of a URL path either.
//
// One possibility would be to make the safe encoding be the lowercase
// hexadecimal encoding of the actual path bytes. This would avoid ever
// needing different casings of a file path, but it would be fairly illegible
// to most programmers when those paths appeared in the file system
// (including in file paths in compiler errors and stack traces)
// in web server logs, and so on. Instead, we want a safe encoding that
// leaves most paths unaltered.
//
// The safe encoding is this:
// replace every uppercase letter with an exclamation mark
// followed by the letter's lowercase equivalent.
//
// For example,
// github.com/Azure/azure-sdk-for-go -> github.com/!azure/azure-sdk-for-go.
// github.com/GoogleCloudPlatform/cloudsql-proxy -> github.com/!google!cloud!platform/cloudsql-proxy
// github.com/Sirupsen/logrus -> github.com/!sirupsen/logrus.
//
// Import paths that avoid upper-case letters are left unchanged.
// Note that because import paths are ASCII-only and avoid various
// problematic punctuation (like : < and >), the safe encoding is also ASCII-only
// and avoids the same problematic punctuation.
//
// Import paths have never allowed exclamation marks, so there is no
// need to define how to encode a literal !.
//
// Although paths are disallowed from using Unicode (see pathOK above),
// the eventual plan is to allow Unicode letters as well, to assume that
// file systems and URLs are Unicode-safe (storing UTF-8), and apply
// the !-for-uppercase convention. Note however that not all runes that
// are different but case-fold equivalent are an upper/lower pair.
// For example, U+004B ('K'), U+006B ('k'), and U+212A ('' for Kelvin)
// are considered to case-fold to each other. When we do add Unicode
// letters, we must not assume that upper/lower are the only case-equivalent pairs.
// Perhaps the Kelvin symbol would be disallowed entirely, for example.
// Or perhaps it would encode as "!!k", or perhaps as "(212A)".
//
// Also, it would be nice to allow Unicode marks as well as letters,
// but marks include combining marks, and then we must deal not
// only with case folding but also normalization: both U+00E9 ('é')
// and U+0065 U+0301 ('e' followed by combining acute accent)
// look the same on the page and are treated by some file systems
// as the same path. If we do allow Unicode marks in paths, there
// must be some kind of normalization to allow only one canonical
// encoding of any character used in an import path.
// EncodePath returns the safe encoding of the given module path.
// It fails if the module path is invalid.
func EncodePath(path string) (encoding string, err error) {
if err := CheckPath(path); err != nil {
return "", err
}
haveUpper := false
for _, r := range path {
if r == '!' || r >= utf8.RuneSelf {
// This should be disallowed by CheckPath, but diagnose anyway.
// The correctness of the encoding loop below depends on it.
return "", fmt.Errorf("internal error: inconsistency in EncodePath")
}
if 'A' <= r && r <= 'Z' {
haveUpper = true
}
}
if !haveUpper {
return path, nil
}
var buf []byte
for _, r := range path {
if 'A' <= r && r <= 'Z' {
buf = append(buf, '!', byte(r+'a'-'A'))
} else {
buf = append(buf, byte(r))
}
}
return string(buf), nil
}
// DecodePath returns the module path of the given safe encoding.
// It fails if the encoding is invalid.
func DecodePath(encoding string) (path string, err error) {
var buf []byte
bang := false
for _, r := range encoding {
if r >= utf8.RuneSelf {
goto BadEncoding
}
if bang {
bang = false
if r < 'a' || 'z' < r {
goto BadEncoding
}
buf = append(buf, byte(r+'A'-'a'))
continue
}
if r == '!' {
bang = true
continue
}
if 'A' <= r && r <= 'Z' {
goto BadEncoding
}
buf = append(buf, byte(r))
}
if bang {
goto BadEncoding
}
path = string(buf)
if err := CheckPath(path); err != nil {
return "", fmt.Errorf("invalid module path encoding %q: %v", encoding, err)
}
return path, nil
BadEncoding:
return "", fmt.Errorf("invalid module path encoding %q", encoding)
}

294
vendor/cmd/go/internal/module/module_test.go поставляемый
Просмотреть файл

@ -37,10 +37,21 @@ var checkTests = []struct {
{"gopkg.in/yaml.v1", "v2.1.5", false},
{"gopkg.in/yaml.v1", "v3.0.0", false},
// For gopkg.in, .v1 means v1 only (not v0).
// But early versions of vgo still generated v0 pseudo-versions for it.
// Even though now we'd generate those as v1 pseudo-versions,
// we accept the old pseudo-versions to avoid breaking existing go.mod files.
// For example gopkg.in/yaml.v2@v2.2.1's go.mod requires check.v1 at a v0 pseudo-version.
{"gopkg.in/check.v1", "v0.0.0", false},
{"gopkg.in/check.v1", "v0.0.0-20160102150405-abcdef123456", true},
{"gopkg.in/yaml.v2", "v1.0.0", false},
{"gopkg.in/yaml.v2", "v2.0.0", true},
{"gopkg.in/yaml.v2", "v2.1.5", true},
{"gopkg.in/yaml.v2", "v3.0.0", false},
{"rsc.io/quote", "v17.0.0", false},
{"rsc.io/quote", "v17.0.0+incompatible", true},
}
func TestCheck(t *testing.T) {
@ -57,90 +68,118 @@ func TestCheck(t *testing.T) {
var checkPathTests = []struct {
path string
ok bool
importOK bool
fileOK bool
}{
{"x.y/z", true},
{"x.y", true},
{"x.y/z", true, true, true},
{"x.y", true, true, true},
{"", false},
{"x.y/\xFFz", false},
{"/x.y/z", false},
{"x./z", false},
{".x/z", false},
{"-x/z", false},
{"x..y/z", false},
{"x.y/z/../../w", false},
{"x.y//z", false},
{"x.y/z//w", false},
{"x.y/z/", false},
{"", false, false, false},
{"x.y/\xFFz", false, false, false},
{"/x.y/z", false, false, false},
{"x./z", false, false, false},
{".x/z", false, false, true},
{"-x/z", false, true, true},
{"x..y/z", false, false, false},
{"x.y/z/../../w", false, false, false},
{"x.y//z", false, false, false},
{"x.y/z//w", false, false, false},
{"x.y/z/", false, false, false},
{"x.y/z/v0", false},
{"x.y/z/v1", false},
{"x.y/z/v2", true},
{"x.y/z/v2.0", false},
{"x.y/z/v0", false, true, true},
{"x.y/z/v1", false, true, true},
{"x.y/z/v2", true, true, true},
{"x.y/z/v2.0", false, true, true},
{"X.y/z", false, true, true},
{"!x.y/z", false},
{"_x.y/z", false},
{"x.y!/z", false},
{"x.y\"/z", false},
{"x.y#/z", false},
{"x.y$/z", false},
{"x.y%/z", false},
{"x.y&/z", false},
{"x.y'/z", false},
{"x.y(/z", false},
{"x.y)/z", false},
{"x.y*/z", false},
{"x.y+/z", false},
{"x.y,/z", false},
{"x.y-/z", true},
{"x.y./zt", false},
{"x.y:/z", false},
{"x.y;/z", false},
{"x.y</z", false},
{"x.y=/z", false},
{"x.y>/z", false},
{"x.y?/z", false},
{"x.y@/z", false},
{"x.y[/z", false},
{"x.y\\/z", false},
{"x.y]/z", false},
{"x.y^/z", false},
{"x.y_/z", false},
{"x.y`/z", false},
{"x.y{/z", false},
{"x.y}/z", false},
{"x.y~/z", false},
{"x.y/z!", false},
{"x.y/z\"", false},
{"x.y/z#", false},
{"x.y/z$", false},
{"x.y/z%", false},
{"x.y/z&", false},
{"x.y/z'", false},
{"x.y/z(", false},
{"x.y/z)", false},
{"x.y/z*", false},
{"x.y/z+", true},
{"x.y/z,", true},
{"x.y/z-", true},
{"x.y/z.t", true},
{"x.y/z/t", true},
{"x.y/z:", false},
{"x.y/z;", false},
{"x.y/z<", false},
{"x.y/z=", false},
{"x.y/z>", false},
{"x.y/z?", false},
{"x.y/z@", false},
{"x.y/z[", false},
{"x.y/z\\", false},
{"x.y/z]", false},
{"x.y/z^", false},
{"x.y/z_", true},
{"x.y/z`", false},
{"x.y/z{", false},
{"x.y/z}", false},
{"x.y/z~", true},
{"!x.y/z", false, false, true},
{"_x.y/z", false, true, true},
{"x.y!/z", false, false, true},
{"x.y\"/z", false, false, false},
{"x.y#/z", false, false, true},
{"x.y$/z", false, false, true},
{"x.y%/z", false, false, true},
{"x.y&/z", false, false, true},
{"x.y'/z", false, false, false},
{"x.y(/z", false, false, true},
{"x.y)/z", false, false, true},
{"x.y*/z", false, false, false},
{"x.y+/z", false, true, true},
{"x.y,/z", false, false, true},
{"x.y-/z", true, true, true},
{"x.y./zt", false, false, false},
{"x.y:/z", false, false, false},
{"x.y;/z", false, false, false},
{"x.y</z", false, false, false},
{"x.y=/z", false, false, true},
{"x.y>/z", false, false, false},
{"x.y?/z", false, false, false},
{"x.y@/z", false, false, true},
{"x.y[/z", false, false, true},
{"x.y\\/z", false, false, false},
{"x.y]/z", false, false, true},
{"x.y^/z", false, false, true},
{"x.y_/z", false, true, true},
{"x.y`/z", false, false, false},
{"x.y{/z", false, false, true},
{"x.y}/z", false, false, true},
{"x.y~/z", false, true, true},
{"x.y/z!", false, false, true},
{"x.y/z\"", false, false, false},
{"x.y/z#", false, false, true},
{"x.y/z$", false, false, true},
{"x.y/z%", false, false, true},
{"x.y/z&", false, false, true},
{"x.y/z'", false, false, false},
{"x.y/z(", false, false, true},
{"x.y/z)", false, false, true},
{"x.y/z*", false, false, false},
{"x.y/z+", true, true, true},
{"x.y/z,", false, false, true},
{"x.y/z-", true, true, true},
{"x.y/z.t", true, true, true},
{"x.y/z/t", true, true, true},
{"x.y/z:", false, false, false},
{"x.y/z;", false, false, false},
{"x.y/z<", false, false, false},
{"x.y/z=", false, false, true},
{"x.y/z>", false, false, false},
{"x.y/z?", false, false, false},
{"x.y/z@", false, false, true},
{"x.y/z[", false, false, true},
{"x.y/z\\", false, false, false},
{"x.y/z]", false, false, true},
{"x.y/z^", false, false, true},
{"x.y/z_", true, true, true},
{"x.y/z`", false, false, false},
{"x.y/z{", false, false, true},
{"x.y/z}", false, false, true},
{"x.y/z~", true, true, true},
{"x.y/x.foo", true, true, true},
{"x.y/aux.foo", false, false, false},
{"x.y/prn", false, false, false},
{"x.y/prn2", true, true, true},
{"x.y/com", true, true, true},
{"x.y/com1", false, false, false},
{"x.y/com1.txt", false, false, false},
{"x.y/calm1", true, true, true},
{"github.com/!123/logrus", false, false, true},
// TODO: CL 41822 allowed Unicode letters in old "go get"
// without due consideration of the implications, and only on github.com (!).
// For now, we disallow non-ASCII characters in module mode,
// in both module paths and general import paths,
// until we can get the implications right.
// When we do, we'll enable them everywhere, not just for GitHub.
{"github.com/user/unicode/испытание", false, false, true},
{"../x", false, false, false},
{"./y", false, false, false},
{"x:y", false, false, false},
{`\temp\foo`, false, false, false},
{".gitignore", false, false, true},
{".github/ISSUE_TEMPLATE", false, false, true},
{"x☺y", false, false, false},
}
func TestCheckPath(t *testing.T) {
@ -151,6 +190,20 @@ func TestCheckPath(t *testing.T) {
} else if !tt.ok && err == nil {
t.Errorf("CheckPath(%q) succeeded, wanted error", tt.path)
}
err = CheckImportPath(tt.path)
if tt.importOK && err != nil {
t.Errorf("CheckImportPath(%q) = %v, wanted nil error", tt.path, err)
} else if !tt.importOK && err == nil {
t.Errorf("CheckImportPath(%q) succeeded, wanted error", tt.path)
}
err = CheckFilePath(tt.path)
if tt.fileOK && err != nil {
t.Errorf("CheckFilePath(%q) = %v, wanted nil error", tt.path, err)
} else if !tt.fileOK && err == nil {
t.Errorf("CheckFilePath(%q) succeeded, wanted error", tt.path)
}
}
}
@ -182,3 +235,84 @@ func TestSplitPathVersion(t *testing.T) {
}
}
}
var encodeTests = []struct {
path string
enc string // empty means same as path
}{
{path: "ascii.com/abcdefghijklmnopqrstuvwxyz.-+/~_0123456789"},
{path: "github.com/GoogleCloudPlatform/omega", enc: "github.com/!google!cloud!platform/omega"},
}
func TestEncodePath(t *testing.T) {
// Check invalid paths.
for _, tt := range checkPathTests {
if !tt.ok {
_, err := EncodePath(tt.path)
if err == nil {
t.Errorf("EncodePath(%q): succeeded, want error (invalid path)", tt.path)
}
}
}
// Check encodings.
for _, tt := range encodeTests {
enc, err := EncodePath(tt.path)
if err != nil {
t.Errorf("EncodePath(%q): unexpected error: %v", tt.path, err)
continue
}
want := tt.enc
if want == "" {
want = tt.path
}
if enc != want {
t.Errorf("EncodePath(%q) = %q, want %q", tt.path, enc, want)
}
}
}
var badDecode = []string{
"github.com/GoogleCloudPlatform/omega",
"github.com/!google!cloud!platform!/omega",
"github.com/!0google!cloud!platform/omega",
"github.com/!_google!cloud!platform/omega",
"github.com/!!google!cloud!platform/omega",
"",
}
func TestDecodePath(t *testing.T) {
// Check invalid decodings.
for _, bad := range badDecode {
_, err := DecodePath(bad)
if err == nil {
t.Errorf("DecodePath(%q): succeeded, want error (invalid decoding)", bad)
}
}
// Check invalid paths (or maybe decodings).
for _, tt := range checkPathTests {
if !tt.ok {
path, err := DecodePath(tt.path)
if err == nil {
t.Errorf("DecodePath(%q) = %q, want error (invalid path)", tt.path, path)
}
}
}
// Check encodings.
for _, tt := range encodeTests {
enc := tt.enc
if enc == "" {
enc = tt.path
}
path, err := DecodePath(enc)
if err != nil {
t.Errorf("DecodePath(%q): unexpected error: %v", enc, err)
continue
}
if path != tt.path {
t.Errorf("DecodePath(%q) = %q, want %q", enc, path, tt.path)
}
}
}

1
vendor/cmd/go/internal/par/work.go поставляемый
Просмотреть файл

@ -55,7 +55,6 @@ func (w *Work) Do(n int, f func(item interface{})) {
if n < 1 {
panic("par.Work.Do: n < 1")
}
n = 1
if w.running >= 1 {
panic("par.Work.Do: already called Do")
}

25
vendor/cmd/go/internal/par/work_test.go поставляемый
Просмотреть файл

@ -7,6 +7,7 @@ package par
import (
"sync/atomic"
"testing"
"time"
)
func TestWork(t *testing.T) {
@ -30,6 +31,30 @@ func TestWork(t *testing.T) {
}
}
func TestWorkParallel(t *testing.T) {
var w Work
for tries := 0; tries < 10; tries++ {
const N = 100
for i := 0; i < N; i++ {
w.Add(i)
}
start := time.Now()
var n int32
w.Do(N, func(x interface{}) {
time.Sleep(1 * time.Millisecond)
atomic.AddInt32(&n, +1)
})
if n != N {
t.Fatalf("par.Work.Do did not do all the work")
}
if time.Since(start) < N/2*time.Millisecond {
return
}
}
t.Fatalf("par.Work.Do does not seem to be parallel")
}
func TestCache(t *testing.T) {
var cache Cache

71
vendor/cmd/go/internal/search/search.go поставляемый
Просмотреть файл

@ -437,3 +437,74 @@ func IsStandardImportPath(path string) bool {
func IsRelativePath(pattern string) bool {
return strings.HasPrefix(pattern, "./") || strings.HasPrefix(pattern, "../") || pattern == "." || pattern == ".."
}
// InDir checks whether path is in the file tree rooted at dir.
// If so, InDir returns an equivalent path relative to dir.
// If not, InDir returns an empty string.
// InDir makes some effort to succeed even in the presence of symbolic links.
// TODO(rsc): Replace internal/test.inDir with a call to this function for Go 1.12.
func InDir(path, dir string) string {
if rel := inDirLex(path, dir); rel != "" {
return rel
}
xpath, err := filepath.EvalSymlinks(path)
if err != nil || xpath == path {
xpath = ""
} else {
if rel := inDirLex(xpath, dir); rel != "" {
return rel
}
}
xdir, err := filepath.EvalSymlinks(dir)
if err == nil && xdir != dir {
if rel := inDirLex(path, xdir); rel != "" {
return rel
}
if xpath != "" {
if rel := inDirLex(xpath, xdir); rel != "" {
return rel
}
}
}
return ""
}
// inDirLex is like inDir but only checks the lexical form of the file names.
// It does not consider symbolic links.
// TODO(rsc): This is a copy of str.HasFilePathPrefix, modified to
// return the suffix. Most uses of str.HasFilePathPrefix should probably
// be calling InDir instead.
func inDirLex(path, dir string) string {
pv := strings.ToUpper(filepath.VolumeName(path))
dv := strings.ToUpper(filepath.VolumeName(dir))
path = path[len(pv):]
dir = dir[len(dv):]
switch {
default:
return ""
case pv != dv:
return ""
case len(path) == len(dir):
if path == dir {
return "."
}
return ""
case dir == "":
return path
case len(path) > len(dir):
if dir[len(dir)-1] == filepath.Separator {
if path[:len(dir)] == dir {
return path[len(dir):]
}
return ""
}
if path[len(dir)] == filepath.Separator && path[:len(dir)] == dir {
if len(path) == len(dir)+1 {
return "."
}
return path[len(dir)+1:]
}
return ""
}
}

2
vendor/cmd/go/internal/str/path.go поставляемый
Просмотреть файл

@ -19,7 +19,7 @@ func HasPathPrefix(s, prefix string) bool {
return true
}
if len(s) > len(prefix) {
if prefix != "" && prefix[len(prefix)-1] == '/' || s[len(prefix)] == '/' {
if prefix[len(prefix)-1] == '/' || s[len(prefix)] == '/' {
return s[:len(prefix)] == prefix
}
}

56
vendor/cmd/go/internal/test/test.go поставляемый
Просмотреть файл

@ -650,7 +650,7 @@ func runTest(cmd *base.Command, args []string) {
}
// Select for coverage all dependencies matching the testCoverPaths patterns.
for _, p := range load.PackageList(pkgs) {
for _, p := range load.TestPackageList(pkgs) {
haveMatch := false
for i := range testCoverPaths {
if match[i](p) {
@ -698,7 +698,7 @@ func runTest(cmd *base.Command, args []string) {
coverFiles = append(coverFiles, p.GoFiles...)
coverFiles = append(coverFiles, p.CgoFiles...)
coverFiles = append(coverFiles, p.TestGoFiles...)
p.Internal.CoverVars = declareCoverVars(p.ImportPath, coverFiles...)
p.Internal.CoverVars = declareCoverVars(p, coverFiles...)
if testCover && testCoverMode == "atomic" {
ensureImport(p, "sync/atomic")
}
@ -716,13 +716,12 @@ func runTest(cmd *base.Command, args []string) {
if err != nil {
str := err.Error()
str = strings.TrimPrefix(str, "\n")
failed := fmt.Sprintf("FAIL\t%s [setup failed]\n", p.ImportPath)
if p.ImportPath != "" {
base.Errorf("# %s\n%s\n%s", p.ImportPath, str, failed)
base.Errorf("# %s\n%s", p.ImportPath, str)
} else {
base.Errorf("%s\n%s", str, failed)
base.Errorf("%s", str)
}
fmt.Printf("FAIL\t%s [setup failed]\n", p.ImportPath)
continue
}
builds = append(builds, buildTest)
@ -781,6 +780,14 @@ var windowsBadWords = []string{
}
func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, printAction *work.Action, err error) {
if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
build := b.CompileAction(work.ModeBuild, work.ModeBuild, p)
run := &work.Action{Mode: "test run", Package: p, Deps: []*work.Action{build}}
addTestVet(b, p, run, nil)
print := &work.Action{Mode: "test print", Func: builderNoTest, Package: p, Deps: []*work.Action{run}}
return build, run, print, nil
}
// Build Package structs describing:
// pmain - pkg.test binary
// ptest - package + test files
@ -958,7 +965,7 @@ func isTestFile(file string) bool {
// declareCoverVars attaches the required cover variables names
// to the files, to be used when annotating the files.
func declareCoverVars(importPath string, files ...string) map[string]*load.CoverVar {
func declareCoverVars(p *load.Package, files ...string) map[string]*load.CoverVar {
coverVars := make(map[string]*load.CoverVar)
coverIndex := 0
// We create the cover counters as new top-level variables in the package.
@ -967,14 +974,25 @@ func declareCoverVars(importPath string, files ...string) map[string]*load.Cover
// so we append 12 hex digits from the SHA-256 of the import path.
// The point is only to avoid accidents, not to defeat users determined to
// break things.
sum := sha256.Sum256([]byte(importPath))
sum := sha256.Sum256([]byte(p.ImportPath))
h := fmt.Sprintf("%x", sum[:6])
for _, file := range files {
if isTestFile(file) {
continue
}
// For a package that is "local" (imported via ./ import or command line, outside GOPATH),
// we record the full path to the file name.
// Otherwise we record the import path, then a forward slash, then the file name.
// This makes profiles within GOPATH file system-independent.
// These names appear in the cmd/cover HTML interface.
var longFile string
if p.Internal.Local {
longFile = filepath.Join(p.Dir, file)
} else {
longFile = path.Join(p.ImportPath, file)
}
coverVars[file] = &load.CoverVar{
File: filepath.Join(importPath, file),
File: longFile,
Var: fmt.Sprintf("GoCover_%d_%x", coverIndex, h),
}
coverIndex++
@ -1168,17 +1186,13 @@ func (c *runCache) builderRunTest(b *work.Builder, a *work.Action) error {
if err == nil {
norun := ""
res := "ok"
if !testShowPass && !testJSON {
buf.Reset()
}
if len(a.Package.TestGoFiles)+len(a.Package.XTestGoFiles) == 0 {
res = "? "
norun = " [no test files]"
} else if bytes.HasPrefix(out, noTestsToRun[1:]) || bytes.Contains(out, noTestsToRun) {
if bytes.HasPrefix(out, noTestsToRun[1:]) || bytes.Contains(out, noTestsToRun) {
norun = " [no tests to run]"
}
fmt.Fprintf(cmd.Stdout, "%s \t%s\t%s%s%s\n", res, a.Package.ImportPath, t, coveragePercentage(out), norun)
fmt.Fprintf(cmd.Stdout, "ok \t%s\t%s%s%s\n", a.Package.ImportPath, t, coveragePercentage(out), norun)
c.saveOutput(a)
} else {
base.SetExitStatus(1)
@ -1592,3 +1606,15 @@ func builderPrintTest(b *work.Builder, a *work.Action) error {
}
return nil
}
// builderNoTest is the action for testing a package with no test files.
func builderNoTest(b *work.Builder, a *work.Action) error {
var stdout io.Writer = os.Stdout
if testJSON {
json := test2json.NewConverter(lockedStdout{}, a.Package.ImportPath, test2json.Timestamp)
defer json.Close()
stdout = json
}
fmt.Fprintf(stdout, "? \t%s\t[no test files]\n", a.Package.ImportPath)
return nil
}

8
vendor/cmd/go/internal/txtar/archive.go поставляемый
Просмотреть файл

@ -22,9 +22,8 @@
// The comment or file content ends at the next file marker line.
// The file marker line must begin with the three-byte sequence "-- "
// and end with the three-byte sequence " --", but the enclosed
// file name can be surrounded by additional white space,
// all of which is stripped. The file name may itself contain spaces,
// which are preserved.
// file name can be surrounding by additional white space,
// all of which is stripped.
//
// If the txtar file is missing a trailing newline on the final line,
// parsers should consider a final newline to be present anyway.
@ -54,8 +53,7 @@ type File struct {
// Format returns the serialized form of an Archive.
// It is assumed that the Archive data structure is well-formed:
// a.Comment and all a.File[i].Data contain no file marker lines,
// and all a.File[i].Name are non-empty and well-formed
// (no leading or trailing spaces, no newlines, and so on).
// and all a.File[i].Name is non-empty.
func Format(a *Archive) []byte {
var buf bytes.Buffer
buf.Write(fixNL(a.Comment))

4
vendor/cmd/go/internal/version/version.go поставляемый
Просмотреть файл

@ -13,8 +13,6 @@ import (
"cmd/go/internal/work"
)
const version = "2018-02-20.1"
var CmdVersion = &base.Command{
Run: runVersion,
UsageLine: "version",
@ -27,5 +25,5 @@ func runVersion(cmd *base.Command, args []string) {
cmd.Usage()
}
fmt.Printf("go version %s %s/%s go:%s\n", work.RuntimeVersion, runtime.GOOS, runtime.GOARCH, version)
fmt.Printf("go version %s %s/%s vgo:%s\n", work.RuntimeVersion, runtime.GOOS, runtime.GOARCH, version)
}

3
vendor/cmd/go/internal/version/vgo.go поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
package version
const version = "devel +88c76dcbab"

29
vendor/cmd/go/internal/work/action.go поставляемый
Просмотреть файл

@ -213,7 +213,6 @@ const (
)
func (b *Builder) Init() {
var err error
b.Print = func(a ...interface{}) (int, error) {
return fmt.Fprint(os.Stderr, a...)
}
@ -225,14 +224,19 @@ func (b *Builder) Init() {
if cfg.BuildN {
b.WorkDir = "$WORK"
} else {
b.WorkDir, err = ioutil.TempDir(os.Getenv("GOTMPDIR"), "go-build")
tmp, err := ioutil.TempDir(os.Getenv("GOTMPDIR"), "go-build")
if err != nil {
base.Fatalf("%s", err)
base.Fatalf("go: creating work dir: %v", err)
}
if !filepath.IsAbs(b.WorkDir) {
os.RemoveAll(b.WorkDir)
base.Fatalf("cmd/go: relative tmpdir not supported")
if !filepath.IsAbs(tmp) {
abs, err := filepath.Abs(tmp)
if err != nil {
os.RemoveAll(tmp)
base.Fatalf("go: creating work dir: %v", err)
}
tmp = abs
}
b.WorkDir = tmp
if cfg.BuildX || cfg.BuildWork {
fmt.Fprintf(os.Stderr, "WORK=%s\n", b.WorkDir)
}
@ -403,7 +407,16 @@ func (b *Builder) vetAction(mode, depMode BuildMode, p *load.Package) *Action {
stk.Pop()
aFmt := b.CompileAction(ModeBuild, depMode, p1)
deps := []*Action{a1, aFmt}
var deps []*Action
if a1.buggyInstall {
// (*Builder).vet expects deps[0] to be the package
// and deps[1] to be "fmt". If we see buggyInstall
// here then a1 is an install of a shared library,
// and the real package is a1.Deps[0].
deps = []*Action{a1.Deps[0], aFmt, a1}
} else {
deps = []*Action{a1, aFmt}
}
for _, p1 := range load.PackageList(p.Internal.Imports) {
deps = append(deps, b.vetAction(mode, depMode, p1))
}
@ -420,7 +433,7 @@ func (b *Builder) vetAction(mode, depMode BuildMode, p *load.Package) *Action {
// Built-in packages like unsafe.
return a
}
a1.needVet = true
deps[0].needVet = true
a.Func = (*Builder).vet
return a
})

43
vendor/cmd/go/internal/work/exec.go поставляемый
Просмотреть файл

@ -196,10 +196,13 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
fmt.Fprintf(h, "goos %s goarch %s\n", cfg.Goos, cfg.Goarch)
fmt.Fprintf(h, "import %q\n", p.ImportPath)
fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix)
if p.Internal.ForceLibrary {
fmt.Fprintf(h, "forcelibrary\n")
}
if len(p.CgoFiles)+len(p.SwigFiles) > 0 {
fmt.Fprintf(h, "cgo %q\n", b.toolID("cgo"))
cppflags, cflags, cxxflags, fflags, _, _ := b.CFlags(p)
fmt.Fprintf(h, "CC=%q %q %q\n", b.ccExe(), cppflags, cflags)
cppflags, cflags, cxxflags, fflags, ldflags, _ := b.CFlags(p)
fmt.Fprintf(h, "CC=%q %q %q %q\n", b.ccExe(), cppflags, cflags, ldflags)
if len(p.CXXFiles)+len(p.SwigFiles) > 0 {
fmt.Fprintf(h, "CXX=%q %q\n", b.cxxExe(), cxxflags)
}
@ -907,11 +910,6 @@ var VetTool string
var VetFlags []string
func (b *Builder) vet(a *Action) error {
b.toolID("vet")
if oldVet {
return nil
}
// a.Deps[0] is the build of the package being vetted.
// a.Deps[1] is the build of the "fmt" package.
@ -985,7 +983,7 @@ func (b *Builder) vet(a *Action) error {
return err
}
var env []string
env := b.cCompilerEnv()
if cfg.BuildToolchainName == "gccgo" {
env = append(env, "GCCGO="+BuildToolchain.compiler())
}
@ -1370,7 +1368,9 @@ func BuildInstallFunc(b *Builder, a *Action) (err error) {
// so the built target is not in the a1.Objdir tree that b.cleanup(a1) removes.
if a1.built == a.Target {
a.built = a.Target
if !a.buggyInstall {
b.cleanup(a1)
}
// Whether we're smart enough to avoid a complete rebuild
// depends on exactly what the staleness and rebuild algorithms
// are, as well as potentially the state of the Go build cache.
@ -1424,7 +1424,9 @@ func BuildInstallFunc(b *Builder, a *Action) (err error) {
}
}
if !a.buggyInstall {
defer b.cleanup(a1)
}
return b.moveOrCopyFile(a.Target, a1.built, perm, false)
}
@ -1858,6 +1860,13 @@ func joinUnambiguously(a []string) string {
return buf.String()
}
// cCompilerEnv returns environment variables to set when running the
// C compiler. This is needed to disable escape codes in clang error
// messages that confuse tools like cgo.
func (b *Builder) cCompilerEnv() []string {
return []string{"TERM=dumb"}
}
// mkdir makes the named directory.
func (b *Builder) Mkdir(dir string) error {
// Make Mkdir(a.Objdir) a no-op instead of an error when a.Objdir == "".
@ -2005,7 +2014,7 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s
if !filepath.IsAbs(outfile) {
outfile = filepath.Join(p.Dir, outfile)
}
output, err := b.runOut(filepath.Dir(file), nil, compiler, flags, "-o", outfile, "-c", filepath.Base(file))
output, err := b.runOut(filepath.Dir(file), b.cCompilerEnv(), compiler, flags, "-o", outfile, "-c", filepath.Base(file))
if len(output) > 0 {
// On FreeBSD 11, when we pass -g to clang 3.8 it
// invokes its internal assembler with -dwarf-version=2.
@ -2045,7 +2054,7 @@ func (b *Builder) gccld(p *load.Package, objdir, out string, flags []string, obj
} else {
cmd = b.GccCmd(p.Dir, objdir)
}
return b.run(nil, p.Dir, p.ImportPath, nil, cmd, "-o", out, objs, flags)
return b.run(nil, p.Dir, p.ImportPath, b.cCompilerEnv(), cmd, "-o", out, objs, flags)
}
// Grab these before main helpfully overwrites them.
@ -2340,7 +2349,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
// along to the host linker. At this point in the code, cgoLDFLAGS
// consists of the original $CGO_LDFLAGS (unchecked) and all the
// flags put together from source code (checked).
var cgoenv []string
cgoenv := b.cCompilerEnv()
if len(cgoLDFLAGS) > 0 {
flags := make([]string, len(cgoLDFLAGS))
for i, f := range cgoLDFLAGS {
@ -2468,7 +2477,15 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe
// we need to use -pie for Linux/ARM to get accurate imported sym
ldflags := cgoLDFLAGS
if (cfg.Goarch == "arm" && cfg.Goos == "linux") || cfg.Goos == "android" {
ldflags = append(ldflags, "-pie")
// -static -pie doesn't make sense, and causes link errors.
// Issue 26197.
n := make([]string, 0, len(ldflags))
for _, flag := range ldflags {
if flag != "-static" {
n = append(n, flag)
}
}
ldflags = append(n, "-pie")
}
if err := b.gccld(p, objdir, dynobj, ldflags, linkobj); err != nil {
return err
@ -2479,7 +2496,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe
if p.Standard && p.ImportPath == "runtime/cgo" {
cgoflags = []string{"-dynlinker"} // record path to dynamic linker
}
return b.run(a, p.Dir, p.ImportPath, nil, cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
return b.run(a, p.Dir, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
}
// Run SWIG on all SWIG input files.

4
vendor/cmd/go/internal/work/init.go поставляемый
Просмотреть файл

@ -48,9 +48,9 @@ func instrumentInit() {
platform := cfg.Goos + "/" + cfg.Goarch
switch platform {
default:
fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, freebsd/amd64, netbsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
os.Exit(2)
case "linux/amd64", "linux/ppc64le", "freebsd/amd64", "darwin/amd64", "windows/amd64":
case "linux/amd64", "linux/ppc64le", "freebsd/amd64", "netbsd/amd64", "darwin/amd64", "windows/amd64":
// race supported on these platforms
}
}

1
vendor/cmd/go/internal/work/security.go поставляемый
Просмотреть файл

@ -136,6 +136,7 @@ var validLinkerFlags = []*regexp.Regexp{
re(`-f(no-)?(pic|PIC|pie|PIE)`),
re(`-f(no-)?openmp(-simd)?`),
re(`-fsanitize=([^@\-].*)`),
re(`-flat_namespace`),
re(`-g([^@\-].*)?`),
re(`-headerpad_max_install_names`),
re(`-m(abi|arch|cpu|fpu|tune)=([^@\-].*)`),

11
vendor/cmd/go/mkalldocs.sh поставляемый
Просмотреть файл

@ -1,11 +0,0 @@
#!/bin/bash
# Copyright 2012 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.
set -e
go build -o go.latest golang.org/x/vgo
./go.latest help documentation | sed 's/^package main/package Main/' >alldocs.go
gofmt -w alldocs.go
rm go.latest

1331
vendor/cmd/go/mod_test.go поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

30
vendor/cmd/go/proxy_test.go поставляемый
Просмотреть файл

@ -18,6 +18,7 @@ import (
"path/filepath"
"strings"
"sync"
"testing"
"cmd/go/internal/modfetch"
"cmd/go/internal/modfetch/codehost"
@ -77,7 +78,12 @@ func readModList() {
if i < 0 {
continue
}
path := strings.Replace(name[:i], "_", "/", -1)
enc := strings.Replace(name[:i], "_", "/", -1)
path, err := module.DecodePath(enc)
if err != nil {
fmt.Fprintf(os.Stderr, "go proxy_test: %v", err)
continue
}
vers := name[i+1:]
modList = append(modList, module.Version{Path: path, Version: vers})
}
@ -98,7 +104,13 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
http.NotFound(w, r)
return
}
path, file := path[:i], path[i+len("/@v/"):]
enc, file := path[:i], path[i+len("/@v/"):]
path, err := module.DecodePath(enc)
if err != nil {
fmt.Fprintf(os.Stderr, "go proxy_test: %v\n", err)
http.NotFound(w, r)
return
}
if file == "list" {
n := 0
for _, m := range modList {
@ -147,6 +159,7 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
a := readArchive(path, vers)
if a == nil {
fmt.Fprintf(os.Stderr, "go proxy: no archive %s %s\n", path, vers)
http.Error(w, "cannot load archive", 500)
return
}
@ -188,6 +201,7 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
}).(cached)
if c.err != nil {
fmt.Fprintf(os.Stderr, "go proxy: %v\n", c.err)
http.Error(w, c.err.Error(), 500)
return
}
@ -217,13 +231,21 @@ func findHash(m module.Version) string {
var archiveCache par.Cache
var cmdGoDir, _ = os.Getwd()
func readArchive(path, vers string) *txtar.Archive {
prefix := strings.Replace(path, "/", "_", -1)
enc, err := module.EncodePath(path)
if err != nil {
fmt.Fprintf(os.Stderr, "go proxy: %v\n", err)
return nil
}
prefix := strings.Replace(enc, "/", "_", -1)
name := filepath.Join(cmdGoDir, "testdata/mod", prefix+"_"+vers+".txt")
a := archiveCache.Do(name, func() interface{} {
a, err := txtar.ParseFile(name)
if err != nil {
if !os.IsNotExist(err) {
if testing.Verbose() || !os.IsNotExist(err) {
fmt.Fprintf(os.Stderr, "go proxy: %v\n", err)
}
a = nil

894
vendor/cmd/go/script_test.go поставляемый Normal file
Просмотреть файл

@ -0,0 +1,894 @@
// 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.
// Script-driven tests.
// See testdata/script/README for an overview.
package Main_test
import (
"bytes"
"fmt"
"internal/testenv"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"testing"
"time"
"cmd/go/internal/imports"
"cmd/go/internal/par"
"cmd/go/internal/txtar"
)
// TestScript runs the tests in testdata/script/*.txt.
func TestScript(t *testing.T) {
testenv.MustHaveGoBuild(t)
if skipExternal {
t.Skipf("skipping external tests on %s/%s", runtime.GOOS, runtime.GOARCH)
}
files, err := filepath.Glob("testdata/script/*.txt")
if err != nil {
t.Fatal(err)
}
for _, file := range files {
file := file
name := strings.TrimSuffix(filepath.Base(file), ".txt")
t.Run(name, func(t *testing.T) {
t.Parallel()
ts := &testScript{t: t, name: name, file: file}
ts.setup()
if !*testWork {
defer removeAll(ts.workdir)
}
ts.run()
})
}
}
// A testScript holds execution state for a single test script.
type testScript struct {
t *testing.T
workdir string // temporary work dir ($WORK)
log bytes.Buffer // test execution log (printed at end of test)
mark int // offset of next log truncation
cd string // current directory during test execution; initially $WORK/gopath/src
name string // short name of test ("foo")
file string // full file name ("testdata/script/foo.txt")
lineno int // line number currently executing
line string // line currently executing
env []string // environment list (for os/exec)
envMap map[string]string // environment mapping (matches env)
stdout string // standard output from last 'go' command; for 'stdout' command
stderr string // standard error from last 'go' command; for 'stderr' command
stopped bool // test wants to stop early
start time.Time // time phase started
}
var extraEnvKeys = []string{
"SYSTEMROOT", // must be preserved on Windows to find DLLs; golang.org/issue/25210
}
// setup sets up the test execution temporary directory and environment.
func (ts *testScript) setup() {
StartProxy()
ts.workdir = filepath.Join(testTmpDir, "script-"+ts.name)
ts.check(os.MkdirAll(filepath.Join(ts.workdir, "tmp"), 0777))
ts.check(os.MkdirAll(filepath.Join(ts.workdir, "gopath/src"), 0777))
ts.cd = filepath.Join(ts.workdir, "gopath/src")
ts.env = []string{
"WORK=" + ts.workdir, // must be first for ts.abbrev
"PATH=" + os.Getenv("PATH"),
homeEnvName() + "=/no-home",
"GOARCH=" + runtime.GOARCH,
"GOCACHE=" + testGOCACHE,
"GOOS=" + runtime.GOOS,
"GOPATH=" + filepath.Join(ts.workdir, "gopath"),
"GOPROXY=" + proxyURL,
"GOROOT=" + testGOROOT,
tempEnvName() + "=" + filepath.Join(ts.workdir, "tmp"),
"devnull=" + os.DevNull,
}
if runtime.GOOS == "windows" {
ts.env = append(ts.env, "exe=.exe")
} else {
ts.env = append(ts.env, "exe=")
}
for _, key := range extraEnvKeys {
if val := os.Getenv(key); val != "" {
ts.env = append(ts.env, key+"="+val)
}
}
ts.envMap = make(map[string]string)
for _, kv := range ts.env {
if i := strings.Index(kv, "="); i >= 0 {
ts.envMap[kv[:i]] = kv[i+1:]
}
}
}
var execCache par.Cache
// run runs the test script.
func (ts *testScript) run() {
// Truncate log at end of last phase marker,
// discarding details of successful phase.
rewind := func() {
if !testing.Verbose() {
ts.log.Truncate(ts.mark)
}
}
// Insert elapsed time for phase at end of phase marker
markTime := func() {
if ts.mark > 0 && !ts.start.IsZero() {
afterMark := append([]byte{}, ts.log.Bytes()[ts.mark:]...)
ts.log.Truncate(ts.mark - 1) // cut \n and afterMark
fmt.Fprintf(&ts.log, " (%.3fs)\n", time.Since(ts.start).Seconds())
ts.log.Write(afterMark)
}
ts.start = time.Time{}
}
defer func() {
markTime()
// Flush testScript log to testing.T log.
ts.t.Log("\n" + ts.abbrev(ts.log.String()))
}()
// Unpack archive.
a, err := txtar.ParseFile(ts.file)
ts.check(err)
for _, f := range a.Files {
name := ts.mkabs(ts.expand(f.Name))
ts.check(os.MkdirAll(filepath.Dir(name), 0777))
ts.check(ioutil.WriteFile(name, f.Data, 0666))
}
// With -v or -testwork, start log with full environment.
if *testWork || testing.Verbose() {
// Display environment.
ts.cmdEnv(false, nil)
fmt.Fprintf(&ts.log, "\n")
ts.mark = ts.log.Len()
}
// Run script.
// See testdata/script/README for documentation of script form.
script := string(a.Comment)
Script:
for script != "" {
// Extract next line.
ts.lineno++
var line string
if i := strings.Index(script, "\n"); i >= 0 {
line, script = script[:i], script[i+1:]
} else {
line, script = script, ""
}
// # is a comment indicating the start of new phase.
if strings.HasPrefix(line, "#") {
// If there was a previous phase, it succeeded,
// so rewind the log to delete its details (unless -v is in use).
// If nothing has happened at all since the mark,
// rewinding is a no-op and adding elapsed time
// for doing nothing is meaningless, so don't.
if ts.log.Len() > ts.mark {
rewind()
markTime()
}
// Print phase heading and mark start of phase output.
fmt.Fprintf(&ts.log, "%s\n", line)
ts.mark = ts.log.Len()
ts.start = time.Now()
continue
}
// Parse input line. Ignore blanks entirely.
args := ts.parse(line)
if len(args) == 0 {
continue
}
// Echo command to log.
fmt.Fprintf(&ts.log, "> %s\n", line)
// Command prefix [cond] means only run this command if cond is satisfied.
for strings.HasPrefix(args[0], "[") && strings.HasSuffix(args[0], "]") {
cond := args[0]
cond = cond[1 : len(cond)-1]
cond = strings.TrimSpace(cond)
args = args[1:]
if len(args) == 0 {
ts.fatalf("missing command after condition")
}
want := true
if strings.HasPrefix(cond, "!") {
want = false
cond = strings.TrimSpace(cond[1:])
}
// Known conds are: $GOOS, $GOARCH, runtime.Compiler, and 'short' (for testing.Short).
//
// NOTE: If you make changes here, update testdata/script/README too!
//
ok := false
switch cond {
case runtime.GOOS, runtime.GOARCH, runtime.Compiler:
ok = true
case "short":
ok = testing.Short()
case "cgo":
ok = canCgo
case "msan":
ok = canMSan
case "race":
ok = canRace
case "net":
ok = testenv.HasExternalNetwork()
case "link":
ok = testenv.HasLink()
case "symlink":
ok = testenv.HasSymlink()
default:
if strings.HasPrefix(cond, "exec:") {
prog := cond[len("exec:"):]
ok = execCache.Do(prog, func() interface{} {
_, err := exec.LookPath(prog)
return err == nil
}).(bool)
break
}
if !imports.KnownArch[cond] && !imports.KnownOS[cond] && cond != "gc" && cond != "gccgo" {
ts.fatalf("unknown condition %q", cond)
}
}
if ok != want {
// Don't run rest of line.
continue Script
}
}
// Command prefix ! means negate the expectations about this command:
// go command should fail, match should not be found, etc.
neg := false
if args[0] == "!" {
neg = true
args = args[1:]
if len(args) == 0 {
ts.fatalf("! on line by itself")
}
}
// Run command.
cmd := scriptCmds[args[0]]
if cmd == nil {
ts.fatalf("unknown command %q", args[0])
}
cmd(ts, neg, args[1:])
// Command can ask script to stop early.
if ts.stopped {
return
}
}
// Final phase ended.
rewind()
markTime()
fmt.Fprintf(&ts.log, "PASS\n")
}
// scriptCmds are the script command implementations.
// Keep list and the implementations below sorted by name.
//
// NOTE: If you make changes here, update testdata/script/README too!
//
var scriptCmds = map[string]func(*testScript, bool, []string){
"addcrlf": (*testScript).cmdAddcrlf,
"cd": (*testScript).cmdCd,
"cmp": (*testScript).cmdCmp,
"cp": (*testScript).cmdCp,
"env": (*testScript).cmdEnv,
"exec": (*testScript).cmdExec,
"exists": (*testScript).cmdExists,
"go": (*testScript).cmdGo,
"grep": (*testScript).cmdGrep,
"mkdir": (*testScript).cmdMkdir,
"rm": (*testScript).cmdRm,
"skip": (*testScript).cmdSkip,
"stale": (*testScript).cmdStale,
"stderr": (*testScript).cmdStderr,
"stdout": (*testScript).cmdStdout,
"stop": (*testScript).cmdStop,
"symlink": (*testScript).cmdSymlink,
}
// addcrlf adds CRLF line endings to the named files.
func (ts *testScript) cmdAddcrlf(neg bool, args []string) {
if len(args) == 0 {
ts.fatalf("usage: addcrlf file...")
}
for _, file := range args {
file = ts.mkabs(file)
data, err := ioutil.ReadFile(file)
ts.check(err)
ts.check(ioutil.WriteFile(file, bytes.Replace(data, []byte("\n"), []byte("\r\n"), -1), 0666))
}
}
// cd changes to a different directory.
func (ts *testScript) cmdCd(neg bool, args []string) {
if neg {
ts.fatalf("unsupported: ! cd")
}
if len(args) != 1 {
ts.fatalf("usage: cd dir")
}
dir := args[0]
if !filepath.IsAbs(dir) {
dir = filepath.Join(ts.cd, dir)
}
info, err := os.Stat(dir)
if os.IsNotExist(err) {
ts.fatalf("directory %s does not exist", dir)
}
ts.check(err)
if !info.IsDir() {
ts.fatalf("%s is not a directory", dir)
}
ts.cd = dir
fmt.Fprintf(&ts.log, "%s\n", ts.cd)
}
// cmp compares two files.
func (ts *testScript) cmdCmp(neg bool, args []string) {
if neg {
// It would be strange to say "this file can have any content except this precise byte sequence".
ts.fatalf("unsupported: ! cmp")
}
if len(args) != 2 {
ts.fatalf("usage: cmp file1 file2")
}
name1, name2 := args[0], args[1]
var text1, text2 string
if name1 == "stdout" {
text1 = ts.stdout
} else if name1 == "stderr" {
text1 = ts.stderr
} else {
data, err := ioutil.ReadFile(ts.mkabs(name1))
ts.check(err)
text1 = string(data)
}
data, err := ioutil.ReadFile(ts.mkabs(name2))
ts.check(err)
text2 = string(data)
if text1 == text2 {
return
}
fmt.Fprintf(&ts.log, "[diff -%s +%s]\n%s\n", name1, name2, diff(text1, text2))
ts.fatalf("%s and %s differ", name1, name2)
}
// cp copies files, maybe eventually directories.
func (ts *testScript) cmdCp(neg bool, args []string) {
if neg {
ts.fatalf("unsupported: ! cp")
}
if len(args) < 2 {
ts.fatalf("usage: cp src... dst")
}
dst := ts.mkabs(args[len(args)-1])
info, err := os.Stat(dst)
dstDir := err == nil && info.IsDir()
if len(args) > 2 && !dstDir {
ts.fatalf("cp: destination %s is not a directory", dst)
}
for _, arg := range args[:len(args)-1] {
src := ts.mkabs(arg)
info, err := os.Stat(src)
ts.check(err)
data, err := ioutil.ReadFile(src)
ts.check(err)
targ := dst
if dstDir {
targ = filepath.Join(dst, filepath.Base(src))
}
ts.check(ioutil.WriteFile(targ, data, info.Mode()&0777))
}
}
// env displays or adds to the environment.
func (ts *testScript) cmdEnv(neg bool, args []string) {
if neg {
ts.fatalf("unsupported: ! env")
}
if len(args) == 0 {
printed := make(map[string]bool) // env list can have duplicates; only print effective value (from envMap) once
for _, kv := range ts.env {
k := kv[:strings.Index(kv, "=")]
if !printed[k] {
fmt.Fprintf(&ts.log, "%s=%s\n", k, ts.envMap[k])
}
}
return
}
for _, env := range args {
i := strings.Index(env, "=")
if i < 0 {
// Display value instead of setting it.
fmt.Fprintf(&ts.log, "%s=%s\n", env, ts.envMap[env])
continue
}
ts.env = append(ts.env, env)
ts.envMap[env[:i]] = env[i+1:]
}
}
// exec runs the given command.
func (ts *testScript) cmdExec(neg bool, args []string) {
if len(args) < 1 {
ts.fatalf("usage: exec program [args...]")
}
var err error
ts.stdout, ts.stderr, err = ts.exec(args[0], args[1:]...)
if ts.stdout != "" {
fmt.Fprintf(&ts.log, "[stdout]\n%s", ts.stdout)
}
if ts.stderr != "" {
fmt.Fprintf(&ts.log, "[stderr]\n%s", ts.stderr)
}
if err != nil {
fmt.Fprintf(&ts.log, "[%v]\n", err)
if !neg {
ts.fatalf("unexpected command failure")
}
} else {
if neg {
ts.fatalf("unexpected command success")
}
}
}
// exists checks that the list of files exists.
func (ts *testScript) cmdExists(neg bool, args []string) {
var readonly bool
if len(args) > 0 && args[0] == "-readonly" {
readonly = true
args = args[1:]
}
if len(args) == 0 {
ts.fatalf("usage: exists [-readonly] file...")
}
for _, file := range args {
file = ts.mkabs(file)
info, err := os.Stat(file)
if err == nil && neg {
what := "file"
if info.IsDir() {
what = "directory"
}
ts.fatalf("%s %s unexpectedly exists", what, file)
}
if err != nil && !neg {
ts.fatalf("%s does not exist", file)
}
if err == nil && !neg && readonly && info.Mode()&0222 != 0 {
ts.fatalf("%s exists but is writable", file)
}
}
}
// go runs the go command.
func (ts *testScript) cmdGo(neg bool, args []string) {
ts.cmdExec(neg, append([]string{testGo}, args...))
}
// mkdir creates directories.
func (ts *testScript) cmdMkdir(neg bool, args []string) {
if neg {
ts.fatalf("unsupported: ! mkdir")
}
if len(args) < 1 {
ts.fatalf("usage: mkdir dir...")
}
for _, arg := range args {
ts.check(os.MkdirAll(ts.mkabs(arg), 0777))
}
}
// rm removes files or directories.
func (ts *testScript) cmdRm(neg bool, args []string) {
if neg {
ts.fatalf("unsupported: ! rm")
}
if len(args) < 1 {
ts.fatalf("usage: rm file...")
}
for _, arg := range args {
file := ts.mkabs(arg)
removeAll(file) // does chmod and then attempts rm
ts.check(os.RemoveAll(file)) // report error
}
}
// skip marks the test skipped.
func (ts *testScript) cmdSkip(neg bool, args []string) {
if len(args) > 1 {
ts.fatalf("usage: skip [msg]")
}
if neg {
ts.fatalf("unsupported: ! skip")
}
if len(args) == 1 {
ts.t.Skip(args[0])
}
ts.t.Skip()
}
// stale checks that the named build targets are stale.
func (ts *testScript) cmdStale(neg bool, args []string) {
if len(args) == 0 {
ts.fatalf("usage: stale target...")
}
tmpl := "{{if .Error}}{{.ImportPath}}: {{.Error.Err}}{else}}"
if neg {
tmpl += "{{if .Stale}}{{.ImportPath}} is unexpectedly stale{{end}}"
} else {
tmpl += "{{if not .Stale}}{{.ImportPath}} is unexpectedly NOT stale{{end}}"
}
tmpl += "{{end}}"
goArgs := append([]string{"list", "-e", "-f=" + tmpl}, args...)
stdout, stderr, err := ts.exec(testGo, goArgs...)
if err != nil {
ts.fatalf("go list: %v\n%s%s", err, stdout, stderr)
}
if stdout != "" {
ts.fatalf("%s", stdout)
}
}
// stdout checks that the last go command standard output matches a regexp.
func (ts *testScript) cmdStdout(neg bool, args []string) {
scriptMatch(ts, neg, args, ts.stdout, "stdout")
}
// stderr checks that the last go command standard output matches a regexp.
func (ts *testScript) cmdStderr(neg bool, args []string) {
scriptMatch(ts, neg, args, ts.stderr, "stderr")
}
// grep checks that file content matches a regexp.
// Like stdout/stderr and unlike Unix grep, it accepts Go regexp syntax.
func (ts *testScript) cmdGrep(neg bool, args []string) {
scriptMatch(ts, neg, args, "", "grep")
}
// scriptMatch implements both stdout and stderr.
func scriptMatch(ts *testScript, neg bool, args []string, text, name string) {
n := 0
if len(args) >= 1 && strings.HasPrefix(args[0], "-count=") {
if neg {
ts.fatalf("cannot use -count= with negated match")
}
var err error
n, err = strconv.Atoi(args[0][len("-count="):])
if err != nil {
ts.fatalf("bad -count=: %v", err)
}
if n < 1 {
ts.fatalf("bad -count=: must be at least 1")
}
args = args[1:]
}
extraUsage := ""
want := 1
if name == "grep" {
extraUsage = " file"
want = 2
}
if len(args) != want {
ts.fatalf("usage: %s [-count=N] 'pattern' file%s", name, extraUsage)
}
pattern := args[0]
re, err := regexp.Compile(`(?m)` + pattern)
ts.check(err)
isGrep := name == "grep"
if isGrep {
name = args[1] // for error messages
data, err := ioutil.ReadFile(ts.mkabs(args[1]))
ts.check(err)
text = string(data)
}
if neg {
if re.MatchString(text) {
if isGrep {
fmt.Fprintf(&ts.log, "[%s]\n%s\n", name, text)
}
ts.fatalf("unexpected match for %#q found in %s: %s", pattern, name, re.FindString(text))
}
} else {
if !re.MatchString(text) {
if isGrep {
fmt.Fprintf(&ts.log, "[%s]\n%s\n", name, text)
}
ts.fatalf("no match for %#q found in %s", pattern, name)
}
if n > 0 {
count := len(re.FindAllString(text, -1))
if count != n {
if isGrep {
fmt.Fprintf(&ts.log, "[%s]\n%s\n", name, text)
}
ts.fatalf("have %d matches for %#q, want %d", count, pattern, n)
}
}
}
}
// stop stops execution of the test (marking it passed).
func (ts *testScript) cmdStop(neg bool, args []string) {
if neg {
ts.fatalf("unsupported: ! stop")
}
if len(args) > 1 {
ts.fatalf("usage: stop [msg]")
}
if len(args) == 1 {
fmt.Fprintf(&ts.log, "stop: %s\n", args[0])
} else {
fmt.Fprintf(&ts.log, "stop\n")
}
ts.stopped = true
}
// symlink creates a symbolic link.
func (ts *testScript) cmdSymlink(neg bool, args []string) {
if neg {
ts.fatalf("unsupported: ! symlink")
}
if len(args) != 3 || args[1] != "->" {
ts.fatalf("usage: symlink file -> target")
}
// Note that the link target args[2] is not interpreted with mkabs:
// it will be interpreted relative to the directory file is in.
ts.check(os.Symlink(args[2], ts.mkabs(args[0])))
}
// Helpers for command implementations.
// abbrev abbreviates the actual work directory in the string s to the literal string "$WORK".
func (ts *testScript) abbrev(s string) string {
s = strings.Replace(s, ts.workdir, "$WORK", -1)
if *testWork {
// Expose actual $WORK value in environment dump on first line of work script,
// so that the user can find out what directory -testwork left behind.
s = "WORK=" + ts.workdir + "\n" + strings.TrimPrefix(s, "WORK=$WORK\n")
}
return s
}
// check calls ts.fatalf if err != nil.
func (ts *testScript) check(err error) {
if err != nil {
ts.fatalf("%v", err)
}
}
// exec runs the given command line (an actual subprocess, not simulated)
// in ts.cd with environment ts.env and then returns collected standard output and standard error.
func (ts *testScript) exec(command string, args ...string) (stdout, stderr string, err error) {
cmd := exec.Command(testGo, args...)
cmd.Dir = ts.cd
cmd.Env = append(ts.env, "PWD="+ts.cd)
var stdoutBuf, stderrBuf strings.Builder
cmd.Stdout = &stdoutBuf
cmd.Stderr = &stderrBuf
err = cmd.Run()
return stdoutBuf.String(), stderrBuf.String(), err
}
// expand applies environment variable expansion to the string s.
func (ts *testScript) expand(s string) string {
return os.Expand(s, func(key string) string { return ts.envMap[key] })
}
// fatalf aborts the test with the given failure message.
func (ts *testScript) fatalf(format string, args ...interface{}) {
fmt.Fprintf(&ts.log, "FAIL: %s:%d: %s\n", ts.file, ts.lineno, fmt.Sprintf(format, args...))
ts.t.FailNow()
}
// mkabs interprets file relative to the test script's current directory
// and returns the corresponding absolute path.
func (ts *testScript) mkabs(file string) string {
if filepath.IsAbs(file) {
return file
}
return filepath.Join(ts.cd, file)
}
// parse parses a single line as a list of space-separated arguments
// subject to environment variable expansion (but not resplitting).
// Single quotes around text disable splitting and expansion.
// To embed a single quote, double it: 'Don''t communicate by sharing memory.'
func (ts *testScript) parse(line string) []string {
ts.line = line
var (
args []string
arg string // text of current arg so far (need to add line[start:i])
start = -1 // if >= 0, position where current arg text chunk starts
quoted = false // currently processing quoted text
)
for i := 0; ; i++ {
if !quoted && (i >= len(line) || line[i] == ' ' || line[i] == '\t' || line[i] == '\r' || line[i] == '#') {
// Found arg-separating space.
if start >= 0 {
arg += ts.expand(line[start:i])
args = append(args, arg)
start = -1
arg = ""
}
if i >= len(line) || line[i] == '#' {
break
}
continue
}
if i >= len(line) {
ts.fatalf("unterminated quoted argument")
}
if line[i] == '\'' {
if !quoted {
// starting a quoted chunk
if start >= 0 {
arg += ts.expand(line[start:i])
}
start = i + 1
quoted = true
continue
}
// 'foo''bar' means foo'bar, like in rc shell and Pascal.
if i+1 < len(line) && line[i+1] == '\'' {
arg += line[start:i]
start = i + 1
i++ // skip over second ' before next iteration
continue
}
// ending a quoted chunk
arg += line[start:i]
start = i + 1
quoted = false
continue
}
// found character worth saving; make sure we're saving
if start < 0 {
start = i
}
}
return args
}
// diff returns a formatted diff of the two texts,
// showing the entire text and the minimum line-level
// additions and removals to turn text1 into text2.
// (That is, lines only in text1 appear with a leading -,
// and lines only in text2 appear with a leading +.)
func diff(text1, text2 string) string {
if text1 != "" && !strings.HasSuffix(text1, "\n") {
text1 += "(missing final newline)"
}
lines1 := strings.Split(text1, "\n")
lines1 = lines1[:len(lines1)-1] // remove empty string after final line
if text2 != "" && !strings.HasSuffix(text2, "\n") {
text2 += "(missing final newline)"
}
lines2 := strings.Split(text2, "\n")
lines2 = lines2[:len(lines2)-1] // remove empty string after final line
// Naive dynamic programming algorithm for edit distance.
// https://en.wikipedia.org/wiki/Wagner–Fischer_algorithm
// dist[i][j] = edit distance between lines1[:len(lines1)-i] and lines2[:len(lines2)-j]
// (The reversed indices make following the minimum cost path
// visit lines in the same order as in the text.)
dist := make([][]int, len(lines1)+1)
for i := range dist {
dist[i] = make([]int, len(lines2)+1)
if i == 0 {
for j := range dist[0] {
dist[0][j] = j
}
continue
}
for j := range dist[i] {
if j == 0 {
dist[i][0] = i
continue
}
cost := dist[i][j-1] + 1
if cost > dist[i-1][j]+1 {
cost = dist[i-1][j] + 1
}
if lines1[len(lines1)-i] == lines2[len(lines2)-j] {
if cost > dist[i-1][j-1] {
cost = dist[i-1][j-1]
}
}
dist[i][j] = cost
}
}
var buf strings.Builder
i, j := len(lines1), len(lines2)
for i > 0 || j > 0 {
cost := dist[i][j]
if i > 0 && j > 0 && cost == dist[i-1][j-1] && lines1[len(lines1)-i] == lines2[len(lines2)-j] {
fmt.Fprintf(&buf, " %s\n", lines1[len(lines1)-i])
i--
j--
} else if i > 0 && cost == dist[i-1][j]+1 {
fmt.Fprintf(&buf, "-%s\n", lines1[len(lines1)-i])
i--
} else {
fmt.Fprintf(&buf, "+%s\n", lines2[len(lines2)-j])
j--
}
}
return buf.String()
}
var diffTests = []struct {
text1 string
text2 string
diff string
}{
{"a b c", "a b d e f", "a b -c +d +e +f"},
{"", "a b c", "+a +b +c"},
{"a b c", "", "-a -b -c"},
{"a b c", "d e f", "-a -b -c +d +e +f"},
{"a b c d e f", "a b d e f", "a b -c d e f"},
{"a b c e f", "a b c d e f", "a b c +d e f"},
}
func TestDiff(t *testing.T) {
for _, tt := range diffTests {
// Turn spaces into \n.
text1 := strings.Replace(tt.text1, " ", "\n", -1)
if text1 != "" {
text1 += "\n"
}
text2 := strings.Replace(tt.text2, " ", "\n", -1)
if text2 != "" {
text2 += "\n"
}
out := diff(text1, text2)
// Cut final \n, cut spaces, turn remaining \n into spaces.
out = strings.Replace(strings.Replace(strings.TrimSuffix(out, "\n"), " ", "", -1), "\n", " ", -1)
if out != tt.diff {
t.Errorf("diff(%q, %q) = %q, want %q", text1, text2, out, tt.diff)
}
}
}

57
vendor/cmd/go/testdata/mod/mod_sync.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,57 @@
env GO111MODULE=on
# sync removes unused y, but everything else is used
go mod -sync -v
stderr '^unused y.1'
! stderr '^unused [^y]'
go list -m all
! stdout '^y'
stdout '^w.1 v1.2.0'
stdout '^z.1 v1.2.0'
-- go.mod --
module m
require (
x.1 v1.0.0
y.1 v1.0.0
w.1 v1.2.0
)
replace x.1 v1.0.0 => ../x
replace y.1 v1.0.0 => ../y
replace z.1 v1.1.0 => ../z
replace z.1 v1.2.0 => ../z
replace w.1 => ../w
-- m.go --
package m
import _ "x.1"
import _ "z.1/sub"
-- w/go.mod --
module w
-- w/w.go --
package w
-- x/go.mod --
module x
require w.1 v1.1.0
require z.1 v1.1.0
-- x/x.go --
package x
import _ "w.1"
-- y/go.mod --
module y
require z.1 v1.2.0
-- z/go.mod --
module z
-- z/sub/sub.go --
package sub

88
vendor/cmd/go/testdata/mod/rsc.io_!q!u!o!t!e_v1.5.2.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,88 @@
rsc.io/quote@v2.0.0 && cp mod/rsc.io_quote_v0.0.0-20180709153244-fd906ed3b100.txt mod/rsc.io_quote_v2.0.0.txt
-- .mod --
module rsc.io/QUOTE
require rsc.io/quote v1.5.2
-- .info --
{"Version":"v1.5.2","Name":"","Short":"","Time":"2018-07-15T16:25:34Z"}
-- go.mod --
module rsc.io/QUOTE
require rsc.io/quote v1.5.2
-- QUOTE/quote.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 QUOTE COLLECTS LOUD SAYINGS.
package QUOTE
import (
"strings"
"rsc.io/quote"
)
// HELLO RETURNS A GREETING.
func HELLO() string {
return strings.ToUpper(quote.Hello())
}
// GLASS RETURNS A USEFUL PHRASE FOR WORLD TRAVELERS.
func GLASS() string {
return strings.ToUpper(quote.GLASS())
}
// GO RETURNS A GO PROVERB.
func GO() string {
return strings.ToUpper(quote.GO())
}
// OPT RETURNS AN OPTIMIZATION TRUTH.
func OPT() string {
return strings.ToUpper(quote.OPT())
}
-- QUOTE/quote_test.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 QUOTE
import (
"os"
"testing"
)
func init() {
os.Setenv("LC_ALL", "en")
}
func TestHELLO(t *testing.T) {
hello := "HELLO, WORLD"
if out := HELLO(); out != hello {
t.Errorf("HELLO() = %q, want %q", out, hello)
}
}
func TestGLASS(t *testing.T) {
glass := "I CAN EAT GLASS AND IT DOESN'T HURT ME."
if out := GLASS(); out != glass {
t.Errorf("GLASS() = %q, want %q", out, glass)
}
}
func TestGO(t *testing.T) {
go1 := "DON'T COMMUNICATE BY SHARING MEMORY, SHARE MEMORY BY COMMUNICATING."
if out := GO(); out != go1 {
t.Errorf("GO() = %q, want %q", out, go1)
}
}
func TestOPT(t *testing.T) {
opt := "IF A PROGRAM IS TOO SLOW, IT MUST HAVE A LOOP."
if out := OPT(); out != opt {
t.Errorf("OPT() = %q, want %q", out, opt)
}
}

14
vendor/cmd/go/testdata/mod/rsc.io_badfile1_v1.0.0.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,14 @@
rsc.io/badfile1 v1.0.0
written by hand
this is part of the badfile test but is a valid zip file.
-- .mod --
module rsc.io/badfile1
-- .info --
{"Version":"v1.0.0"}
-- go.mod --
module rsc.io/badfile1
-- α.go --
package α
-- .gitignore --
-- x/y/z/.gitignore --

12
vendor/cmd/go/testdata/mod/rsc.io_badfile2_v1.0.0.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,12 @@
rsc.io/badfile1 v1.0.0
written by hand
-- .mod --
module rsc.io/badfile2
-- .info --
{"Version":"v1.0.0"}
-- go.mod --
module rsc.io/badfile2
-- ☺.go --
package smiley

12
vendor/cmd/go/testdata/mod/rsc.io_badfile3_v1.0.0.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,12 @@
rsc.io/badfile3 v1.0.0
written by hand
-- .mod --
module rsc.io/badfile3
-- .info --
{"Version":"v1.0.0"}
-- go.mod --
module rsc.io/badfile3
-- x?y.go --
package x

15
vendor/cmd/go/testdata/mod/rsc.io_badfile4_v1.0.0.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,15 @@
rsc.io/badfile4 v1.0.0
written by hand
-- .mod --
module rsc.io/badfile4
-- .info --
{"Version":"v1.0.0"}
-- go.mod --
module rsc.io/badfile4
-- x/Y.go --
package x
-- x/y.go --
package x

13
vendor/cmd/go/testdata/mod/rsc.io_badfile5_v1.0.0.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,13 @@
rsc.io/badfile5 v1.0.0
written by hand
-- .mod --
module rsc.io/badfile5
-- .info --
{"Version":"v1.0.0"}
-- go.mod --
module rsc.io/badfile5
-- x/y/z/w.go --
package z
-- x/Y/zz/ww.go --
package zz

11
vendor/cmd/go/testdata/mod/rsc.io_breaker_v1.0.0.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,11 @@
rsc.io/breaker v1.0.0
written by hand
-- .mod --
module rsc.io/breaker
-- .info --
{"Version":"v1.0.0"}
-- breaker.go --
package breaker
const X = 1

Просмотреть файл

@ -0,0 +1,11 @@
rsc.io/breaker v2.0.0+incompatible
written by hand
-- .mod --
module rsc.io/breaker
-- .info --
{"Version":"v2.0.0+incompatible", "Name": "7307b307f4f0dde421900f8e5126fadac1e13aed", "Short": "7307b307f4f0"}
-- breaker.go --
package breaker
const XX = 2

11
vendor/cmd/go/testdata/mod/rsc.io_breaker_v2.0.0.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,11 @@
rsc.io/breaker v2.0.0+incompatible
written by hand
-- .mod --
module rsc.io/breaker
-- .info --
{"Version":"v2.0.0+incompatible", "Name": "7307b307f4f0dde421900f8e5126fadac1e13aed", "Short": "7307b307f4f0"}
-- breaker.go --
package breaker
const XX = 2

Просмотреть файл

@ -1,166 +0,0 @@
generated by: go run savedir.go .
-- LICENSE --
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- README.md --
This package collects pithy sayings.
It's part of a demonstration of
[package versioning in Go](https://research.swtch.com/vgo1).
-- buggy/buggy_test.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 buggy
import "testing"
func Test(t *testing.T) {
t.Fatal("buggy!")
}
-- go.mod --
module rsc.io/quote
require rsc.io/sampler v1.3.0
-- quote.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 quote collects pithy sayings.
package quote // import "rsc.io/quote"
import "rsc.io/quote/v2"
// Hello returns a greeting.
func Hello() string {
return quote.HelloV2()
}
// Glass returns a useful phrase for world travelers.
func Glass() string {
// See http://www.oocities.org/nodotus/hbglass.html.
return quote.GlassV2()
}
// Go returns a Go proverb.
func Go() string {
return quote.GoV2()
}
// Opt returns an optimization truth.
func Opt() string {
// Wisdom from ken.
return quote.OptV2()
}
-- quote_test.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 quote
import (
"os"
"testing"
)
func init() {
os.Setenv("LC_ALL", "en")
}
func TestHello(t *testing.T) {
hello := "Hello, world."
if out := Hello(); out != hello {
t.Errorf("Hello() = %q, want %q", out, hello)
}
}
func TestGlass(t *testing.T) {
glass := "I can eat glass and it doesn't hurt me."
if out := Glass(); out != glass {
t.Errorf("Glass() = %q, want %q", out, glass)
}
}
func TestGo(t *testing.T) {
go1 := "Don't communicate by sharing memory, share memory by communicating."
if out := Go(); out != go1 {
t.Errorf("Go() = %q, want %q", out, go1)
}
}
func TestOpt(t *testing.T) {
opt := "If a program is too slow, it must have a loop."
if out := Opt(); out != opt {
t.Errorf("Opt() = %q, want %q", out, opt)
}
}
-- v3/go.mod --
module rsc.io/quote/v3
require rsc.io/sampler v1.3.0
-- v3/go.sum --
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/sampler v1.99.99 h1:7i08f/p5TBU5joCPW3GjWG1ZFCmr28ybGqlXtelhEK8=
rsc.io/sampler v1.99.99/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
-- v3/quote.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 quote collects pithy sayings.
package quote // import "rsc.io/quote"
import "rsc.io/sampler"
// Hello returns a greeting.
func HelloV3() string {
return sampler.Hello()
}
// Glass returns a useful phrase for world travelers.
func GlassV3() string {
// See http://www.oocities.org/nodotus/hbglass.html.
return "I can eat glass and it doesn't hurt me."
}
// Go returns a Go proverb.
func GoV3() string {
return "Don't communicate by sharing memory, share memory by communicating."
}
// Opt returns an optimization truth.
func OptV3() string {
// Wisdom from ken.
return "If a program is too slow, it must have a loop."
}

Просмотреть файл

@ -1,151 +0,0 @@
generated by: go run savedir.go .
-- LICENSE --
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- README.md --
This package collects pithy sayings.
It's part of a demonstration of
[package versioning in Go](https://research.swtch.com/vgo1).
-- buggy/buggy_test.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 buggy
import "testing"
func Test(t *testing.T) {
t.Fatal("buggy!")
}
-- go.mod --
module rsc.io/quote
require (
rsc.io/quote/v3 v3.0.0
rsc.io/sampler v1.3.0
)
-- quote.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 quote collects pithy sayings.
package quote // import "rsc.io/quote"
import "rsc.io/quote/v3"
// Hello returns a greeting.
func Hello() string {
return quote.HelloV3()
}
// Glass returns a useful phrase for world travelers.
func Glass() string {
// See http://www.oocities.org/nodotus/hbglass.html.
return quote.GlassV3()
}
// Go returns a Go proverb.
func Go() string {
return quote.GoV3()
}
// Opt returns an optimization truth.
func Opt() string {
// Wisdom from ken.
return quote.OptV3()
}
-- quote_test.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 quote
import (
"os"
"testing"
)
func init() {
os.Setenv("LC_ALL", "en")
}
func TestHello(t *testing.T) {
hello := "Hello, world."
if out := Hello(); out != hello {
t.Errorf("Hello() = %q, want %q", out, hello)
}
}
func TestGlass(t *testing.T) {
glass := "I can eat glass and it doesn't hurt me."
if out := Glass(); out != glass {
t.Errorf("Glass() = %q, want %q", out, glass)
}
}
func TestGo(t *testing.T) {
go1 := "Don't communicate by sharing memory, share memory by communicating."
if out := Go(); out != go1 {
t.Errorf("Go() = %q, want %q", out, go1)
}
}
func TestOpt(t *testing.T) {
opt := "If a program is too slow, it must have a loop."
if out := Opt(); out != opt {
t.Errorf("Opt() = %q, want %q", out, opt)
}
}
-- v3/go.mod --
module rsc.io/quote/v3
require rsc.io/sampler v1.3.0
-- v3/go.sum --
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/sampler v1.99.99 h1:7i08f/p5TBU5joCPW3GjWG1ZFCmr28ybGqlXtelhEK8=
rsc.io/sampler v1.99.99/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
-- v3/quote.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 quote collects pithy sayings.
package quote // import "rsc.io/quote"
import "rsc.io/sampler"
// Hello returns a greeting.
func HelloV3() string {
return sampler.Hello()

Просмотреть файл

@ -1,148 +0,0 @@
generated by: go run savedir.go .
-- LICENSE --
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- README.md --
This package collects pithy sayings.
It's part of a demonstration of
[package versioning in Go](https://research.swtch.com/vgo1).
-- buggy/buggy_test.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 buggy
import "testing"
func Test(t *testing.T) {
t.Fatal("buggy!")
}
-- go.mod --
module rsc.io/quote
require rsc.io/sampler v1.3.0
-- quote.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 quote collects pithy sayings.
package quote // import "rsc.io/quote"
import "rsc.io/quote/v3"
// Hello returns a greeting.
func Hello() string {
return quote.HelloV3()
}
// Glass returns a useful phrase for world travelers.
func Glass() string {
// See http://www.oocities.org/nodotus/hbglass.html.
return quote.GlassV3()
}
// Go returns a Go proverb.
func Go() string {
return quote.GoV3()
}
// Opt returns an optimization truth.
func Opt() string {
// Wisdom from ken.
return quote.OptV3()
}
-- quote_test.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 quote
import (
"os"
"testing"
)
func init() {
os.Setenv("LC_ALL", "en")
}
func TestHello(t *testing.T) {
hello := "Hello, world."
if out := Hello(); out != hello {
t.Errorf("Hello() = %q, want %q", out, hello)
}
}
func TestGlass(t *testing.T) {
glass := "I can eat glass and it doesn't hurt me."
if out := Glass(); out != glass {
t.Errorf("Glass() = %q, want %q", out, glass)
}
}
func TestGo(t *testing.T) {
go1 := "Don't communicate by sharing memory, share memory by communicating."
if out := Go(); out != go1 {
t.Errorf("Go() = %q, want %q", out, go1)
}
}
func TestOpt(t *testing.T) {
opt := "If a program is too slow, it must have a loop."
if out := Opt(); out != opt {
t.Errorf("Opt() = %q, want %q", out, opt)
}
}
-- v3/go.mod --
module rsc.io/quote/v3
require rsc.io/sampler v1.3.0
-- v3/go.sum --
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/sampler v1.99.99 h1:7i08f/p5TBU5joCPW3GjWG1ZFCmr28ybGqlXtelhEK8=
rsc.io/sampler v1.99.99/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
-- v3/quote.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 quote collects pithy sayings.
package quote // import "rsc.io/quote"
import "rsc.io/sampler"
// Hello returns a greeting.
func HelloV3() string {
return sampler.Hello()

Просмотреть файл

@ -1,169 +0,0 @@
generated by: go run savedir.go .
-- LICENSE --
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- README.md --
This package collects pithy sayings.
It's part of a demonstration of
[package versioning in Go](https://research.swtch.com/vgo1).
-- buggy/buggy_test.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 buggy
import "testing"
func Test(t *testing.T) {
t.Fatal("buggy!")
}
-- go.mod --
module rsc.io/quote
require (
rsc.io/quote/v2 v2.0.1
rsc.io/sampler v1.3.0
)
-- quote.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 quote collects pithy sayings.
package quote // import "rsc.io/quote"
import "rsc.io/quote/v2"
// Hello returns a greeting.
func Hello() string {
return quote.HelloV2()
}
// Glass returns a useful phrase for world travelers.
func Glass() string {
// See http://www.oocities.org/nodotus/hbglass.html.
return quote.GlassV2()
}
// Go returns a Go proverb.
func Go() string {
return quote.GoV2()
}
// Opt returns an optimization truth.
func Opt() string {
// Wisdom from ken.
return quote.OptV2()
}
-- quote_test.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 quote
import (
"os"
"testing"
)
func init() {
os.Setenv("LC_ALL", "en")
}
func TestHello(t *testing.T) {
hello := "Hello, world."
if out := Hello(); out != hello {
t.Errorf("Hello() = %q, want %q", out, hello)
}
}
func TestGlass(t *testing.T) {
glass := "I can eat glass and it doesn't hurt me."
if out := Glass(); out != glass {
t.Errorf("Glass() = %q, want %q", out, glass)
}
}
func TestGo(t *testing.T) {
go1 := "Don't communicate by sharing memory, share memory by communicating."
if out := Go(); out != go1 {
t.Errorf("Go() = %q, want %q", out, go1)
}
}
func TestOpt(t *testing.T) {
opt := "If a program is too slow, it must have a loop."
if out := Opt(); out != opt {
t.Errorf("Opt() = %q, want %q", out, opt)
}
}
-- v3/go.mod --
module rsc.io/quote/v3
require rsc.io/sampler v1.3.0
-- v3/go.sum --
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/sampler v1.99.99 h1:7i08f/p5TBU5joCPW3GjWG1ZFCmr28ybGqlXtelhEK8=
rsc.io/sampler v1.99.99/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
-- v3/quote.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 quote collects pithy sayings.
package quote // import "rsc.io/quote"
import "rsc.io/sampler"
// Hello returns a greeting.
func HelloV3() string {
return sampler.Hello()
}
// Glass returns a useful phrase for world travelers.
func GlassV3() string {
// See http://www.oocities.org/nodotus/hbglass.html.
return "I can eat glass and it doesn't hurt me."
}
// Go returns a Go proverb.
func GoV3() string {
return "Don't communicate by sharing memory, share memory by communicating."
}
// Opt returns an optimization truth.
func OptV3() string {
// Wisdom from ken.
return "If a program is too slow, it must have a loop."
}

Просмотреть файл

@ -1,151 +0,0 @@
generated by: go run savedir.go .
-- LICENSE --
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- README.md --
This package collects pithy sayings.
It's part of a demonstration of
[package versioning in Go](https://research.swtch.com/vgo1).
-- buggy/buggy_test.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 buggy
import "testing"
func Test(t *testing.T) {
t.Fatal("buggy!")
}
-- go.mod --
module rsc.io/quote
require (
rsc.io/quote/v2 v2.0.1
rsc.io/sampler v1.3.0
)
-- quote.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 quote collects pithy sayings.
package quote // import "rsc.io/quote"
import "rsc.io/quote/v2"
// Hello returns a greeting.
func Hello() string {
return quote.HelloV2()
}
// Glass returns a useful phrase for world travelers.
func Glass() string {
// See http://www.oocities.org/nodotus/hbglass.html.
return quote.GlassV2()
}
// Go returns a Go proverb.
func Go() string {
return quote.GoV2()
}
// Opt returns an optimization truth.
func Opt() string {
// Wisdom from ken.
return quote.OptV2()
}
-- quote_test.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 quote
import (
"os"
"testing"
)
func init() {
os.Setenv("LC_ALL", "en")
}
func TestHello(t *testing.T) {
hello := "Hello, world."
if out := Hello(); out != hello {
t.Errorf("Hello() = %q, want %q", out, hello)
}
}
func TestGlass(t *testing.T) {
glass := "I can eat glass and it doesn't hurt me."
if out := Glass(); out != glass {
t.Errorf("Glass() = %q, want %q", out, glass)
}
}
func TestGo(t *testing.T) {
go1 := "Don't communicate by sharing memory, share memory by communicating."
if out := Go(); out != go1 {
t.Errorf("Go() = %q, want %q", out, go1)
}
}
func TestOpt(t *testing.T) {
opt := "If a program is too slow, it must have a loop."
if out := Opt(); out != opt {
t.Errorf("Opt() = %q, want %q", out, opt)
}
}
-- v3/go.mod --
module rsc.io/quote/v3
require rsc.io/sampler v1.3.0
-- v3/go.sum --
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/sampler v1.99.99 h1:7i08f/p5TBU5joCPW3GjWG1ZFCmr28ybGqlXtelhEK8=
rsc.io/sampler v1.99.99/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
-- v3/quote.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 quote collects pithy sayings.
package quote // import "rsc.io/quote"
import "rsc.io/sampler"
// Hello returns a greeting.
func HelloV3() string {
return sampler.Hello()

261
vendor/cmd/go/testdata/script/README поставляемый Normal file
Просмотреть файл

@ -0,0 +1,261 @@
This directory holds test scripts *.txt run during 'go test cmd/go'.
To run a specific script foo.txt
go test cmd/go -run=Script/^foo$
In general script files should have short names: a few words, not whole sentences.
The first word should be the general category of behavior being tested,
often the name of a go subcommand (list, build, test, ...) or concept (vendor, pattern).
Each script is a text archive (go doc cmd/go/internal/txtar).
The script begins with an actual command script to run
followed by the content of zero or more supporting files to
create in the script's temporary file system before it starts executing.
As an example, run_hello.txt says:
# hello world
go run hello.go
stderr 'hello world'
! stdout .
-- hello.go --
package main
func main() { println("hello world") }
Each script runs in a fresh temporary work directory tree, available to scripts as $WORK.
Scripts also have access to these other environment variables:
GOARCH=<target GOARCH>
GOCACHE=<actual GOCACHE being used outside the test>
GOOS=<target GOOS>
GOPATH=$WORK/gopath
GOPROXY=<local module proxy serving from cmd/go/testdata/mod>
GOROOT=<actual GOROOT>
HOME=/no-home
PATH=<actual PATH>
TMPDIR=$WORK/tmp
devnull=<value of os.DevNull>
The environment variable $exe (lowercase) is an empty string on most systems, ".exe" on Windows.
The scripts supporting files are unpacked relative to $GOPATH/src (aka $WORK/gopath/src)
and then the script begins execution in that directory as well. Thus the example above runs
in $WORK/gopath/src with GOPATH=$WORK/gopath and $WORK/gopath/src/hello.go
containing the listed contents.
The lines at the top of the script are a sequence of commands to be executed
by a tiny script engine in ../../script_test.go (not the system shell).
The script stops and the overall test fails if any particular command fails.
Each line is parsed into a sequence of space-separated command words,
with environment variable expansion and # marking an end-of-line comment.
Adding single quotes around text keeps spaces in that text from being treated
as word separators and also disables environment variable expansion.
Inside a single-quoted block of text, a repeated single quote indicates
a literal single quote, as in:
'Don''t communicate by sharing memory.'
A line beginning with # is a comment and conventionally explains what is
being done or tested at the start of a new phase in the script.
The command prefix ! indicates that the command on the rest of the line
(typically go or a matching predicate) must fail, not succeed. Only certain
commands support this prefix. They are indicated below by [!] in the synopsis.
The command prefix [cond] indicates that the command on the rest of the line
should only run when the condition is satisfied. The available conditions are:
- GOOS and GOARCH values, like [386], [windows], and so on.
- Compiler names, like [gccgo], [gc].
- Test environment details:
- [short] for testing.Short()
- [cgo], [msan], [race] for whether cgo, msan, and the race detector can be used
- [net] for whether the external network can be used
- [link] for testenv.HasLink()
- [symlink] for testenv.HasSymlink()
- [exec:prog] for whether prog is available for execution (found by exec.LookPath)
A condition can be negated: [!short] means to run the rest of the line
when testing.Short() is false.
The commands are:
- cd dir
Change to the given directory for future commands.
- cmp file1 file2
Check that the named files have the same content.
By convention, file1 is the actual data and file2 the expected data.
File1 can be "stdout" or "stderr" to use the standard output or standard error
from the most recent exec or go command.
(If the files have differing content, the failure prints a diff.)
- cp src... dst
Copy the listed files to the target file or existing directory.
- env [key=value...]
With no arguments, print the environment (useful for debugging).
Otherwise add the listed key=value pairs to the environment.
- [!] exec program [args...]
Run the given executable program with the arguments.
It must (or must not) succeed.
Note that 'exec' does not terminate the script (unlike in Unix shells).
- [!] exists [-readonly] file...
Each of the listed files or directories must (or must not) exist.
If -readonly is given, the files or directories must be unwritable.
- [!] go args...
Run the (test copy of the) go command with the given arguments.
It must (or must not) succeed.
- [!] grep [-count=N] pattern file
The file's content must (or must not) match the regular expression pattern.
For positive matches, -count=N specifies an exact number of matches to require.
- mkdir path...
Create the listed directories, if they do not already exists.
- rm file...
Remove the listed files or directories.
- skip [message]
Mark the test skipped, including the message if given.
- [!] stale path...
The packages named by the path arguments must (or must not)
be reported as "stale" by the go command.
- [!] stderr [-count=N] pattern
Apply the grep command (see above) to the standard error
from the most recent exec or go command.
- [!] stdout [-count=N] pattern
Apply the grep command (see above) to the standard output
from the most recent exec or go command.
- stop [message]
Stop the test early (marking it as passing), including the message if given.
- symlink file -> target
Create file as a symlink to target. The -> (like in ls -l output) is required.
When TestScript runs a script and the script fails, by default TestScript shows
the execution of the most recent phase of the script (since the last # comment)
and only shows the # comments for earlier phases. For example, here is a
multi-phase script with a bug in it:
# GOPATH with p1 in d2, p2 in d2
env GOPATH=$WORK/d1:$WORK/d2
# build & install p1
env
go install -i p1
! stale p1
! stale p2
# modify p2 - p1 should appear stale
cp $WORK/p2x.go $WORK/d2/src/p2/p2.go
stale p1 p2
# build & install p1 again
go install -i p11
! stale p1
! stale p2
-- $WORK/d1/src/p1/p1.go --
package p1
import "p2"
func F() { p2.F() }
-- $WORK/d2/src/p2/p2.go --
package p2
func F() {}
-- $WORK/p2x.go --
package p2
func F() {}
func G() {}
The bug is that the final phase installs p11 instead of p1. The test failure looks like:
$ go test -run=Script
--- FAIL: TestScript (3.75s)
--- FAIL: TestScript/install_rebuild_gopath (0.16s)
script_test.go:223:
# GOPATH with p1 in d2, p2 in d2 (0.000s)
# build & install p1 (0.087s)
# modify p2 - p1 should appear stale (0.029s)
# build & install p1 again (0.022s)
> go install -i p11
[stderr]
can't load package: package p11: cannot find package "p11" in any of:
/Users/rsc/go/src/p11 (from $GOROOT)
$WORK/d1/src/p11 (from $GOPATH)
$WORK/d2/src/p11
[exit status 1]
FAIL: unexpected go command failure
script_test.go:73: failed at testdata/script/install_rebuild_gopath.txt:15 in $WORK/gopath/src
FAIL
exit status 1
FAIL cmd/go 4.875s
$
Note that the commands in earlier phases have been hidden, so that the relevant
commands are more easily found, and the elapsed time for a completed phase
is shown next to the phase heading. To see the entire execution, use "go test -v",
which also adds an initial environment dump to the beginning of the log.
Note also that in reported output, the actual name of the per-script temporary directory
has been consistently replaced with the literal string $WORK.
The cmd/go test flag -testwork (which must appear on the "go test" command line after
standard test flags) causes each test to log the name of its $WORK directory and other
environment variable settings and also to leave that directory behind when it exits,
for manual debugging of failing tests:
$ go test -run=Script -work
--- FAIL: TestScript (3.75s)
--- FAIL: TestScript/install_rebuild_gopath (0.16s)
script_test.go:223:
WORK=/tmp/cmd-go-test-745953508/script-install_rebuild_gopath
GOARCH=
GOCACHE=/Users/rsc/Library/Caches/go-build
GOOS=
GOPATH=$WORK/gopath
GOROOT=/Users/rsc/go
HOME=/no-home
TMPDIR=$WORK/tmp
exe=
# GOPATH with p1 in d2, p2 in d2 (0.000s)
# build & install p1 (0.085s)
# modify p2 - p1 should appear stale (0.030s)
# build & install p1 again (0.019s)
> go install -i p11
[stderr]
can't load package: package p11: cannot find package "p11" in any of:
/Users/rsc/go/src/p11 (from $GOROOT)
$WORK/d1/src/p11 (from $GOPATH)
$WORK/d2/src/p11
[exit status 1]
FAIL: unexpected go command failure
script_test.go:73: failed at testdata/script/install_rebuild_gopath.txt:15 in $WORK/gopath/src
FAIL
exit status 1
FAIL cmd/go 4.875s
$
$ WORK=/tmp/cmd-go-test-745953508/script-install_rebuild_gopath
$ cd $WORK/d1/src/p1
$ cat p1.go
package p1
import "p2"
func F() { p2.F() }
$

11
vendor/cmd/go/testdata/script/build_GOTMPDIR.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,11 @@
# Build should use GOTMPDIR if set.
env GOTMPDIR=$WORK/my-favorite-tmpdir
env GOCACHE=off
mkdir $GOTMPDIR
go build -work hello.go
stderr ^WORK=.*my-favorite-tmpdir
-- hello.go --
package main
func main() { println("hello") }

18
vendor/cmd/go/testdata/script/build_cache_compile.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,18 @@
# Set up fresh GOCACHE.
env GOCACHE=$WORK/gocache
mkdir $GOCACHE
# Building trivial non-main package should run compiler the first time.
go build -x lib.go
stderr '(compile|gccgo)( |\.exe).*lib\.go'
# ... but not again ...
go build -x lib.go
! stderr '(compile|gccgo)( |\.exe).*lib\.go'
# ... unless we use -a.
go build -a -x lib.go
stderr '(compile|gccgo)( |\.exe)'
-- lib.go --
package lib

23
vendor/cmd/go/testdata/script/build_cache_link.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,23 @@
# Set up fresh GOCACHE.
env GOCACHE=$WORK/gocache
mkdir $GOCACHE
# Building a main package should run the compiler and linker ...
go build -o $devnull -x main.go
stderr '(compile|gccgo)( |\.exe).*main\.go'
stderr '(link|gccgo)( |\.exe)'
# ... and then the linker again ...
go build -o $devnull -x main.go
! stderr '(compile|gccgo)( |\.exe).*main\.go'
stderr '(link|gccgo)( |\.exe)'
# ... but the output binary can serve as a cache.
go build -o main$exe -x main.go
stderr '(link|gccgo)( |\.exe)'
go build -o main$exe -x main.go
! stderr '(link|gccgo)( |\.exe)'
-- main.go --
package main
func main() {}

19
vendor/cmd/go/testdata/script/build_cache_output.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,19 @@
[!gc] skip
# Set up fresh GOCACHE.
env GOCACHE=$WORK/gocache
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 '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 'lib.go:2.* can inline f'
-- lib.go --
package p
func f(x *int) *int { return x }

6
vendor/cmd/go/testdata/script/fileline.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,6 @@
# look for short, relative file:line in error message
! go run ../../gopath/x/y/z/err.go
stderr ^..[\\/]x[\\/]y[\\/]z[\\/]err.go:
-- ../x/y/z/err.go --
package main; import "bar"

22
vendor/cmd/go/testdata/script/install_cleans_build.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,22 @@
# 'go install' with no arguments should clean up after go build
cd mycmd
go build
exists mycmd$exe
go install
! exists mycmd$exe
# 'go install mycmd' does not clean up, even in the mycmd directory
go build
exists mycmd$exe
go install mycmd
exists mycmd$exe
# 'go install mycmd' should not clean up in an unrelated current directory either
cd ..
cp mycmd/mycmd$exe mycmd$exe
go install mycmd
exists mycmd$exe
-- mycmd/main.go --
package main
func main() {}

23
vendor/cmd/go/testdata/script/install_cross_gobin.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,23 @@
cd mycmd
go build mycmd
# cross-compile install with implicit GOBIN=$GOPATH/bin can make subdirectory
env GOARCH=386
[386] env GOARCH=amd64
env GOOS=linux
go install mycmd
exists $GOPATH/bin/linux_$GOARCH/mycmd
# cross-compile install with explicit GOBIN cannot make subdirectory
env GOBIN=$WORK/bin
! go install mycmd
! exists $GOBIN/linux_$GOARCH
# installing standard command should still work
# (should also be mtime update only if cmd/pack is up-to-date).
! stale cmd/pack
[!short] go install cmd/pack
-- mycmd/x.go --
package main
func main() {}

29
vendor/cmd/go/testdata/script/install_rebuild_gopath.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,29 @@
# GOPATH with p1 in d1, p2 in d2
[!windows] env GOPATH=$WORK/d1:$WORK/d2
[windows] env GOPATH=$WORK/d1;$WORK/d2
# build & install p1
go install -i p1
! stale p1 p2
# modify p2 - p1 should appear stale
cp $WORK/p2x.go $WORK/d2/src/p2/p2.go
stale p1 p2
# build & install p1 again
go install -i p1
! stale p1 p2
-- $WORK/d1/src/p1/p1.go --
package p1
import "p2"
func F() { p2.F() }
-- $WORK/d2/src/p2/p2.go --
package p2
func F() {}
-- $WORK/p2x.go --
package p2
func F() {}
func G() {}

42
vendor/cmd/go/testdata/script/install_rebuild_removed.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,42 @@
# go command should detect package staleness as source file set changes
go install mypkg
! stale mypkg
# z.go was not compiled; removing it should NOT make mypkg stale
rm mypkg/z.go
! stale mypkg
# y.go was compiled; removing it should make mypkg stale
rm mypkg/y.go
stale mypkg
# go command should detect executable staleness too
go install mycmd
! stale mycmd
rm mycmd/z.go
! stale mycmd
rm mycmd/y.go
stale mycmd
-- mypkg/x.go --
package mypkg
-- mypkg/y.go --
package mypkg
-- mypkg/z.go --
// +build missingtag
package mypkg
-- mycmd/x.go --
package main
func main() {}
-- mycmd/y.go --
package main
-- mycmd/z.go --
// +build missingtag
package main

7
vendor/cmd/go/testdata/script/linkname.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,7 @@
# check for linker name in error message about linker crash
[!gc] skip
! go build -ldflags=-crash_for_testing x.go
stderr [\\/]tool[\\/].*[\\/]link
-- x.go --
package main; func main() {}

12
vendor/cmd/go/testdata/script/list_std.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,12 @@
[!gc] skip
# listing GOROOT should only find standard packages
cd $GOROOT/src
go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' ./...
! stdout .
# TODO: ignore _/blah/go/src in output
# our vendored packages should be reported as standard
go list std cmd
stdout golang_org/x/net/http2/hpack
stdout cmd/vendor/golang\.org/x/arch/x86/x86asm

8
vendor/cmd/go/testdata/script/list_tags.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,8 @@
# go list supports -tags
go list -tags=thetag ./my...
stdout mypkg
-- mypkg/x.go --
// +build thetag
package mypkg

21
vendor/cmd/go/testdata/script/mod_bad_domain.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,21 @@
env GO111MODULE=on
# explicit get should report errors about bad names
! go get appengine
stderr 'cannot find module providing package appengine'
! go get x/y.z
stderr 'cannot find module providing package x/y.z'
# build should skip over appengine imports
! go build
! stderr appengine
stderr 'cannot find module providing package nonexistent.rsc.io'
-- go.mod --
module x
-- x.go --
package x
import _ "appengine"
import _ "nonexistent.rsc.io" // domain does not exist

11
vendor/cmd/go/testdata/script/mod_bad_filenames.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,11 @@
env GO111MODULE=on
! go get rsc.io/badfile1 rsc.io/badfile2 rsc.io/badfile3 rsc.io/badfile4 rsc.io/badfile5
! stderr 'unzip.*badfile1'
stderr 'unzip.*badfile2[\\/]@v[\\/]v1.0.0.zip:.*malformed file path "☺.go": invalid char ''☺'''
stderr 'unzip.*badfile3[\\/]@v[\\/]v1.0.0.zip: malformed file path "x\?y.go": invalid char ''\?'''
stderr 'unzip.*badfile4[\\/]@v[\\/]v1.0.0.zip: case-insensitive file name collision: "x/Y.go" and "x/y.go"'
stderr 'unzip.*badfile5[\\/]@v[\\/]v1.0.0.zip: case-insensitive file name collision: "x/y" and "x/Y"'
-- go.mod --
module x

30
vendor/cmd/go/testdata/script/mod_build_tags.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,30 @@
# Test that build tags are used.
# golang.org/issue/24053.
env GO111MODULE=on
cd x
! go list -f {{.GoFiles}}
stderr 'build constraints exclude all Go files'
go list -f {{.GoFiles}} -tags tag1
stdout '\[x.go\]'
go list -f {{.GoFiles}} -tags tag2
stdout '\[y\.go\]'
go list -f {{.GoFiles}} -tags 'tag1 tag2'
stdout '\[x\.go y\.go\]'
-- x/go.mod --
module x
-- x/x.go --
// +build tag1
package y
-- x/y.go --
// +build tag2
package y

13
vendor/cmd/go/testdata/script/mod_case.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,13 @@
env GO111MODULE=on
go get rsc.io/QUOTE
go list -m all
stdout '^rsc.io/quote v1.5.2'
stdout '^rsc.io/QUOTE v1.5.2'
go list -f 'DIR {{.Dir}} DEPS {{.Deps}}' rsc.io/QUOTE/QUOTE
stdout 'DEPS.*rsc.io/quote'
stdout 'DIR.*!q!u!o!t!e'
-- go.mod --
module x

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше