libgo: update to Go1.13
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/194698 From-SVN: r275691
This commit is contained in:
parent
d6ecb707cc
commit
656297e1fe
|
@ -1,4 +1,4 @@
|
||||||
0950e905939f88c1421f8667ac4dc9e14528471c
|
ceb1e4f5614b4772eed44f9cf57780e52f44753e
|
||||||
|
|
||||||
The first line of this file holds the git revision number of the last
|
The first line of this file holds the git revision number of the last
|
||||||
merge done from the gofrontend repository.
|
merge done from the gofrontend repository.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
60f14fddfee107dedd76c0be6b422a3d8ccc841a
|
cc8838d645b2b7026c1f3aaceb011775c5ca3a08
|
||||||
|
|
||||||
The first line of this file holds the git revision number of the
|
The first line of this file holds the git revision number of the
|
||||||
last merge done from the master library sources.
|
last merge done from the master library sources.
|
||||||
|
|
|
@ -401,6 +401,7 @@ toolexeclibgounicode_DATA = \
|
||||||
# Force them to be built.
|
# Force them to be built.
|
||||||
noinst_DATA = \
|
noinst_DATA = \
|
||||||
golang.org/x/net/nettest.gox \
|
golang.org/x/net/nettest.gox \
|
||||||
|
internal/cfg.gox \
|
||||||
internal/testenv.gox \
|
internal/testenv.gox \
|
||||||
internal/trace.gox \
|
internal/trace.gox \
|
||||||
net/internal/socktest.gox \
|
net/internal/socktest.gox \
|
||||||
|
|
|
@ -856,10 +856,10 @@ toolexeclibgounicode_DATA = \
|
||||||
# Some packages are only needed for tests, so unlike the other
|
# Some packages are only needed for tests, so unlike the other
|
||||||
# internal packages nothing will explicitly depend on them.
|
# internal packages nothing will explicitly depend on them.
|
||||||
# Force them to be built.
|
# Force them to be built.
|
||||||
noinst_DATA = golang.org/x/net/nettest.gox internal/testenv.gox \
|
noinst_DATA = golang.org/x/net/nettest.gox internal/cfg.gox \
|
||||||
internal/trace.gox net/internal/socktest.gox \
|
internal/testenv.gox internal/trace.gox \
|
||||||
os/signal/internal/pty.gox runtime/pprof/internal/profile.gox \
|
net/internal/socktest.gox os/signal/internal/pty.gox \
|
||||||
zdefaultcc.go
|
runtime/pprof/internal/profile.gox zdefaultcc.go
|
||||||
@LIBGO_IS_RTEMS_FALSE@rtems_task_variable_add_file =
|
@LIBGO_IS_RTEMS_FALSE@rtems_task_variable_add_file =
|
||||||
@LIBGO_IS_RTEMS_TRUE@rtems_task_variable_add_file = runtime/rtems-task-variable-add.c
|
@LIBGO_IS_RTEMS_TRUE@rtems_task_variable_add_file = runtime/rtems-task-variable-add.c
|
||||||
runtime_files = \
|
runtime_files = \
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
go1.13beta1
|
go1.13
|
||||||
|
|
|
@ -106,7 +106,6 @@ image/png
|
||||||
index/suffixarray
|
index/suffixarray
|
||||||
internal/cpu
|
internal/cpu
|
||||||
internal/fmtsort
|
internal/fmtsort
|
||||||
internal/oserror
|
|
||||||
internal/poll
|
internal/poll
|
||||||
internal/reflectlite
|
internal/reflectlite
|
||||||
internal/singleflight
|
internal/singleflight
|
||||||
|
|
|
@ -811,10 +811,10 @@ func (p *Package) rewriteCall(f *File, call *Call) (string, bool) {
|
||||||
params := name.FuncType.Params
|
params := name.FuncType.Params
|
||||||
args := call.Call.Args
|
args := call.Call.Args
|
||||||
|
|
||||||
// Avoid a crash if the number of arguments is
|
// Avoid a crash if the number of arguments doesn't match
|
||||||
// less than the number of parameters.
|
// the number of parameters.
|
||||||
// This will be caught when the generated file is compiled.
|
// This will be caught when the generated file is compiled.
|
||||||
if len(args) < len(params) {
|
if len(args) != len(params) {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1257,6 +1257,8 @@ func (p *Package) isType(t ast.Expr) bool {
|
||||||
if strings.HasPrefix(t.Name, "_Ctype_") {
|
if strings.HasPrefix(t.Name, "_Ctype_") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
case *ast.ParenExpr:
|
||||||
|
return p.isType(t.X)
|
||||||
case *ast.StarExpr:
|
case *ast.StarExpr:
|
||||||
return p.isType(t.X)
|
return p.isType(t.X)
|
||||||
case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType,
|
case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType,
|
||||||
|
|
|
@ -273,6 +273,35 @@ func (p *Package) writeDefs() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// elfImportedSymbols is like elf.File.ImportedSymbols, but it
|
||||||
|
// includes weak symbols.
|
||||||
|
//
|
||||||
|
// A bug in some versions of LLD (at least LLD 8) cause it to emit
|
||||||
|
// several pthreads symbols as weak, but we need to import those. See
|
||||||
|
// issue #31912 or https://bugs.llvm.org/show_bug.cgi?id=42442.
|
||||||
|
//
|
||||||
|
// When doing external linking, we hand everything off to the external
|
||||||
|
// linker, which will create its own dynamic symbol tables. For
|
||||||
|
// internal linking, this may turn weak imports into strong imports,
|
||||||
|
// which could cause dynamic linking to fail if a symbol really isn't
|
||||||
|
// defined. However, the standard library depends on everything it
|
||||||
|
// imports, and this is the primary use of dynamic symbol tables with
|
||||||
|
// internal linking.
|
||||||
|
func elfImportedSymbols(f *elf.File) []elf.ImportedSymbol {
|
||||||
|
syms, _ := f.DynamicSymbols()
|
||||||
|
var imports []elf.ImportedSymbol
|
||||||
|
for _, s := range syms {
|
||||||
|
if (elf.ST_BIND(s.Info) == elf.STB_GLOBAL || elf.ST_BIND(s.Info) == elf.STB_WEAK) && s.Section == elf.SHN_UNDEF {
|
||||||
|
imports = append(imports, elf.ImportedSymbol{
|
||||||
|
Name: s.Name,
|
||||||
|
Library: s.Library,
|
||||||
|
Version: s.Version,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return imports
|
||||||
|
}
|
||||||
|
|
||||||
func dynimport(obj string) {
|
func dynimport(obj string) {
|
||||||
stdout := os.Stdout
|
stdout := os.Stdout
|
||||||
if *dynout != "" {
|
if *dynout != "" {
|
||||||
|
@ -295,7 +324,7 @@ func dynimport(obj string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sym, _ := f.ImportedSymbols()
|
sym := elfImportedSymbols(f)
|
||||||
for _, s := range sym {
|
for _, s := range sym {
|
||||||
targ := s.Name
|
targ := s.Name
|
||||||
if s.Version != "" {
|
if s.Version != "" {
|
||||||
|
|
|
@ -78,6 +78,8 @@
|
||||||
// If the arguments to build are a list of .go files from a single directory,
|
// If the arguments to build are a list of .go files from a single directory,
|
||||||
// build treats them as a list of source files specifying a single package.
|
// build treats them as a list of source files specifying a single package.
|
||||||
//
|
//
|
||||||
|
// When compiling packages, build ignores files that end in '_test.go'.
|
||||||
|
//
|
||||||
// When compiling a single main package, build writes
|
// When compiling a single main package, build writes
|
||||||
// the resulting executable to an output file named after
|
// the resulting executable to an output file named after
|
||||||
// the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe')
|
// the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe')
|
||||||
|
@ -88,8 +90,6 @@
|
||||||
// build compiles the packages but discards the resulting object,
|
// build compiles the packages but discards the resulting object,
|
||||||
// serving only as a check that the packages can be built.
|
// serving only as a check that the packages can be built.
|
||||||
//
|
//
|
||||||
// When compiling packages, build ignores files that end in '_test.go'.
|
|
||||||
//
|
|
||||||
// The -o flag forces build to write the resulting executable or object
|
// The -o flag forces build to write the resulting executable or object
|
||||||
// to the named output file or directory, instead of the default behavior described
|
// to the named output file or directory, instead of the default behavior described
|
||||||
// in the last two paragraphs. If the named output is a directory that exists,
|
// in the last two paragraphs. If the named output is a directory that exists,
|
||||||
|
@ -566,17 +566,27 @@
|
||||||
// The first step is to resolve which dependencies to add.
|
// The first step is to resolve which dependencies to add.
|
||||||
//
|
//
|
||||||
// For each named package or package pattern, get must decide which version of
|
// For each named package or package pattern, get must decide which version of
|
||||||
// the corresponding module to use. By default, get chooses the latest tagged
|
// the corresponding module to use. By default, get looks up the latest tagged
|
||||||
// release version, such as v0.4.5 or v1.2.3. If there are no tagged release
|
// release version, such as v0.4.5 or v1.2.3. If there are no tagged release
|
||||||
// versions, get chooses the latest tagged pre-release version, such as
|
// versions, get looks up the latest tagged pre-release version, such as
|
||||||
// v0.0.1-pre1. If there are no tagged versions at all, get chooses the latest
|
// v0.0.1-pre1. If there are no tagged versions at all, get looks up the latest
|
||||||
// known commit.
|
// known commit. If the module is not already required at a later version
|
||||||
|
// (for example, a pre-release newer than the latest release), get will use
|
||||||
|
// the version it looked up. Otherwise, get will use the currently
|
||||||
|
// required version.
|
||||||
//
|
//
|
||||||
// This default version selection can be overridden by adding an @version
|
// This default version selection can be overridden by adding an @version
|
||||||
// suffix to the package argument, as in 'go get golang.org/x/text@v0.3.0'.
|
// suffix to the package argument, as in 'go get golang.org/x/text@v0.3.0'.
|
||||||
|
// The version may be a prefix: @v1 denotes the latest available version starting
|
||||||
|
// with v1. See 'go help modules' under the heading 'Module queries' for the
|
||||||
|
// full query syntax.
|
||||||
|
//
|
||||||
// For modules stored in source control repositories, the version suffix can
|
// For modules stored in source control repositories, the version suffix can
|
||||||
// also be a commit hash, branch identifier, or other syntax known to the
|
// also be a commit hash, branch identifier, or other syntax known to the
|
||||||
// source control system, as in 'go get golang.org/x/text@master'.
|
// source control system, as in 'go get golang.org/x/text@master'. Note that
|
||||||
|
// branches with names that overlap with other module query syntax cannot be
|
||||||
|
// selected explicitly. For example, the suffix @v2 means the latest version
|
||||||
|
// starting with v2, not the branch named v2.
|
||||||
//
|
//
|
||||||
// If a module under consideration is already a dependency of the current
|
// If a module under consideration is already a dependency of the current
|
||||||
// development module, then get will update the required version.
|
// development module, then get will update the required version.
|
||||||
|
@ -586,12 +596,14 @@
|
||||||
// depending on it as needed.
|
// depending on it as needed.
|
||||||
//
|
//
|
||||||
// The version suffix @latest explicitly requests the latest minor release of the
|
// The version suffix @latest explicitly requests the latest minor release of the
|
||||||
// given path. The suffix @patch requests the latest patch release: if the path
|
// module named by the given path. The suffix @upgrade is like @latest but
|
||||||
// is already in the build list, the selected version will have the same minor
|
// will not downgrade a module if it is already required at a revision or
|
||||||
// version. If the path is not already in the build list, @patch is equivalent
|
// pre-release version newer than the latest released version. The suffix
|
||||||
// to @latest. Neither @latest nor @patch will cause 'go get' to downgrade a module
|
// @patch requests the latest patch release: the latest released version
|
||||||
// in the build list if it is required at a newer pre-release version that is
|
// with the same major and minor version numbers as the currently required
|
||||||
// newer than the latest released version.
|
// version. Like @upgrade, @patch will not downgrade a module already required
|
||||||
|
// at a newer version. If the path is not already required, @upgrade and @patch
|
||||||
|
// are equivalent to @latest.
|
||||||
//
|
//
|
||||||
// Although get defaults to using the latest version of the module containing
|
// Although get defaults to using the latest version of the module containing
|
||||||
// a named package, it does not use the latest version of that module's
|
// a named package, it does not use the latest version of that module's
|
||||||
|
@ -1006,6 +1018,7 @@
|
||||||
// Dir string // absolute path to cached source root directory
|
// Dir string // absolute path to cached source root directory
|
||||||
// Sum string // checksum for path, version (as in go.sum)
|
// Sum string // checksum for path, version (as in go.sum)
|
||||||
// GoModSum string // checksum for go.mod (as in go.sum)
|
// GoModSum string // checksum for go.mod (as in go.sum)
|
||||||
|
// Latest bool // would @latest resolve to this version?
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// See 'go help modules' for more about module queries.
|
// See 'go help modules' for more about module queries.
|
||||||
|
@ -1562,6 +1575,9 @@
|
||||||
// GOCACHE
|
// GOCACHE
|
||||||
// The directory where the go command will store cached
|
// The directory where the go command will store cached
|
||||||
// information for reuse in future builds.
|
// information for reuse in future builds.
|
||||||
|
// GODEBUG
|
||||||
|
// Enable various debugging facilities. See 'go doc runtime'
|
||||||
|
// for details.
|
||||||
// GOENV
|
// GOENV
|
||||||
// The location of the Go environment configuration file.
|
// The location of the Go environment configuration file.
|
||||||
// Cannot be set using 'go env -w'.
|
// Cannot be set using 'go env -w'.
|
||||||
|
@ -2496,12 +2512,25 @@
|
||||||
// The string "latest" matches the latest available tagged version,
|
// The string "latest" matches the latest available tagged version,
|
||||||
// or else the underlying source repository's latest untagged revision.
|
// or else the underlying source repository's latest untagged revision.
|
||||||
//
|
//
|
||||||
// A revision identifier for the underlying source repository,
|
// The string "upgrade" is like "latest", but if the module is
|
||||||
// such as a commit hash prefix, revision tag, or branch name,
|
// currently required at a later version than the version "latest"
|
||||||
// selects that specific code revision. If the revision is
|
// would select (for example, a newer pre-release version), "upgrade"
|
||||||
// also tagged with a semantic version, the query evaluates to
|
// will select the later version instead.
|
||||||
// that semantic version. Otherwise the query evaluates to a
|
//
|
||||||
// pseudo-version for the commit.
|
// The string "patch" matches the latest available tagged version
|
||||||
|
// of a module with the same major and minor version numbers as the
|
||||||
|
// currently required version. If no version is currently required,
|
||||||
|
// "patch" is equivalent to "latest".
|
||||||
|
//
|
||||||
|
// A revision identifier for the underlying source repository, such as
|
||||||
|
// a commit hash prefix, revision tag, or branch name, selects that
|
||||||
|
// specific code revision. If the revision is also tagged with a
|
||||||
|
// semantic version, the query evaluates to that semantic version.
|
||||||
|
// Otherwise the query evaluates to a pseudo-version for the commit.
|
||||||
|
// Note that branches and tags with names that are matched by other
|
||||||
|
// query syntax cannot be selected this way. For example, the query
|
||||||
|
// "v2" means the latest version starting with "v2", not the branch
|
||||||
|
// named "v2".
|
||||||
//
|
//
|
||||||
// All queries prefer release versions to pre-release versions.
|
// All queries prefer release versions to pre-release versions.
|
||||||
// For example, "<v1.2.3" will prefer to return "v1.2.2"
|
// For example, "<v1.2.3" will prefer to return "v1.2.2"
|
||||||
|
@ -2714,9 +2743,11 @@
|
||||||
// GOSUMDB="sum.golang.org+<publickey>"
|
// GOSUMDB="sum.golang.org+<publickey>"
|
||||||
// GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"
|
// GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"
|
||||||
//
|
//
|
||||||
// The go command knows the public key of sum.golang.org; use of any other
|
// The go command knows the public key of sum.golang.org, and also that the name
|
||||||
// database requires giving the public key explicitly. The URL defaults to
|
// sum.golang.google.cn (available inside mainland China) connects to the
|
||||||
// "https://" followed by the database name.
|
// sum.golang.org checksum database; use of any other database requires giving
|
||||||
|
// the public key explicitly.
|
||||||
|
// The URL defaults to "https://" followed by the database name.
|
||||||
//
|
//
|
||||||
// GOSUMDB defaults to "sum.golang.org", the Go checksum database run by Google.
|
// GOSUMDB defaults to "sum.golang.org", the Go checksum database run by Google.
|
||||||
// See https://sum.golang.org/privacy for the service's privacy policy.
|
// See https://sum.golang.org/privacy for the service's privacy policy.
|
||||||
|
|
|
@ -3177,6 +3177,12 @@ func TestGoTestFooTestWorks(t *testing.T) {
|
||||||
tg.run("test", "testdata/standalone_test.go")
|
tg.run("test", "testdata/standalone_test.go")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGoTestTestMainSeesTestingFlags(t *testing.T) {
|
||||||
|
tg := testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
tg.run("test", "testdata/standalone_testmain_flag_test.go")
|
||||||
|
}
|
||||||
|
|
||||||
// Issue 22388
|
// Issue 22388
|
||||||
func TestGoTestMainWithWrongSignature(t *testing.T) {
|
func TestGoTestMainWithWrongSignature(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
|
|
|
@ -173,7 +173,7 @@ func (c *Cache) get(id ActionID) (Entry, error) {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
tm, err := strconv.ParseInt(string(etime[i:]), 10, 64)
|
tm, err := strconv.ParseInt(string(etime[i:]), 10, 64)
|
||||||
if err != nil || size < 0 {
|
if err != nil || tm < 0 {
|
||||||
return missing()
|
return missing()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +322,7 @@ func (c *Cache) putIndexEntry(id ActionID, out OutputID, size int64, allowVerify
|
||||||
// in verify mode we are double-checking that the cache entries
|
// in verify mode we are double-checking that the cache entries
|
||||||
// are entirely reproducible. As just noted, this may be unrealistic
|
// are entirely reproducible. As just noted, this may be unrealistic
|
||||||
// in some cases but the check is also useful for shaking out real bugs.
|
// in some cases but the check is also useful for shaking out real bugs.
|
||||||
entry := []byte(fmt.Sprintf("v1 %x %x %20d %20d\n", id, out, size, time.Now().UnixNano()))
|
entry := fmt.Sprintf("v1 %x %x %20d %20d\n", id, out, size, time.Now().UnixNano())
|
||||||
if verify && allowVerify {
|
if verify && allowVerify {
|
||||||
old, err := c.get(id)
|
old, err := c.get(id)
|
||||||
if err == nil && (old.OutputID != out || old.Size != size) {
|
if err == nil && (old.OutputID != out || old.Size != size) {
|
||||||
|
@ -332,7 +332,28 @@ func (c *Cache) putIndexEntry(id ActionID, out OutputID, size int64, allowVerify
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file := c.fileName(id, "a")
|
file := c.fileName(id, "a")
|
||||||
if err := ioutil.WriteFile(file, entry, 0666); err != nil {
|
|
||||||
|
// Copy file to cache directory.
|
||||||
|
mode := os.O_WRONLY | os.O_CREATE
|
||||||
|
f, err := os.OpenFile(file, mode, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = f.WriteString(entry)
|
||||||
|
if err == nil {
|
||||||
|
// Truncate the file only *after* writing it.
|
||||||
|
// (This should be a no-op, but truncate just in case of previous corruption.)
|
||||||
|
//
|
||||||
|
// This differs from ioutil.WriteFile, which truncates to 0 *before* writing
|
||||||
|
// via os.O_TRUNC. Truncating only after writing ensures that a second write
|
||||||
|
// of the same content to the same file is idempotent, and does not — even
|
||||||
|
// temporarily! — undo the effect of the first write.
|
||||||
|
err = f.Truncate(int64(len(entry)))
|
||||||
|
}
|
||||||
|
if closeErr := f.Close(); err == nil {
|
||||||
|
err = closeErr
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
// TODO(bcmills): This Remove potentially races with another go command writing to file.
|
// TODO(bcmills): This Remove potentially races with another go command writing to file.
|
||||||
// Can we eliminate it?
|
// Can we eliminate it?
|
||||||
os.Remove(file)
|
os.Remove(file)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
|
"internal/cfg"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -221,61 +222,9 @@ func Getenv(key string) string {
|
||||||
|
|
||||||
// CanGetenv reports whether key is a valid go/env configuration key.
|
// CanGetenv reports whether key is a valid go/env configuration key.
|
||||||
func CanGetenv(key string) bool {
|
func CanGetenv(key string) bool {
|
||||||
return strings.Contains(knownEnv, "\t"+key+"\n")
|
return strings.Contains(cfg.KnownEnv, "\t"+key+"\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
var knownEnv = `
|
|
||||||
AR
|
|
||||||
CC
|
|
||||||
CGO_CFLAGS
|
|
||||||
CGO_CFLAGS_ALLOW
|
|
||||||
CGO_CFLAGS_DISALLOW
|
|
||||||
CGO_CPPFLAGS
|
|
||||||
CGO_CPPFLAGS_ALLOW
|
|
||||||
CGO_CPPFLAGS_DISALLOW
|
|
||||||
CGO_CXXFLAGS
|
|
||||||
CGO_CXXFLAGS_ALLOW
|
|
||||||
CGO_CXXFLAGS_DISALLOW
|
|
||||||
CGO_ENABLED
|
|
||||||
CGO_FFLAGS
|
|
||||||
CGO_FFLAGS_ALLOW
|
|
||||||
CGO_FFLAGS_DISALLOW
|
|
||||||
CGO_LDFLAGS
|
|
||||||
CGO_LDFLAGS_ALLOW
|
|
||||||
CGO_LDFLAGS_DISALLOW
|
|
||||||
CXX
|
|
||||||
FC
|
|
||||||
GCCGO
|
|
||||||
GO111MODULE
|
|
||||||
GO386
|
|
||||||
GOARCH
|
|
||||||
GOARM
|
|
||||||
GOBIN
|
|
||||||
GOCACHE
|
|
||||||
GOENV
|
|
||||||
GOEXE
|
|
||||||
GOFLAGS
|
|
||||||
GOGCCFLAGS
|
|
||||||
GOHOSTARCH
|
|
||||||
GOHOSTOS
|
|
||||||
GOMIPS
|
|
||||||
GOMIPS64
|
|
||||||
GONOPROXY
|
|
||||||
GONOSUMDB
|
|
||||||
GOOS
|
|
||||||
GOPATH
|
|
||||||
GOPPC64
|
|
||||||
GOPRIVATE
|
|
||||||
GOPROXY
|
|
||||||
GOROOT
|
|
||||||
GOSUMDB
|
|
||||||
GOTMPDIR
|
|
||||||
GOTOOLDIR
|
|
||||||
GOWASM
|
|
||||||
GO_EXTLINK_ENABLED
|
|
||||||
PKG_CONFIG
|
|
||||||
`
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
GOROOT = BuildContext.GOROOT
|
GOROOT = BuildContext.GOROOT
|
||||||
GOBIN = Getenv("GOBIN")
|
GOBIN = Getenv("GOBIN")
|
||||||
|
|
|
@ -164,8 +164,14 @@ var vcsGit = &vcsCmd{
|
||||||
// See golang.org/issue/9032.
|
// See golang.org/issue/9032.
|
||||||
tagSyncDefault: []string{"submodule update --init --recursive"},
|
tagSyncDefault: []string{"submodule update --init --recursive"},
|
||||||
|
|
||||||
scheme: []string{"git", "https", "http", "git+ssh", "ssh"},
|
scheme: []string{"git", "https", "http", "git+ssh", "ssh"},
|
||||||
pingCmd: "ls-remote -- {scheme}://{repo}",
|
|
||||||
|
// Leave out the '--' separator in the ls-remote command: git 2.7.4 does not
|
||||||
|
// support such a separator for that command, and this use should be safe
|
||||||
|
// without it because the {scheme} value comes from the predefined list above.
|
||||||
|
// See golang.org/issue/33836.
|
||||||
|
pingCmd: "ls-remote {scheme}://{repo}",
|
||||||
|
|
||||||
remoteRepo: gitRemoteRepo,
|
remoteRepo: gitRemoteRepo,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ Args:
|
||||||
// helpSuccess is the help command using as many args as possible that would succeed.
|
// helpSuccess is the help command using as many args as possible that would succeed.
|
||||||
helpSuccess := "go help"
|
helpSuccess := "go help"
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
helpSuccess = " " + strings.Join(args[:i], " ")
|
helpSuccess += " " + strings.Join(args[:i], " ")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, "go help %s: unknown help topic. Run '%s'.\n", strings.Join(args, " "), helpSuccess)
|
fmt.Fprintf(os.Stderr, "go help %s: unknown help topic. Run '%s'.\n", strings.Join(args, " "), helpSuccess)
|
||||||
base.SetExitStatus(2) // failed at 'go help cmd'
|
base.SetExitStatus(2) // failed at 'go help cmd'
|
||||||
|
|
|
@ -493,6 +493,9 @@ General-purpose environment variables:
|
||||||
GOCACHE
|
GOCACHE
|
||||||
The directory where the go command will store cached
|
The directory where the go command will store cached
|
||||||
information for reuse in future builds.
|
information for reuse in future builds.
|
||||||
|
GODEBUG
|
||||||
|
Enable various debugging facilities. See 'go doc runtime'
|
||||||
|
for details.
|
||||||
GOENV
|
GOENV
|
||||||
The location of the Go environment configuration file.
|
The location of the Go environment configuration file.
|
||||||
Cannot be set using 'go env -w'.
|
Cannot be set using 'go env -w'.
|
||||||
|
|
|
@ -390,7 +390,7 @@ func runList(cmd *base.Command, args []string) {
|
||||||
if !*listE {
|
if !*listE {
|
||||||
for _, m := range mods {
|
for _, m := range mods {
|
||||||
if m.Error != nil {
|
if m.Error != nil {
|
||||||
base.Errorf("go list -m %s: %v", m.Path, m.Error.Err)
|
base.Errorf("go list -m: %v", m.Error.Err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
base.ExitIfErrors()
|
base.ExitIfErrors()
|
||||||
|
@ -459,7 +459,7 @@ func runList(cmd *base.Command, args []string) {
|
||||||
}
|
}
|
||||||
if pmain != nil {
|
if pmain != nil {
|
||||||
pkgs = append(pkgs, pmain)
|
pkgs = append(pkgs, pmain)
|
||||||
data := pmain.Internal.TestmainGo
|
data := *pmain.Internal.TestmainGo
|
||||||
h := cache.NewHash("testmain")
|
h := cache.NewHash("testmain")
|
||||||
h.Write([]byte("testmain\n"))
|
h.Write([]byte("testmain\n"))
|
||||||
h.Write(data)
|
h.Write(data)
|
||||||
|
|
|
@ -64,7 +64,7 @@ type PackagePublic struct {
|
||||||
Doc string `json:",omitempty"` // package documentation string
|
Doc string `json:",omitempty"` // package documentation string
|
||||||
Target string `json:",omitempty"` // installed target for this package (may be executable)
|
Target string `json:",omitempty"` // installed target for this package (may be executable)
|
||||||
Shlib string `json:",omitempty"` // the shared library that contains this package (only set when -linkshared)
|
Shlib string `json:",omitempty"` // the shared library that contains this package (only set when -linkshared)
|
||||||
Root string `json:",omitempty"` // Go root or Go path dir containing this package
|
Root string `json:",omitempty"` // Go root, Go path dir, or module root dir containing this package
|
||||||
ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
|
ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
|
||||||
ForTest string `json:",omitempty"` // package is only for use in named test
|
ForTest string `json:",omitempty"` // package is only for use in named test
|
||||||
Export string `json:",omitempty"` // file containing export data (set by go list -export)
|
Export string `json:",omitempty"` // file containing export data (set by go list -export)
|
||||||
|
@ -177,8 +177,7 @@ type PackageInternal struct {
|
||||||
OmitDebug bool // tell linker not to write debug information
|
OmitDebug bool // tell linker not to write debug information
|
||||||
GobinSubdir bool // install target would be subdir of GOBIN
|
GobinSubdir bool // install target would be subdir of GOBIN
|
||||||
BuildInfo string // add this info to package main
|
BuildInfo string // add this info to package main
|
||||||
TestinginitGo []byte // content for _testinginit.go
|
TestmainGo *[]byte // content for _testmain.go
|
||||||
TestmainGo []byte // content for _testmain.go
|
|
||||||
|
|
||||||
Asmflags []string // -asmflags for this package
|
Asmflags []string // -asmflags for this package
|
||||||
Gcflags []string // -gcflags for this package
|
Gcflags []string // -gcflags for this package
|
||||||
|
@ -647,9 +646,14 @@ func loadPackageData(path, parentPath, parentDir, parentRoot string, parentIsStd
|
||||||
buildMode = build.ImportComment
|
buildMode = build.ImportComment
|
||||||
}
|
}
|
||||||
data.p, data.err = cfg.BuildContext.ImportDir(r.dir, buildMode)
|
data.p, data.err = cfg.BuildContext.ImportDir(r.dir, buildMode)
|
||||||
|
if data.p.Root == "" && cfg.ModulesEnabled {
|
||||||
|
if info := ModPackageModuleInfo(path); info != nil {
|
||||||
|
data.p.Root = info.Dir
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if r.err != nil {
|
} else if r.err != nil {
|
||||||
data.p = new(build.Package)
|
data.p = new(build.Package)
|
||||||
data.err = fmt.Errorf("unknown import path %q: %v", r.path, r.err)
|
data.err = r.err
|
||||||
} else if cfg.ModulesEnabled && path != "unsafe" {
|
} else if cfg.ModulesEnabled && path != "unsafe" {
|
||||||
data.p = new(build.Package)
|
data.p = new(build.Package)
|
||||||
data.err = fmt.Errorf("unknown import path %q: internal error: module loader did not resolve import", r.path)
|
data.err = fmt.Errorf("unknown import path %q: internal error: module loader did not resolve import", r.path)
|
||||||
|
|
|
@ -102,7 +102,6 @@ func TestPackagesAndErrors(p *Package, cover *TestCover) (pmain, ptest, pxtest *
|
||||||
var stk ImportStack
|
var stk ImportStack
|
||||||
stk.Push(p.ImportPath + " (test)")
|
stk.Push(p.ImportPath + " (test)")
|
||||||
rawTestImports := str.StringList(p.TestImports)
|
rawTestImports := str.StringList(p.TestImports)
|
||||||
var ptestImportsTesting, pxtestImportsTesting bool
|
|
||||||
for i, path := range p.TestImports {
|
for i, path := range p.TestImports {
|
||||||
p1 := loadImport(pre, path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport)
|
p1 := loadImport(pre, path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport)
|
||||||
if str.Contains(p1.Deps, p.ImportPath) || p1.ImportPath == p.ImportPath {
|
if str.Contains(p1.Deps, p.ImportPath) || p1.ImportPath == p.ImportPath {
|
||||||
|
@ -117,9 +116,6 @@ func TestPackagesAndErrors(p *Package, cover *TestCover) (pmain, ptest, pxtest *
|
||||||
}
|
}
|
||||||
p.TestImports[i] = p1.ImportPath
|
p.TestImports[i] = p1.ImportPath
|
||||||
imports = append(imports, p1)
|
imports = append(imports, p1)
|
||||||
if path == "testing" {
|
|
||||||
ptestImportsTesting = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
stk.Pop()
|
stk.Pop()
|
||||||
stk.Push(p.ImportPath + "_test")
|
stk.Push(p.ImportPath + "_test")
|
||||||
|
@ -133,9 +129,6 @@ func TestPackagesAndErrors(p *Package, cover *TestCover) (pmain, ptest, pxtest *
|
||||||
ximports = append(ximports, p1)
|
ximports = append(ximports, p1)
|
||||||
}
|
}
|
||||||
p.XTestImports[i] = p1.ImportPath
|
p.XTestImports[i] = p1.ImportPath
|
||||||
if path == "testing" {
|
|
||||||
pxtestImportsTesting = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
stk.Pop()
|
stk.Pop()
|
||||||
|
|
||||||
|
@ -145,9 +138,6 @@ func TestPackagesAndErrors(p *Package, cover *TestCover) (pmain, ptest, pxtest *
|
||||||
*ptest = *p
|
*ptest = *p
|
||||||
ptest.Error = ptestErr
|
ptest.Error = ptestErr
|
||||||
ptest.ForTest = p.ImportPath
|
ptest.ForTest = p.ImportPath
|
||||||
if ptestImportsTesting {
|
|
||||||
ptest.Internal.TestinginitGo = formatTestinginit(p)
|
|
||||||
}
|
|
||||||
ptest.GoFiles = nil
|
ptest.GoFiles = nil
|
||||||
ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
|
ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
|
||||||
ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
|
ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
|
||||||
|
@ -212,9 +202,6 @@ func TestPackagesAndErrors(p *Package, cover *TestCover) (pmain, ptest, pxtest *
|
||||||
Gccgoflags: p.Internal.Gccgoflags,
|
Gccgoflags: p.Internal.Gccgoflags,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if pxtestImportsTesting {
|
|
||||||
pxtest.Internal.TestinginitGo = formatTestinginit(pxtest)
|
|
||||||
}
|
|
||||||
if pxtestNeedsPtest {
|
if pxtestNeedsPtest {
|
||||||
pxtest.Internal.Imports = append(pxtest.Internal.Imports, ptest)
|
pxtest.Internal.Imports = append(pxtest.Internal.Imports, ptest)
|
||||||
}
|
}
|
||||||
|
@ -337,7 +324,9 @@ func TestPackagesAndErrors(p *Package, cover *TestCover) (pmain, ptest, pxtest *
|
||||||
if err != nil && pmain.Error == nil {
|
if err != nil && pmain.Error == nil {
|
||||||
pmain.Error = &PackageError{Err: err.Error()}
|
pmain.Error = &PackageError{Err: err.Error()}
|
||||||
}
|
}
|
||||||
pmain.Internal.TestmainGo = data
|
if data != nil {
|
||||||
|
pmain.Internal.TestmainGo = &data
|
||||||
|
}
|
||||||
|
|
||||||
return pmain, ptest, pxtest
|
return pmain, ptest, pxtest
|
||||||
}
|
}
|
||||||
|
@ -485,15 +474,6 @@ func loadTestFuncs(ptest *Package) (*testFuncs, error) {
|
||||||
return t, err
|
return t, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// formatTestinginit returns the content of the _testinginit.go file for p.
|
|
||||||
func formatTestinginit(p *Package) []byte {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
if err := testinginitTmpl.Execute(&buf, p); err != nil {
|
|
||||||
panic("testinginit template execution failed") // shouldn't be possible
|
|
||||||
}
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// formatTestmain returns the content of the _testmain.go file for t.
|
// formatTestmain returns the content of the _testmain.go file for t.
|
||||||
func formatTestmain(t *testFuncs) ([]byte, error) {
|
func formatTestmain(t *testFuncs) ([]byte, error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
@ -623,23 +603,6 @@ func checkTestFunc(fn *ast.FuncDecl, arg string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var testinginitTmpl = lazytemplate.New("init", `
|
|
||||||
package {{.Name}}
|
|
||||||
|
|
||||||
import _go_testing "testing"
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Call testing.Init before any other user initialization code runs.
|
|
||||||
(This file is passed to the compiler first.)
|
|
||||||
This provides the illusion of the old behavior where testing flags
|
|
||||||
were registered as part of the testing package's initialization.
|
|
||||||
*/}}
|
|
||||||
var _ = func() bool {
|
|
||||||
_go_testing.Init()
|
|
||||||
return true
|
|
||||||
}()
|
|
||||||
`)
|
|
||||||
|
|
||||||
var testmainTmpl = lazytemplate.New("main", `
|
var testmainTmpl = lazytemplate.New("main", `
|
||||||
// Code generated by 'go test'. DO NOT EDIT.
|
// Code generated by 'go test'. DO NOT EDIT.
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ corresponding to this Go struct:
|
||||||
Dir string // absolute path to cached source root directory
|
Dir string // absolute path to cached source root directory
|
||||||
Sum string // checksum for path, version (as in go.sum)
|
Sum string // checksum for path, version (as in go.sum)
|
||||||
GoModSum string // checksum for go.mod (as in go.sum)
|
GoModSum string // checksum for go.mod (as in go.sum)
|
||||||
|
Latest bool // would @latest resolve to this version?
|
||||||
}
|
}
|
||||||
|
|
||||||
See 'go help modules' for more about module queries.
|
See 'go help modules' for more about module queries.
|
||||||
|
@ -65,6 +66,7 @@ type moduleJSON struct {
|
||||||
Dir string `json:",omitempty"`
|
Dir string `json:",omitempty"`
|
||||||
Sum string `json:",omitempty"`
|
Sum string `json:",omitempty"`
|
||||||
GoModSum string `json:",omitempty"`
|
GoModSum string `json:",omitempty"`
|
||||||
|
Latest bool `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func runDownload(cmd *base.Command, args []string) {
|
func runDownload(cmd *base.Command, args []string) {
|
||||||
|
@ -87,7 +89,8 @@ func runDownload(cmd *base.Command, args []string) {
|
||||||
if info.Replace != nil {
|
if info.Replace != nil {
|
||||||
info = info.Replace
|
info = info.Replace
|
||||||
}
|
}
|
||||||
if info.Version == "" {
|
if info.Version == "" && info.Error == nil {
|
||||||
|
// main module
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
m := &moduleJSON{
|
m := &moduleJSON{
|
||||||
|
@ -95,9 +98,38 @@ func runDownload(cmd *base.Command, args []string) {
|
||||||
Version: info.Version,
|
Version: info.Version,
|
||||||
}
|
}
|
||||||
mods = append(mods, m)
|
mods = append(mods, m)
|
||||||
|
if info.Error != nil {
|
||||||
|
m.Error = info.Error.Err
|
||||||
|
continue
|
||||||
|
}
|
||||||
work.Add(m)
|
work.Add(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
latest := map[string]string{} // path → version
|
||||||
|
if *downloadJSON {
|
||||||
|
// We need to populate the Latest field, but if the main module depends on a
|
||||||
|
// version newer than latest — or if the version requested on the command
|
||||||
|
// line is itself newer than latest — that's not trivial to determine from
|
||||||
|
// the info returned by ListModules. Instead, we issue a separate
|
||||||
|
// ListModules request for "latest", which should be inexpensive relative to
|
||||||
|
// downloading the modules.
|
||||||
|
var latestArgs []string
|
||||||
|
for _, m := range mods {
|
||||||
|
if m.Error != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
latestArgs = append(latestArgs, m.Path+"@latest")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(latestArgs) > 0 {
|
||||||
|
for _, info := range modload.ListModules(latestArgs, listU, listVersions) {
|
||||||
|
if info.Version != "" {
|
||||||
|
latest[info.Path] = info.Version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
work.Do(10, func(item interface{}) {
|
work.Do(10, func(item interface{}) {
|
||||||
m := item.(*moduleJSON)
|
m := item.(*moduleJSON)
|
||||||
var err error
|
var err error
|
||||||
|
@ -128,6 +160,9 @@ func runDownload(cmd *base.Command, args []string) {
|
||||||
m.Error = err.Error()
|
m.Error = err.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if latest[m.Path] == m.Version {
|
||||||
|
m.Latest = true
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if *downloadJSON {
|
if *downloadJSON {
|
||||||
|
@ -144,7 +179,7 @@ func runDownload(cmd *base.Command, args []string) {
|
||||||
} else {
|
} else {
|
||||||
for _, m := range mods {
|
for _, m := range mods {
|
||||||
if m.Error != "" {
|
if m.Error != "" {
|
||||||
base.Errorf("%s@%s: %s\n", m.Path, m.Version, m.Error)
|
base.Errorf("%s", m.Error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
base.ExitIfErrors()
|
base.ExitIfErrors()
|
||||||
|
|
|
@ -341,7 +341,9 @@ func (r *vcsRepo) Stat(rev string) (*RevInfo, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *vcsRepo) fetch() {
|
func (r *vcsRepo) fetch() {
|
||||||
_, r.fetchErr = Run(r.dir, r.cmd.fetch)
|
if len(r.cmd.fetch) > 0 {
|
||||||
|
_, r.fetchErr = Run(r.dir, r.cmd.fetch)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *vcsRepo) statLocal(rev string) (*RevInfo, error) {
|
func (r *vcsRepo) statLocal(rev string) (*RevInfo, error) {
|
||||||
|
|
|
@ -31,7 +31,7 @@ type codeRepo struct {
|
||||||
codeRoot string
|
codeRoot string
|
||||||
// codeDir is the directory (relative to root) at which we expect to find the module.
|
// codeDir is the directory (relative to root) at which we expect to find the module.
|
||||||
// If pathMajor is non-empty and codeRoot is not the full modPath,
|
// If pathMajor is non-empty and codeRoot is not the full modPath,
|
||||||
// then we look in both codeDir and codeDir+modPath
|
// then we look in both codeDir and codeDir/pathMajor[1:].
|
||||||
codeDir string
|
codeDir string
|
||||||
|
|
||||||
// pathMajor is the suffix of modPath that indicates its major version,
|
// pathMajor is the suffix of modPath that indicates its major version,
|
||||||
|
@ -192,7 +192,13 @@ func (r *codeRepo) Stat(rev string) (*RevInfo, error) {
|
||||||
codeRev := r.revToRev(rev)
|
codeRev := r.revToRev(rev)
|
||||||
info, err := r.code.Stat(codeRev)
|
info, err := r.code.Stat(codeRev)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, &module.ModuleError{
|
||||||
|
Path: r.modPath,
|
||||||
|
Err: &module.InvalidVersionError{
|
||||||
|
Version: rev,
|
||||||
|
Err: err,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return r.convert(info, rev)
|
return r.convert(info, rev)
|
||||||
}
|
}
|
||||||
|
@ -248,20 +254,25 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e
|
||||||
// exist as required by info2.Version and the module path represented by r.
|
// exist as required by info2.Version and the module path represented by r.
|
||||||
checkGoMod := func() (*RevInfo, error) {
|
checkGoMod := func() (*RevInfo, error) {
|
||||||
// If r.codeDir is non-empty, then the go.mod file must exist: the module
|
// If r.codeDir is non-empty, then the go.mod file must exist: the module
|
||||||
// author, not the module consumer, gets to decide how to carve up the repo
|
// author — not the module consumer, — gets to decide how to carve up the repo
|
||||||
// into modules.
|
// into modules.
|
||||||
if r.codeDir != "" {
|
//
|
||||||
_, _, _, err := r.findDir(info2.Version)
|
// Conversely, if the go.mod file exists, the module author — not the module
|
||||||
if err != nil {
|
// consumer — gets to determine the module's path
|
||||||
// TODO: It would be nice to return an error like "not a module".
|
//
|
||||||
// Right now we return "missing go.mod", which is a little confusing.
|
// r.findDir verifies both of these conditions. Execute it now so that
|
||||||
return nil, &module.ModuleError{
|
// r.Stat will correctly return a notExistError if the go.mod location or
|
||||||
Path: r.modPath,
|
// declared module path doesn't match.
|
||||||
Err: &module.InvalidVersionError{
|
_, _, _, err := r.findDir(info2.Version)
|
||||||
Version: info2.Version,
|
if err != nil {
|
||||||
Err: notExistError(err.Error()),
|
// TODO: It would be nice to return an error like "not a module".
|
||||||
},
|
// Right now we return "missing go.mod", which is a little confusing.
|
||||||
}
|
return nil, &module.ModuleError{
|
||||||
|
Path: r.modPath,
|
||||||
|
Err: &module.InvalidVersionError{
|
||||||
|
Version: info2.Version,
|
||||||
|
Err: notExistError(err.Error()),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,6 +485,11 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string)
|
||||||
return fmt.Errorf("does not match version-control timestamp (%s)", info.Time.UTC().Format(time.RFC3339))
|
return fmt.Errorf("does not match version-control timestamp (%s)", info.Time.UTC().Format(time.RFC3339))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tagPrefix := ""
|
||||||
|
if r.codeDir != "" {
|
||||||
|
tagPrefix = r.codeDir + "/"
|
||||||
|
}
|
||||||
|
|
||||||
// A pseudo-version should have a precedence just above its parent revisions,
|
// A pseudo-version should have a precedence just above its parent revisions,
|
||||||
// and no higher. Otherwise, it would be possible for library authors to "pin"
|
// and no higher. Otherwise, it would be possible for library authors to "pin"
|
||||||
// dependency versions (and bypass the usual minimum version selection) by
|
// dependency versions (and bypass the usual minimum version selection) by
|
||||||
|
@ -499,11 +515,26 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string)
|
||||||
return fmt.Errorf("major version without preceding tag must be v0, not v1")
|
return fmt.Errorf("major version without preceding tag must be v0, not v1")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
} else {
|
||||||
|
for _, tag := range info.Tags {
|
||||||
tagPrefix := ""
|
versionOnly := strings.TrimPrefix(tag, tagPrefix)
|
||||||
if r.codeDir != "" {
|
if versionOnly == base {
|
||||||
tagPrefix = r.codeDir + "/"
|
// The base version is canonical, so if the version from the tag is
|
||||||
|
// literally equal (not just equivalent), then the tag is canonical too.
|
||||||
|
//
|
||||||
|
// We allow pseudo-versions to be derived from non-canonical tags on the
|
||||||
|
// same commit, so that tags like "v1.1.0+some-metadata" resolve as
|
||||||
|
// close as possible to the canonical version ("v1.1.0") while still
|
||||||
|
// enforcing a total ordering ("v1.1.1-0.[…]" with a unique suffix).
|
||||||
|
//
|
||||||
|
// However, canonical tags already have a total ordering, so there is no
|
||||||
|
// reason not to use the canonical tag directly, and we know that the
|
||||||
|
// canonical tag must already exist because the pseudo-version is
|
||||||
|
// derived from it. In that case, referring to the revision by a
|
||||||
|
// pseudo-version derived from its own canonical tag is just confusing.
|
||||||
|
return fmt.Errorf("tag (%s) found on revision %s is already canonical, so should not be replaced with a pseudo-version derived from that tag", tag, rev)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tags, err := r.code.Tags(tagPrefix + base)
|
tags, err := r.code.Tags(tagPrefix + base)
|
||||||
|
@ -571,6 +602,10 @@ func (r *codeRepo) versionToRev(version string) (rev string, err error) {
|
||||||
return r.revToRev(version), nil
|
return r.revToRev(version), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// findDir locates the directory within the repo containing the module.
|
||||||
|
//
|
||||||
|
// If r.pathMajor is non-empty, this can be either r.codeDir or — if a go.mod
|
||||||
|
// file exists — r.codeDir/r.pathMajor[1:].
|
||||||
func (r *codeRepo) findDir(version string) (rev, dir string, gomod []byte, err error) {
|
func (r *codeRepo) findDir(version string) (rev, dir string, gomod []byte, err error) {
|
||||||
rev, err = r.versionToRev(version)
|
rev, err = r.versionToRev(version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -83,6 +83,26 @@ var codeRepoTests = []codeRepoTest{
|
||||||
"pkg/p.go",
|
"pkg/p.go",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
vcs: "git",
|
||||||
|
path: "github.com/rsc/vgotest1",
|
||||||
|
rev: "v0.0.0-20180219231006-80d85c5d4d17",
|
||||||
|
version: "v0.0.0-20180219231006-80d85c5d4d17",
|
||||||
|
name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
|
||||||
|
short: "80d85c5d4d17",
|
||||||
|
time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
|
||||||
|
zip: []string{
|
||||||
|
"LICENSE",
|
||||||
|
"README.md",
|
||||||
|
"pkg/p.go",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vcs: "git",
|
||||||
|
path: "github.com/rsc/vgotest1",
|
||||||
|
rev: "v0.0.1-0.20180219231006-80d85c5d4d17",
|
||||||
|
err: `github.com/rsc/vgotest1@v0.0.1-0.20180219231006-80d85c5d4d17: invalid pseudo-version: tag (v0.0.0) found on revision 80d85c5d4d17 is already canonical, so should not be replaced with a pseudo-version derived from that tag`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
vcs: "git",
|
vcs: "git",
|
||||||
path: "github.com/rsc/vgotest1",
|
path: "github.com/rsc/vgotest1",
|
||||||
|
@ -105,7 +125,7 @@ var codeRepoTests = []codeRepoTest{
|
||||||
name: "45f53230a74ad275c7127e117ac46914c8126160",
|
name: "45f53230a74ad275c7127e117ac46914c8126160",
|
||||||
short: "45f53230a74a",
|
short: "45f53230a74a",
|
||||||
time: time.Date(2018, 7, 19, 1, 21, 27, 0, time.UTC),
|
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",
|
err: "missing github.com/rsc/vgotest1/go.mod and .../v2/go.mod at revision v2.0.0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
vcs: "git",
|
vcs: "git",
|
||||||
|
@ -136,15 +156,14 @@ var codeRepoTests = []codeRepoTest{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
vcs: "git",
|
vcs: "git",
|
||||||
path: "github.com/rsc/vgotest1/v2",
|
path: "github.com/rsc/vgotest1/v2",
|
||||||
rev: "45f53230a",
|
rev: "45f53230a",
|
||||||
version: "v2.0.0",
|
version: "v2.0.0",
|
||||||
name: "45f53230a74ad275c7127e117ac46914c8126160",
|
name: "45f53230a74ad275c7127e117ac46914c8126160",
|
||||||
short: "45f53230a74a",
|
short: "45f53230a74a",
|
||||||
time: time.Date(2018, 7, 19, 1, 21, 27, 0, time.UTC),
|
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",
|
err: "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",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
vcs: "git",
|
vcs: "git",
|
||||||
|
@ -154,7 +173,7 @@ var codeRepoTests = []codeRepoTest{
|
||||||
name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
|
name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
|
||||||
short: "80d85c5d4d17",
|
short: "80d85c5d4d17",
|
||||||
time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
|
time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
|
||||||
ziperr: "missing github.com/rsc/vgotest1/go.mod and .../v54321/go.mod at revision 80d85c5d4d17",
|
err: "missing github.com/rsc/vgotest1/go.mod and .../v54321/go.mod at revision 80d85c5d4d17",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
vcs: "git",
|
vcs: "git",
|
||||||
|
@ -210,24 +229,24 @@ var codeRepoTests = []codeRepoTest{
|
||||||
gomod: "module \"github.com/rsc/vgotest1/v2\" // root go.mod\n",
|
gomod: "module \"github.com/rsc/vgotest1/v2\" // root go.mod\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
vcs: "git",
|
vcs: "git",
|
||||||
path: "github.com/rsc/vgotest1/v2",
|
path: "github.com/rsc/vgotest1/v2",
|
||||||
rev: "v2.0.3",
|
rev: "v2.0.3",
|
||||||
version: "v2.0.3",
|
version: "v2.0.3",
|
||||||
name: "f18795870fb14388a21ef3ebc1d75911c8694f31",
|
name: "f18795870fb14388a21ef3ebc1d75911c8694f31",
|
||||||
short: "f18795870fb1",
|
short: "f18795870fb1",
|
||||||
time: time.Date(2018, 2, 19, 23, 16, 4, 0, time.UTC),
|
time: time.Date(2018, 2, 19, 23, 16, 4, 0, time.UTC),
|
||||||
gomoderr: "github.com/rsc/vgotest1/v2/go.mod has non-.../v2 module path \"github.com/rsc/vgotest\" at revision v2.0.3",
|
err: "github.com/rsc/vgotest1/v2/go.mod has non-.../v2 module path \"github.com/rsc/vgotest\" at revision v2.0.3",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
vcs: "git",
|
vcs: "git",
|
||||||
path: "github.com/rsc/vgotest1/v2",
|
path: "github.com/rsc/vgotest1/v2",
|
||||||
rev: "v2.0.4",
|
rev: "v2.0.4",
|
||||||
version: "v2.0.4",
|
version: "v2.0.4",
|
||||||
name: "1f863feb76bc7029b78b21c5375644838962f88d",
|
name: "1f863feb76bc7029b78b21c5375644838962f88d",
|
||||||
short: "1f863feb76bc",
|
short: "1f863feb76bc",
|
||||||
time: time.Date(2018, 2, 20, 0, 3, 38, 0, time.UTC),
|
time: time.Date(2018, 2, 20, 0, 3, 38, 0, time.UTC),
|
||||||
gomoderr: "github.com/rsc/vgotest1/go.mod and .../v2/go.mod both have .../v2 module paths at revision v2.0.4",
|
err: "github.com/rsc/vgotest1/go.mod and .../v2/go.mod both have .../v2 module paths at revision v2.0.4",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
vcs: "git",
|
vcs: "git",
|
||||||
|
@ -504,6 +523,7 @@ func TestCodeRepo(t *testing.T) {
|
||||||
tt.name = remap(tt.name, m)
|
tt.name = remap(tt.name, m)
|
||||||
tt.short = remap(tt.short, m)
|
tt.short = remap(tt.short, m)
|
||||||
tt.rev = remap(tt.rev, m)
|
tt.rev = remap(tt.rev, m)
|
||||||
|
tt.err = remap(tt.err, m)
|
||||||
tt.gomoderr = remap(tt.gomoderr, m)
|
tt.gomoderr = remap(tt.gomoderr, m)
|
||||||
tt.ziperr = remap(tt.ziperr, m)
|
tt.ziperr = remap(tt.ziperr, m)
|
||||||
t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt))
|
t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt))
|
||||||
|
@ -515,7 +535,7 @@ func TestCodeRepo(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var hgmap = map[string]string{
|
var hgmap = map[string]string{
|
||||||
"github.com/rsc/vgotest1/": "vcs-test.golang.org/hg/vgotest1.hg/",
|
"github.com/rsc/vgotest1": "vcs-test.golang.org/hg/vgotest1.hg",
|
||||||
"f18795870fb14388a21ef3ebc1d75911c8694f31": "a9ad6d1d14eb544f459f446210c7eb3b009807c6",
|
"f18795870fb14388a21ef3ebc1d75911c8694f31": "a9ad6d1d14eb544f459f446210c7eb3b009807c6",
|
||||||
"ea65f87c8f52c15ea68f3bdd9925ef17e20d91e9": "f1fc0f22021b638d073d31c752847e7bf385def7",
|
"ea65f87c8f52c15ea68f3bdd9925ef17e20d91e9": "f1fc0f22021b638d073d31c752847e7bf385def7",
|
||||||
"b769f2de407a4db81af9c5de0a06016d60d2ea09": "92c7eb888b4fac17f1c6bd2e1060a1b881a3b832",
|
"b769f2de407a4db81af9c5de0a06016d60d2ea09": "92c7eb888b4fac17f1c6bd2e1060a1b881a3b832",
|
||||||
|
@ -631,15 +651,30 @@ var latestTests = []struct {
|
||||||
err: "no commits",
|
err: "no commits",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
vcs: "git",
|
vcs: "git",
|
||||||
path: "github.com/rsc/vgotest1",
|
path: "github.com/rsc/vgotest1",
|
||||||
version: "v0.0.0-20180219223237-a08abb797a67",
|
err: `github.com/rsc/vgotest1@v0.0.0-20180219223237-a08abb797a67: invalid version: go.mod has post-v0 module path "github.com/vgotest1/v2" at revision a08abb797a67`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vcs: "git",
|
||||||
|
path: "github.com/rsc/vgotest1/v2",
|
||||||
|
err: `github.com/rsc/vgotest1/v2@v2.0.0-20180219223237-a08abb797a67: invalid version: github.com/rsc/vgotest1/go.mod and .../v2/go.mod both have .../v2 module paths at revision a08abb797a67`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
vcs: "git",
|
vcs: "git",
|
||||||
path: "github.com/rsc/vgotest1/subdir",
|
path: "github.com/rsc/vgotest1/subdir",
|
||||||
err: "github.com/rsc/vgotest1/subdir@v0.0.0-20180219223237-a08abb797a67: invalid version: missing github.com/rsc/vgotest1/subdir/go.mod at revision a08abb797a67",
|
err: "github.com/rsc/vgotest1/subdir@v0.0.0-20180219223237-a08abb797a67: invalid version: missing github.com/rsc/vgotest1/subdir/go.mod at revision a08abb797a67",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
vcs: "git",
|
||||||
|
path: "vcs-test.golang.org/git/commit-after-tag.git",
|
||||||
|
version: "v1.0.1-0.20190715211727-b325d8217783",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vcs: "git",
|
||||||
|
path: "vcs-test.golang.org/git/no-tags.git",
|
||||||
|
version: "v0.0.0-20190715212047-e706ba1d9f6d",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
vcs: "mod",
|
vcs: "mod",
|
||||||
path: "swtch.com/testmod",
|
path: "swtch.com/testmod",
|
||||||
|
|
|
@ -701,9 +701,11 @@ to use and optionally its public key and URL, as in:
|
||||||
GOSUMDB="sum.golang.org+<publickey>"
|
GOSUMDB="sum.golang.org+<publickey>"
|
||||||
GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"
|
GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"
|
||||||
|
|
||||||
The go command knows the public key of sum.golang.org; use of any other
|
The go command knows the public key of sum.golang.org, and also that the name
|
||||||
database requires giving the public key explicitly. The URL defaults to
|
sum.golang.google.cn (available inside mainland China) connects to the
|
||||||
"https://" followed by the database name.
|
sum.golang.org checksum database; use of any other database requires giving
|
||||||
|
the public key explicitly.
|
||||||
|
The URL defaults to "https://" followed by the database name.
|
||||||
|
|
||||||
GOSUMDB defaults to "sum.golang.org", the Go checksum database run by Google.
|
GOSUMDB defaults to "sum.golang.org", the Go checksum database run by Google.
|
||||||
See https://sum.golang.org/privacy for the service's privacy policy.
|
See https://sum.golang.org/privacy for the service's privacy policy.
|
||||||
|
|
|
@ -345,7 +345,9 @@ func (p *proxyRepo) Stat(rev string) (*RevInfo, error) {
|
||||||
func (p *proxyRepo) Latest() (*RevInfo, error) {
|
func (p *proxyRepo) Latest() (*RevInfo, error) {
|
||||||
data, err := p.getBytes("@latest")
|
data, err := p.getBytes("@latest")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO return err if not 404
|
if !errors.Is(err, os.ErrNotExist) {
|
||||||
|
return nil, p.versionError("", err)
|
||||||
|
}
|
||||||
return p.latest()
|
return p.latest()
|
||||||
}
|
}
|
||||||
info := new(RevInfo)
|
info := new(RevInfo)
|
||||||
|
|
|
@ -240,7 +240,7 @@ func lookup(proxy, path string) (r Repo, err error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errModVendor = errors.New("module lookup disabled by -mod=vendor")
|
errModVendor = errors.New("module lookup disabled by -mod=vendor")
|
||||||
errProxyOff = errors.New("module lookup disabled by GOPROXY=off")
|
errProxyOff = notExistError("module lookup disabled by GOPROXY=off")
|
||||||
errNoproxy error = notExistError("disabled by GOPRIVATE/GONOPROXY")
|
errNoproxy error = notExistError("disabled by GOPRIVATE/GONOPROXY")
|
||||||
errUseProxy error = notExistError("path does not match GOPRIVATE/GONOPROXY")
|
errUseProxy error = notExistError("path does not match GOPRIVATE/GONOPROXY")
|
||||||
)
|
)
|
||||||
|
|
|
@ -60,7 +60,17 @@ func dbDial() (dbName string, db *sumweb.Conn, err error) {
|
||||||
// $GOSUMDB can be "key" or "key url",
|
// $GOSUMDB can be "key" or "key url",
|
||||||
// and the key can be a full verifier key
|
// and the key can be a full verifier key
|
||||||
// or a host on our list of known keys.
|
// or a host on our list of known keys.
|
||||||
key := strings.Fields(cfg.GOSUMDB)
|
|
||||||
|
// Special case: sum.golang.google.cn
|
||||||
|
// is an alias, reachable inside mainland China,
|
||||||
|
// for sum.golang.org. If there are more
|
||||||
|
// of these we should add a map like knownGOSUMDB.
|
||||||
|
gosumdb := cfg.GOSUMDB
|
||||||
|
if gosumdb == "sum.golang.google.cn" {
|
||||||
|
gosumdb = "sum.golang.org https://sum.golang.google.cn"
|
||||||
|
}
|
||||||
|
|
||||||
|
key := strings.Fields(gosumdb)
|
||||||
if len(key) >= 1 {
|
if len(key) >= 1 {
|
||||||
if k := knownGOSUMDB[key[0]]; k != "" {
|
if k := knownGOSUMDB[key[0]]; k != "" {
|
||||||
key[0] = k
|
key[0] = k
|
||||||
|
@ -232,10 +242,10 @@ func (*dbClient) WriteConfig(file string, old, new []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadCache reads cached lookups or tiles from
|
// ReadCache reads cached lookups or tiles from
|
||||||
// GOPATH/pkg/mod/download/cache/sumdb,
|
// GOPATH/pkg/mod/cache/download/sumdb,
|
||||||
// which will be deleted by "go clean -modcache".
|
// which will be deleted by "go clean -modcache".
|
||||||
func (*dbClient) ReadCache(file string) ([]byte, error) {
|
func (*dbClient) ReadCache(file string) ([]byte, error) {
|
||||||
targ := filepath.Join(PkgMod, "download/cache/sumdb", file)
|
targ := filepath.Join(PkgMod, "cache/download/sumdb", file)
|
||||||
data, err := lockedfile.Read(targ)
|
data, err := lockedfile.Read(targ)
|
||||||
// lockedfile.Write does not atomically create the file with contents.
|
// lockedfile.Write does not atomically create the file with contents.
|
||||||
// There is a moment between file creation and locking the file for writing,
|
// There is a moment between file creation and locking the file for writing,
|
||||||
|
@ -249,7 +259,7 @@ func (*dbClient) ReadCache(file string) ([]byte, error) {
|
||||||
|
|
||||||
// WriteCache updates cached lookups or tiles.
|
// WriteCache updates cached lookups or tiles.
|
||||||
func (*dbClient) WriteCache(file string, data []byte) {
|
func (*dbClient) WriteCache(file string, data []byte) {
|
||||||
targ := filepath.Join(PkgMod, "download/cache/sumdb", file)
|
targ := filepath.Join(PkgMod, "cache/download/sumdb", file)
|
||||||
os.MkdirAll(filepath.Dir(targ), 0777)
|
os.MkdirAll(filepath.Dir(targ), 0777)
|
||||||
lockedfile.Write(targ, bytes.NewReader(data), 0666)
|
lockedfile.Write(targ, bytes.NewReader(data), 0666)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,17 +39,27 @@ and then builds and installs them.
|
||||||
The first step is to resolve which dependencies to add.
|
The first step is to resolve which dependencies to add.
|
||||||
|
|
||||||
For each named package or package pattern, get must decide which version of
|
For each named package or package pattern, get must decide which version of
|
||||||
the corresponding module to use. By default, get chooses the latest tagged
|
the corresponding module to use. By default, get looks up the latest tagged
|
||||||
release version, such as v0.4.5 or v1.2.3. If there are no tagged release
|
release version, such as v0.4.5 or v1.2.3. If there are no tagged release
|
||||||
versions, get chooses the latest tagged pre-release version, such as
|
versions, get looks up the latest tagged pre-release version, such as
|
||||||
v0.0.1-pre1. If there are no tagged versions at all, get chooses the latest
|
v0.0.1-pre1. If there are no tagged versions at all, get looks up the latest
|
||||||
known commit.
|
known commit. If the module is not already required at a later version
|
||||||
|
(for example, a pre-release newer than the latest release), get will use
|
||||||
|
the version it looked up. Otherwise, get will use the currently
|
||||||
|
required version.
|
||||||
|
|
||||||
This default version selection can be overridden by adding an @version
|
This default version selection can be overridden by adding an @version
|
||||||
suffix to the package argument, as in 'go get golang.org/x/text@v0.3.0'.
|
suffix to the package argument, as in 'go get golang.org/x/text@v0.3.0'.
|
||||||
|
The version may be a prefix: @v1 denotes the latest available version starting
|
||||||
|
with v1. See 'go help modules' under the heading 'Module queries' for the
|
||||||
|
full query syntax.
|
||||||
|
|
||||||
For modules stored in source control repositories, the version suffix can
|
For modules stored in source control repositories, the version suffix can
|
||||||
also be a commit hash, branch identifier, or other syntax known to the
|
also be a commit hash, branch identifier, or other syntax known to the
|
||||||
source control system, as in 'go get golang.org/x/text@master'.
|
source control system, as in 'go get golang.org/x/text@master'. Note that
|
||||||
|
branches with names that overlap with other module query syntax cannot be
|
||||||
|
selected explicitly. For example, the suffix @v2 means the latest version
|
||||||
|
starting with v2, not the branch named v2.
|
||||||
|
|
||||||
If a module under consideration is already a dependency of the current
|
If a module under consideration is already a dependency of the current
|
||||||
development module, then get will update the required version.
|
development module, then get will update the required version.
|
||||||
|
@ -59,12 +69,14 @@ dependency should be removed entirely, downgrading or removing modules
|
||||||
depending on it as needed.
|
depending on it as needed.
|
||||||
|
|
||||||
The version suffix @latest explicitly requests the latest minor release of the
|
The version suffix @latest explicitly requests the latest minor release of the
|
||||||
given path. The suffix @patch requests the latest patch release: if the path
|
module named by the given path. The suffix @upgrade is like @latest but
|
||||||
is already in the build list, the selected version will have the same minor
|
will not downgrade a module if it is already required at a revision or
|
||||||
version. If the path is not already in the build list, @patch is equivalent
|
pre-release version newer than the latest released version. The suffix
|
||||||
to @latest. Neither @latest nor @patch will cause 'go get' to downgrade a module
|
@patch requests the latest patch release: the latest released version
|
||||||
in the build list if it is required at a newer pre-release version that is
|
with the same major and minor version numbers as the currently required
|
||||||
newer than the latest released version.
|
version. Like @upgrade, @patch will not downgrade a module already required
|
||||||
|
at a newer version. If the path is not already required, @upgrade and @patch
|
||||||
|
are equivalent to @latest.
|
||||||
|
|
||||||
Although get defaults to using the latest version of the module containing
|
Although get defaults to using the latest version of the module containing
|
||||||
a named package, it does not use the latest version of that module's
|
a named package, it does not use the latest version of that module's
|
||||||
|
@ -178,7 +190,7 @@ func (v *upgradeFlag) Set(s string) error {
|
||||||
s = ""
|
s = ""
|
||||||
}
|
}
|
||||||
if s == "true" {
|
if s == "true" {
|
||||||
s = "latest"
|
s = "upgrade"
|
||||||
}
|
}
|
||||||
*v = upgradeFlag(s)
|
*v = upgradeFlag(s)
|
||||||
return nil
|
return nil
|
||||||
|
@ -202,8 +214,9 @@ type getArg struct {
|
||||||
// if there is no "@"). path specifies the modules or packages to get.
|
// if there is no "@"). path specifies the modules or packages to get.
|
||||||
path string
|
path string
|
||||||
|
|
||||||
// vers is the part of the argument after "@" (or "" if there is no "@").
|
// vers is the part of the argument after "@" or an implied
|
||||||
// vers specifies the module version to get.
|
// "upgrade" or "patch" if there is no "@". vers specifies the
|
||||||
|
// module version to get.
|
||||||
vers string
|
vers string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +262,7 @@ func runGet(cmd *base.Command, args []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch getU {
|
switch getU {
|
||||||
case "", "latest", "patch":
|
case "", "upgrade", "patch":
|
||||||
// ok
|
// ok
|
||||||
default:
|
default:
|
||||||
base.Fatalf("go get: unknown upgrade flag -u=%s", getU)
|
base.Fatalf("go get: unknown upgrade flag -u=%s", getU)
|
||||||
|
@ -283,11 +296,11 @@ func runGet(cmd *base.Command, args []string) {
|
||||||
|
|
||||||
// Parse command-line arguments and report errors. The command-line
|
// Parse command-line arguments and report errors. The command-line
|
||||||
// arguments are of the form path@version or simply path, with implicit
|
// arguments are of the form path@version or simply path, with implicit
|
||||||
// @latest. path@none is "downgrade away".
|
// @upgrade. path@none is "downgrade away".
|
||||||
var gets []getArg
|
var gets []getArg
|
||||||
var queries []*query
|
var queries []*query
|
||||||
for _, arg := range search.CleanPatterns(args) {
|
for _, arg := range search.CleanPatterns(args) {
|
||||||
// Argument is module query path@vers, or else path with implicit @latest.
|
// Argument is path or path@vers.
|
||||||
path := arg
|
path := arg
|
||||||
vers := ""
|
vers := ""
|
||||||
if i := strings.Index(arg, "@"); i >= 0 {
|
if i := strings.Index(arg, "@"); i >= 0 {
|
||||||
|
@ -298,10 +311,14 @@ func runGet(cmd *base.Command, args []string) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user runs 'go get -u=patch some/module', update some/module to a
|
// If no version suffix is specified, assume @upgrade.
|
||||||
// patch release, not a minor version.
|
// If -u=patch was specified, assume @patch instead.
|
||||||
if vers == "" && getU != "" {
|
if vers == "" {
|
||||||
vers = string(getU)
|
if getU != "" {
|
||||||
|
vers = string(getU)
|
||||||
|
} else {
|
||||||
|
vers = "upgrade"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gets = append(gets, getArg{raw: arg, path: path, vers: vers})
|
gets = append(gets, getArg{raw: arg, path: path, vers: vers})
|
||||||
|
@ -358,7 +375,7 @@ func runGet(cmd *base.Command, args []string) {
|
||||||
// The argument is a package path.
|
// The argument is a package path.
|
||||||
if pkgs := modload.TargetPackages(path); len(pkgs) != 0 {
|
if pkgs := modload.TargetPackages(path); len(pkgs) != 0 {
|
||||||
// The path is in the main module. Nothing to query.
|
// The path is in the main module. Nothing to query.
|
||||||
if vers != "" && vers != "latest" && vers != "patch" {
|
if vers != "upgrade" && vers != "patch" {
|
||||||
base.Errorf("go get %s: can't request explicit version of path in main module", arg)
|
base.Errorf("go get %s: can't request explicit version of path in main module", arg)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
@ -376,8 +393,8 @@ func runGet(cmd *base.Command, args []string) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're querying "latest" or "patch", we need to know the current
|
// If we're querying "upgrade" or "patch", we need to know the current
|
||||||
// version of the module. For "latest", we want to avoid accidentally
|
// version of the module. For "upgrade", we want to avoid accidentally
|
||||||
// downgrading from a newer prerelease. For "patch", we need to query
|
// downgrading from a newer prerelease. For "patch", we need to query
|
||||||
// the correct minor version.
|
// the correct minor version.
|
||||||
// Here, we check if "path" is the name of a module in the build list
|
// Here, we check if "path" is the name of a module in the build list
|
||||||
|
@ -718,7 +735,7 @@ func runQueries(cache map[querySpec]*query, queries []*query, modOnly map[string
|
||||||
return byPath
|
return byPath
|
||||||
}
|
}
|
||||||
|
|
||||||
// getQuery evaluates the given package path, version pair
|
// getQuery evaluates the given (package or module) path and version
|
||||||
// to determine the underlying module version being requested.
|
// to determine the underlying module version being requested.
|
||||||
// If forceModulePath is set, getQuery must interpret path
|
// If forceModulePath is set, getQuery must interpret path
|
||||||
// as a module path.
|
// as a module path.
|
||||||
|
@ -736,34 +753,51 @@ func getQuery(path, vers string, prevM module.Version, forceModulePath bool) (mo
|
||||||
base.Fatalf("go get: internal error: prevM may be set if and only if forceModulePath is set")
|
base.Fatalf("go get: internal error: prevM may be set if and only if forceModulePath is set")
|
||||||
}
|
}
|
||||||
|
|
||||||
if vers == "" || vers == "patch" && prevM.Version == "" {
|
// If the query must be a module path, try only that module path.
|
||||||
vers = "latest"
|
if forceModulePath {
|
||||||
}
|
|
||||||
|
|
||||||
if forceModulePath || !strings.Contains(path, "...") {
|
|
||||||
if path == modload.Target.Path {
|
if path == modload.Target.Path {
|
||||||
if vers != "latest" {
|
if vers != "latest" {
|
||||||
return module.Version{}, fmt.Errorf("can't get a specific version of the main module")
|
return module.Version{}, fmt.Errorf("can't get a specific version of the main module")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the path doesn't contain a wildcard, try interpreting it as a module path.
|
|
||||||
info, err := modload.Query(path, vers, prevM.Version, modload.Allowed)
|
info, err := modload.Query(path, vers, prevM.Version, modload.Allowed)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return module.Version{Path: path, Version: info.Version}, nil
|
return module.Version{Path: path, Version: info.Version}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the query fails, and the path must be a real module, report the query error.
|
// If the query was "upgrade" or "patch" and the current version has been
|
||||||
if forceModulePath {
|
// replaced, check to see whether the error was for that same version:
|
||||||
return module.Version{}, err
|
// if so, the version was probably replaced because it is invalid,
|
||||||
|
// and we should keep that replacement without complaining.
|
||||||
|
if vers == "upgrade" || vers == "patch" {
|
||||||
|
var vErr *module.InvalidVersionError
|
||||||
|
if errors.As(err, &vErr) && vErr.Version == prevM.Version && modload.Replacement(prevM).Path != "" {
|
||||||
|
return prevM, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, try a package path or pattern.
|
|
||||||
results, err := modload.QueryPattern(path, vers, modload.Allowed)
|
|
||||||
if err != nil {
|
|
||||||
return module.Version{}, err
|
return module.Version{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the query may be either a package or a module, try it as a package path.
|
||||||
|
// If it turns out to only exist as a module, we can detect the resulting
|
||||||
|
// PackageNotInModuleError and avoid a second round-trip through (potentially)
|
||||||
|
// all of the configured proxies.
|
||||||
|
results, err := modload.QueryPattern(path, vers, modload.Allowed)
|
||||||
|
if err != nil {
|
||||||
|
// If the path doesn't contain a wildcard, check whether it was actually a
|
||||||
|
// module path instead. If so, return that.
|
||||||
|
if !strings.Contains(path, "...") {
|
||||||
|
var modErr *modload.PackageNotInModuleError
|
||||||
|
if errors.As(err, &modErr) && modErr.Mod.Path == path {
|
||||||
|
return modErr.Mod, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return module.Version{}, err
|
||||||
|
}
|
||||||
|
|
||||||
return results[0].Mod, nil
|
return results[0].Mod, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,13 +927,23 @@ func (u *upgrader) Upgrade(m module.Version) (module.Version, error) {
|
||||||
// which may return a pseudoversion for the latest commit.
|
// which may return a pseudoversion for the latest commit.
|
||||||
// Query "latest" returns the newest tagged version or the newest
|
// Query "latest" returns the newest tagged version or the newest
|
||||||
// prerelease version if there are no non-prereleases, or repo.Latest
|
// prerelease version if there are no non-prereleases, or repo.Latest
|
||||||
// if there aren't any tagged versions. Since we're providing the previous
|
// if there aren't any tagged versions.
|
||||||
// version, Query will confirm the latest version is actually newer
|
// If we're querying "upgrade" or "patch", Query will compare the current
|
||||||
// and will return the current version if not.
|
// version against the chosen version and will return the current version
|
||||||
|
// if it is newer.
|
||||||
info, err := modload.Query(m.Path, string(getU), m.Version, modload.Allowed)
|
info, err := modload.Query(m.Path, string(getU), m.Version, modload.Allowed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Report error but return m, to let version selection continue.
|
// Report error but return m, to let version selection continue.
|
||||||
// (Reporting the error will fail the command at the next base.ExitIfErrors.)
|
// (Reporting the error will fail the command at the next base.ExitIfErrors.)
|
||||||
|
|
||||||
|
// Special case: if the error is for m.Version itself and m.Version has a
|
||||||
|
// replacement, then keep it and don't report the error: the fact that the
|
||||||
|
// version is invalid is likely the reason it was replaced to begin with.
|
||||||
|
var vErr *module.InvalidVersionError
|
||||||
|
if errors.As(err, &vErr) && vErr.Version == m.Version && modload.Replacement(m).Path != "" {
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Special case: if the error is "no matching versions" then don't
|
// Special case: if the error is "no matching versions" then don't
|
||||||
// even report the error. Because Query does not consider pseudo-versions,
|
// even report the error. Because Query does not consider pseudo-versions,
|
||||||
// it may happen that we have a pseudo-version but during -u=patch
|
// it may happen that we have a pseudo-version but during -u=patch
|
||||||
|
|
|
@ -79,7 +79,7 @@ func addUpdate(m *modinfo.ModulePublic) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if info, err := Query(m.Path, "latest", m.Version, Allowed); err == nil && semver.Compare(info.Version, m.Version) > 0 {
|
if info, err := Query(m.Path, "upgrade", m.Version, Allowed); err == nil && semver.Compare(info.Version, m.Version) > 0 {
|
||||||
m.Update = &modinfo.ModulePublic{
|
m.Update = &modinfo.ModulePublic{
|
||||||
Path: m.Path,
|
Path: m.Path,
|
||||||
Version: info.Version,
|
Version: info.Version,
|
||||||
|
|
|
@ -231,12 +231,25 @@ evaluates to the available tagged version nearest to the comparison target
|
||||||
The string "latest" matches the latest available tagged version,
|
The string "latest" matches the latest available tagged version,
|
||||||
or else the underlying source repository's latest untagged revision.
|
or else the underlying source repository's latest untagged revision.
|
||||||
|
|
||||||
A revision identifier for the underlying source repository,
|
The string "upgrade" is like "latest", but if the module is
|
||||||
such as a commit hash prefix, revision tag, or branch name,
|
currently required at a later version than the version "latest"
|
||||||
selects that specific code revision. If the revision is
|
would select (for example, a newer pre-release version), "upgrade"
|
||||||
also tagged with a semantic version, the query evaluates to
|
will select the later version instead.
|
||||||
that semantic version. Otherwise the query evaluates to a
|
|
||||||
pseudo-version for the commit.
|
The string "patch" matches the latest available tagged version
|
||||||
|
of a module with the same major and minor version numbers as the
|
||||||
|
currently required version. If no version is currently required,
|
||||||
|
"patch" is equivalent to "latest".
|
||||||
|
|
||||||
|
A revision identifier for the underlying source repository, such as
|
||||||
|
a commit hash prefix, revision tag, or branch name, selects that
|
||||||
|
specific code revision. If the revision is also tagged with a
|
||||||
|
semantic version, the query evaluates to that semantic version.
|
||||||
|
Otherwise the query evaluates to a pseudo-version for the commit.
|
||||||
|
Note that branches and tags with names that are matched by other
|
||||||
|
query syntax cannot be selected this way. For example, the query
|
||||||
|
"v2" means the latest version starting with "v2", not the branch
|
||||||
|
named "v2".
|
||||||
|
|
||||||
All queries prefer release versions to pre-release versions.
|
All queries prefer release versions to pre-release versions.
|
||||||
For example, "<v1.2.3" will prefer to return "v1.2.2"
|
For example, "<v1.2.3" will prefer to return "v1.2.2"
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"cmd/go/internal/par"
|
"cmd/go/internal/par"
|
||||||
"cmd/go/internal/search"
|
"cmd/go/internal/search"
|
||||||
"cmd/go/internal/semver"
|
"cmd/go/internal/semver"
|
||||||
|
"cmd/go/internal/str"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ImportMissingError struct {
|
type ImportMissingError struct {
|
||||||
|
@ -35,6 +36,9 @@ type ImportMissingError struct {
|
||||||
|
|
||||||
func (e *ImportMissingError) Error() string {
|
func (e *ImportMissingError) Error() string {
|
||||||
if e.Module.Path == "" {
|
if e.Module.Path == "" {
|
||||||
|
if str.HasPathPrefix(e.ImportPath, "cmd") {
|
||||||
|
return fmt.Sprintf("package %s is not in GOROOT (%s)", e.ImportPath, filepath.Join(cfg.GOROOT, "src", e.ImportPath))
|
||||||
|
}
|
||||||
return "cannot find module providing package " + e.ImportPath
|
return "cannot find module providing package " + e.ImportPath
|
||||||
}
|
}
|
||||||
return "missing module for import: " + e.Module.Path + "@" + e.Module.Version + " provides " + e.ImportPath
|
return "missing module for import: " + e.Module.Path + "@" + e.Module.Version + " provides " + e.ImportPath
|
||||||
|
@ -74,6 +78,9 @@ func Import(path string) (m module.Version, dir string, err error) {
|
||||||
dir := filepath.Join(cfg.GOROOT, "src", path)
|
dir := filepath.Join(cfg.GOROOT, "src", path)
|
||||||
return module.Version{}, dir, nil
|
return module.Version{}, dir, nil
|
||||||
}
|
}
|
||||||
|
if str.HasPathPrefix(path, "cmd") {
|
||||||
|
return module.Version{}, "", &ImportMissingError{ImportPath: path}
|
||||||
|
}
|
||||||
|
|
||||||
// -mod=vendor is special.
|
// -mod=vendor is special.
|
||||||
// Everything must be in the main module or the main module's vendor directory.
|
// Everything must be in the main module or the main module's vendor directory.
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package modload
|
package modload
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -70,9 +71,7 @@ func listModules(args []string, listVersions bool) []*modinfo.ModulePublic {
|
||||||
mods = append(mods, &modinfo.ModulePublic{
|
mods = append(mods, &modinfo.ModulePublic{
|
||||||
Path: path,
|
Path: path,
|
||||||
Version: vers,
|
Version: vers,
|
||||||
Error: &modinfo.ModuleError{
|
Error: modinfoError(path, vers, err),
|
||||||
Err: err.Error(),
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -116,19 +115,15 @@ func listModules(args []string, listVersions bool) []*modinfo.ModulePublic {
|
||||||
mods = append(mods, moduleInfo(module.Version{Path: arg, Version: info.Version}, false))
|
mods = append(mods, moduleInfo(module.Version{Path: arg, Version: info.Version}, false))
|
||||||
} else {
|
} else {
|
||||||
mods = append(mods, &modinfo.ModulePublic{
|
mods = append(mods, &modinfo.ModulePublic{
|
||||||
Path: arg,
|
Path: arg,
|
||||||
Error: &modinfo.ModuleError{
|
Error: modinfoError(arg, "", err),
|
||||||
Err: err.Error(),
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
mods = append(mods, &modinfo.ModulePublic{
|
mods = append(mods, &modinfo.ModulePublic{
|
||||||
Path: arg,
|
Path: arg,
|
||||||
Error: &modinfo.ModuleError{
|
Error: modinfoError(arg, "", errors.New("not a known dependency")),
|
||||||
Err: fmt.Sprintf("module %q is not a known dependency", arg),
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg)
|
fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg)
|
||||||
|
@ -138,3 +133,21 @@ func listModules(args []string, listVersions bool) []*modinfo.ModulePublic {
|
||||||
|
|
||||||
return mods
|
return mods
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// modinfoError wraps an error to create an error message in
|
||||||
|
// modinfo.ModuleError with minimal redundancy.
|
||||||
|
func modinfoError(path, vers string, err error) *modinfo.ModuleError {
|
||||||
|
var nerr *NoMatchingVersionError
|
||||||
|
var merr *module.ModuleError
|
||||||
|
if errors.As(err, &nerr) {
|
||||||
|
// NoMatchingVersionError contains the query, so we don't mention the
|
||||||
|
// query again in ModuleError.
|
||||||
|
err = &module.ModuleError{Path: path, Err: err}
|
||||||
|
} else if !errors.As(err, &merr) {
|
||||||
|
// If the error does not contain path and version, wrap it in a
|
||||||
|
// module.ModuleError.
|
||||||
|
err = &module.ModuleError{Path: path, Version: vers, Err: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &modinfo.ModuleError{Err: err.Error()}
|
||||||
|
}
|
||||||
|
|
|
@ -100,11 +100,31 @@ func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match {
|
||||||
dir = filepath.Clean(dir)
|
dir = filepath.Clean(dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// golang.org/issue/32917: We should resolve a relative path to a
|
||||||
|
// package path only if the relative path actually contains the code
|
||||||
|
// for that package.
|
||||||
|
if !dirContainsPackage(dir) {
|
||||||
|
// If we're outside of a module, ensure that the failure mode
|
||||||
|
// indicates that.
|
||||||
|
ModRoot()
|
||||||
|
|
||||||
|
// If the directory is local but does not exist, don't return it
|
||||||
|
// while loader is iterating, since this might trigger a fetch.
|
||||||
|
// After loader is done iterating, we still need to return the
|
||||||
|
// path, so that "go list -e" produces valid output.
|
||||||
|
if !iterating {
|
||||||
|
// We don't have a valid path to resolve to, so report the
|
||||||
|
// unresolved path.
|
||||||
|
m.Pkgs = append(m.Pkgs, pkg)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// Note: The checks for @ here are just to avoid misinterpreting
|
// Note: The checks for @ here are just to avoid misinterpreting
|
||||||
// the module cache directories (formerly GOPATH/src/mod/foo@v1.5.2/bar).
|
// the module cache directories (formerly GOPATH/src/mod/foo@v1.5.2/bar).
|
||||||
// It's not strictly necessary but helpful to keep the checks.
|
// It's not strictly necessary but helpful to keep the checks.
|
||||||
if modRoot != "" && dir == modRoot {
|
if modRoot != "" && dir == modRoot {
|
||||||
pkg = Target.Path
|
pkg = targetPrefix
|
||||||
} else if modRoot != "" && strings.HasPrefix(dir, modRoot+string(filepath.Separator)) && !strings.Contains(dir[len(modRoot):], "@") {
|
} else if modRoot != "" && strings.HasPrefix(dir, modRoot+string(filepath.Separator)) && !strings.Contains(dir[len(modRoot):], "@") {
|
||||||
suffix := filepath.ToSlash(dir[len(modRoot):])
|
suffix := filepath.ToSlash(dir[len(modRoot):])
|
||||||
if strings.HasPrefix(suffix, "/vendor/") {
|
if strings.HasPrefix(suffix, "/vendor/") {
|
||||||
|
@ -121,7 +141,13 @@ func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pkg = Target.Path + suffix
|
modPkg := targetPrefix + suffix
|
||||||
|
if _, ok := dirInModule(modPkg, targetPrefix, modRoot, true); ok {
|
||||||
|
pkg = modPkg
|
||||||
|
} else if !iterating {
|
||||||
|
ModRoot()
|
||||||
|
base.Errorf("go: directory %s is outside main module", base.ShortPath(dir))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if sub := search.InDir(dir, cfg.GOROOTsrc); sub != "" && sub != "." && !strings.Contains(sub, "@") {
|
} else if sub := search.InDir(dir, cfg.GOROOTsrc); sub != "" && sub != "." && !strings.Contains(sub, "@") {
|
||||||
pkg = filepath.ToSlash(sub)
|
pkg = filepath.ToSlash(sub)
|
||||||
|
@ -134,16 +160,6 @@ func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match {
|
||||||
base.Errorf("go: directory %s outside available modules", base.ShortPath(dir))
|
base.Errorf("go: directory %s outside available modules", base.ShortPath(dir))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info, err := os.Stat(dir)
|
|
||||||
if err != nil || !info.IsDir() {
|
|
||||||
// If the directory is local but does not exist, don't return it
|
|
||||||
// while loader is iterating, since this would trigger a fetch.
|
|
||||||
// After loader is done iterating, we still need to return the
|
|
||||||
// path, so that "go list -e" produces valid output.
|
|
||||||
if iterating {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Pkgs = append(m.Pkgs, pkg)
|
m.Pkgs = append(m.Pkgs, pkg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,14 +263,30 @@ func pathInModuleCache(dir string) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// warnPattern returns list, the result of matching pattern,
|
var dirContainsPackageCache sync.Map // absolute dir → bool
|
||||||
// but if list is empty then first it prints a warning about
|
|
||||||
// the pattern not matching any packages.
|
func dirContainsPackage(dir string) bool {
|
||||||
func warnPattern(pattern string, list []string) []string {
|
isPkg, ok := dirContainsPackageCache.Load(dir)
|
||||||
if len(list) == 0 {
|
if !ok {
|
||||||
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
|
_, err := cfg.BuildContext.ImportDir(dir, 0)
|
||||||
|
if err == nil {
|
||||||
|
isPkg = true
|
||||||
|
} else {
|
||||||
|
if fi, statErr := os.Stat(dir); statErr != nil || !fi.IsDir() {
|
||||||
|
// A non-directory or inaccessible directory is not a Go package.
|
||||||
|
isPkg = false
|
||||||
|
} else if _, noGo := err.(*build.NoGoError); noGo {
|
||||||
|
// A directory containing no Go source files is not a Go package.
|
||||||
|
isPkg = false
|
||||||
|
} else {
|
||||||
|
// An error other than *build.NoGoError indicates that the package exists
|
||||||
|
// but has some other problem (such as a syntax error).
|
||||||
|
isPkg = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isPkg, _ = dirContainsPackageCache.LoadOrStore(dir, isPkg)
|
||||||
}
|
}
|
||||||
return list
|
return isPkg.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportFromFiles adds modules to the build list as needed
|
// ImportFromFiles adds modules to the build list as needed
|
||||||
|
@ -355,11 +387,13 @@ func loadAll(testAll bool) []string {
|
||||||
|
|
||||||
var paths []string
|
var paths []string
|
||||||
for _, pkg := range loaded.pkgs {
|
for _, pkg := range loaded.pkgs {
|
||||||
if e, ok := pkg.err.(*ImportMissingError); ok && e.Module.Path == "" {
|
if pkg.err != nil {
|
||||||
continue // Package doesn't actually exist.
|
base.Errorf("%s: %v", pkg.stackText(), pkg.err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
paths = append(paths, pkg.path)
|
paths = append(paths, pkg.path)
|
||||||
}
|
}
|
||||||
|
base.ExitIfErrors()
|
||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1108,7 +1142,9 @@ func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
|
||||||
return nil, module.VersionError(mod, errors.New("parsing go.mod: missing module line"))
|
return nil, module.VersionError(mod, errors.New("parsing go.mod: missing module line"))
|
||||||
}
|
}
|
||||||
if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path {
|
if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path {
|
||||||
return nil, module.VersionError(mod, fmt.Errorf("parsing go.mod: unexpected module path %q", mpath))
|
return nil, module.VersionError(mod, fmt.Errorf(`parsing go.mod:
|
||||||
|
module declares its path as: %s
|
||||||
|
but was required as: %s`, mpath, mod.Path))
|
||||||
}
|
}
|
||||||
if f.Go != nil {
|
if f.Go != nil {
|
||||||
r.versions.LoadOrStore(mod, f.Go.Version)
|
r.versions.LoadOrStore(mod, f.Go.Version)
|
||||||
|
|
|
@ -28,9 +28,10 @@ import (
|
||||||
// tagged version, with non-prereleases preferred over prereleases.
|
// tagged version, with non-prereleases preferred over prereleases.
|
||||||
// If there are no tagged versions in the repo, latest returns the most
|
// If there are no tagged versions in the repo, latest returns the most
|
||||||
// recent commit.
|
// recent commit.
|
||||||
|
// - the literal string "upgrade", equivalent to "latest" except that if
|
||||||
|
// current is a newer version, current will be returned (see below).
|
||||||
// - the literal string "patch", denoting the latest available tagged version
|
// - the literal string "patch", denoting the latest available tagged version
|
||||||
// with the same major and minor number as current. If current is "",
|
// with the same major and minor number as current (see below).
|
||||||
// "patch" is equivalent to "latest".
|
|
||||||
// - v1, denoting the latest available tagged version v1.x.x.
|
// - v1, denoting the latest available tagged version v1.x.x.
|
||||||
// - v1.2, denoting the latest available tagged version v1.2.x.
|
// - v1.2, denoting the latest available tagged version v1.2.x.
|
||||||
// - v1.2.3, a semantic version string denoting that tagged version.
|
// - v1.2.3, a semantic version string denoting that tagged version.
|
||||||
|
@ -39,11 +40,12 @@ import (
|
||||||
// with non-prereleases preferred over prereleases.
|
// with non-prereleases preferred over prereleases.
|
||||||
// - a repository commit identifier or tag, denoting that commit.
|
// - a repository commit identifier or tag, denoting that commit.
|
||||||
//
|
//
|
||||||
// current is optional, denoting the current version of the module.
|
// current denotes the current version of the module; it may be "" if the
|
||||||
// If query is "latest" or "patch", current will be returned if it is a newer
|
// current version is unknown or should not be considered. If query is
|
||||||
// semantic version or if it is a chronologically later pseudoversion. This
|
// "upgrade" or "patch", current will be returned if it is a newer
|
||||||
// prevents accidental downgrades from newer prerelease or development
|
// semantic version or a chronologically later pseudo-version than the
|
||||||
// versions.
|
// version that would otherwise be chosen. This prevents accidental downgrades
|
||||||
|
// from newer pre-release or development versions.
|
||||||
//
|
//
|
||||||
// If the allowed function is non-nil, Query excludes any versions for which
|
// If the allowed function is non-nil, Query excludes any versions for which
|
||||||
// allowed returns false.
|
// allowed returns false.
|
||||||
|
@ -81,6 +83,10 @@ func queryProxy(proxy, path, query, current string, allowed func(module.Version)
|
||||||
ok = allowed
|
ok = allowed
|
||||||
mayUseLatest = true
|
mayUseLatest = true
|
||||||
|
|
||||||
|
case query == "upgrade":
|
||||||
|
ok = allowed
|
||||||
|
mayUseLatest = true
|
||||||
|
|
||||||
case query == "patch":
|
case query == "patch":
|
||||||
if current == "" {
|
if current == "" {
|
||||||
ok = allowed
|
ok = allowed
|
||||||
|
@ -202,9 +208,9 @@ func queryProxy(proxy, path, query, current string, allowed func(module.Version)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// For "latest" and "patch", make sure we don't accidentally downgrade
|
// For "upgrade" and "patch", make sure we don't accidentally downgrade
|
||||||
// from a newer prerelease or from a chronologically newer pseudoversion.
|
// from a newer prerelease or from a chronologically newer pseudoversion.
|
||||||
if current != "" && (query == "latest" || query == "patch") {
|
if current != "" && (query == "upgrade" || query == "patch") {
|
||||||
currentTime, err := modfetch.PseudoVersionTime(current)
|
currentTime, err := modfetch.PseudoVersionTime(current)
|
||||||
if semver.Compare(rev.Version, current) < 0 || (err == nil && rev.Time.Before(currentTime)) {
|
if semver.Compare(rev.Version, current) < 0 || (err == nil && rev.Time.Before(currentTime)) {
|
||||||
return repo.Stat(current)
|
return repo.Stat(current)
|
||||||
|
@ -374,10 +380,10 @@ func QueryPattern(pattern, query string, allowed func(module.Version) bool) ([]Q
|
||||||
}
|
}
|
||||||
r.Packages = match(r.Mod, root, isLocal)
|
r.Packages = match(r.Mod, root, isLocal)
|
||||||
if len(r.Packages) == 0 {
|
if len(r.Packages) == 0 {
|
||||||
return r, &packageNotInModuleError{
|
return r, &PackageNotInModuleError{
|
||||||
mod: r.Mod,
|
Mod: r.Mod,
|
||||||
query: query,
|
Query: query,
|
||||||
pattern: pattern,
|
Pattern: pattern,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r, nil
|
return r, nil
|
||||||
|
@ -440,30 +446,31 @@ func queryPrefixModules(candidateModules []string, queryModule func(path string)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
// Classify the results. In case of failure, identify the error that the user
|
// Classify the results. In case of failure, identify the error that the user
|
||||||
// is most likely to find helpful.
|
// is most likely to find helpful: the most useful class of error at the
|
||||||
|
// longest matching path.
|
||||||
var (
|
var (
|
||||||
|
noPackage *PackageNotInModuleError
|
||||||
noVersion *NoMatchingVersionError
|
noVersion *NoMatchingVersionError
|
||||||
noPackage *packageNotInModuleError
|
|
||||||
notExistErr error
|
notExistErr error
|
||||||
)
|
)
|
||||||
for _, r := range results {
|
for _, r := range results {
|
||||||
switch rErr := r.err.(type) {
|
switch rErr := r.err.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
found = append(found, r.QueryResult)
|
found = append(found, r.QueryResult)
|
||||||
|
case *PackageNotInModuleError:
|
||||||
|
if noPackage == nil {
|
||||||
|
noPackage = rErr
|
||||||
|
}
|
||||||
case *NoMatchingVersionError:
|
case *NoMatchingVersionError:
|
||||||
if noVersion == nil {
|
if noVersion == nil {
|
||||||
noVersion = rErr
|
noVersion = rErr
|
||||||
}
|
}
|
||||||
case *packageNotInModuleError:
|
|
||||||
if noPackage == nil {
|
|
||||||
noPackage = rErr
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
if errors.Is(rErr, os.ErrNotExist) {
|
if errors.Is(rErr, os.ErrNotExist) {
|
||||||
if notExistErr == nil {
|
if notExistErr == nil {
|
||||||
notExistErr = rErr
|
notExistErr = rErr
|
||||||
}
|
}
|
||||||
} else {
|
} else if err == nil {
|
||||||
err = r.err
|
err = r.err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -503,37 +510,37 @@ type NoMatchingVersionError struct {
|
||||||
|
|
||||||
func (e *NoMatchingVersionError) Error() string {
|
func (e *NoMatchingVersionError) Error() string {
|
||||||
currentSuffix := ""
|
currentSuffix := ""
|
||||||
if (e.query == "latest" || e.query == "patch") && e.current != "" {
|
if (e.query == "upgrade" || e.query == "patch") && e.current != "" {
|
||||||
currentSuffix = fmt.Sprintf(" (current version is %s)", e.current)
|
currentSuffix = fmt.Sprintf(" (current version is %s)", e.current)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("no matching versions for query %q", e.query) + currentSuffix
|
return fmt.Sprintf("no matching versions for query %q", e.query) + currentSuffix
|
||||||
}
|
}
|
||||||
|
|
||||||
// A packageNotInModuleError indicates that QueryPattern found a candidate
|
// A PackageNotInModuleError indicates that QueryPattern found a candidate
|
||||||
// module at the requested version, but that module did not contain any packages
|
// module at the requested version, but that module did not contain any packages
|
||||||
// matching the requested pattern.
|
// matching the requested pattern.
|
||||||
//
|
//
|
||||||
// NOTE: packageNotInModuleError MUST NOT implement Is(os.ErrNotExist).
|
// NOTE: PackageNotInModuleError MUST NOT implement Is(os.ErrNotExist).
|
||||||
//
|
//
|
||||||
// If the module came from a proxy, that proxy had to return a successful status
|
// If the module came from a proxy, that proxy had to return a successful status
|
||||||
// code for the versions it knows about, and thus did not have the opportunity
|
// code for the versions it knows about, and thus did not have the opportunity
|
||||||
// to return a non-400 status code to suppress fallback.
|
// to return a non-400 status code to suppress fallback.
|
||||||
type packageNotInModuleError struct {
|
type PackageNotInModuleError struct {
|
||||||
mod module.Version
|
Mod module.Version
|
||||||
query string
|
Query string
|
||||||
pattern string
|
Pattern string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *packageNotInModuleError) Error() string {
|
func (e *PackageNotInModuleError) Error() string {
|
||||||
found := ""
|
found := ""
|
||||||
if e.query != e.mod.Version {
|
if e.Query != e.Mod.Version {
|
||||||
found = fmt.Sprintf(" (%s)", e.mod.Version)
|
found = fmt.Sprintf(" (%s)", e.Mod.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(e.pattern, "...") {
|
if strings.Contains(e.Pattern, "...") {
|
||||||
return fmt.Sprintf("module %s@%s%s found, but does not contain packages matching %s", e.mod.Path, e.query, found, e.pattern)
|
return fmt.Sprintf("module %s@%s%s found, but does not contain packages matching %s", e.Mod.Path, e.Query, found, e.Pattern)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("module %s@%s%s found, but does not contain package %s", e.mod.Path, e.query, found, e.pattern)
|
return fmt.Sprintf("module %s@%s%s found, but does not contain package %s", e.Mod.Path, e.Query, found, e.Pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModuleHasRootPackage returns whether module m contains a package m.Path.
|
// ModuleHasRootPackage returns whether module m contains a package m.Path.
|
||||||
|
|
|
@ -100,7 +100,7 @@ var queryTests = []struct {
|
||||||
{path: queryRepo, query: ">=v0.0.0", vers: "v0.0.0"},
|
{path: queryRepo, query: ">=v0.0.0", vers: "v0.0.0"},
|
||||||
{path: queryRepo, query: "v0.0.1", vers: "v0.0.1"},
|
{path: queryRepo, query: "v0.0.1", vers: "v0.0.1"},
|
||||||
{path: queryRepo, query: "v0.0.1+foo", vers: "v0.0.1"},
|
{path: queryRepo, query: "v0.0.1+foo", vers: "v0.0.1"},
|
||||||
{path: queryRepo, query: "v0.0.99", err: `unknown revision v0.0.99`},
|
{path: queryRepo, query: "v0.0.99", err: `vcs-test.golang.org/git/querytest.git@v0.0.99: invalid version: unknown revision v0.0.99`},
|
||||||
{path: queryRepo, query: "v0", vers: "v0.3.0"},
|
{path: queryRepo, query: "v0", vers: "v0.3.0"},
|
||||||
{path: queryRepo, query: "v0.1", vers: "v0.1.2"},
|
{path: queryRepo, query: "v0.1", vers: "v0.1.2"},
|
||||||
{path: queryRepo, query: "v0.2", err: `no matching versions for query "v0.2"`},
|
{path: queryRepo, query: "v0.2", err: `no matching versions for query "v0.2"`},
|
||||||
|
@ -112,15 +112,17 @@ var queryTests = []struct {
|
||||||
// unconditionally).
|
// unconditionally).
|
||||||
{path: queryRepo, query: "42abcb6df8ee", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
|
{path: queryRepo, query: "42abcb6df8ee", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
|
||||||
|
|
||||||
{path: queryRepo, query: "v1.9.10-pre2+wrongmetadata", err: `unknown revision v1.9.10-pre2+wrongmetadata`},
|
{path: queryRepo, query: "v1.9.10-pre2+wrongmetadata", err: `vcs-test.golang.org/git/querytest.git@v1.9.10-pre2+wrongmetadata: invalid version: unknown revision v1.9.10-pre2+wrongmetadata`},
|
||||||
{path: queryRepo, query: "v1.9.10-pre2", err: `unknown revision v1.9.10-pre2`},
|
{path: queryRepo, query: "v1.9.10-pre2", err: `vcs-test.golang.org/git/querytest.git@v1.9.10-pre2: invalid version: unknown revision v1.9.10-pre2`},
|
||||||
{path: queryRepo, query: "latest", vers: "v1.9.9"},
|
{path: queryRepo, query: "latest", vers: "v1.9.9"},
|
||||||
{path: queryRepo, query: "latest", current: "v1.9.10-pre1", vers: "v1.9.10-pre1"},
|
{path: queryRepo, query: "latest", current: "v1.9.10-pre1", vers: "v1.9.9"},
|
||||||
{path: queryRepo, query: "latest", current: "v1.9.10-pre2+metadata", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
|
{path: queryRepo, query: "upgrade", vers: "v1.9.9"},
|
||||||
{path: queryRepo, query: "latest", current: "v0.0.0-20190513201126-42abcb6df8ee", vers: "v0.0.0-20190513201126-42abcb6df8ee"},
|
{path: queryRepo, query: "upgrade", current: "v1.9.10-pre1", vers: "v1.9.10-pre1"},
|
||||||
{path: queryRepo, query: "latest", allow: "NOMATCH", err: `no matching versions for query "latest"`},
|
{path: queryRepo, query: "upgrade", current: "v1.9.10-pre2+metadata", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
|
||||||
{path: queryRepo, query: "latest", current: "v1.9.9", allow: "NOMATCH", err: `no matching versions for query "latest" (current version is v1.9.9)`},
|
{path: queryRepo, query: "upgrade", current: "v0.0.0-20190513201126-42abcb6df8ee", vers: "v0.0.0-20190513201126-42abcb6df8ee"},
|
||||||
{path: queryRepo, query: "latest", current: "v1.99.99", err: `unknown revision v1.99.99`},
|
{path: queryRepo, query: "upgrade", allow: "NOMATCH", err: `no matching versions for query "upgrade"`},
|
||||||
|
{path: queryRepo, query: "upgrade", current: "v1.9.9", allow: "NOMATCH", err: `no matching versions for query "upgrade" (current version is v1.9.9)`},
|
||||||
|
{path: queryRepo, query: "upgrade", current: "v1.99.99", err: `vcs-test.golang.org/git/querytest.git@v1.99.99: invalid version: unknown revision v1.99.99`},
|
||||||
{path: queryRepo, query: "patch", current: "", vers: "v1.9.9"},
|
{path: queryRepo, query: "patch", current: "", vers: "v1.9.9"},
|
||||||
{path: queryRepo, query: "patch", current: "v0.1.0", vers: "v0.1.2"},
|
{path: queryRepo, query: "patch", current: "v0.1.0", vers: "v0.1.2"},
|
||||||
{path: queryRepo, query: "patch", current: "v1.9.0", vers: "v1.9.9"},
|
{path: queryRepo, query: "patch", current: "v1.9.0", vers: "v1.9.9"},
|
||||||
|
@ -159,8 +161,11 @@ var queryTests = []struct {
|
||||||
{path: queryRepoV2, query: "v2.6.0-pre1", vers: "v2.6.0-pre1"},
|
{path: queryRepoV2, query: "v2.6.0-pre1", vers: "v2.6.0-pre1"},
|
||||||
{path: queryRepoV2, query: "latest", vers: "v2.5.5"},
|
{path: queryRepoV2, query: "latest", vers: "v2.5.5"},
|
||||||
|
|
||||||
{path: queryRepoV3, query: "e0cf3de987e6", vers: "v3.0.0-20180704024501-e0cf3de987e6"},
|
// e0cf3de987e6 is the latest commit on the master branch, and it's actually
|
||||||
{path: queryRepoV3, query: "latest", vers: "v3.0.0-20180704024501-e0cf3de987e6"},
|
// v1.19.10-pre1, not anything resembling v3: attempting to query it as such
|
||||||
|
// should fail.
|
||||||
|
{path: queryRepoV3, query: "e0cf3de987e6", err: `vcs-test.golang.org/git/querytest.git/v3@v3.0.0-20180704024501-e0cf3de987e6: invalid version: go.mod has non-.../v3 module path "vcs-test.golang.org/git/querytest.git" (and .../v3/go.mod does not exist) at revision e0cf3de987e6`},
|
||||||
|
{path: queryRepoV3, query: "latest", err: `no matching versions for query "latest"`},
|
||||||
|
|
||||||
{path: emptyRepo, query: "latest", vers: "v0.0.0-20180704023549-7bb914627242"},
|
{path: emptyRepo, query: "latest", vers: "v0.0.0-20180704023549-7bb914627242"},
|
||||||
{path: emptyRepo, query: ">v0.0.0", err: `no matching versions for query ">v0.0.0"`},
|
{path: emptyRepo, query: ">v0.0.0", err: `no matching versions for query ">v0.0.0"`},
|
||||||
|
@ -180,7 +185,10 @@ func TestQuery(t *testing.T) {
|
||||||
ok, _ := path.Match(allow, m.Version)
|
ok, _ := path.Match(allow, m.Version)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
tt := tt
|
||||||
t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.query+"/"+tt.current+"/"+allow, func(t *testing.T) {
|
t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.query+"/"+tt.current+"/"+allow, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
info, err := Query(tt.path, tt.query, tt.current, allowed)
|
info, err := Query(tt.path, tt.query, tt.current, allowed)
|
||||||
if tt.err != "" {
|
if tt.err != "" {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
|
@ -216,8 +216,8 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct the list by traversing the graph again, replacing older
|
// The final list is the minimum version of each module found in the graph.
|
||||||
// modules with required minimum versions.
|
|
||||||
if v := min[target.Path]; v != target.Version {
|
if v := min[target.Path]; v != target.Version {
|
||||||
// TODO(jayconrod): there is a special case in modload.mvsReqs.Max
|
// TODO(jayconrod): there is a special case in modload.mvsReqs.Max
|
||||||
// that prevents us from selecting a newer version of a module
|
// that prevents us from selecting a newer version of a module
|
||||||
|
@ -228,19 +228,18 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (m
|
||||||
}
|
}
|
||||||
|
|
||||||
list := []module.Version{target}
|
list := []module.Version{target}
|
||||||
listed := map[string]bool{target.Path: true}
|
for path, vers := range min {
|
||||||
for i := 0; i < len(list); i++ {
|
if path != target.Path {
|
||||||
n := modGraph[list[i]]
|
list = append(list, module.Version{Path: path, Version: vers})
|
||||||
|
}
|
||||||
|
|
||||||
|
n := modGraph[module.Version{Path: path, Version: vers}]
|
||||||
required := n.required
|
required := n.required
|
||||||
for _, r := range required {
|
for _, r := range required {
|
||||||
v := min[r.Path]
|
v := min[r.Path]
|
||||||
if r.Path != target.Path && reqs.Max(v, r.Version) != v {
|
if r.Path != target.Path && reqs.Max(v, r.Version) != v {
|
||||||
panic(fmt.Sprintf("mistake: version %q does not satisfy requirement %+v", v, r)) // TODO: Don't panic.
|
panic(fmt.Sprintf("mistake: version %q does not satisfy requirement %+v", v, r)) // TODO: Don't panic.
|
||||||
}
|
}
|
||||||
if !listed[r.Path] {
|
|
||||||
list = append(list, module.Version{Path: r.Path, Version: v})
|
|
||||||
listed[r.Path] = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,12 +288,12 @@ func Req(target module.Version, list []module.Version, base []string, reqs Reqs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk modules in reverse post-order, only adding those not implied already.
|
// Walk modules in reverse post-order, only adding those not implied already.
|
||||||
have := map[string]string{}
|
have := map[module.Version]bool{}
|
||||||
walk = func(m module.Version) error {
|
walk = func(m module.Version) error {
|
||||||
if v, ok := have[m.Path]; ok && reqs.Max(m.Version, v) == v {
|
if have[m] {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
have[m.Path] = m.Version
|
have[m] = true
|
||||||
for _, m1 := range reqCache[m] {
|
for _, m1 := range reqCache[m] {
|
||||||
walk(m1)
|
walk(m1)
|
||||||
}
|
}
|
||||||
|
@ -322,7 +321,7 @@ func Req(target module.Version, list []module.Version, base []string, reqs Reqs)
|
||||||
// Older version.
|
// Older version.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if have[m.Path] != m.Version {
|
if !have[m] {
|
||||||
min = append(min, m)
|
min = append(min, m)
|
||||||
walk(m)
|
walk(m)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ D5: E2
|
||||||
G1: C4
|
G1: C4
|
||||||
A2: B1 C4 D4
|
A2: B1 C4 D4
|
||||||
build A: A B1 C2 D4 E2 F1
|
build A: A B1 C2 D4 E2 F1
|
||||||
upgrade* A: A B1 C4 D5 E2 G1
|
upgrade* A: A B1 C4 D5 E2 F1 G1
|
||||||
upgrade A C4: A B1 C4 D4 E2 F1 G1
|
upgrade A C4: A B1 C4 D4 E2 F1 G1
|
||||||
downgrade A2 D2: A2 C4 D2
|
downgrade A2 D2: A2 C4 D2
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ A: B1 C2
|
||||||
B1: D3
|
B1: D3
|
||||||
C2: B2
|
C2: B2
|
||||||
B2:
|
B2:
|
||||||
build A: A B2 C2
|
build A: A B2 C2 D3
|
||||||
|
|
||||||
# Cross-dependency between D and E.
|
# Cross-dependency between D and E.
|
||||||
# No matter how it arises, should get result of merging all build lists via max,
|
# No matter how it arises, should get result of merging all build lists via max,
|
||||||
|
@ -157,7 +157,18 @@ D1: E2
|
||||||
E1: D2
|
E1: D2
|
||||||
build A: A B C D2 E2
|
build A: A B C D2 E2
|
||||||
|
|
||||||
# Upgrade from B1 to B2 should drop the transitive dep on D.
|
# golang.org/issue/31248:
|
||||||
|
# Even though we select X2, the requirement on I1
|
||||||
|
# via X1 should be preserved.
|
||||||
|
name: cross8
|
||||||
|
M: A1 B1
|
||||||
|
A1: X1
|
||||||
|
B1: X2
|
||||||
|
X1: I1
|
||||||
|
X2:
|
||||||
|
build M: M A1 B1 I1 X2
|
||||||
|
|
||||||
|
# Upgrade from B1 to B2 should not drop the transitive dep on D.
|
||||||
name: drop
|
name: drop
|
||||||
A: B1 C1
|
A: B1 C1
|
||||||
B1: D1
|
B1: D1
|
||||||
|
@ -165,14 +176,14 @@ B2:
|
||||||
C2:
|
C2:
|
||||||
D2:
|
D2:
|
||||||
build A: A B1 C1 D1
|
build A: A B1 C1 D1
|
||||||
upgrade* A: A B2 C2
|
upgrade* A: A B2 C2 D2
|
||||||
|
|
||||||
name: simplify
|
name: simplify
|
||||||
A: B1 C1
|
A: B1 C1
|
||||||
B1: C2
|
B1: C2
|
||||||
C1: D1
|
C1: D1
|
||||||
C2:
|
C2:
|
||||||
build A: A B1 C2
|
build A: A B1 C2 D1
|
||||||
|
|
||||||
name: up1
|
name: up1
|
||||||
A: B1 C1
|
A: B1 C1
|
||||||
|
@ -254,8 +265,9 @@ build A: A B1
|
||||||
upgrade A B2: A B2
|
upgrade A B2: A B2
|
||||||
upgrade* A: A B3
|
upgrade* A: A B3
|
||||||
|
|
||||||
|
# golang.org/issue/29773:
|
||||||
# Requirements of older versions of the target
|
# Requirements of older versions of the target
|
||||||
# must not be carried over.
|
# must be carried over.
|
||||||
name: cycle2
|
name: cycle2
|
||||||
A: B1
|
A: B1
|
||||||
A1: C1
|
A1: C1
|
||||||
|
@ -265,8 +277,8 @@ B2: A2
|
||||||
C1: A2
|
C1: A2
|
||||||
C2:
|
C2:
|
||||||
D2:
|
D2:
|
||||||
build A: A B1
|
build A: A B1 C1 D1
|
||||||
upgrade* A: A B2
|
upgrade* A: A B2 C2 D2
|
||||||
|
|
||||||
# Requirement minimization.
|
# Requirement minimization.
|
||||||
|
|
||||||
|
@ -283,6 +295,14 @@ H1: G1
|
||||||
req A: G1
|
req A: G1
|
||||||
req A G: G1
|
req A G: G1
|
||||||
req A H: H1
|
req A H: H1
|
||||||
|
|
||||||
|
name: req3
|
||||||
|
M: A1 B1
|
||||||
|
A1: X1
|
||||||
|
B1: X2
|
||||||
|
X1: I1
|
||||||
|
X2:
|
||||||
|
req M: A1 B1
|
||||||
`
|
`
|
||||||
|
|
||||||
func Test(t *testing.T) {
|
func Test(t *testing.T) {
|
||||||
|
|
|
@ -843,7 +843,7 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
|
||||||
if !cfg.BuildN {
|
if !cfg.BuildN {
|
||||||
// writeTestmain writes _testmain.go,
|
// writeTestmain writes _testmain.go,
|
||||||
// using the test description gathered in t.
|
// using the test description gathered in t.
|
||||||
if err := ioutil.WriteFile(testDir+"_testmain.go", pmain.Internal.TestmainGo, 0666); err != nil {
|
if err := ioutil.WriteFile(testDir+"_testmain.go", *pmain.Internal.TestmainGo, 0666); err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1250,6 +1250,15 @@ func (c *runCache) tryCacheWithID(b *work.Builder, a *work.Action, id string) bo
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if a.Package.Root == "" {
|
||||||
|
// Caching does not apply to tests outside of any module, GOPATH, or GOROOT.
|
||||||
|
if cache.DebugTest {
|
||||||
|
fmt.Fprintf(os.Stderr, "testcache: caching disabled for package outside of module root, GOPATH, or GOROOT: %s\n", a.Package.ImportPath)
|
||||||
|
}
|
||||||
|
c.disableCache = true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
var cacheArgs []string
|
var cacheArgs []string
|
||||||
for _, arg := range testArgs {
|
for _, arg := range testArgs {
|
||||||
i := strings.Index(arg, "=")
|
i := strings.Index(arg, "=")
|
||||||
|
@ -1437,8 +1446,8 @@ func computeTestInputsID(a *work.Action, testlog []byte) (cache.ActionID, error)
|
||||||
if !filepath.IsAbs(name) {
|
if !filepath.IsAbs(name) {
|
||||||
name = filepath.Join(pwd, name)
|
name = filepath.Join(pwd, name)
|
||||||
}
|
}
|
||||||
if !inDir(name, a.Package.Root) {
|
if a.Package.Root == "" || !inDir(name, a.Package.Root) {
|
||||||
// Do not recheck files outside the GOPATH or GOROOT root.
|
// Do not recheck files outside the module, GOPATH, or GOROOT root.
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
fmt.Fprintf(h, "stat %s %x\n", name, hashStat(name))
|
fmt.Fprintf(h, "stat %s %x\n", name, hashStat(name))
|
||||||
|
@ -1446,8 +1455,8 @@ func computeTestInputsID(a *work.Action, testlog []byte) (cache.ActionID, error)
|
||||||
if !filepath.IsAbs(name) {
|
if !filepath.IsAbs(name) {
|
||||||
name = filepath.Join(pwd, name)
|
name = filepath.Join(pwd, name)
|
||||||
}
|
}
|
||||||
if !inDir(name, a.Package.Root) {
|
if a.Package.Root == "" || !inDir(name, a.Package.Root) {
|
||||||
// Do not recheck files outside the GOPATH or GOROOT root.
|
// Do not recheck files outside the module, GOPATH, or GOROOT root.
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
fh, err := hashOpen(name)
|
fh, err := hashOpen(name)
|
||||||
|
|
|
@ -103,6 +103,11 @@ func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *elfExe) DataStart() uint64 {
|
func (x *elfExe) DataStart() uint64 {
|
||||||
|
for _, s := range x.f.Sections {
|
||||||
|
if s.Name == ".go.buildinfo" {
|
||||||
|
return s.Addr
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, p := range x.f.Progs {
|
for _, p := range x.f.Progs {
|
||||||
if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W {
|
if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W {
|
||||||
return p.Vaddr
|
return p.Vaddr
|
||||||
|
@ -208,7 +213,13 @@ func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *machoExe) DataStart() uint64 {
|
func (x *machoExe) DataStart() uint64 {
|
||||||
// Assume data is first non-empty writable segment.
|
// Look for section named "__go_buildinfo".
|
||||||
|
for _, sec := range x.f.Sections {
|
||||||
|
if sec.Name == "__go_buildinfo" {
|
||||||
|
return sec.Addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Try the first non-empty writable segment.
|
||||||
const RW = 3
|
const RW = 3
|
||||||
for _, load := range x.f.Loads {
|
for _, load := range x.f.Loads {
|
||||||
seg, ok := load.(*macho.Segment)
|
seg, ok := load.(*macho.Segment)
|
||||||
|
|
|
@ -30,6 +30,8 @@ along with their dependencies, but it does not install the results.
|
||||||
If the arguments to build are a list of .go files from a single directory,
|
If the arguments to build are a list of .go files from a single directory,
|
||||||
build treats them as a list of source files specifying a single package.
|
build treats them as a list of source files specifying a single package.
|
||||||
|
|
||||||
|
When compiling packages, build ignores files that end in '_test.go'.
|
||||||
|
|
||||||
When compiling a single main package, build writes
|
When compiling a single main package, build writes
|
||||||
the resulting executable to an output file named after
|
the resulting executable to an output file named after
|
||||||
the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe')
|
the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe')
|
||||||
|
@ -40,8 +42,6 @@ When compiling multiple packages or a single non-main package,
|
||||||
build compiles the packages but discards the resulting object,
|
build compiles the packages but discards the resulting object,
|
||||||
serving only as a check that the packages can be built.
|
serving only as a check that the packages can be built.
|
||||||
|
|
||||||
When compiling packages, build ignores files that end in '_test.go'.
|
|
||||||
|
|
||||||
The -o flag forces build to write the resulting executable or object
|
The -o flag forces build to write the resulting executable or object
|
||||||
to the named output file or directory, instead of the default behavior described
|
to the named output file or directory, instead of the default behavior described
|
||||||
in the last two paragraphs. If the named output is a directory that exists,
|
in the last two paragraphs. If the named output is a directory that exists,
|
||||||
|
|
|
@ -203,8 +203,9 @@ func (b *Builder) toolID(name string) string {
|
||||||
// On the development branch, use the content ID part of the build ID.
|
// On the development branch, use the content ID part of the build ID.
|
||||||
id = contentID(f[len(f)-1])
|
id = contentID(f[len(f)-1])
|
||||||
} else {
|
} else {
|
||||||
// For a release, the output is like: "compile version go1.9.1". Use the whole line.
|
// For a release, the output is like: "compile version go1.9.1 X:framepointer".
|
||||||
id = f[2]
|
// Use the whole line.
|
||||||
|
id = strings.TrimSpace(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.id.Lock()
|
b.id.Lock()
|
||||||
|
|
|
@ -542,15 +542,6 @@ func (b *Builder) build(a *Action) (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write out the _testinginit.go file for any test packages that import "testing".
|
|
||||||
if a.Package.Internal.TestinginitGo != nil {
|
|
||||||
initfile := objdir + "_testinginit.go"
|
|
||||||
if err := b.writeFile(initfile, a.Package.Internal.TestinginitGo); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
gofiles = append([]string{initfile}, gofiles...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run cgo.
|
// Run cgo.
|
||||||
if a.Package.UsesCgo() || a.Package.UsesSwig() {
|
if a.Package.UsesCgo() || a.Package.UsesSwig() {
|
||||||
// In a package using cgo, cgo compiles the C, C++ and assembly files with gcc.
|
// In a package using cgo, cgo compiles the C, C++ and assembly files with gcc.
|
||||||
|
|
|
@ -1,19 +1,16 @@
|
||||||
// Copyright 2019 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 flag_test
|
package flag_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"log"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var v = flag.Int("v", 0, "v flag")
|
var v = flag.Int("v", 0, "v flag")
|
||||||
|
|
||||||
// Run this as go test pkg -args -v=7
|
// Run this as go test pkg -v=7
|
||||||
func TestVFlagIsSet(t *testing.T) {
|
func TestVFlagIsSet(t *testing.T) {
|
||||||
if *v != 7 {
|
if *v != 7 {
|
||||||
t.Fatal("v flag not set")
|
log.Fatal("v flag not set")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
example.com/badchain/c v1.1.0
|
example.com/badchain/c v1.1.0
|
||||||
|
|
||||||
-- .mod --
|
-- .mod --
|
||||||
module example.com/badchain/wrong
|
module badchain.example.com/c
|
||||||
-- .info --
|
-- .info --
|
||||||
{"Version":"v1.1.0"}
|
{"Version":"v1.1.0"}
|
||||||
-- c.go --
|
-- c.go --
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
env GO111MODULE=off
|
env GO111MODULE=off
|
||||||
|
env GODEBUG=gocachetest=1
|
||||||
|
|
||||||
[!gc] skip
|
[!gc] skip
|
||||||
[short] skip # clears cache, rebuilds too much
|
[short] skip # clears cache, rebuilds too much
|
||||||
|
@ -32,7 +33,7 @@ stderr 'main.go:2.* can inline main' # from compiler
|
||||||
stderr '\d+ symbols' # from linker
|
stderr '\d+ symbols' # from linker
|
||||||
|
|
||||||
# Running a test should run the compiler, linker, and the test the first time.
|
# Running a test should run the compiler, linker, and the test the first time.
|
||||||
go test -v -x -gcflags=-m -ldflags=-v p_test.go
|
go test -v -x -gcflags=-m -ldflags=-v p
|
||||||
stderr 'compile( |\.exe"?)'
|
stderr 'compile( |\.exe"?)'
|
||||||
stderr 'p_test.go:.*can inline Test' # from compile of p_test
|
stderr 'p_test.go:.*can inline Test' # from compile of p_test
|
||||||
stderr 'testmain\.go:.*inlin' # from compile of testmain
|
stderr 'testmain\.go:.*inlin' # from compile of testmain
|
||||||
|
@ -42,7 +43,7 @@ stderr 'p\.test( |\.exe"?)'
|
||||||
stdout 'TEST' # from test
|
stdout 'TEST' # from test
|
||||||
|
|
||||||
# ... but not the second, even though it still prints the compiler, linker, and test output.
|
# ... but not the second, even though it still prints the compiler, linker, and test output.
|
||||||
go test -v -x -gcflags=-m -ldflags=-v p_test.go
|
go test -v -x -gcflags=-m -ldflags=-v p
|
||||||
! stderr 'compile( |\.exe"?)'
|
! stderr 'compile( |\.exe"?)'
|
||||||
stderr 'p_test.go:.*can inline Test' # from compile of p_test
|
stderr 'p_test.go:.*can inline Test' # from compile of p_test
|
||||||
stderr 'testmain\.go:.*inlin' # from compile of testmain
|
stderr 'testmain\.go:.*inlin' # from compile of testmain
|
||||||
|
@ -60,7 +61,7 @@ func f(x *int) *int { return x }
|
||||||
package main
|
package main
|
||||||
func main() {}
|
func main() {}
|
||||||
|
|
||||||
-- p_test.go --
|
-- p/p_test.go --
|
||||||
package p
|
package p
|
||||||
import "testing"
|
import "testing"
|
||||||
func Test(t *testing.T) {println("TEST")}
|
func Test(t *testing.T) {println("TEST")}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
env GO111MODULE=on
|
||||||
|
|
||||||
|
# Regression test for golang.org/issue/31031:
|
||||||
|
# Importing or loading a non-existent package in cmd/ should print
|
||||||
|
# a clear error in module mode.
|
||||||
|
|
||||||
|
! go list cmd/unknown
|
||||||
|
stderr '^can''t load package: package cmd/unknown: package cmd/unknown is not in GOROOT \('$GOROOT'[/\\]src[/\\]cmd[/\\]unknown\)$'
|
||||||
|
|
||||||
|
go list -f '{{range .DepsErrors}}{{.Err}}{{end}}' x.go
|
||||||
|
stdout '^package cmd/unknown is not in GOROOT \('$GOROOT'[/\\]src[/\\]cmd[/\\]unknown\)$'
|
||||||
|
|
||||||
|
-- x.go --
|
||||||
|
package x
|
||||||
|
|
||||||
|
import _ "cmd/unknown"
|
|
@ -3,6 +3,7 @@
|
||||||
env GO111MODULE=on
|
env GO111MODULE=on
|
||||||
[short] skip
|
[short] skip
|
||||||
|
|
||||||
|
# Check when module x is inside GOPATH/src.
|
||||||
go doc y
|
go doc y
|
||||||
stdout 'Package y is.*alphabet'
|
stdout 'Package y is.*alphabet'
|
||||||
stdout 'import "x/y"'
|
stdout 'import "x/y"'
|
||||||
|
@ -16,13 +17,25 @@ stdout 'Hello returns a greeting'
|
||||||
go doc quote
|
go doc quote
|
||||||
stdout 'Package quote collects pithy sayings.'
|
stdout 'Package quote collects pithy sayings.'
|
||||||
|
|
||||||
# Double-check go doc y when y is not in GOPATH/src.
|
# Double-check when module x is outside GOPATH/src.
|
||||||
env GOPATH=$WORK/altgopath
|
env GOPATH=$WORK/emptygopath
|
||||||
go doc x/y
|
go doc x/y
|
||||||
stdout 'Package y is.*alphabet'
|
stdout 'Package y is.*alphabet'
|
||||||
go doc y
|
go doc y
|
||||||
stdout 'Package y is.*alphabet'
|
stdout 'Package y is.*alphabet'
|
||||||
|
|
||||||
|
# Triple-check when module x is outside GOPATH/src,
|
||||||
|
# but other packages with same import paths are in GOPATH/src.
|
||||||
|
# Since go doc is running in module mode here, packages in active module
|
||||||
|
# should be preferred over packages in GOPATH. See golang.org/issue/28992.
|
||||||
|
env GOPATH=$WORK/gopath2
|
||||||
|
go doc x/y
|
||||||
|
! stdout 'Package y is.*GOPATH'
|
||||||
|
stdout 'Package y is.*alphabet'
|
||||||
|
go doc rsc.io/quote
|
||||||
|
! stdout 'Package quote is located in a GOPATH workspace.'
|
||||||
|
stdout 'Package quote collects pithy sayings.'
|
||||||
|
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
module x
|
module x
|
||||||
require rsc.io/quote v1.5.2
|
require rsc.io/quote v1.5.2
|
||||||
|
@ -33,3 +46,13 @@ package y
|
||||||
|
|
||||||
-- x.go --
|
-- x.go --
|
||||||
package x
|
package x
|
||||||
|
|
||||||
|
-- $WORK/gopath2/src/x/y/y.go --
|
||||||
|
// Package y is located in a GOPATH workspace.
|
||||||
|
package y
|
||||||
|
-- $WORK/gopath2/src/rsc.io/quote/quote.go --
|
||||||
|
// Package quote is located in a GOPATH workspace.
|
||||||
|
package quote
|
||||||
|
|
||||||
|
// Hello is located in a GOPATH workspace.
|
||||||
|
func Hello() string { return "" }
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
env GO111MODULE=on
|
||||||
|
|
||||||
|
# golang.org/issue/32917 and golang.org/issue/28459: 'go build' and 'go test'
|
||||||
|
# in an empty directory should refer to the path '.' and should not attempt
|
||||||
|
# to resolve an external module.
|
||||||
|
cd dir
|
||||||
|
! go get .
|
||||||
|
stderr 'go get \.: path .* is not a package in module rooted at .*[/\\]dir$'
|
||||||
|
! go list
|
||||||
|
! stderr 'cannot find module providing package'
|
||||||
|
stderr '^can.t load package: package \.: no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir$'
|
||||||
|
|
||||||
|
cd subdir
|
||||||
|
! go list
|
||||||
|
! stderr 'cannot find module providing package'
|
||||||
|
stderr '^can.t load package: package \.: no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]subdir$'
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# golang.org/issue/30590: if a package is found in the filesystem
|
||||||
|
# but is not in the main module, the error message should not say
|
||||||
|
# "cannot find module providing package", and we shouldn't try
|
||||||
|
# to find a module providing the package.
|
||||||
|
! go list ./othermodule
|
||||||
|
! stderr 'cannot find module providing package'
|
||||||
|
stderr 'go: directory othermodule is outside main module'
|
||||||
|
|
||||||
|
-- dir/go.mod --
|
||||||
|
module example.com
|
||||||
|
go 1.13
|
||||||
|
-- dir/subdir/README --
|
||||||
|
There are no Go source files in this directory.
|
||||||
|
-- dir/othermodule/go.mod --
|
||||||
|
module example.com/othermodule
|
||||||
|
go 1.13
|
||||||
|
-- dir/othermodule/om.go --
|
||||||
|
package othermodule
|
|
@ -17,6 +17,7 @@ stderr 'this.domain.is.invalid'
|
||||||
stdout '"Error": ".*this.domain.is.invalid.*"'
|
stdout '"Error": ".*this.domain.is.invalid.*"'
|
||||||
|
|
||||||
# download -json with version should print JSON
|
# download -json with version should print JSON
|
||||||
|
# and download the .info file for the 'latest' version.
|
||||||
go mod download -json 'rsc.io/quote@<=v1.5.0'
|
go mod download -json 'rsc.io/quote@<=v1.5.0'
|
||||||
stdout '^\t"Path": "rsc.io/quote"'
|
stdout '^\t"Path": "rsc.io/quote"'
|
||||||
stdout '^\t"Version": "v1.5.0"'
|
stdout '^\t"Version": "v1.5.0"'
|
||||||
|
@ -27,13 +28,14 @@ stdout '^\t"Sum": "h1:6fJa6E\+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE="' # hash of
|
||||||
stdout '^\t"GoModSum": "h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe\+TKr0="'
|
stdout '^\t"GoModSum": "h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe\+TKr0="'
|
||||||
! stdout '"Error"'
|
! stdout '"Error"'
|
||||||
|
|
||||||
|
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info
|
||||||
|
|
||||||
# download queries above should not have added to go.mod.
|
# download queries above should not have added to go.mod.
|
||||||
go list -m all
|
go list -m all
|
||||||
! stdout rsc.io
|
! stdout rsc.io
|
||||||
|
|
||||||
# add to go.mod so we can test non-query downloads
|
# add to go.mod so we can test non-query downloads
|
||||||
go mod edit -require rsc.io/quote@v1.5.2
|
go mod edit -require rsc.io/quote@v1.5.2
|
||||||
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info
|
|
||||||
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
|
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod
|
||||||
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
|
! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip
|
||||||
|
|
||||||
|
@ -83,6 +85,16 @@ exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.zip
|
||||||
go mod download -json rsc.io/quote@v1.5.1
|
go mod download -json rsc.io/quote@v1.5.1
|
||||||
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.1.zip
|
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.1.zip
|
||||||
|
|
||||||
|
# download reports errors encountered when locating modules
|
||||||
|
! go mod download bad/path
|
||||||
|
stderr '^module bad/path: not a known dependency$'
|
||||||
|
! go mod download bad/path@latest
|
||||||
|
stderr '^bad/path@latest: malformed module path "bad/path": missing dot in first path element$'
|
||||||
|
! go mod download rsc.io/quote@v1.999.999
|
||||||
|
stderr '^rsc.io/quote@v1.999.999: reading .*/v1.999.999.info: 404 Not Found$'
|
||||||
|
! go mod download -json bad/path
|
||||||
|
stdout '^\t"Error": "module bad/path: not a known dependency"'
|
||||||
|
|
||||||
# allow go mod download without go.mod
|
# allow go mod download without go.mod
|
||||||
env GO111MODULE=auto
|
env GO111MODULE=auto
|
||||||
rm go.mod
|
rm go.mod
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
env GO111MODULE=on
|
||||||
|
|
||||||
|
# If the module is the latest version of itself,
|
||||||
|
# the Latest field should be set.
|
||||||
|
go mod download -json rsc.io/quote@v1.5.2
|
||||||
|
stdout '"Latest":\s*true'
|
||||||
|
|
||||||
|
# If the module is older than latest, the field should be unset.
|
||||||
|
go mod download -json rsc.io/quote@v1.5.1
|
||||||
|
! stdout '"Latest":'
|
||||||
|
|
||||||
|
# If the module is newer than "latest", the field should be unset...
|
||||||
|
go mod download -json rsc.io/quote@v1.5.3-pre1
|
||||||
|
! stdout '"Latest":'
|
||||||
|
|
||||||
|
# ...even if that version is also what is required by the main module.
|
||||||
|
go mod init example.com
|
||||||
|
go mod edit -require rsc.io/quote@v1.5.3-pre1
|
||||||
|
go mod download -json rsc.io/quote@v1.5.3-pre1
|
||||||
|
! stdout '"Latest":'
|
|
@ -34,11 +34,11 @@ stderr 'import lookup disabled'
|
||||||
|
|
||||||
! go build -mod=readonly ./nonexist
|
! go build -mod=readonly ./nonexist
|
||||||
! stderr 'import lookup disabled'
|
! stderr 'import lookup disabled'
|
||||||
stderr 'unknown import path "m/nonexist": cannot find package'
|
stderr '^can.t load package: package ./nonexist: cannot find package "." in:\n\t'$WORK'[/\\]gopath[/\\]src[/\\]x[/\\]nonexist$'
|
||||||
|
|
||||||
! go build -mod=readonly ./go.mod
|
! go build -mod=readonly ./go.mod
|
||||||
! stderr 'import lookup disabled'
|
! stderr 'import lookup disabled'
|
||||||
stderr 'unknown import path "m/go.mod": cannot find package'
|
stderr 'can.t load package: package ./go.mod: cannot find package'
|
||||||
|
|
||||||
-- x/go.mod --
|
-- x/go.mod --
|
||||||
module m
|
module m
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
env GO111MODULE=on
|
||||||
|
|
||||||
|
[!net] skip
|
||||||
|
|
||||||
|
env GOPROXY=https://proxy.golang.org,direct
|
||||||
|
env GOSUMDB=off
|
||||||
|
|
||||||
|
go get -x -v -d golang.org/x/tools/cmd/goimports
|
||||||
|
stderr '# get https://proxy.golang.org/golang.org/x/tools/@latest'
|
||||||
|
! stderr '# get https://golang.org'
|
|
@ -4,13 +4,19 @@ env GO111MODULE=on
|
||||||
# @patch and @latest within the main module refer to the current version.
|
# @patch and @latest within the main module refer to the current version.
|
||||||
# The main module won't be upgraded, but missing dependencies will be added.
|
# The main module won't be upgraded, but missing dependencies will be added.
|
||||||
cp go.mod.orig go.mod
|
cp go.mod.orig go.mod
|
||||||
go get -d rsc.io/x@latest
|
go get -d rsc.io/x
|
||||||
|
grep 'rsc.io/quote v1.5.2' go.mod
|
||||||
|
go get -d rsc.io/x@upgrade
|
||||||
grep 'rsc.io/quote v1.5.2' go.mod
|
grep 'rsc.io/quote v1.5.2' go.mod
|
||||||
cp go.mod.orig go.mod
|
cp go.mod.orig go.mod
|
||||||
go get -d rsc.io/x@patch
|
go get -d rsc.io/x@patch
|
||||||
grep 'rsc.io/quote v1.5.2' go.mod
|
grep 'rsc.io/quote v1.5.2' go.mod
|
||||||
cp go.mod.orig go.mod
|
cp go.mod.orig go.mod
|
||||||
|
|
||||||
|
# The main module cannot be updated to @latest, which is a specific version.
|
||||||
|
! go get -d rsc.io/x@latest
|
||||||
|
stderr '^go get rsc.io/x@latest: can.t request explicit version of path in main module$'
|
||||||
|
|
||||||
# The main module cannot be updated to a specific version.
|
# The main module cannot be updated to a specific version.
|
||||||
! go get rsc.io/x@v0.1.0
|
! go get rsc.io/x@v0.1.0
|
||||||
stderr '^go get rsc.io/x@v0.1.0: can.t request explicit version of path in main module$'
|
stderr '^go get rsc.io/x@v0.1.0: can.t request explicit version of path in main module$'
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
env GO111MODULE=on
|
env GO111MODULE=on
|
||||||
|
|
||||||
# Download modules to avoid stderr chatter
|
# Download modules to avoid stderr chatter
|
||||||
|
go mod download example.com@v1.0.0
|
||||||
go mod download example.com/newcycle/a@v1.0.0
|
go mod download example.com/newcycle/a@v1.0.0
|
||||||
go mod download example.com/newcycle/a@v1.0.1
|
go mod download example.com/newcycle/a@v1.0.1
|
||||||
go mod download example.com/newcycle/b@v1.0.0
|
go mod download example.com/newcycle/b@v1.0.0
|
||||||
|
@ -10,5 +11,6 @@ go mod init m
|
||||||
cmp stderr stderr-expected
|
cmp stderr stderr-expected
|
||||||
|
|
||||||
-- stderr-expected --
|
-- stderr-expected --
|
||||||
|
go: finding example.com/newcycle v1.0.0
|
||||||
go get: inconsistent versions:
|
go get: inconsistent versions:
|
||||||
example.com/newcycle/a@v1.0.0 requires example.com/newcycle/a@v1.0.1 (not example.com/newcycle/a@v1.0.0)
|
example.com/newcycle/a@v1.0.0 requires example.com/newcycle/a@v1.0.1 (not example.com/newcycle/a@v1.0.0)
|
||||||
|
|
|
@ -10,11 +10,11 @@ grep 'require rsc.io/quote' go.mod
|
||||||
|
|
||||||
cp go.mod.orig go.mod
|
cp go.mod.orig go.mod
|
||||||
! go get -d rsc.io/quote/x...
|
! go get -d rsc.io/quote/x...
|
||||||
stderr 'go get rsc.io/quote/x...: module rsc.io/quote@latest \(v1.5.2\) found, but does not contain packages matching rsc.io/quote/x...'
|
stderr 'go get rsc.io/quote/x...: module rsc.io/quote@upgrade \(v1.5.2\) found, but does not contain packages matching rsc.io/quote/x...'
|
||||||
! grep 'require rsc.io/quote' go.mod
|
! grep 'require rsc.io/quote' go.mod
|
||||||
|
|
||||||
! go get -d rsc.io/quote/x/...
|
! go get -d rsc.io/quote/x/...
|
||||||
stderr 'go get rsc.io/quote/x/...: module rsc.io/quote@latest \(v1.5.2\) found, but does not contain packages matching rsc.io/quote/x/...'
|
stderr 'go get rsc.io/quote/x/...: module rsc.io/quote@upgrade \(v1.5.2\) found, but does not contain packages matching rsc.io/quote/x/...'
|
||||||
! grep 'require rsc.io/quote' go.mod
|
! grep 'require rsc.io/quote' go.mod
|
||||||
|
|
||||||
# If a pattern matches no packages within a module, the module should not
|
# If a pattern matches no packages within a module, the module should not
|
||||||
|
|
|
@ -2,19 +2,26 @@
|
||||||
[!exec:svn] skip
|
[!exec:svn] skip
|
||||||
|
|
||||||
env GO111MODULE=on
|
env GO111MODULE=on
|
||||||
env GOPROXY=direct # obtain llvm.org directory, not via svn.
|
env GOPROXY=direct
|
||||||
|
env GOSUMDB=off
|
||||||
|
|
||||||
# Attempting to get a module zip using svn should fail with a reasonable
|
# Attempting to get a module zip using svn should fail with a reasonable
|
||||||
# message instead of a panic.
|
# message instead of a panic.
|
||||||
# TODO(golang.org/issue/26092): Really, it shouldn't fail at all.
|
# TODO(golang.org/issue/26092): Really, it shouldn't fail at all.
|
||||||
! go get -d llvm.org/llvm/bindings/go/llvm
|
! go get -d vcs-test.golang.org/svn/hello.svn
|
||||||
stderr 'ReadZip not implemented for svn'
|
stderr 'ReadZip not implemented for svn'
|
||||||
! go install .
|
! go install .
|
||||||
stderr 'ReadZip not implemented for svn'
|
stderr 'ReadZip not implemented for svn'
|
||||||
|
|
||||||
|
# Attempting to get a nonexistent module using svn should fail with a
|
||||||
|
# reasonable message instead of a panic.
|
||||||
|
! go get -d vcs-test.golang.org/svn/nonexistent.svn
|
||||||
|
! stderr panic
|
||||||
|
stderr 'go get vcs-test.golang.org/svn/nonexistent.svn: no matching versions for query "upgrade"'
|
||||||
|
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
module golang/go/issues/28943/main
|
module golang/go/issues/28943/main
|
||||||
-- main.go --
|
-- main.go --
|
||||||
package main
|
package main
|
||||||
import _ "llvm.org/llvm/bindings/go/llvm"
|
import _ "vcs-test.golang.org/svn/hello.svn"
|
||||||
func main() {}
|
func main() {}
|
||||||
|
|
|
@ -9,18 +9,33 @@ env GO111MODULE=on
|
||||||
# The v0.1.1 pseudo-version is semantically higher than the latest tag.
|
# The v0.1.1 pseudo-version is semantically higher than the latest tag.
|
||||||
# The v0.0.0 pseudo-version is chronologically newer.
|
# The v0.0.0 pseudo-version is chronologically newer.
|
||||||
|
|
||||||
# 'get -u' should not downgrade to the (lower) tagged version.
|
# Start at v0.1.1-0.20190429073117-b5426c86b553
|
||||||
go get -d example.com/pseudoupgrade@b5426c8
|
go get -d example.com/pseudoupgrade@b5426c8
|
||||||
|
go list -m -u all
|
||||||
|
stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$'
|
||||||
|
|
||||||
|
# 'get -u' should not downgrade to the (lower) tagged version.
|
||||||
go get -d -u
|
go get -d -u
|
||||||
go list -m -u all
|
go list -m -u all
|
||||||
stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$'
|
stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$'
|
||||||
|
|
||||||
# 'get example.com/pseudoupgrade@latest' should not downgrade to
|
# 'get example.com/pseudoupgrade@upgrade' should not downgrade.
|
||||||
# the (lower) tagged version.
|
go get -d example.com/pseudoupgrade@upgrade
|
||||||
go get -d example.com/pseudoupgrade@latest
|
|
||||||
go list -m all
|
go list -m all
|
||||||
stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$'
|
stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$'
|
||||||
|
|
||||||
|
# 'get example.com/pseudoupgrade' should not downgrade.
|
||||||
|
# This is equivalent to 'get example.com/pseudoupgrade@upgrade'.
|
||||||
|
go get -d example.com/pseudoupgrade
|
||||||
|
go list -m all
|
||||||
|
stdout '^example.com/pseudoupgrade v0.1.1-0.20190429073117-b5426c86b553$'
|
||||||
|
|
||||||
|
# 'get example.com/pseudoupgrade@latest' should downgrade.
|
||||||
|
# @latest should not consider the current version.
|
||||||
|
go get -d example.com/pseudoupgrade@latest
|
||||||
|
go list -m all
|
||||||
|
stdout '^example.com/pseudoupgrade v0.1.0$'
|
||||||
|
|
||||||
# We should observe the same behavior with the newer pseudo-version.
|
# We should observe the same behavior with the newer pseudo-version.
|
||||||
go get -d example.com/pseudoupgrade@v0.0.0-20190430073000-30950c05d534
|
go get -d example.com/pseudoupgrade@v0.0.0-20190430073000-30950c05d534
|
||||||
|
|
||||||
|
@ -29,12 +44,21 @@ go get -d -u
|
||||||
go list -m -u all
|
go list -m -u all
|
||||||
stdout '^example.com/pseudoupgrade v0.0.0-20190430073000-30950c05d534$'
|
stdout '^example.com/pseudoupgrade v0.0.0-20190430073000-30950c05d534$'
|
||||||
|
|
||||||
# 'get example.com/pseudoupgrade@latest' should not downgrade to the
|
# 'get example.com/pseudoupgrade@upgrade should not downgrade.
|
||||||
# chronologically older tagged version.
|
go get -d example.com/pseudoupgrade@upgrade
|
||||||
go get -d example.com/pseudoupgrade@latest
|
|
||||||
go list -m -u all
|
go list -m -u all
|
||||||
stdout '^example.com/pseudoupgrade v0.0.0-20190430073000-30950c05d534$'
|
stdout '^example.com/pseudoupgrade v0.0.0-20190430073000-30950c05d534$'
|
||||||
|
|
||||||
|
# 'get example.com/pseudoupgrade' should not downgrade.
|
||||||
|
go get -d example.com/pseudoupgrade
|
||||||
|
go list -m -u all
|
||||||
|
stdout '^example.com/pseudoupgrade v0.0.0-20190430073000-30950c05d534$'
|
||||||
|
|
||||||
|
# 'get example.com/pseudoupgrade@latest' should downgrade.
|
||||||
|
go get -d example.com/pseudoupgrade@latest
|
||||||
|
go list -m -u all
|
||||||
|
stdout '^example.com/pseudoupgrade v0.1.0$'
|
||||||
|
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
module x
|
module x
|
||||||
|
|
||||||
|
|
|
@ -62,15 +62,31 @@ import (
|
||||||
"go/build"
|
"go/build"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
p, err := build.Import(os.Args[1], os.Args[2], 0)
|
// build.Import should support relative and absolute source dir paths.
|
||||||
|
path := os.Args[1]
|
||||||
|
srcDir := os.Args[2]
|
||||||
|
p1, err := build.Import(path, srcDir, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
fmt.Printf("%s\n%s\n", p.Dir, strings.Join(p.GoFiles, " "))
|
absSrcDir, err := filepath.Abs(srcDir)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
p2, err := build.Import(path, absSrcDir, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if p1.Dir != p2.Dir {
|
||||||
|
log.Fatalf("different packages loaded with relative and absolute paths:\n\t%s\n\t%s", p1.Dir, p2.Dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%s\n%s\n", p1.Dir, strings.Join(p1.GoFiles, " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
-- $GOPATH/other/go.mod --
|
-- $GOPATH/other/go.mod --
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
env GO111MODULE=on
|
||||||
|
|
||||||
|
# golang.org/issue/31248: module requirements imposed by dependency versions
|
||||||
|
# older than the selected version must still be taken into account.
|
||||||
|
|
||||||
|
env GOFLAGS=-mod=readonly
|
||||||
|
|
||||||
|
# Indirect dependencies required via older-than-selected versions must exist in
|
||||||
|
# the module graph, but do not need to be listed explicitly in the go.mod file
|
||||||
|
# (since they are implied).
|
||||||
|
go mod graph
|
||||||
|
stdout i@v0.1.0
|
||||||
|
|
||||||
|
# The modules must also appear in the build list, not just the graph.
|
||||||
|
go list -m all
|
||||||
|
stdout '^i v0.1.0'
|
||||||
|
|
||||||
|
# The packages provided by those dependencies must resolve.
|
||||||
|
go list all
|
||||||
|
stdout '^i$'
|
||||||
|
|
||||||
|
-- go.mod --
|
||||||
|
module main
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
||||||
|
require (
|
||||||
|
a v0.0.0
|
||||||
|
b v0.0.0
|
||||||
|
c v0.0.0
|
||||||
|
)
|
||||||
|
|
||||||
|
// Apply replacements so that the test can be self-contained.
|
||||||
|
// (It's easier to see all of the modules here than to go
|
||||||
|
// rooting around in testdata/mod.)
|
||||||
|
replace (
|
||||||
|
a => ./a
|
||||||
|
b => ./b
|
||||||
|
c => ./c
|
||||||
|
x v0.1.0 => ./x1
|
||||||
|
x v0.2.0 => ./x2
|
||||||
|
i => ./i
|
||||||
|
)
|
||||||
|
-- main.go --
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "a"
|
||||||
|
_ "b"
|
||||||
|
_ "c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {}
|
||||||
|
-- a/go.mod --
|
||||||
|
module a
|
||||||
|
go 1.13
|
||||||
|
require x v0.1.0
|
||||||
|
-- a/a.go --
|
||||||
|
package a
|
||||||
|
-- b/go.mod --
|
||||||
|
module b
|
||||||
|
go 1.13
|
||||||
|
require x v0.2.0
|
||||||
|
-- b/b.go --
|
||||||
|
package b
|
||||||
|
-- c/go.mod --
|
||||||
|
module c
|
||||||
|
go 1.13
|
||||||
|
-- c/c.go --
|
||||||
|
package c
|
||||||
|
import _ "i"
|
||||||
|
-- x1/go.mod --
|
||||||
|
module x
|
||||||
|
go1.13
|
||||||
|
require i v0.1.0
|
||||||
|
-- x2/go.mod --
|
||||||
|
module x
|
||||||
|
go1.13
|
||||||
|
-- i/go.mod --
|
||||||
|
-- i/i.go --
|
||||||
|
package i
|
|
@ -0,0 +1,65 @@
|
||||||
|
env GO111MODULE=on
|
||||||
|
|
||||||
|
# Regression test for golang.org/issue/29773: 'go list -m' was not following
|
||||||
|
# dependencies through older versions of the main module.
|
||||||
|
|
||||||
|
go list -f '{{with .Module}}{{.Path}}{{with .Version}} {{.}}{{end}}{{end}}' all
|
||||||
|
cmp stdout pkgmods.txt
|
||||||
|
|
||||||
|
go list -m all
|
||||||
|
cmp stdout mods.txt
|
||||||
|
|
||||||
|
go mod graph
|
||||||
|
cmp stdout graph.txt
|
||||||
|
|
||||||
|
-- go.mod --
|
||||||
|
module golang.org/issue/root
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
replace (
|
||||||
|
golang.org/issue/mirror v0.1.0 => ./mirror-v0.1.0
|
||||||
|
golang.org/issue/pkg v0.1.0 => ./pkg-v0.1.0
|
||||||
|
golang.org/issue/root v0.1.0 => ./root-v0.1.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require golang.org/issue/mirror v0.1.0
|
||||||
|
|
||||||
|
-- root.go --
|
||||||
|
package root
|
||||||
|
|
||||||
|
import _ "golang.org/issue/mirror"
|
||||||
|
|
||||||
|
-- mirror-v0.1.0/go.mod --
|
||||||
|
module golang.org/issue/mirror
|
||||||
|
|
||||||
|
require golang.org/issue/root v0.1.0
|
||||||
|
|
||||||
|
-- mirror-v0.1.0/mirror.go --
|
||||||
|
package mirror
|
||||||
|
|
||||||
|
import _ "golang.org/issue/pkg"
|
||||||
|
|
||||||
|
-- pkg-v0.1.0/go.mod --
|
||||||
|
module golang.org/issue/pkg
|
||||||
|
|
||||||
|
-- pkg-v0.1.0/pkg.go --
|
||||||
|
package pkg
|
||||||
|
|
||||||
|
-- root-v0.1.0/go.mod --
|
||||||
|
module golang.org/issue/root
|
||||||
|
|
||||||
|
require golang.org/issue/pkg v0.1.0
|
||||||
|
|
||||||
|
-- pkgmods.txt --
|
||||||
|
golang.org/issue/mirror v0.1.0
|
||||||
|
golang.org/issue/pkg v0.1.0
|
||||||
|
golang.org/issue/root
|
||||||
|
-- mods.txt --
|
||||||
|
golang.org/issue/root
|
||||||
|
golang.org/issue/mirror v0.1.0 => ./mirror-v0.1.0
|
||||||
|
golang.org/issue/pkg v0.1.0 => ./pkg-v0.1.0
|
||||||
|
-- graph.txt --
|
||||||
|
golang.org/issue/root golang.org/issue/mirror@v0.1.0
|
||||||
|
golang.org/issue/mirror@v0.1.0 golang.org/issue/root@v0.1.0
|
||||||
|
golang.org/issue/root@v0.1.0 golang.org/issue/pkg@v0.1.0
|
|
@ -0,0 +1,60 @@
|
||||||
|
env GO111MODULE=on
|
||||||
|
|
||||||
|
# golang.org/issue/31248: loading the build list must not add explicit entries
|
||||||
|
# for indirect dependencies already implied by older-than-selected versions
|
||||||
|
# already in the build list.
|
||||||
|
|
||||||
|
cp go.mod.orig go.mod
|
||||||
|
go mod tidy
|
||||||
|
cmp go.mod go.mod.orig
|
||||||
|
|
||||||
|
cp go.mod.orig go.mod
|
||||||
|
go list -m all
|
||||||
|
cmp go.mod go.mod.orig
|
||||||
|
|
||||||
|
-- go.mod.orig --
|
||||||
|
module main
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
||||||
|
require a v0.0.0
|
||||||
|
|
||||||
|
replace (
|
||||||
|
a v0.0.0 => ./a
|
||||||
|
b v0.0.0 => ./b
|
||||||
|
i v0.0.0 => ./i
|
||||||
|
x v0.1.0 => ./x1
|
||||||
|
x v0.2.0 => ./x2
|
||||||
|
)
|
||||||
|
-- main.go --
|
||||||
|
package main
|
||||||
|
|
||||||
|
import _ "a"
|
||||||
|
|
||||||
|
func main() {}
|
||||||
|
-- a/go.mod --
|
||||||
|
module a
|
||||||
|
go 1.13
|
||||||
|
require (
|
||||||
|
x v0.2.0
|
||||||
|
b v0.0.0
|
||||||
|
)
|
||||||
|
-- a/a.go --
|
||||||
|
package a
|
||||||
|
-- b/go.mod --
|
||||||
|
module b
|
||||||
|
go 1.13
|
||||||
|
require x v0.1.0
|
||||||
|
-- x1/go.mod --
|
||||||
|
module x
|
||||||
|
go 1.13
|
||||||
|
require (
|
||||||
|
b v0.0.0
|
||||||
|
i v0.0.0
|
||||||
|
)
|
||||||
|
-- x2/go.mod --
|
||||||
|
module x
|
||||||
|
go 1.13
|
||||||
|
-- i/go.mod --
|
||||||
|
module i
|
||||||
|
go 1.13
|
|
@ -134,6 +134,19 @@ cd ..
|
||||||
go list -m golang.org/x/text
|
go list -m golang.org/x/text
|
||||||
stdout 'golang.org/x/text v0.0.0-0.20170915032832-14c0d48ead0c => golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c'
|
stdout 'golang.org/x/text v0.0.0-0.20170915032832-14c0d48ead0c => golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c'
|
||||||
|
|
||||||
|
# A 'replace' directive can replace an invalid 'latest' version, and
|
||||||
|
# should suppress errors for that version in 'go get -u'
|
||||||
|
cp go.mod.orig go.mod
|
||||||
|
go mod edit -require golang.org/x/text@v1.999999.0
|
||||||
|
go mod edit -replace golang.org/x/text@v1.999999.0=golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c
|
||||||
|
cd outside
|
||||||
|
! go get -d golang.org/x/text@upgrade
|
||||||
|
stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v1.999999.0: reading golang.org/x/text/go.mod at revision v1.999999.0: unknown revision v1.999999.0'
|
||||||
|
cd ..
|
||||||
|
go get -d golang.org/x/text@upgrade
|
||||||
|
go list -m golang.org/x/text
|
||||||
|
stdout 'golang.org/x/text v1.999999.0 => golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c'
|
||||||
|
|
||||||
# A pseudo-version derived from a non-ancestor tag is invalid.
|
# A pseudo-version derived from a non-ancestor tag is invalid.
|
||||||
cp go.mod.orig go.mod
|
cp go.mod.orig go.mod
|
||||||
go mod edit -require golang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c
|
go mod edit -require golang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c
|
||||||
|
@ -144,6 +157,16 @@ cd ..
|
||||||
! go list -m golang.org/x/text
|
! go list -m golang.org/x/text
|
||||||
stderr 'golang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c: invalid pseudo-version: revision 14c0d48ead0c is not a descendent of preceding tag \(v0.2.0\)'
|
stderr 'golang.org/x/text@v0.2.1-0.20170915032832-14c0d48ead0c: invalid pseudo-version: revision 14c0d48ead0c is not a descendent of preceding tag \(v0.2.0\)'
|
||||||
|
|
||||||
|
# A pseudo-version derived from a canonical tag on the same revision is invalid.
|
||||||
|
cp go.mod.orig go.mod
|
||||||
|
go mod edit -require golang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac
|
||||||
|
cd outside
|
||||||
|
! go list -m golang.org/x/text
|
||||||
|
stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag'
|
||||||
|
cd ..
|
||||||
|
! go list -m golang.org/x/text
|
||||||
|
stderr 'golang.org/x/text@v0.2.1-0.20171213102548-c4d099d611ac: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag'
|
||||||
|
|
||||||
# A +incompatible suffix is not allowed on a version that is actually compatible.
|
# A +incompatible suffix is not allowed on a version that is actually compatible.
|
||||||
cp go.mod.orig go.mod
|
cp go.mod.orig go.mod
|
||||||
go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c+incompatible
|
go mod edit -require golang.org/x/text@v0.1.1-0.20170915032832-14c0d48ead0c+incompatible
|
||||||
|
@ -165,15 +188,15 @@ go list -m github.com/pierrec/lz4
|
||||||
stdout 'github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1'
|
stdout 'github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1'
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
# A +incompatible version for a module that has an explicit go.mod file is invalid.
|
# A +incompatible pseudo-version for a module that has an explicit go.mod file is invalid.
|
||||||
cp go.mod.orig go.mod
|
cp go.mod.orig go.mod
|
||||||
go mod edit -require github.com/pierrec/lz4@v2.0.9-0.20190131084431-473cd7ce01a1+incompatible
|
go mod edit -require github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d+incompatible
|
||||||
cd outside
|
cd outside
|
||||||
! go list -m github.com/pierrec/lz4
|
! go list -m github.com/pierrec/lz4
|
||||||
stderr 'go: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190131084431-473cd7ce01a1\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
|
stderr 'go: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
|
||||||
cd ..
|
cd ..
|
||||||
! go list -m github.com/pierrec/lz4
|
! go list -m github.com/pierrec/lz4
|
||||||
stderr 'github.com/pierrec/lz4@v2.0.9-0.20190131084431-473cd7ce01a1\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
|
stderr 'github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
|
||||||
|
|
||||||
# A +incompatible pseudo-version is valid for a revision of the module
|
# A +incompatible pseudo-version is valid for a revision of the module
|
||||||
# that lacks a go.mod file.
|
# that lacks a go.mod file.
|
||||||
|
|
|
@ -34,12 +34,12 @@ go list rsc.io/quote/buggy
|
||||||
|
|
||||||
# rsc.io/quote/buggy should not be listable as a module
|
# rsc.io/quote/buggy should not be listable as a module
|
||||||
go list -m -e -f '{{.Error.Err}}' nonexist rsc.io/quote/buggy
|
go list -m -e -f '{{.Error.Err}}' nonexist rsc.io/quote/buggy
|
||||||
stdout '^module "nonexist" is not a known dependency'
|
stdout '^module nonexist: not a known dependency$'
|
||||||
stdout '^module "rsc.io/quote/buggy" is not a known dependency'
|
stdout '^module rsc.io/quote/buggy: not a known dependency$'
|
||||||
|
|
||||||
! go list -m nonexist rsc.io/quote/buggy
|
! go list -m nonexist rsc.io/quote/buggy
|
||||||
stderr '^go list -m nonexist: module "nonexist" is not a known dependency'
|
stderr '^go list -m: module nonexist: not a known dependency'
|
||||||
stderr '^go list -m rsc.io/quote/buggy: module "rsc.io/quote/buggy" is not a known dependency'
|
stderr '^go list -m: module rsc.io/quote/buggy: not a known dependency'
|
||||||
|
|
||||||
# Module loader does not interfere with list -e (golang.org/issue/24149).
|
# Module loader does not interfere with list -e (golang.org/issue/24149).
|
||||||
go list -e -f '{{.Error.Err}}' database
|
go list -e -f '{{.Error.Err}}' database
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
env GO111MODULE=on
|
||||||
|
|
||||||
|
[short] skip
|
||||||
|
|
||||||
|
# Regression test for golang.org/issue/29667:
|
||||||
|
# spurious 'failed to cache compiled Go files' errors.
|
||||||
|
# This test failed reliably when run with -count=10
|
||||||
|
# on a Linux workstation.
|
||||||
|
|
||||||
|
env GOCACHE=$WORK/gocache
|
||||||
|
mkdir $GOCACHE
|
||||||
|
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
go list -json -compiled -test=false -export=false -deps=true -- . &
|
||||||
|
|
||||||
|
wait
|
||||||
|
|
||||||
|
-- go.mod --
|
||||||
|
module sandbox/bar
|
||||||
|
-- bar.go --
|
||||||
|
package bar
|
||||||
|
|
||||||
|
import "C"
|
|
@ -12,9 +12,10 @@ stdout ^math$
|
||||||
go list -f '{{.ImportPath}}' .
|
go list -f '{{.ImportPath}}' .
|
||||||
stdout ^x$
|
stdout ^x$
|
||||||
! go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
|
! go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
|
||||||
stderr 'unknown import path "rsc.io/quote": cannot find package'
|
stderr '^can.t load package: package '$WORK'[/\\]gopath/pkg/mod/rsc.io/quote@v1.5.2: can only use path@version syntax with .go get.'
|
||||||
|
|
||||||
go list -e -f '{{with .Error}}{{.}}{{end}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
|
go list -e -f '{{with .Error}}{{.}}{{end}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
|
||||||
stdout 'unknown import path "rsc.io/quote": cannot find package'
|
stdout '^package '$WORK'[/\\]gopath/pkg/mod/rsc.io/quote@v1.5.2: can only use path@version syntax with .go get.'
|
||||||
go mod download rsc.io/quote@v1.5.2
|
go mod download rsc.io/quote@v1.5.2
|
||||||
go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
|
go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
|
||||||
stdout '^rsc.io/quote$'
|
stdout '^rsc.io/quote$'
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
env GO111MODULE=on
|
||||||
|
env GOPROXY=direct
|
||||||
|
env GOSUMDB=off
|
||||||
|
|
||||||
|
[!net] skip
|
||||||
|
[!exec:git] skip
|
||||||
|
|
||||||
|
# golang.org/issue/33099: if an import path ends in a major-version suffix,
|
||||||
|
# ensure that 'direct' mode can resolve the package to the module.
|
||||||
|
# For a while, (*modfetch.codeRepo).Stat was not checking for a go.mod file,
|
||||||
|
# which would produce a hard error at the subsequent call to GoMod.
|
||||||
|
|
||||||
|
go list all
|
||||||
|
|
||||||
|
-- go.mod --
|
||||||
|
module example.com
|
||||||
|
go 1.13
|
||||||
|
|
||||||
|
-- main.go --
|
||||||
|
package main
|
||||||
|
|
||||||
|
import _ "vcs-test.golang.org/git/v3pkg.git/v3"
|
||||||
|
|
||||||
|
func main() {}
|
|
@ -6,7 +6,7 @@ env GO111MODULE=on
|
||||||
go mod download
|
go mod download
|
||||||
|
|
||||||
! go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
|
! go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
|
||||||
stderr 'outside available modules'
|
stderr 'can only use path@version syntax with .go get.'
|
||||||
|
|
||||||
go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.1
|
go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.1
|
||||||
stdout 'rsc.io/quote'
|
stdout 'rsc.io/quote'
|
||||||
|
|
|
@ -1,8 +1,28 @@
|
||||||
env GO111MODULE=on
|
env GO111MODULE=on
|
||||||
|
|
||||||
|
# If the current version is not latest, 'go list -u' should include its upgrade.
|
||||||
go list -m -u all
|
go list -m -u all
|
||||||
stdout 'rsc.io/quote v1.2.0 \[v1\.5\.2\]'
|
stdout 'rsc.io/quote v1.2.0 \[v1\.5\.2\]'
|
||||||
|
|
||||||
|
# If the current version is latest, 'go list -u' should omit the upgrade.
|
||||||
|
go get -d rsc.io/quote@v1.5.2
|
||||||
|
go list -m -u all
|
||||||
|
stdout 'rsc.io/quote v1.5.2$'
|
||||||
|
|
||||||
|
# If the current version is newer than latest, 'go list -u' should
|
||||||
|
# omit the upgrade.
|
||||||
|
go get -d rsc.io/quote@v1.5.3-pre1
|
||||||
|
go list -m -u all
|
||||||
|
stdout 'rsc.io/quote v1.5.3-pre1$'
|
||||||
|
|
||||||
|
# If the current build list has a higher version and the user asks about
|
||||||
|
# a lower one, -u should report the upgrade for the lower one
|
||||||
|
# but leave the build list unchanged.
|
||||||
|
go list -m -u rsc.io/quote@v1.5.1
|
||||||
|
stdout 'rsc.io/quote v1.5.1 \[v1.5.2\]$'
|
||||||
|
go list -m -u rsc.io/quote
|
||||||
|
stdout 'rsc.io/quote v1.5.3-pre1$'
|
||||||
|
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
module x
|
module x
|
||||||
require rsc.io/quote v1.2.0
|
require rsc.io/quote v1.2.0
|
||||||
|
|
|
@ -57,19 +57,29 @@ import (
|
||||||
func Test(t *testing.T) {}
|
func Test(t *testing.T) {}
|
||||||
-- update-main-expected --
|
-- update-main-expected --
|
||||||
go get: example.com/badchain/c@v1.0.0 updating to
|
go get: example.com/badchain/c@v1.0.0 updating to
|
||||||
example.com/badchain/c@v1.1.0: parsing go.mod: unexpected module path "example.com/badchain/wrong"
|
example.com/badchain/c@v1.1.0: parsing go.mod:
|
||||||
|
module declares its path as: badchain.example.com/c
|
||||||
|
but was required as: example.com/badchain/c
|
||||||
-- update-a-expected --
|
-- update-a-expected --
|
||||||
go get: example.com/badchain/a@v1.1.0 requires
|
go get: example.com/badchain/a@v1.1.0 requires
|
||||||
example.com/badchain/b@v1.1.0 requires
|
example.com/badchain/b@v1.1.0 requires
|
||||||
example.com/badchain/c@v1.1.0: parsing go.mod: unexpected module path "example.com/badchain/wrong"
|
example.com/badchain/c@v1.1.0: parsing go.mod:
|
||||||
|
module declares its path as: badchain.example.com/c
|
||||||
|
but was required as: example.com/badchain/c
|
||||||
-- list-expected --
|
-- list-expected --
|
||||||
go: example.com/badchain/a@v1.1.0 requires
|
go: example.com/badchain/a@v1.1.0 requires
|
||||||
example.com/badchain/b@v1.1.0 requires
|
example.com/badchain/b@v1.1.0 requires
|
||||||
example.com/badchain/c@v1.1.0: parsing go.mod: unexpected module path "example.com/badchain/wrong"
|
example.com/badchain/c@v1.1.0: parsing go.mod:
|
||||||
|
module declares its path as: badchain.example.com/c
|
||||||
|
but was required as: example.com/badchain/c
|
||||||
-- list-missing-expected --
|
-- list-missing-expected --
|
||||||
go: m/use imports
|
go: m/use imports
|
||||||
example.com/badchain/c: example.com/badchain/c@v1.1.0: parsing go.mod: unexpected module path "example.com/badchain/wrong"
|
example.com/badchain/c: example.com/badchain/c@v1.1.0: parsing go.mod:
|
||||||
|
module declares its path as: badchain.example.com/c
|
||||||
|
but was required as: example.com/badchain/c
|
||||||
-- list-missing-test-expected --
|
-- list-missing-test-expected --
|
||||||
go: m/testuse tested by
|
go: m/testuse tested by
|
||||||
m/testuse.test imports
|
m/testuse.test imports
|
||||||
example.com/badchain/c: example.com/badchain/c@v1.1.0: parsing go.mod: unexpected module path "example.com/badchain/wrong"
|
example.com/badchain/c: example.com/badchain/c@v1.1.0: parsing go.mod:
|
||||||
|
module declares its path as: badchain.example.com/c
|
||||||
|
but was required as: example.com/badchain/c
|
||||||
|
|
|
@ -22,7 +22,7 @@ go list -m rsc.io/quote@<v1.5.4
|
||||||
stdout 'rsc.io/quote v1.5.2$'
|
stdout 'rsc.io/quote v1.5.2$'
|
||||||
|
|
||||||
! go list -m rsc.io/quote@>v1.5.3
|
! go list -m rsc.io/quote@>v1.5.3
|
||||||
stderr 'go list -m rsc.io/quote: no matching versions for query ">v1.5.3"'
|
stderr 'go list -m: module rsc.io/quote: no matching versions for query ">v1.5.3"'
|
||||||
|
|
||||||
go list -m -e -f '{{.Error.Err}}' rsc.io/quote@>v1.5.3
|
go list -m -e -f '{{.Error.Err}}' rsc.io/quote@>v1.5.3
|
||||||
stdout 'no matching versions for query ">v1.5.3"'
|
stdout 'no matching versions for query ">v1.5.3"'
|
||||||
|
|
|
@ -28,6 +28,20 @@ go list -m example.com/join/...
|
||||||
! stdout 'example.com/join/subpkg'
|
! stdout 'example.com/join/subpkg'
|
||||||
stdout 'example.com/join v1.1.0'
|
stdout 'example.com/join v1.1.0'
|
||||||
|
|
||||||
|
# If the proxy provides an empty @v/list but rejects @latest with
|
||||||
|
# some other explicit error (for example, a "permission denied" error),
|
||||||
|
# that error should be reported to the user (and override a successful
|
||||||
|
# result for other possible module paths).
|
||||||
|
#
|
||||||
|
# Depending on how the specific platform enforces permissions, the 'go get' may
|
||||||
|
# fail either due to the intended permission error or due to a parse error.
|
||||||
|
# We accept either failure message.
|
||||||
|
env GOPROXY=file:///$WORK/gatekeeper
|
||||||
|
chmod 0000 $WORK/gatekeeper/example.com/join/subpkg/@latest
|
||||||
|
cp go.mod.orig go.mod
|
||||||
|
! go get -d example.com/join/subpkg
|
||||||
|
stderr 'go get example.com/join/subpkg: module example.com/join/subpkg: (invalid character .+|reading file://.*/gatekeeper/example.com/join/subpkg/@latest: .+)'
|
||||||
|
|
||||||
-- go.mod.orig --
|
-- go.mod.orig --
|
||||||
module example.com/othermodule
|
module example.com/othermodule
|
||||||
go 1.13
|
go 1.13
|
||||||
|
@ -50,3 +64,10 @@ v1.0.0-does-not-exist
|
||||||
v1.1.0
|
v1.1.0
|
||||||
-- $WORK/notfound/example.com/join/@v/v1.1.0.info --
|
-- $WORK/notfound/example.com/join/@v/v1.1.0.info --
|
||||||
{"Version": "v1.1.0"}
|
{"Version": "v1.1.0"}
|
||||||
|
-- $WORK/gatekeeper/example.com/join/subpkg/@v/list --
|
||||||
|
-- $WORK/gatekeeper/example.com/join/subpkg/@latest --
|
||||||
|
ERROR: Latest version is forbidden.
|
||||||
|
-- $WORK/gatekeeper/example.com/join/@v/list --
|
||||||
|
v1.1.0
|
||||||
|
-- $WORK/gatekeeper/example.com/join/@v/v1.1.0.info --
|
||||||
|
{"Version": "v1.1.0"}
|
||||||
|
|
|
@ -9,8 +9,8 @@ env dbname=localhost.localdev/sumdb
|
||||||
cp go.mod.orig go.mod
|
cp go.mod.orig go.mod
|
||||||
env GOSUMDB=$sumdb' '$proxy/sumdb-wrong
|
env GOSUMDB=$sumdb' '$proxy/sumdb-wrong
|
||||||
! go get -d rsc.io/quote
|
! go get -d rsc.io/quote
|
||||||
stderr 'verifying rsc.io/quote@v1.5.2/go.mod: checksum mismatch'
|
stderr 'verifying rsc.io/quote@v1.5.2: checksum mismatch'
|
||||||
stderr 'downloaded: h1:LzX7'
|
stderr 'downloaded: h1:3fEy'
|
||||||
stderr 'localhost.localdev/sumdb: h1:wrong'
|
stderr 'localhost.localdev/sumdb: h1:wrong'
|
||||||
stderr 'SECURITY ERROR\nThis download does NOT match the one reported by the checksum server.'
|
stderr 'SECURITY ERROR\nThis download does NOT match the one reported by the checksum server.'
|
||||||
! go get -d rsc.io/sampler
|
! go get -d rsc.io/sampler
|
||||||
|
|
|
@ -28,7 +28,7 @@ cp go.mod.orig go.mod
|
||||||
rm go.sum
|
rm go.sum
|
||||||
env GOPROXY=off
|
env GOPROXY=off
|
||||||
go get -d rsc.io/quote@v1.5.2 # using cache
|
go get -d rsc.io/quote@v1.5.2 # using cache
|
||||||
rm $GOPATH/pkg/mod/download/cache/sumdb/localhost.localdev/sumdb/lookup/rsc.io/quote@v1.5.2
|
rm $GOPATH/pkg/mod/cache/download/sumdb/localhost.localdev/sumdb/lookup/rsc.io/quote@v1.5.2
|
||||||
go get -d rsc.io/quote@v1.5.2 # using go.sum
|
go get -d rsc.io/quote@v1.5.2 # using go.sum
|
||||||
|
|
||||||
# fetch fails once we lose access to both cache and go.sum
|
# fetch fails once we lose access to both cache and go.sum
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
env GO111MODULE=on
|
env GO111MODULE=on
|
||||||
env GOSUMDB=
|
env GOSUMDB=
|
||||||
|
env GOPATH=$WORK/gopath1
|
||||||
|
|
||||||
# With a file-based proxy with an empty checksum directory,
|
# With a file-based proxy with an empty checksum directory,
|
||||||
# downloading a new module should fail, even if a subsequent
|
# downloading a new module should fail, even if a subsequent
|
||||||
|
@ -18,11 +19,20 @@ stderr '^verifying golang.org/x/text.*: Not Found'
|
||||||
[!windows] env GOPROXY=file://$WORK/emptyproxy,https://proxy.golang.org
|
[!windows] env GOPROXY=file://$WORK/emptyproxy,https://proxy.golang.org
|
||||||
go get -d golang.org/x/text@v0.3.2
|
go get -d golang.org/x/text@v0.3.2
|
||||||
|
|
||||||
|
# After a successful sumdb lookup, the lookup can be repeated
|
||||||
|
# using the download cache as a proxy.
|
||||||
|
cp supported $GOPATH/pkg/mod/cache/download/sumdb/sum.golang.org/supported
|
||||||
|
[windows] env GOPROXY=file:///$WORK/gopath1/pkg/mod/cache/download,file:///$WORK/sumproxy
|
||||||
|
[!windows] env GOPROXY=file://$WORK/gopath1/pkg/mod/cache/download,file://$WORK/sumproxy
|
||||||
|
env GOPATH=$WORK/gopath2
|
||||||
|
rm go.sum
|
||||||
|
go get -d -x -v golang.org/x/text@v0.3.2
|
||||||
|
|
||||||
# Once the checksum is present in the go.sum file,
|
# Once the checksum is present in the go.sum file,
|
||||||
# an empty file-based sumdb can be used in conjunction with
|
# an empty file-based sumdb can be used in conjunction with
|
||||||
# a fallback module mirror.
|
# a fallback module mirror.
|
||||||
grep golang.org/x/text go.sum
|
grep golang.org/x/text go.sum
|
||||||
go clean -modcache
|
env GOPATH=$WORK/gopath3
|
||||||
[windows] env GOPROXY=file:///$WORK/sumproxy
|
[windows] env GOPROXY=file:///$WORK/sumproxy
|
||||||
[!windows] env GOPROXY=file://$WORK/sumproxy
|
[!windows] env GOPROXY=file://$WORK/sumproxy
|
||||||
! go get -d golang.org/x/text@v0.3.2
|
! go get -d golang.org/x/text@v0.3.2
|
||||||
|
@ -30,6 +40,8 @@ go clean -modcache
|
||||||
[!windows] env GOPROXY=file://$WORK/sumproxy,https://proxy.golang.org
|
[!windows] env GOPROXY=file://$WORK/sumproxy,https://proxy.golang.org
|
||||||
go get -d golang.org/x/text@v0.3.2
|
go get -d golang.org/x/text@v0.3.2
|
||||||
|
|
||||||
|
-- supported --
|
||||||
|
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
module example.com
|
module example.com
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
|
@ -14,31 +14,39 @@ stdout '^sum.golang.org$'
|
||||||
[!exec:git] skip
|
[!exec:git] skip
|
||||||
env GOSUMDB=sum.golang.org
|
env GOSUMDB=sum.golang.org
|
||||||
env GOPROXY=direct
|
env GOPROXY=direct
|
||||||
go get -d rsc.io/quote
|
go get -d rsc.io/quote@v1.5.2
|
||||||
|
cp go.sum saved.sum
|
||||||
|
|
||||||
# download from proxy.golang.org with go.sum entry already
|
# download from proxy.golang.org with go.sum entry already
|
||||||
go clean -modcache
|
go clean -modcache
|
||||||
env GOSUMDB=
|
env GOSUMDB=
|
||||||
env GOPROXY=
|
env GOPROXY=
|
||||||
go get -x -d rsc.io/quote
|
go get -x -d rsc.io/quote@v1.5.2
|
||||||
! stderr github
|
! stderr github
|
||||||
stderr proxy.golang.org/rsc.io/quote
|
stderr proxy.golang.org/rsc.io/quote
|
||||||
! stderr sum.golang.org/tile
|
! stderr sum.golang.org/tile
|
||||||
! stderr sum.golang.org/lookup/rsc.io/quote
|
! stderr sum.golang.org/lookup/rsc.io/quote
|
||||||
|
cmp go.sum saved.sum
|
||||||
|
|
||||||
# download again, using checksum database to validate new go.sum lines
|
# Download again.
|
||||||
|
# Should use the checksum database to validate new go.sum lines,
|
||||||
|
# but not need to fetch any new data from the proxy.
|
||||||
rm go.sum
|
rm go.sum
|
||||||
go get -x -d rsc.io/quote
|
go get -x -d rsc.io/quote@v1.5.2
|
||||||
! stderr github
|
! stderr github
|
||||||
stderr proxy.golang.org/rsc.io/quote
|
! stderr proxy.golang.org/rsc.io/quote
|
||||||
stderr sum.golang.org/tile
|
stderr sum.golang.org/tile
|
||||||
stderr sum.golang.org/lookup/rsc.io/quote
|
stderr sum.golang.org/lookup/rsc.io/quote
|
||||||
|
cmp go.sum saved.sum
|
||||||
|
|
||||||
# test fallback to direct
|
# test fallback to direct
|
||||||
env TESTGOPROXY404=1
|
env TESTGOPROXY404=1
|
||||||
go get -x -d rsc.io/quote
|
go clean -modcache
|
||||||
|
rm go.sum
|
||||||
|
go get -x -d rsc.io/quote@v1.5.2
|
||||||
stderr 'proxy.golang.org.*404 testing'
|
stderr 'proxy.golang.org.*404 testing'
|
||||||
stderr github.com/rsc
|
stderr github.com/rsc
|
||||||
|
cmp go.sum saved.sum
|
||||||
|
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
module m
|
module m
|
||||||
|
|
|
@ -6,14 +6,14 @@ env GOPROXY GONOPROXY GOSUMDB GONOSUMDB
|
||||||
# basic fetch (through proxy) works
|
# basic fetch (through proxy) works
|
||||||
cp go.mod.orig go.mod
|
cp go.mod.orig go.mod
|
||||||
go get -d rsc.io/fortune@v1.0.0 # note: must use test proxy, does not exist in real world
|
go get -d rsc.io/fortune@v1.0.0 # note: must use test proxy, does not exist in real world
|
||||||
rm $GOPATH/pkg/mod/download/cache/sumdb # rm sumdb cache but NOT package download cache
|
rm $GOPATH/pkg/mod/cache/download/sumdb # rm sumdb cache but NOT package download cache
|
||||||
rm go.sum
|
rm go.sum
|
||||||
|
|
||||||
# can fetch by explicit URL
|
# can fetch by explicit URL
|
||||||
cp go.mod.orig go.mod
|
cp go.mod.orig go.mod
|
||||||
env GOSUMDB=$sumdb' '$proxy/sumdb-direct
|
env GOSUMDB=$sumdb' '$proxy/sumdb-direct
|
||||||
go get -d rsc.io/fortune@v1.0.0
|
go get -d rsc.io/fortune@v1.0.0
|
||||||
rm $GOPATH/pkg/mod/download/cache/sumdb
|
rm $GOPATH/pkg/mod/cache/download/sumdb
|
||||||
rm go.sum
|
rm go.sum
|
||||||
|
|
||||||
# direct access fails (because localhost.localdev does not exist)
|
# direct access fails (because localhost.localdev does not exist)
|
||||||
|
@ -25,7 +25,7 @@ env GOSUMDB=$sumdb
|
||||||
env GOPROXY=direct
|
env GOPROXY=direct
|
||||||
! go get -d rsc.io/fortune@v1.0.0
|
! go get -d rsc.io/fortune@v1.0.0
|
||||||
stderr 'verifying.*localhost.localdev'
|
stderr 'verifying.*localhost.localdev'
|
||||||
rm $GOPATH/pkg/mod/download/cache/sumdb
|
rm $GOPATH/pkg/mod/cache/download/sumdb
|
||||||
rm go.sum
|
rm go.sum
|
||||||
|
|
||||||
# proxy 404 falls back to direct access (which fails)
|
# proxy 404 falls back to direct access (which fails)
|
||||||
|
@ -34,7 +34,7 @@ env GOSUMDB=$sumdb
|
||||||
env GOPROXY=$proxy/sumdb-404
|
env GOPROXY=$proxy/sumdb-404
|
||||||
! go get -d rsc.io/fortune@v1.0.0
|
! go get -d rsc.io/fortune@v1.0.0
|
||||||
stderr 'verifying.*localhost.localdev'
|
stderr 'verifying.*localhost.localdev'
|
||||||
rm $GOPATH/pkg/mod/download/cache/sumdb
|
rm $GOPATH/pkg/mod/cache/download/sumdb
|
||||||
rm go.sum
|
rm go.sum
|
||||||
|
|
||||||
# proxy non-200/404/410 stops direct access
|
# proxy non-200/404/410 stops direct access
|
||||||
|
@ -43,7 +43,7 @@ env GOSUMDB=$sumdb
|
||||||
env GOPROXY=$proxy/sumdb-503
|
env GOPROXY=$proxy/sumdb-503
|
||||||
! go get -d rsc.io/fortune@v1.0.0
|
! go get -d rsc.io/fortune@v1.0.0
|
||||||
stderr '503 Service Unavailable'
|
stderr '503 Service Unavailable'
|
||||||
rm $GOPATH/pkg/mod/download/cache/sumdb
|
rm $GOPATH/pkg/mod/cache/download/sumdb
|
||||||
rm go.sum
|
rm go.sum
|
||||||
|
|
||||||
-- go.mod.orig --
|
-- go.mod.orig --
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
[short] skip
|
||||||
|
|
||||||
|
env GO111MODULE=on
|
||||||
|
env GOCACHE=$WORK/gocache
|
||||||
|
env GODEBUG=gocachetest=1
|
||||||
|
|
||||||
|
# The first run of a test should not be cached.
|
||||||
|
# The second run should be.
|
||||||
|
go test -run=WriteTmp .
|
||||||
|
! stdout '(cached)'
|
||||||
|
go test -run=WriteTmp .
|
||||||
|
stdout '(cached)'
|
||||||
|
|
||||||
|
# 'go test' without arguments should never be cached.
|
||||||
|
go test -run=WriteTmp
|
||||||
|
! stdout '(cached)'
|
||||||
|
go test -run=WriteTmp
|
||||||
|
! stdout '(cached)'
|
||||||
|
|
||||||
|
# We should never cache a test run from command-line files.
|
||||||
|
go test -run=WriteTmp ./foo_test.go
|
||||||
|
! stdout '(cached)'
|
||||||
|
go test -run=WriteTmp ./foo_test.go
|
||||||
|
! stdout '(cached)'
|
||||||
|
|
||||||
|
[!exec:sleep] stop
|
||||||
|
# The go command refuses to cache access to files younger than 2s, so sleep that long.
|
||||||
|
exec sleep 2
|
||||||
|
|
||||||
|
# Touching a file that the test reads from within its testdata should invalidate the cache.
|
||||||
|
go test -run=ReadTestdata .
|
||||||
|
! stdout '(cached)'
|
||||||
|
go test -run=ReadTestdata .
|
||||||
|
stdout '(cached)'
|
||||||
|
cp testdata/bar.txt testdata/foo.txt
|
||||||
|
go test -run=ReadTestdata .
|
||||||
|
! stdout '(cached)'
|
||||||
|
|
||||||
|
-- go.mod --
|
||||||
|
module golang.org/issue/29111/foo
|
||||||
|
|
||||||
|
-- foo.go --
|
||||||
|
package foo
|
||||||
|
|
||||||
|
-- testdata/foo.txt --
|
||||||
|
foo
|
||||||
|
-- testdata/bar.txt --
|
||||||
|
bar
|
||||||
|
|
||||||
|
-- foo_test.go --
|
||||||
|
package foo_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWriteTmp(t *testing.T) {
|
||||||
|
dir, err := ioutil.TempDir("", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
err = ioutil.WriteFile(filepath.Join(dir, "x"), nil, 0666)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadTestdata(t *testing.T) {
|
||||||
|
_, err := ioutil.ReadFile("testdata/foo.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
env GO111MODULE=on
|
||||||
|
|
||||||
|
# Regression test for golang.org/issue/27063:
|
||||||
|
# 'go mod tidy' and 'go mod vendor' should not hide loading errors.
|
||||||
|
|
||||||
|
! go mod tidy
|
||||||
|
stderr '^issue27063 imports\n\tnonexist: malformed module path "nonexist": missing dot in first path element'
|
||||||
|
stderr '^issue27063 imports\n\tnonexist.example.com: cannot find module providing package nonexist.example.com'
|
||||||
|
stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: cannot find module providing package other.example.com/nonexist'
|
||||||
|
|
||||||
|
! go mod vendor
|
||||||
|
stderr '^issue27063 imports\n\tnonexist: malformed module path "nonexist": missing dot in first path element'
|
||||||
|
stderr '^issue27063 imports\n\tnonexist.example.com: cannot find module providing package nonexist.example.com'
|
||||||
|
stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: cannot find module providing package other.example.com/nonexist'
|
||||||
|
|
||||||
|
-- go.mod --
|
||||||
|
module issue27063
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
||||||
|
require issue27063/other v0.0.0
|
||||||
|
replace issue27063/other => ./other
|
||||||
|
-- x.go --
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"nonexist"
|
||||||
|
|
||||||
|
"nonexist.example.com"
|
||||||
|
"issue27063/other"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {}
|
||||||
|
-- other/go.mod --
|
||||||
|
module issue27063/other
|
||||||
|
-- other/other.go --
|
||||||
|
package other
|
||||||
|
|
||||||
|
import "other.example.com/nonexist"
|
|
@ -171,12 +171,6 @@ package m
|
||||||
|
|
||||||
import _ "appengine"
|
import _ "appengine"
|
||||||
import _ "appengine/datastore"
|
import _ "appengine/datastore"
|
||||||
-- nonexistent.go --
|
|
||||||
// +build alternatereality
|
|
||||||
|
|
||||||
package m
|
|
||||||
|
|
||||||
import _ "nonexistent.rsc.io"
|
|
||||||
-- mypkg/go.mod --
|
-- mypkg/go.mod --
|
||||||
module me
|
module me
|
||||||
-- mypkg/mydir/d.go --
|
-- mypkg/mydir/d.go --
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
env GO111MODULE=on
|
||||||
|
go mod init foo
|
||||||
|
go test
|
||||||
|
stdout ^ok\s+foo
|
||||||
|
env GO111MODULE=off
|
||||||
|
go test
|
||||||
|
stdout ^ok\s+
|
||||||
|
! stdout ^ok\s+(cache)$
|
||||||
|
|
||||||
|
-- main_test.go --
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestF(t *testing.T) {}
|
|
@ -1,86 +0,0 @@
|
||||||
# Tests for automatic testing.Init calls when using 'go test'.
|
|
||||||
|
|
||||||
env GO111MODULE=on
|
|
||||||
|
|
||||||
# A TestMain should be able to access testing flags if it calls flag.Parse
|
|
||||||
# without needing to use testing.Init.
|
|
||||||
# Test code can use the name 'testing' without colliding with generated
|
|
||||||
# testinginit code.
|
|
||||||
# Tests running under 'go test' should observe that testing.Init is called
|
|
||||||
# before any user package initialization code runs.
|
|
||||||
go test
|
|
||||||
stdout TestMain
|
|
||||||
stdout TestInit
|
|
||||||
stdout TestExt
|
|
||||||
|
|
||||||
-- go.mod --
|
|
||||||
module m
|
|
||||||
|
|
||||||
-- init_test.go --
|
|
||||||
package testinitflag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
Testing "testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func testFlagsInitialized() bool {
|
|
||||||
found := false
|
|
||||||
flag.VisitAll(func(f *flag.Flag) {
|
|
||||||
if f.Name == "test.count" {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return found
|
|
||||||
}
|
|
||||||
|
|
||||||
var testing int
|
|
||||||
var testingInitAtInitialization = testFlagsInitialized()
|
|
||||||
|
|
||||||
func TestInit(t *Testing.T) {
|
|
||||||
if !testingInitAtInitialization {
|
|
||||||
t.Fatal("testing.Init not called before package initialization")
|
|
||||||
}
|
|
||||||
fmt.Printf("TestInit\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMain(m *Testing.M) {
|
|
||||||
fmt.Printf("TestMain\n")
|
|
||||||
flag.Parse()
|
|
||||||
if !testFlagsInitialized() {
|
|
||||||
fmt.Println("testing flags not registered")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
os.Exit(m.Run())
|
|
||||||
}
|
|
||||||
|
|
||||||
-- external_test.go --
|
|
||||||
package testinitflag_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
Testing "testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func testFlagsInitialized() bool {
|
|
||||||
found := false
|
|
||||||
flag.VisitAll(func(f *flag.Flag) {
|
|
||||||
if f.Name == "test.count" {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return found
|
|
||||||
}
|
|
||||||
|
|
||||||
var testing int
|
|
||||||
var testingInitAtInitialization = testFlagsInitialized()
|
|
||||||
|
|
||||||
func TestExt(t *Testing.T) {
|
|
||||||
fmt.Printf("TestExt\n")
|
|
||||||
if !testingInitAtInitialization {
|
|
||||||
t.Fatal("testing.Init not called before package initialization")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,5 +8,12 @@ go version -m fortune.exe
|
||||||
stdout '^\tpath\trsc.io/fortune'
|
stdout '^\tpath\trsc.io/fortune'
|
||||||
stdout '^\tmod\trsc.io/fortune\tv1.0.0'
|
stdout '^\tmod\trsc.io/fortune\tv1.0.0'
|
||||||
|
|
||||||
|
go build -buildmode=pie -o external.exe rsc.io/fortune
|
||||||
|
go version external.exe
|
||||||
|
stdout '^external.exe: .+'
|
||||||
|
go version -m external.exe
|
||||||
|
stdout '^\tpath\trsc.io/fortune'
|
||||||
|
stdout '^\tmod\trsc.io/fortune\tv1.0.0'
|
||||||
|
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
module m
|
module m
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2019 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 standalone_testmain_flag_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
// A TestMain should be able to access testing flags if it calls
|
||||||
|
// flag.Parse without needing to use testing.Init.
|
||||||
|
flag.Parse()
|
||||||
|
found := false
|
||||||
|
flag.VisitAll(func(f *flag.Flag) {
|
||||||
|
if f.Name == "test.count" {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if !found {
|
||||||
|
fmt.Println("testing flags not registered")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
os.Exit(m.Run())
|
||||||
|
}
|
|
@ -0,0 +1,186 @@
|
||||||
|
package p
|
||||||
|
|
||||||
|
const (
|
||||||
|
// 0-octals
|
||||||
|
_ = 0
|
||||||
|
_ = 0123
|
||||||
|
_ = 0123456
|
||||||
|
|
||||||
|
_ = 0_123
|
||||||
|
_ = 0123_456
|
||||||
|
|
||||||
|
// decimals
|
||||||
|
_ = 1
|
||||||
|
_ = 1234
|
||||||
|
_ = 1234567
|
||||||
|
|
||||||
|
_ = 1_234
|
||||||
|
_ = 1_234_567
|
||||||
|
|
||||||
|
// hexadecimals
|
||||||
|
_ = 0x0
|
||||||
|
_ = 0x1234
|
||||||
|
_ = 0xcafef00d
|
||||||
|
|
||||||
|
_ = 0x0
|
||||||
|
_ = 0x1234
|
||||||
|
_ = 0xCAFEf00d
|
||||||
|
|
||||||
|
_ = 0x_0
|
||||||
|
_ = 0x_1234
|
||||||
|
_ = 0x_CAFE_f00d
|
||||||
|
|
||||||
|
// octals
|
||||||
|
_ = 0o0
|
||||||
|
_ = 0o1234
|
||||||
|
_ = 0o01234567
|
||||||
|
|
||||||
|
_ = 0o0
|
||||||
|
_ = 0o1234
|
||||||
|
_ = 0o01234567
|
||||||
|
|
||||||
|
_ = 0o_0
|
||||||
|
_ = 0o_1234
|
||||||
|
_ = 0o0123_4567
|
||||||
|
|
||||||
|
_ = 0o_0
|
||||||
|
_ = 0o_1234
|
||||||
|
_ = 0o0123_4567
|
||||||
|
|
||||||
|
// binaries
|
||||||
|
_ = 0b0
|
||||||
|
_ = 0b1011
|
||||||
|
_ = 0b00101101
|
||||||
|
|
||||||
|
_ = 0b0
|
||||||
|
_ = 0b1011
|
||||||
|
_ = 0b00101101
|
||||||
|
|
||||||
|
_ = 0b_0
|
||||||
|
_ = 0b10_11
|
||||||
|
_ = 0b_0010_1101
|
||||||
|
|
||||||
|
// decimal floats
|
||||||
|
_ = 0.
|
||||||
|
_ = 123.
|
||||||
|
_ = 0123.
|
||||||
|
|
||||||
|
_ = .0
|
||||||
|
_ = .123
|
||||||
|
_ = .0123
|
||||||
|
|
||||||
|
_ = 0e0
|
||||||
|
_ = 123e+0
|
||||||
|
_ = 0123e-1
|
||||||
|
|
||||||
|
_ = 0e-0
|
||||||
|
_ = 123e+0
|
||||||
|
_ = 0123e123
|
||||||
|
|
||||||
|
_ = 0.e+1
|
||||||
|
_ = 123.e-10
|
||||||
|
_ = 0123.e123
|
||||||
|
|
||||||
|
_ = .0e-1
|
||||||
|
_ = .123e+10
|
||||||
|
_ = .0123e123
|
||||||
|
|
||||||
|
_ = 0.0
|
||||||
|
_ = 123.123
|
||||||
|
_ = 0123.0123
|
||||||
|
|
||||||
|
_ = 0.0e1
|
||||||
|
_ = 123.123e-10
|
||||||
|
_ = 0123.0123e+456
|
||||||
|
|
||||||
|
_ = 1_2_3.
|
||||||
|
_ = 0_123.
|
||||||
|
|
||||||
|
_ = 0_0e0
|
||||||
|
_ = 1_2_3e0
|
||||||
|
_ = 0_123e0
|
||||||
|
|
||||||
|
_ = 0e-0_0
|
||||||
|
_ = 1_2_3e+0
|
||||||
|
_ = 0123e1_2_3
|
||||||
|
|
||||||
|
_ = 0.e+1
|
||||||
|
_ = 123.e-1_0
|
||||||
|
_ = 01_23.e123
|
||||||
|
|
||||||
|
_ = .0e-1
|
||||||
|
_ = .123e+10
|
||||||
|
_ = .0123e123
|
||||||
|
|
||||||
|
_ = 1_2_3.123
|
||||||
|
_ = 0123.01_23
|
||||||
|
|
||||||
|
// hexadecimal floats
|
||||||
|
_ = 0x0.p+0
|
||||||
|
_ = 0xdeadcafe.p-10
|
||||||
|
_ = 0x1234.p123
|
||||||
|
|
||||||
|
_ = 0x.1p-0
|
||||||
|
_ = 0x.deadcafep2
|
||||||
|
_ = 0x.1234p+10
|
||||||
|
|
||||||
|
_ = 0x0p0
|
||||||
|
_ = 0xdeadcafep+1
|
||||||
|
_ = 0x1234p-10
|
||||||
|
|
||||||
|
_ = 0x0.0p0
|
||||||
|
_ = 0xdead.cafep+1
|
||||||
|
_ = 0x12.34p-10
|
||||||
|
|
||||||
|
_ = 0xdead_cafep+1
|
||||||
|
_ = 0x_1234p-10
|
||||||
|
|
||||||
|
_ = 0x_dead_cafe.p-10
|
||||||
|
_ = 0x12_34.p1_2_3
|
||||||
|
_ = 0x1_2_3_4.p-1_2_3
|
||||||
|
|
||||||
|
// imaginaries
|
||||||
|
_ = 0i
|
||||||
|
_ = 0i
|
||||||
|
_ = 8i
|
||||||
|
_ = 0i
|
||||||
|
_ = 123i
|
||||||
|
_ = 123i
|
||||||
|
_ = 56789i
|
||||||
|
_ = 1234i
|
||||||
|
_ = 1234567i
|
||||||
|
|
||||||
|
_ = 0i
|
||||||
|
_ = 0i
|
||||||
|
_ = 8i
|
||||||
|
_ = 0i
|
||||||
|
_ = 123i
|
||||||
|
_ = 123i
|
||||||
|
_ = 56_789i
|
||||||
|
_ = 1_234i
|
||||||
|
_ = 1_234_567i
|
||||||
|
|
||||||
|
_ = 0.i
|
||||||
|
_ = 123.i
|
||||||
|
_ = 0123.i
|
||||||
|
_ = 000123.i
|
||||||
|
|
||||||
|
_ = 0e0i
|
||||||
|
_ = 123e0i
|
||||||
|
_ = 0123e0i
|
||||||
|
_ = 000123e0i
|
||||||
|
|
||||||
|
_ = 0.e+1i
|
||||||
|
_ = 123.e-1_0i
|
||||||
|
_ = 01_23.e123i
|
||||||
|
_ = 00_01_23.e123i
|
||||||
|
|
||||||
|
_ = 0b1010i
|
||||||
|
_ = 0b1010i
|
||||||
|
_ = 0o660i
|
||||||
|
_ = 0o660i
|
||||||
|
_ = 0xabcDEFi
|
||||||
|
_ = 0xabcDEFi
|
||||||
|
_ = 0xabcDEFp0i
|
||||||
|
_ = 0xabcDEFp0i
|
||||||
|
)
|
|
@ -0,0 +1,186 @@
|
||||||
|
package p
|
||||||
|
|
||||||
|
const (
|
||||||
|
// 0-octals
|
||||||
|
_ = 0
|
||||||
|
_ = 0123
|
||||||
|
_ = 0123456
|
||||||
|
|
||||||
|
_ = 0_123
|
||||||
|
_ = 0123_456
|
||||||
|
|
||||||
|
// decimals
|
||||||
|
_ = 1
|
||||||
|
_ = 1234
|
||||||
|
_ = 1234567
|
||||||
|
|
||||||
|
_ = 1_234
|
||||||
|
_ = 1_234_567
|
||||||
|
|
||||||
|
// hexadecimals
|
||||||
|
_ = 0x0
|
||||||
|
_ = 0x1234
|
||||||
|
_ = 0xcafef00d
|
||||||
|
|
||||||
|
_ = 0X0
|
||||||
|
_ = 0X1234
|
||||||
|
_ = 0XCAFEf00d
|
||||||
|
|
||||||
|
_ = 0X_0
|
||||||
|
_ = 0X_1234
|
||||||
|
_ = 0X_CAFE_f00d
|
||||||
|
|
||||||
|
// octals
|
||||||
|
_ = 0o0
|
||||||
|
_ = 0o1234
|
||||||
|
_ = 0o01234567
|
||||||
|
|
||||||
|
_ = 0O0
|
||||||
|
_ = 0O1234
|
||||||
|
_ = 0O01234567
|
||||||
|
|
||||||
|
_ = 0o_0
|
||||||
|
_ = 0o_1234
|
||||||
|
_ = 0o0123_4567
|
||||||
|
|
||||||
|
_ = 0O_0
|
||||||
|
_ = 0O_1234
|
||||||
|
_ = 0O0123_4567
|
||||||
|
|
||||||
|
// binaries
|
||||||
|
_ = 0b0
|
||||||
|
_ = 0b1011
|
||||||
|
_ = 0b00101101
|
||||||
|
|
||||||
|
_ = 0B0
|
||||||
|
_ = 0B1011
|
||||||
|
_ = 0B00101101
|
||||||
|
|
||||||
|
_ = 0b_0
|
||||||
|
_ = 0b10_11
|
||||||
|
_ = 0b_0010_1101
|
||||||
|
|
||||||
|
// decimal floats
|
||||||
|
_ = 0.
|
||||||
|
_ = 123.
|
||||||
|
_ = 0123.
|
||||||
|
|
||||||
|
_ = .0
|
||||||
|
_ = .123
|
||||||
|
_ = .0123
|
||||||
|
|
||||||
|
_ = 0e0
|
||||||
|
_ = 123e+0
|
||||||
|
_ = 0123E-1
|
||||||
|
|
||||||
|
_ = 0e-0
|
||||||
|
_ = 123E+0
|
||||||
|
_ = 0123E123
|
||||||
|
|
||||||
|
_ = 0.e+1
|
||||||
|
_ = 123.E-10
|
||||||
|
_ = 0123.e123
|
||||||
|
|
||||||
|
_ = .0e-1
|
||||||
|
_ = .123E+10
|
||||||
|
_ = .0123E123
|
||||||
|
|
||||||
|
_ = 0.0
|
||||||
|
_ = 123.123
|
||||||
|
_ = 0123.0123
|
||||||
|
|
||||||
|
_ = 0.0e1
|
||||||
|
_ = 123.123E-10
|
||||||
|
_ = 0123.0123e+456
|
||||||
|
|
||||||
|
_ = 1_2_3.
|
||||||
|
_ = 0_123.
|
||||||
|
|
||||||
|
_ = 0_0e0
|
||||||
|
_ = 1_2_3e0
|
||||||
|
_ = 0_123e0
|
||||||
|
|
||||||
|
_ = 0e-0_0
|
||||||
|
_ = 1_2_3E+0
|
||||||
|
_ = 0123E1_2_3
|
||||||
|
|
||||||
|
_ = 0.e+1
|
||||||
|
_ = 123.E-1_0
|
||||||
|
_ = 01_23.e123
|
||||||
|
|
||||||
|
_ = .0e-1
|
||||||
|
_ = .123E+10
|
||||||
|
_ = .0123E123
|
||||||
|
|
||||||
|
_ = 1_2_3.123
|
||||||
|
_ = 0123.01_23
|
||||||
|
|
||||||
|
// hexadecimal floats
|
||||||
|
_ = 0x0.p+0
|
||||||
|
_ = 0Xdeadcafe.p-10
|
||||||
|
_ = 0x1234.P123
|
||||||
|
|
||||||
|
_ = 0x.1p-0
|
||||||
|
_ = 0X.deadcafep2
|
||||||
|
_ = 0x.1234P+10
|
||||||
|
|
||||||
|
_ = 0x0p0
|
||||||
|
_ = 0Xdeadcafep+1
|
||||||
|
_ = 0x1234P-10
|
||||||
|
|
||||||
|
_ = 0x0.0p0
|
||||||
|
_ = 0Xdead.cafep+1
|
||||||
|
_ = 0x12.34P-10
|
||||||
|
|
||||||
|
_ = 0Xdead_cafep+1
|
||||||
|
_ = 0x_1234P-10
|
||||||
|
|
||||||
|
_ = 0X_dead_cafe.p-10
|
||||||
|
_ = 0x12_34.P1_2_3
|
||||||
|
_ = 0X1_2_3_4.P-1_2_3
|
||||||
|
|
||||||
|
// imaginaries
|
||||||
|
_ = 0i
|
||||||
|
_ = 00i
|
||||||
|
_ = 08i
|
||||||
|
_ = 0000000000i
|
||||||
|
_ = 0123i
|
||||||
|
_ = 0000000123i
|
||||||
|
_ = 0000056789i
|
||||||
|
_ = 1234i
|
||||||
|
_ = 1234567i
|
||||||
|
|
||||||
|
_ = 0i
|
||||||
|
_ = 0_0i
|
||||||
|
_ = 0_8i
|
||||||
|
_ = 0_000_000_000i
|
||||||
|
_ = 0_123i
|
||||||
|
_ = 0_000_000_123i
|
||||||
|
_ = 0_000_056_789i
|
||||||
|
_ = 1_234i
|
||||||
|
_ = 1_234_567i
|
||||||
|
|
||||||
|
_ = 0.i
|
||||||
|
_ = 123.i
|
||||||
|
_ = 0123.i
|
||||||
|
_ = 000123.i
|
||||||
|
|
||||||
|
_ = 0e0i
|
||||||
|
_ = 123e0i
|
||||||
|
_ = 0123E0i
|
||||||
|
_ = 000123E0i
|
||||||
|
|
||||||
|
_ = 0.e+1i
|
||||||
|
_ = 123.E-1_0i
|
||||||
|
_ = 01_23.e123i
|
||||||
|
_ = 00_01_23.e123i
|
||||||
|
|
||||||
|
_ = 0b1010i
|
||||||
|
_ = 0B1010i
|
||||||
|
_ = 0o660i
|
||||||
|
_ = 0O660i
|
||||||
|
_ = 0xabcDEFi
|
||||||
|
_ = 0XabcDEFi
|
||||||
|
_ = 0xabcDEFP0i
|
||||||
|
_ = 0XabcDEFp0i
|
||||||
|
)
|
|
@ -8,6 +8,11 @@ import (
|
||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,9 @@ import (
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import("fmt"
|
||||||
|
"math")
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
//gofmt -r=a&&b!=2->a
|
||||||
|
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
// Issue 18987.
|
||||||
|
|
||||||
|
package p
|
||||||
|
|
||||||
|
const _ = x != 1
|
|
@ -0,0 +1,11 @@
|
||||||
|
//gofmt -r=a&&b!=2->a
|
||||||
|
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
// Issue 18987.
|
||||||
|
|
||||||
|
package p
|
||||||
|
|
||||||
|
const _ = x != 1 && x != 2
|
|
@ -0,0 +1,24 @@
|
||||||
|
package q
|
||||||
|
|
||||||
|
import "p"
|
||||||
|
|
||||||
|
type _ = int
|
||||||
|
type a = struct{ x int }
|
||||||
|
type b = p.B
|
||||||
|
|
||||||
|
type (
|
||||||
|
_ = chan<- int
|
||||||
|
aa = interface{}
|
||||||
|
bb = p.BB
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(gri) We may want to put the '=' into a separate column if
|
||||||
|
// we have mixed (regular and alias) type declarations in a group.
|
||||||
|
type (
|
||||||
|
_ chan<- int
|
||||||
|
_ = chan<- int
|
||||||
|
aa0 interface{}
|
||||||
|
aaa = interface{}
|
||||||
|
bb0 p.BB
|
||||||
|
bbb = p.BB
|
||||||
|
)
|
|
@ -0,0 +1,24 @@
|
||||||
|
package q
|
||||||
|
|
||||||
|
import "p"
|
||||||
|
|
||||||
|
type _ = int
|
||||||
|
type a = struct{ x int }
|
||||||
|
type b = p.B
|
||||||
|
|
||||||
|
type (
|
||||||
|
_ = chan<- int
|
||||||
|
aa = interface{}
|
||||||
|
bb = p.BB
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(gri) We may want to put the '=' into a separate column if
|
||||||
|
// we have mixed (regular and alias) type declarations in a group.
|
||||||
|
type (
|
||||||
|
_ chan<- int
|
||||||
|
_ = chan<- int
|
||||||
|
aa0 interface{}
|
||||||
|
aaa = interface{}
|
||||||
|
bb0 p.BB
|
||||||
|
bbb = p.BB
|
||||||
|
)
|
|
@ -86,6 +86,10 @@ func (versionFlag) Set(s string) error {
|
||||||
name = name[strings.LastIndex(name, `/`)+1:]
|
name = name[strings.LastIndex(name, `/`)+1:]
|
||||||
name = name[strings.LastIndex(name, `\`)+1:]
|
name = name[strings.LastIndex(name, `\`)+1:]
|
||||||
name = strings.TrimSuffix(name, ".exe")
|
name = strings.TrimSuffix(name, ".exe")
|
||||||
|
|
||||||
|
// If there's an active experiment, include that,
|
||||||
|
// to distinguish go1.10.2 with an experiment
|
||||||
|
// from go1.10.2 without an experiment.
|
||||||
p := Expstring()
|
p := Expstring()
|
||||||
if p == DefaultExpstring() {
|
if p == DefaultExpstring() {
|
||||||
p = ""
|
p = ""
|
||||||
|
@ -101,12 +105,6 @@ func (versionFlag) Set(s string) error {
|
||||||
// build ID of the binary, so that if the compiler is changed and
|
// build ID of the binary, so that if the compiler is changed and
|
||||||
// rebuilt, we notice and rebuild all packages.
|
// rebuilt, we notice and rebuild all packages.
|
||||||
if s == "full" {
|
if s == "full" {
|
||||||
// If there's an active experiment, include that,
|
|
||||||
// to distinguish go1.10.2 with an experiment
|
|
||||||
// from go1.10.2 without an experiment.
|
|
||||||
if x := Expstring(); x != "" {
|
|
||||||
p += " " + x
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(Version, "devel") {
|
if strings.HasPrefix(Version, "devel") {
|
||||||
p += " buildID=" + buildID
|
p += " buildID=" + buildID
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,6 @@ package context
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"internal/oserror"
|
|
||||||
"internal/reflectlite"
|
"internal/reflectlite"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -163,9 +162,6 @@ type deadlineExceededError struct{}
|
||||||
func (deadlineExceededError) Error() string { return "context deadline exceeded" }
|
func (deadlineExceededError) Error() string { return "context deadline exceeded" }
|
||||||
func (deadlineExceededError) Timeout() bool { return true }
|
func (deadlineExceededError) Timeout() bool { return true }
|
||||||
func (deadlineExceededError) Temporary() bool { return true }
|
func (deadlineExceededError) Temporary() bool { return true }
|
||||||
func (deadlineExceededError) Is(target error) bool {
|
|
||||||
return target == oserror.ErrTimeout || target == oserror.ErrTemporary
|
|
||||||
}
|
|
||||||
|
|
||||||
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
|
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
|
||||||
// struct{}, since vars of this type must have distinct addresses.
|
// struct{}, since vars of this type must have distinct addresses.
|
||||||
|
|
|
@ -5,10 +5,8 @@
|
||||||
package context
|
package context
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -649,7 +647,4 @@ func XTestDeadlineExceededSupportsTimeout(t testingT) {
|
||||||
if !i.Timeout() {
|
if !i.Timeout() {
|
||||||
t.Fatal("wrong value for timeout")
|
t.Fatal("wrong value for timeout")
|
||||||
}
|
}
|
||||||
if !errors.Is(DeadlineExceeded, os.ErrTimeout) {
|
|
||||||
t.Fatal("errors.Is(DeadlineExceeded, os.ErrTimeout) = false, want true")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -555,7 +555,7 @@ func decryptAndCheck(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecryptOAEP decrypts ciphertext using RSA-OAEP.
|
// DecryptOAEP decrypts ciphertext using RSA-OAEP.
|
||||||
|
//
|
||||||
// OAEP is parameterised by a hash function that is used as a random oracle.
|
// OAEP is parameterised by a hash function that is used as a random oracle.
|
||||||
// Encryption and decryption of a given message must use the same hash function
|
// Encryption and decryption of a given message must use the same hash function
|
||||||
// and sha256.New() is a reasonable choice.
|
// and sha256.New() is a reasonable choice.
|
||||||
|
|
|
@ -23,11 +23,14 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VersionSSL30 = 0x0300
|
|
||||||
VersionTLS10 = 0x0301
|
VersionTLS10 = 0x0301
|
||||||
VersionTLS11 = 0x0302
|
VersionTLS11 = 0x0302
|
||||||
VersionTLS12 = 0x0303
|
VersionTLS12 = 0x0303
|
||||||
VersionTLS13 = 0x0304
|
VersionTLS13 = 0x0304
|
||||||
|
|
||||||
|
// Deprecated: SSLv3 is cryptographically broken, and will be
|
||||||
|
// removed in Go 1.14. See golang.org/issue/32716.
|
||||||
|
VersionSSL30 = 0x0300
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -791,6 +794,10 @@ var supportedVersions = []uint16{
|
||||||
func (c *Config) supportedVersions(isClient bool) []uint16 {
|
func (c *Config) supportedVersions(isClient bool) []uint16 {
|
||||||
versions := make([]uint16, 0, len(supportedVersions))
|
versions := make([]uint16, 0, len(supportedVersions))
|
||||||
for _, v := range supportedVersions {
|
for _, v := range supportedVersions {
|
||||||
|
// TLS 1.0 is the default minimum version.
|
||||||
|
if (c == nil || c.MinVersion == 0) && v < VersionTLS10 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if c != nil && c.MinVersion != 0 && v < c.MinVersion {
|
if c != nil && c.MinVersion != 0 && v < c.MinVersion {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,20 @@ func TestRejectBadProtocolVersion(t *testing.T) {
|
||||||
}, "unsupported versions")
|
}, "unsupported versions")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSSLv3OptIn(t *testing.T) {
|
||||||
|
config := testConfig.Clone()
|
||||||
|
config.MinVersion = 0
|
||||||
|
testClientHelloFailure(t, config, &clientHelloMsg{
|
||||||
|
vers: VersionSSL30,
|
||||||
|
random: make([]byte, 32),
|
||||||
|
}, "unsupported versions")
|
||||||
|
testClientHelloFailure(t, config, &clientHelloMsg{
|
||||||
|
vers: VersionTLS12,
|
||||||
|
supportedVersions: []uint16{VersionSSL30},
|
||||||
|
random: make([]byte, 32),
|
||||||
|
}, "unsupported versions")
|
||||||
|
}
|
||||||
|
|
||||||
func TestNoSuiteOverlap(t *testing.T) {
|
func TestNoSuiteOverlap(t *testing.T) {
|
||||||
clientHello := &clientHelloMsg{
|
clientHello := &clientHelloMsg{
|
||||||
vers: VersionTLS10,
|
vers: VersionTLS10,
|
||||||
|
|
|
@ -222,28 +222,65 @@ func tempFile(contents string) string {
|
||||||
// localListener is set up by TestMain and used by localPipe to create Conn
|
// localListener is set up by TestMain and used by localPipe to create Conn
|
||||||
// pairs like net.Pipe, but connected by an actual buffered TCP connection.
|
// pairs like net.Pipe, but connected by an actual buffered TCP connection.
|
||||||
var localListener struct {
|
var localListener struct {
|
||||||
sync.Mutex
|
mu sync.Mutex
|
||||||
net.Listener
|
addr net.Addr
|
||||||
|
ch chan net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
const localFlakes = 0 // change to 1 or 2 to exercise localServer/localPipe handling of mismatches
|
||||||
|
|
||||||
|
func localServer(l net.Listener) {
|
||||||
|
for n := 0; ; n++ {
|
||||||
|
c, err := l.Accept()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if localFlakes == 1 && n%2 == 0 {
|
||||||
|
c.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
localListener.ch <- c
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func localPipe(t testing.TB) (net.Conn, net.Conn) {
|
func localPipe(t testing.TB) (net.Conn, net.Conn) {
|
||||||
localListener.Lock()
|
localListener.mu.Lock()
|
||||||
defer localListener.Unlock()
|
defer localListener.mu.Unlock()
|
||||||
c := make(chan net.Conn)
|
|
||||||
go func() {
|
addr := localListener.addr
|
||||||
conn, err := localListener.Accept()
|
|
||||||
|
Dialing:
|
||||||
|
// We expect a rare mismatch, but probably not 5 in a row.
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
tooSlow := time.NewTimer(1 * time.Second)
|
||||||
|
defer tooSlow.Stop()
|
||||||
|
c1, err := net.Dial(addr.Network(), addr.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to accept local connection: %v", err)
|
t.Fatalf("localPipe: %v", err)
|
||||||
|
}
|
||||||
|
if localFlakes == 2 && i == 0 {
|
||||||
|
c1.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-tooSlow.C:
|
||||||
|
t.Logf("localPipe: timeout waiting for %v", c1.LocalAddr())
|
||||||
|
c1.Close()
|
||||||
|
continue Dialing
|
||||||
|
|
||||||
|
case c2 := <-localListener.ch:
|
||||||
|
if c2.RemoteAddr().String() == c1.LocalAddr().String() {
|
||||||
|
return c1, c2
|
||||||
|
}
|
||||||
|
t.Logf("localPipe: unexpected connection: %v != %v", c2.RemoteAddr(), c1.LocalAddr())
|
||||||
|
c2.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
c <- conn
|
|
||||||
}()
|
|
||||||
addr := localListener.Addr()
|
|
||||||
c1, err := net.Dial(addr.Network(), addr.String())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to dial local connection: %v", err)
|
|
||||||
}
|
}
|
||||||
c2 := <-c
|
|
||||||
return c1, c2
|
t.Fatalf("localPipe: failed to connect")
|
||||||
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
|
||||||
// zeroSource is an io.Reader that returns an unlimited number of zero bytes.
|
// zeroSource is an io.Reader that returns an unlimited number of zero bytes.
|
||||||
|
@ -293,8 +330,10 @@ func runMain(m *testing.M) int {
|
||||||
fmt.Fprintf(os.Stderr, "Failed to open local listener: %v", err)
|
fmt.Fprintf(os.Stderr, "Failed to open local listener: %v", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
localListener.Listener = l
|
localListener.ch = make(chan net.Conn)
|
||||||
defer localListener.Close()
|
localListener.addr = l.Addr()
|
||||||
|
defer l.Close()
|
||||||
|
go localServer(l)
|
||||||
|
|
||||||
if err := checkOpenSSLVersion(); err != nil {
|
if err := checkOpenSSLVersion(); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v", err)
|
fmt.Fprintf(os.Stderr, "Error: %v", err)
|
||||||
|
|
|
@ -359,50 +359,6 @@ func TestVerifyHostname(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVerifyHostnameResumed(t *testing.T) {
|
|
||||||
t.Run("TLSv12", func(t *testing.T) { testVerifyHostnameResumed(t, VersionTLS12) })
|
|
||||||
t.Run("TLSv13", func(t *testing.T) { testVerifyHostnameResumed(t, VersionTLS13) })
|
|
||||||
}
|
|
||||||
|
|
||||||
func testVerifyHostnameResumed(t *testing.T, version uint16) {
|
|
||||||
testenv.MustHaveExternalNetwork(t)
|
|
||||||
|
|
||||||
config := &Config{
|
|
||||||
MaxVersion: version,
|
|
||||||
ClientSessionCache: NewLRUClientSessionCache(32),
|
|
||||||
}
|
|
||||||
for i := 0; i < 2; i++ {
|
|
||||||
c, err := DialWithDialer(&net.Dialer{
|
|
||||||
Timeout: 10 * time.Second,
|
|
||||||
}, "tcp", "mail.google.com:https", config)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Dial #%d: %v", i, err)
|
|
||||||
}
|
|
||||||
cs := c.ConnectionState()
|
|
||||||
if i > 0 && !cs.DidResume {
|
|
||||||
t.Fatalf("Subsequent connection unexpectedly didn't resume")
|
|
||||||
}
|
|
||||||
if cs.Version != version {
|
|
||||||
t.Fatalf("Unexpectedly negotiated version %x", cs.Version)
|
|
||||||
}
|
|
||||||
if cs.VerifiedChains == nil {
|
|
||||||
t.Fatalf("Dial #%d: cs.VerifiedChains == nil", i)
|
|
||||||
}
|
|
||||||
if err := c.VerifyHostname("mail.google.com"); err != nil {
|
|
||||||
t.Fatalf("verify mail.google.com #%d: %v", i, err)
|
|
||||||
}
|
|
||||||
// Have the server send some data so session tickets are delivered.
|
|
||||||
c.SetDeadline(time.Now().Add(5 * time.Second))
|
|
||||||
if _, err := io.WriteString(c, "HEAD / HTTP/1.0\n\n"); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if _, err := c.Read(make([]byte, 1)); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
c.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConnCloseBreakingWrite(t *testing.T) {
|
func TestConnCloseBreakingWrite(t *testing.T) {
|
||||||
ln := newLocalListener(t)
|
ln := newLocalListener(t)
|
||||||
defer ln.Close()
|
defer ln.Close()
|
||||||
|
|
|
@ -171,6 +171,11 @@ type Symbol struct {
|
||||||
Info, Other byte
|
Info, Other byte
|
||||||
Section SectionIndex
|
Section SectionIndex
|
||||||
Value, Size uint64
|
Value, Size uint64
|
||||||
|
|
||||||
|
// Version and Library are present only for the dynamic symbol
|
||||||
|
// table.
|
||||||
|
Version string
|
||||||
|
Library string
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1321,12 +1326,23 @@ func (f *File) Symbols() ([]Symbol, error) {
|
||||||
// DynamicSymbols returns the dynamic symbol table for f. The symbols
|
// DynamicSymbols returns the dynamic symbol table for f. The symbols
|
||||||
// will be listed in the order they appear in f.
|
// will be listed in the order they appear in f.
|
||||||
//
|
//
|
||||||
|
// If f has a symbol version table, the returned Symbols will have
|
||||||
|
// initialized Version and Library fields.
|
||||||
|
//
|
||||||
// For compatibility with Symbols, DynamicSymbols omits the null symbol at index 0.
|
// For compatibility with Symbols, DynamicSymbols omits the null symbol at index 0.
|
||||||
// After retrieving the symbols as symtab, an externally supplied index x
|
// After retrieving the symbols as symtab, an externally supplied index x
|
||||||
// corresponds to symtab[x-1], not symtab[x].
|
// corresponds to symtab[x-1], not symtab[x].
|
||||||
func (f *File) DynamicSymbols() ([]Symbol, error) {
|
func (f *File) DynamicSymbols() ([]Symbol, error) {
|
||||||
sym, _, err := f.getSymbols(SHT_DYNSYM)
|
sym, str, err := f.getSymbols(SHT_DYNSYM)
|
||||||
return sym, err
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if f.gnuVersionInit(str) {
|
||||||
|
for i := range sym {
|
||||||
|
sym[i].Library, sym[i].Version = f.gnuVersion(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sym, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImportedSymbol struct {
|
type ImportedSymbol struct {
|
||||||
|
@ -1349,7 +1365,8 @@ func (f *File) ImportedSymbols() ([]ImportedSymbol, error) {
|
||||||
for i, s := range sym {
|
for i, s := range sym {
|
||||||
if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
|
if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
|
||||||
all = append(all, ImportedSymbol{Name: s.Name})
|
all = append(all, ImportedSymbol{Name: s.Name})
|
||||||
f.gnuVersion(i, &all[len(all)-1])
|
sym := &all[len(all)-1]
|
||||||
|
sym.Library, sym.Version = f.gnuVersion(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return all, nil
|
return all, nil
|
||||||
|
@ -1362,11 +1379,16 @@ type verneed struct {
|
||||||
|
|
||||||
// gnuVersionInit parses the GNU version tables
|
// gnuVersionInit parses the GNU version tables
|
||||||
// for use by calls to gnuVersion.
|
// for use by calls to gnuVersion.
|
||||||
func (f *File) gnuVersionInit(str []byte) {
|
func (f *File) gnuVersionInit(str []byte) bool {
|
||||||
|
if f.gnuNeed != nil {
|
||||||
|
// Already initialized
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Accumulate verneed information.
|
// Accumulate verneed information.
|
||||||
vn := f.SectionByType(SHT_GNU_VERNEED)
|
vn := f.SectionByType(SHT_GNU_VERNEED)
|
||||||
if vn == nil {
|
if vn == nil {
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
d, _ := vn.Data()
|
d, _ := vn.Data()
|
||||||
|
|
||||||
|
@ -1421,17 +1443,18 @@ func (f *File) gnuVersionInit(str []byte) {
|
||||||
// Versym parallels symbol table, indexing into verneed.
|
// Versym parallels symbol table, indexing into verneed.
|
||||||
vs := f.SectionByType(SHT_GNU_VERSYM)
|
vs := f.SectionByType(SHT_GNU_VERSYM)
|
||||||
if vs == nil {
|
if vs == nil {
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
d, _ = vs.Data()
|
d, _ = vs.Data()
|
||||||
|
|
||||||
f.gnuNeed = need
|
f.gnuNeed = need
|
||||||
f.gnuVersym = d
|
f.gnuVersym = d
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// gnuVersion adds Library and Version information to sym,
|
// gnuVersion adds Library and Version information to sym,
|
||||||
// which came from offset i of the symbol table.
|
// which came from offset i of the symbol table.
|
||||||
func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
|
func (f *File) gnuVersion(i int) (library string, version string) {
|
||||||
// Each entry is two bytes.
|
// Each entry is two bytes.
|
||||||
i = (i + 1) * 2
|
i = (i + 1) * 2
|
||||||
if i >= len(f.gnuVersym) {
|
if i >= len(f.gnuVersym) {
|
||||||
|
@ -1442,8 +1465,7 @@ func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
n := &f.gnuNeed[j]
|
n := &f.gnuNeed[j]
|
||||||
sym.Library = n.File
|
return n.File, n.Name
|
||||||
sym.Version = n.Name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportedLibraries returns the names of all libraries
|
// ImportedLibraries returns the names of all libraries
|
||||||
|
|
|
@ -819,6 +819,8 @@ var dynamicSymbolsGolden = map[string][]Symbol{
|
||||||
Section: 0x0,
|
Section: 0x0,
|
||||||
Value: 0x0,
|
Value: 0x0,
|
||||||
Size: 0x18C,
|
Size: 0x18C,
|
||||||
|
Version: "GLIBC_2.2.5",
|
||||||
|
Library: "libc.so.6",
|
||||||
},
|
},
|
||||||
Symbol{
|
Symbol{
|
||||||
Name: "__libc_start_main",
|
Name: "__libc_start_main",
|
||||||
|
@ -827,6 +829,8 @@ var dynamicSymbolsGolden = map[string][]Symbol{
|
||||||
Section: 0x0,
|
Section: 0x0,
|
||||||
Value: 0x0,
|
Value: 0x0,
|
||||||
Size: 0x1C2,
|
Size: 0x1C2,
|
||||||
|
Version: "GLIBC_2.2.5",
|
||||||
|
Library: "libc.so.6",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"testdata/go-relocation-test-clang-x86.obj": {},
|
"testdata/go-relocation-test-clang-x86.obj": {},
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue