mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/go: test remote lookup of packages with leading dots in path elements
Follow-up to CL 297530. For #43985 For #34992 Change-Id: I2cfa6c41c013e627c3464c383ca42f5c9ebe521a Reviewed-on: https://go-review.googlesource.com/c/go/+/297634 Trust: Jay Conrod <jayconrod@google.com> Run-TryBot: Jay Conrod <jayconrod@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
parent
ccf9acefa8
commit
a1a3d33b0d
9 changed files with 126 additions and 26 deletions
|
|
@ -6,7 +6,7 @@ require (
|
||||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2
|
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2
|
||||||
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff
|
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff
|
||||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
|
||||||
golang.org/x/mod v0.4.2-0.20210309222212-d6ab96f2441f
|
golang.org/x/mod v0.4.3-0.20210310185834-19d50cac98aa
|
||||||
golang.org/x/sys v0.0.0-20210218145245-beda7e5e158e // indirect
|
golang.org/x/sys v0.0.0-20210218145245-beda7e5e158e // indirect
|
||||||
golang.org/x/tools v0.1.1-0.20210220032852-2363391a5b2f
|
golang.org/x/tools v0.1.1-0.20210220032852-2363391a5b2f
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
|
||||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2-0.20210309222212-d6ab96f2441f h1:mQozKYYFIVK0MXcDB8Dvw0dR3rxKLnkSCJHWznfaodQ=
|
golang.org/x/mod v0.4.3-0.20210310185834-19d50cac98aa h1:++oSKjoJSsXNHyhUdK1BtBKMAaMHER+GWyKN3319OZA=
|
||||||
golang.org/x/mod v0.4.2-0.20210309222212-d6ab96f2441f/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.3-0.20210310185834-19d50cac98aa/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
|
|
||||||
|
|
@ -695,7 +695,9 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin
|
||||||
|
|
||||||
// modulePrefixesExcludingTarget returns all prefixes of path that may plausibly
|
// modulePrefixesExcludingTarget returns all prefixes of path that may plausibly
|
||||||
// exist as a module, excluding targetPrefix but otherwise including path
|
// exist as a module, excluding targetPrefix but otherwise including path
|
||||||
// itself, sorted by descending length.
|
// itself, sorted by descending length. Prefixes that are not valid module paths
|
||||||
|
// but are valid package paths (like "m" or "example.com/.gen") are included,
|
||||||
|
// since they might be replaced.
|
||||||
func modulePrefixesExcludingTarget(path string) []string {
|
func modulePrefixesExcludingTarget(path string) []string {
|
||||||
prefixes := make([]string, 0, strings.Count(path, "/")+1)
|
prefixes := make([]string, 0, strings.Count(path, "/")+1)
|
||||||
|
|
||||||
|
|
@ -747,6 +749,7 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod
|
||||||
noPackage *PackageNotInModuleError
|
noPackage *PackageNotInModuleError
|
||||||
noVersion *NoMatchingVersionError
|
noVersion *NoMatchingVersionError
|
||||||
noPatchBase *NoPatchBaseError
|
noPatchBase *NoPatchBaseError
|
||||||
|
invalidPath *module.InvalidPathError // see comment in case below
|
||||||
notExistErr error
|
notExistErr error
|
||||||
)
|
)
|
||||||
for _, r := range results {
|
for _, r := range results {
|
||||||
|
|
@ -767,6 +770,17 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod
|
||||||
if noPatchBase == nil {
|
if noPatchBase == nil {
|
||||||
noPatchBase = rErr
|
noPatchBase = rErr
|
||||||
}
|
}
|
||||||
|
case *module.InvalidPathError:
|
||||||
|
// The prefix was not a valid module path, and there was no replacement.
|
||||||
|
// Prefixes like this may appear in candidateModules, since we handle
|
||||||
|
// replaced modules that weren't required in the repo lookup process
|
||||||
|
// (see lookupRepo).
|
||||||
|
//
|
||||||
|
// A shorter prefix may be a valid module path and may contain a valid
|
||||||
|
// import path, so this is a low-priority error.
|
||||||
|
if invalidPath == nil {
|
||||||
|
invalidPath = rErr
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
if errors.Is(rErr, fs.ErrNotExist) {
|
if errors.Is(rErr, fs.ErrNotExist) {
|
||||||
if notExistErr == nil {
|
if notExistErr == nil {
|
||||||
|
|
@ -800,6 +814,8 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod
|
||||||
err = noVersion
|
err = noVersion
|
||||||
case noPatchBase != nil:
|
case noPatchBase != nil:
|
||||||
err = noPatchBase
|
err = noPatchBase
|
||||||
|
case invalidPath != nil:
|
||||||
|
err = invalidPath
|
||||||
case notExistErr != nil:
|
case notExistErr != nil:
|
||||||
err = notExistErr
|
err = notExistErr
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -362,7 +362,7 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
z := zip.NewWriter(&buf)
|
z := zip.NewWriter(&buf)
|
||||||
for _, f := range a.Files {
|
for _, f := range a.Files {
|
||||||
if strings.HasPrefix(f.Name, ".") {
|
if f.Name == ".info" || f.Name == ".mod" || f.Name == ".zip" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var zipName string
|
var zipName string
|
||||||
|
|
|
||||||
12
src/cmd/go/testdata/mod/example.com_dotname_v1.0.0.txt
vendored
Normal file
12
src/cmd/go/testdata/mod/example.com_dotname_v1.0.0.txt
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
-- .info --
|
||||||
|
{"Version":"v1.0.0"}
|
||||||
|
-- .mod --
|
||||||
|
module example.com/dotname
|
||||||
|
|
||||||
|
go 1.16
|
||||||
|
-- go.mod --
|
||||||
|
module example.com/dotname
|
||||||
|
|
||||||
|
go 1.16
|
||||||
|
-- .dot/dot.go --
|
||||||
|
package dot
|
||||||
46
src/cmd/go/testdata/script/mod_invalid_path_dotname.txt
vendored
Normal file
46
src/cmd/go/testdata/script/mod_invalid_path_dotname.txt
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
# Test that an import path containing an element with a leading dot
|
||||||
|
# in another module is valid.
|
||||||
|
|
||||||
|
# 'go get' works with no version query.
|
||||||
|
cp go.mod.empty go.mod
|
||||||
|
go get -d example.com/dotname/.dot
|
||||||
|
go list -m example.com/dotname
|
||||||
|
stdout '^example.com/dotname v1.0.0$'
|
||||||
|
|
||||||
|
# 'go get' works with a version query.
|
||||||
|
cp go.mod.empty go.mod
|
||||||
|
go get -d example.com/dotname/.dot@latest
|
||||||
|
go list -m example.com/dotname
|
||||||
|
stdout '^example.com/dotname v1.0.0$'
|
||||||
|
|
||||||
|
# 'go get' works on an importing package.
|
||||||
|
cp go.mod.empty go.mod
|
||||||
|
go get -d .
|
||||||
|
go list -m example.com/dotname
|
||||||
|
stdout '^example.com/dotname v1.0.0$'
|
||||||
|
|
||||||
|
# 'go list' works on the dotted package.
|
||||||
|
go list example.com/dotname/.dot
|
||||||
|
stdout '^example.com/dotname/.dot$'
|
||||||
|
|
||||||
|
# 'go list' works on an importing package.
|
||||||
|
go list .
|
||||||
|
stdout '^m$'
|
||||||
|
|
||||||
|
# 'go mod tidy' works.
|
||||||
|
cp go.mod.empty go.mod
|
||||||
|
go mod tidy
|
||||||
|
go list -m example.com/dotname
|
||||||
|
stdout '^example.com/dotname v1.0.0$'
|
||||||
|
|
||||||
|
-- go.mod.empty --
|
||||||
|
module m
|
||||||
|
|
||||||
|
go 1.16
|
||||||
|
-- go.sum --
|
||||||
|
example.com/dotname v1.0.0 h1:Q0JMAn464CnwFVCshs1n4+f5EFiW/eRhnx/fTWjw2Ag=
|
||||||
|
example.com/dotname v1.0.0/go.mod h1:7K4VLT7QylRI8H7yZwUkeDH2s19wQnyfp/3oBlItWJ0=
|
||||||
|
-- use.go --
|
||||||
|
package use
|
||||||
|
|
||||||
|
import _ "example.com/dotname/.dot"
|
||||||
|
|
@ -2,18 +2,22 @@
|
||||||
# The '+' character should be disallowed in module paths, but allowed in package
|
# The '+' character should be disallowed in module paths, but allowed in package
|
||||||
# paths within valid modules.
|
# paths within valid modules.
|
||||||
|
|
||||||
|
# 'go list' accepts package paths with pluses.
|
||||||
|
cp go.mod.orig go.mod
|
||||||
go get -d example.net/cmd
|
go get -d example.net/cmd
|
||||||
go list example.net/cmd/x++
|
go list example.net/cmd/x++
|
||||||
|
|
||||||
|
# 'go list -m' rejects module paths with pluses.
|
||||||
! go list -versions -m 'example.net/bad++'
|
! go list -versions -m 'example.net/bad++'
|
||||||
stderr '^go list -m: malformed module path "example.net/bad\+\+": invalid char ''\+''$'
|
stderr '^go list -m: malformed module path "example.net/bad\+\+": invalid char ''\+''$'
|
||||||
|
|
||||||
# TODO(bcmills): 'go get -d example.net/cmd/x++' should also work, but currently
|
# 'go get' accepts package paths with pluses.
|
||||||
# it does not. This might be fixed by https://golang.org/cl/297891.
|
cp go.mod.orig go.mod
|
||||||
! go get -d example.net/cmd/x++
|
go get -d example.net/cmd/x++
|
||||||
stderr '^go get: malformed module path "example.net/cmd/x\+\+": invalid char ''\+''$'
|
go list -m example.net/cmd
|
||||||
|
stdout '^example.net/cmd v0.0.0-00010101000000-000000000000 => ./cmd$'
|
||||||
|
|
||||||
-- go.mod --
|
-- go.mod.orig --
|
||||||
module example.com/m
|
module example.com/m
|
||||||
|
|
||||||
go 1.16
|
go 1.16
|
||||||
|
|
|
||||||
52
src/cmd/vendor/golang.org/x/mod/module/module.go
generated
vendored
52
src/cmd/vendor/golang.org/x/mod/module/module.go
generated
vendored
|
|
@ -192,6 +192,21 @@ func (e *InvalidVersionError) Error() string {
|
||||||
|
|
||||||
func (e *InvalidVersionError) Unwrap() error { return e.Err }
|
func (e *InvalidVersionError) Unwrap() error { return e.Err }
|
||||||
|
|
||||||
|
// An InvalidPathError indicates a module, import, or file path doesn't
|
||||||
|
// satisfy all naming constraints. See CheckPath, CheckImportPath,
|
||||||
|
// and CheckFilePath for specific restrictions.
|
||||||
|
type InvalidPathError struct {
|
||||||
|
Kind string // "module", "import", or "file"
|
||||||
|
Path string
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *InvalidPathError) Error() string {
|
||||||
|
return fmt.Sprintf("malformed %s path %q: %v", e.Kind, e.Path, e.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *InvalidPathError) Unwrap() error { return e.Err }
|
||||||
|
|
||||||
// Check checks that a given module path, version pair is valid.
|
// Check checks that a given module path, version pair is valid.
|
||||||
// In addition to the path being a valid module path
|
// In addition to the path being a valid module path
|
||||||
// and the version being a valid semantic version,
|
// and the version being a valid semantic version,
|
||||||
|
|
@ -296,30 +311,36 @@ func fileNameOK(r rune) bool {
|
||||||
// this second requirement is replaced by a requirement that the path
|
// this second requirement is replaced by a requirement that the path
|
||||||
// follow the gopkg.in server's conventions.
|
// follow the gopkg.in server's conventions.
|
||||||
// Third, no path element may begin with a dot.
|
// Third, no path element may begin with a dot.
|
||||||
func CheckPath(path string) error {
|
func CheckPath(path string) (err error) {
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
err = &InvalidPathError{Kind: "module", Path: path, Err: err}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if err := checkPath(path, modulePath); err != nil {
|
if err := checkPath(path, modulePath); err != nil {
|
||||||
return fmt.Errorf("malformed module path %q: %v", path, err)
|
return err
|
||||||
}
|
}
|
||||||
i := strings.Index(path, "/")
|
i := strings.Index(path, "/")
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
i = len(path)
|
i = len(path)
|
||||||
}
|
}
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
return fmt.Errorf("malformed module path %q: leading slash", path)
|
return fmt.Errorf("leading slash")
|
||||||
}
|
}
|
||||||
if !strings.Contains(path[:i], ".") {
|
if !strings.Contains(path[:i], ".") {
|
||||||
return fmt.Errorf("malformed module path %q: missing dot in first path element", path)
|
return fmt.Errorf("missing dot in first path element")
|
||||||
}
|
}
|
||||||
if path[0] == '-' {
|
if path[0] == '-' {
|
||||||
return fmt.Errorf("malformed module path %q: leading dash in first path element", path)
|
return fmt.Errorf("leading dash in first path element")
|
||||||
}
|
}
|
||||||
for _, r := range path[:i] {
|
for _, r := range path[:i] {
|
||||||
if !firstPathOK(r) {
|
if !firstPathOK(r) {
|
||||||
return fmt.Errorf("malformed module path %q: invalid char %q in first path element", path, r)
|
return fmt.Errorf("invalid char %q in first path element", r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, _, ok := SplitPathVersion(path); !ok {
|
if _, _, ok := SplitPathVersion(path); !ok {
|
||||||
return fmt.Errorf("malformed module path %q: invalid version", path)
|
return fmt.Errorf("invalid version")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -343,7 +364,7 @@ func CheckPath(path string) error {
|
||||||
// subtleties of Unicode.
|
// subtleties of Unicode.
|
||||||
func CheckImportPath(path string) error {
|
func CheckImportPath(path string) error {
|
||||||
if err := checkPath(path, importPath); err != nil {
|
if err := checkPath(path, importPath); err != nil {
|
||||||
return fmt.Errorf("malformed import path %q: %v", path, err)
|
return &InvalidPathError{Kind: "import", Path: path, Err: err}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -358,12 +379,13 @@ const (
|
||||||
filePath
|
filePath
|
||||||
)
|
)
|
||||||
|
|
||||||
// checkPath checks that a general path is valid.
|
// checkPath checks that a general path is valid. kind indicates what
|
||||||
// It returns an error describing why but not mentioning path.
|
// specific constraints should be applied.
|
||||||
// Because these checks apply to both module paths and import paths,
|
//
|
||||||
// the caller is expected to add the "malformed ___ path %q: " prefix.
|
// checkPath returns an error describing why the path is not valid.
|
||||||
// fileName indicates whether the final element of the path is a file name
|
// Because these checks apply to module, import, and file paths,
|
||||||
// (as opposed to a directory name).
|
// and because other checks may be applied, the caller is expected to wrap
|
||||||
|
// this error with InvalidPathError.
|
||||||
func checkPath(path string, kind pathKind) error {
|
func checkPath(path string, kind pathKind) error {
|
||||||
if !utf8.ValidString(path) {
|
if !utf8.ValidString(path) {
|
||||||
return fmt.Errorf("invalid UTF-8")
|
return fmt.Errorf("invalid UTF-8")
|
||||||
|
|
@ -477,7 +499,7 @@ func checkElem(elem string, kind pathKind) error {
|
||||||
// subtleties of Unicode.
|
// subtleties of Unicode.
|
||||||
func CheckFilePath(path string) error {
|
func CheckFilePath(path string) error {
|
||||||
if err := checkPath(path, filePath); err != nil {
|
if err := checkPath(path, filePath); err != nil {
|
||||||
return fmt.Errorf("malformed file path %q: %v", path, err)
|
return &InvalidPathError{Kind: "file", Path: path, Err: err}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
src/cmd/vendor/modules.txt
vendored
2
src/cmd/vendor/modules.txt
vendored
|
|
@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm
|
||||||
golang.org/x/crypto/ed25519
|
golang.org/x/crypto/ed25519
|
||||||
golang.org/x/crypto/ed25519/internal/edwards25519
|
golang.org/x/crypto/ed25519/internal/edwards25519
|
||||||
golang.org/x/crypto/ssh/terminal
|
golang.org/x/crypto/ssh/terminal
|
||||||
# golang.org/x/mod v0.4.2-0.20210309222212-d6ab96f2441f
|
# golang.org/x/mod v0.4.3-0.20210310185834-19d50cac98aa
|
||||||
## explicit
|
## explicit
|
||||||
golang.org/x/mod/internal/lazyregexp
|
golang.org/x/mod/internal/lazyregexp
|
||||||
golang.org/x/mod/modfile
|
golang.org/x/mod/modfile
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue