libgo: update to Go1.16rc1

Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/287493
This commit is contained in:
Ian Lance Taylor 2021-01-27 17:55:50 -08:00
parent 91a95ad2ae
commit 726b7aa004
188 changed files with 10373 additions and 10112 deletions

View File

@ -1,4 +1,4 @@
83eea1930671ce2bba863582a67f2609bc4f9f36
2663206528a6d46cbde60dbccf84c8288707ab8d
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.

View File

@ -1,4 +1,4 @@
2ff33f5e443165e55a080f3a649e4c070c4096d1
3e06467282c6d5678a6273747658c04314e013ef
The first line of this file holds the git revision number of the
last merge done from the master library sources.

View File

@ -656,7 +656,7 @@ noinst_DATA += zdefaultcc.go
# Generate the list of go std packages that were included in libgo
zstdpkglist.go: s-zstdpkglist; @true
s-zstdpkglist: Makefile
s-zstdpkglist: Makefile libgo-packages.txt
rm -f zstdpkglist.go.tmp
echo 'package goroot' > zstdpkglist.go.tmp
echo "" >> zstdpkglist.go.tmp

View File

@ -2828,7 +2828,7 @@ s-runtime-inc: runtime.lo mkruntimeinc.sh Makefile
# Generate the list of go std packages that were included in libgo
zstdpkglist.go: s-zstdpkglist; @true
s-zstdpkglist: Makefile
s-zstdpkglist: Makefile libgo-packages.txt
rm -f zstdpkglist.go.tmp
echo 'package goroot' > zstdpkglist.go.tmp
echo "" >> zstdpkglist.go.tmp

View File

@ -1 +1 @@
go1.16beta1
go1.16rc1

View File

@ -80,6 +80,7 @@ flag
fmt
go/ast
go/build
go/build/constraint
go/constant
go/doc
go/format
@ -107,6 +108,7 @@ image/jpeg
image/png
index/suffixarray
internal/cpu
internal/execabs
internal/fmtsort
internal/poll
internal/profile

View File

@ -28,7 +28,7 @@ func isASCII(s string) bool {
}
// toASCII converts the input to an ASCII C-style string.
// This a best effort conversion, so invalid characters are dropped.
// This is a best effort conversion, so invalid characters are dropped.
func toASCII(s string) string {
if isASCII(s) {
return s

View File

@ -1567,7 +1567,14 @@ func (p *Package) gccBaseCmd() []string {
func (p *Package) gccMachine() []string {
switch goarch {
case "amd64":
if goos == "darwin" {
return []string{"-arch", "x86_64", "-m64"}
}
return []string{"-m64"}
case "arm64":
if goos == "darwin" {
return []string{"-arch", "arm64"}
}
case "386":
return []string{"-m32"}
case "arm":

View File

@ -14,10 +14,10 @@ import (
"go/ast"
"go/printer"
"go/token"
exec "internal/execabs"
"internal/xcoff"
"io"
"os"
"os/exec"
"path/filepath"
"regexp"
"sort"
@ -958,9 +958,9 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
// Build the wrapper function compiled by gcc.
gccExport := ""
if goos == "windows" {
gccExport = "__declspec(dllexport)"
gccExport = "__declspec(dllexport) "
}
s := fmt.Sprintf("%s %s %s(", gccExport, gccResult, exp.ExpName)
s := fmt.Sprintf("%s%s %s(", gccExport, gccResult, exp.ExpName)
if fn.Recv != nil {
s += p.cgoType(fn.Recv.List[0].Type).C.String()
s += " recv"

View File

@ -8,9 +8,9 @@ import (
"bytes"
"fmt"
"go/token"
exec "internal/execabs"
"io/ioutil"
"os"
"os/exec"
)
// run runs the command argv, feeding in stdin on standard input.
@ -63,7 +63,7 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
p.Env = append(os.Environ(), "TERM=dumb")
err := p.Run()
if _, ok := err.(*exec.ExitError); err != nil && !ok {
fatalf("%s", err)
fatalf("exec %s: %s", argv[0], err)
}
ok = p.ProcessState.Success()
stdout, stderr = bout.Bytes(), berr.Bytes()
@ -88,7 +88,7 @@ func fatalf(msg string, args ...interface{}) {
// If we've already printed other errors, they might have
// caused the fatal condition. Assume they're enough.
if nerrors == 0 {
fmt.Fprintf(os.Stderr, msg+"\n", args...)
fmt.Fprintf(os.Stderr, "cgo: "+msg+"\n", args...)
}
os.Exit(2)
}

View File

@ -6,7 +6,7 @@ require (
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
golang.org/x/mod v0.4.0
golang.org/x/mod v0.4.1
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
golang.org/x/tools v0.0.0-20201211025543-abf6a1d87e11
golang.org/x/tools v0.0.0-20210107193943-4ed967dd8eff
)

File diff suppressed because it is too large Load Diff

View File

@ -216,6 +216,7 @@ func TestMain(m *testing.M) {
}
// Don't let these environment variables confuse the test.
os.Setenv("GOENV", "off")
os.Unsetenv("GOFLAGS")
os.Unsetenv("GOBIN")
os.Unsetenv("GOPATH")
os.Unsetenv("GIT_ALLOW_PROTOCOL")
@ -2655,12 +2656,12 @@ func TestBadCommandLines(t *testing.T) {
tg.tempFile("src/@x/x.go", "package x\n")
tg.setenv("GOPATH", tg.path("."))
tg.runFail("build", "@x")
tg.grepStderr("invalid input directory name \"@x\"|cannot use path@version syntax", "did not reject @x directory")
tg.grepStderr("invalid input directory name \"@x\"|can only use path@version syntax with 'go get' and 'go install' in module-aware mode", "did not reject @x directory")
tg.tempFile("src/@x/y/y.go", "package y\n")
tg.setenv("GOPATH", tg.path("."))
tg.runFail("build", "@x/y")
tg.grepStderr("invalid import path \"@x/y\"|cannot use path@version syntax", "did not reject @x/y import path")
tg.grepStderr("invalid import path \"@x/y\"|can only use path@version syntax with 'go get' and 'go install' in module-aware mode", "did not reject @x/y import path")
tg.tempFile("src/-x/x.go", "package x\n")
tg.setenv("GOPATH", tg.path("."))

View File

@ -10,9 +10,9 @@ import (
"context"
"flag"
"fmt"
exec "internal/execabs"
"log"
"os"
"os/exec"
"strings"
"sync"

View File

@ -9,10 +9,10 @@ import (
"bytes"
"context"
"fmt"
exec "internal/execabs"
"io"
urlpkg "net/url"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"

View File

@ -75,7 +75,8 @@ func runFmt(ctx context.Context, cmd *base.Command, args []string) {
}
if pkg.Error != nil {
var nogo *load.NoGoError
if errors.As(pkg.Error, &nogo) && len(pkg.InternalAllGoFiles()) > 0 {
var embed *load.EmbedError
if (errors.As(pkg.Error, &nogo) || errors.As(pkg.Error, &embed)) && len(pkg.InternalAllGoFiles()) > 0 {
// Skip this error, as we will format
// all files regardless.
} else {

View File

@ -12,10 +12,10 @@ import (
"fmt"
"go/parser"
"go/token"
exec "internal/execabs"
"io"
"log"
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"
@ -52,15 +52,6 @@ that can be run locally. It must either be in the shell path
(gofmt), a fully qualified path (/usr/you/bin/mytool), or a
command alias, described below.
To convey to humans and machine tools that code is generated,
generated source should have a line that matches the following
regular expression (in Go syntax):
^// Code generated .* DO NOT EDIT\.$
The line may appear anywhere in the file, but is typically
placed near the beginning so it is easy to find.
Note that go generate does not parse the file, so lines that look
like directives in comments or multiline strings will be treated
as directives.
@ -72,6 +63,15 @@ arguments when it is run.
Quoted strings use Go syntax and are evaluated before execution; a
quoted string appears as a single argument to the generator.
To convey to humans and machine tools that code is generated,
generated source should have a line that matches the following
regular expression (in Go syntax):
^// Code generated .* DO NOT EDIT\.$
This line must appear before the first non-comment, non-blank
text in the file.
Go generate sets several variables when it runs the generator:
$GOARCH

View File

@ -202,7 +202,7 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
func downloadPaths(patterns []string) []string {
for _, arg := range patterns {
if strings.Contains(arg, "@") {
base.Fatalf("go: cannot use path@version syntax in GOPATH mode")
base.Fatalf("go: can only use path@version syntax with 'go get' and 'go install' in module-aware mode")
continue
}

View File

@ -266,7 +266,7 @@ listed in the GOPATH environment variable.
(See 'go help gopath-get' and 'go help gopath'.)
When using modules, downloaded packages are stored in the module cache.
(See 'go help module-get' and 'go help goproxy'.)
See https://golang.org/ref/mod#module-cache.
When using modules, an additional variant of the go-import meta tag is
recognized and is preferred over those listing version control systems.
@ -276,7 +276,8 @@ That variant uses "mod" as the vcs in the content value, as in:
This tag means to fetch modules with paths beginning with example.org
from the module proxy available at the URL https://code.org/moduleproxy.
See 'go help goproxy' for details about the proxy protocol.
See https://golang.org/ref/mod#goproxy-protocol for details about the
proxy protocol.
Import path checking
@ -483,6 +484,10 @@ See 'go help env' for details.
General-purpose environment variables:
GO111MODULE
Controls whether the go command runs in module-aware mode or GOPATH mode.
May be "off", "on", or "auto".
See https://golang.org/ref/mod#mod-commands.
GCCGO
The gccgo command to run for 'go build -compiler=gccgo'.
GOARCH
@ -521,20 +526,24 @@ General-purpose environment variables:
GOPATH
For more details see: 'go help gopath'.
GOPROXY
URL of Go module proxy. See 'go help modules'.
URL of Go module proxy. See https://golang.org/ref/mod#environment-variables
and https://golang.org/ref/mod#module-proxy for details.
GOPRIVATE, GONOPROXY, GONOSUMDB
Comma-separated list of glob patterns (in the syntax of Go's path.Match)
of module path prefixes that should always be fetched directly
or that should not be compared against the checksum database.
See 'go help private'.
See https://golang.org/ref/mod#private-modules.
GOROOT
The root of the go tree.
GOSUMDB
The name of checksum database to use and optionally its public key and
URL. See 'go help module-auth'.
URL. See https://golang.org/ref/mod#authenticating.
GOTMPDIR
The directory where the go command will write
temporary source files, packages, and binaries.
GOVCS
Lists version control commands that may be used with matching servers.
See 'go help vcs'.
Environment variables for use with cgo:

View File

@ -89,6 +89,14 @@ to -f '{{.ImportPath}}'. The struct being passed to the template is:
TestGoFiles []string // _test.go files in package
XTestGoFiles []string // _test.go files outside package
// Embedded files
EmbedPatterns []string // //go:embed patterns
EmbedFiles []string // files matched by EmbedPatterns
TestEmbedPatterns []string // //go:embed patterns in TestGoFiles
TestEmbedFiles []string // files matched by TestEmbedPatterns
XTestEmbedPatterns []string // //go:embed patterns in XTestGoFiles
XTestEmbedFiles []string // files matched by XTestEmbedPatterns
// Cgo directives
CgoCFLAGS []string // cgo: flags for C compiler
CgoCPPFLAGS []string // cgo: flags for C preprocessor
@ -300,7 +308,7 @@ For more about build flags, see 'go help build'.
For more about specifying packages, see 'go help packages'.
For more about modules, see 'go help modules'.
For more about modules, see https://golang.org/ref/mod.
`,
}
@ -577,8 +585,6 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
// Show vendor-expanded paths in listing
p.TestImports = p.Resolve(p.TestImports)
p.XTestImports = p.Resolve(p.XTestImports)
p.TestEmbedFiles = p.ResolveEmbed(p.TestEmbedPatterns)
p.XTestEmbedFiles = p.ResolveEmbed(p.XTestEmbedPatterns)
p.DepOnly = !cmdline[p]
if *listCompiled {

View File

@ -96,7 +96,7 @@ type PackagePublic struct {
// Embedded files
EmbedPatterns []string `json:",omitempty"` // //go:embed patterns
EmbedFiles []string `json:",omitempty"` // files and directories matched by EmbedPatterns
EmbedFiles []string `json:",omitempty"` // files matched by EmbedPatterns
// Cgo directives
CgoCFLAGS []string `json:",omitempty"` // cgo: flags for C compiler
@ -122,11 +122,11 @@ type PackagePublic struct {
TestGoFiles []string `json:",omitempty"` // _test.go files in package
TestImports []string `json:",omitempty"` // imports from TestGoFiles
TestEmbedPatterns []string `json:",omitempty"` // //go:embed patterns
TestEmbedFiles []string `json:",omitempty"` // //files matched by EmbedPatterns
TestEmbedFiles []string `json:",omitempty"` // files matched by TestEmbedPatterns
XTestGoFiles []string `json:",omitempty"` // _test.go files outside package
XTestImports []string `json:",omitempty"` // imports from XTestGoFiles
XTestEmbedPatterns []string `json:",omitempty"` // //go:embed patterns
XTestEmbedFiles []string `json:",omitempty"` // //files matched by EmbedPatterns
XTestEmbedFiles []string `json:",omitempty"` // files matched by XTestEmbedPatterns
}
// AllFiles returns the names of all the files considered for the package.
@ -304,7 +304,7 @@ func (p *Package) setLoadPackageDataError(err error, path string, stk *ImportSta
}
if path != stk.Top() {
p = setErrorPos(p, importPos)
p.Error.setPos(importPos)
}
}
@ -412,6 +412,9 @@ type PackageError struct {
}
func (p *PackageError) Error() string {
// TODO(#43696): decide when to print the stack or the position based on
// the error type and whether the package is in the main module.
// Document the rationale.
if p.Pos != "" && (len(p.ImportStack) == 0 || !p.alwaysPrintStack) {
// Omit import stack. The full path to the file where the error
// is the most important thing.
@ -447,6 +450,15 @@ func (p *PackageError) MarshalJSON() ([]byte, error) {
return json.Marshal(perr)
}
func (p *PackageError) setPos(posList []token.Position) {
if len(posList) == 0 {
return
}
pos := posList[0]
pos.Filename = base.ShortPath(pos.Filename)
p.Pos = pos.String()
}
// ImportPathError is a type of error that prevents a package from being loaded
// for a given import path. When such a package is loaded, a *Package is
// returned with Err wrapping an ImportPathError: the error is attached to
@ -695,17 +707,19 @@ func loadImport(ctx context.Context, pre *preload, path, srcDir string, parent *
Err: ImportErrorf(path, "non-canonical import path %q: should be %q", path, pathpkg.Clean(path)),
}
p.Incomplete = true
setErrorPos(p, importPos)
p.Error.setPos(importPos)
}
}
// Checked on every import because the rules depend on the code doing the importing.
if perr := disallowInternal(srcDir, parent, parentPath, p, stk); perr != p {
return setErrorPos(perr, importPos)
perr.Error.setPos(importPos)
return perr
}
if mode&ResolveImport != 0 {
if perr := disallowVendor(srcDir, path, parentPath, p, stk); perr != p {
return setErrorPos(perr, importPos)
perr.Error.setPos(importPos)
return perr
}
}
@ -715,7 +729,8 @@ func loadImport(ctx context.Context, pre *preload, path, srcDir string, parent *
ImportStack: stk.Copy(),
Err: ImportErrorf(path, "import %q is a program, not an importable package", path),
}
return setErrorPos(&perr, importPos)
perr.Error.setPos(importPos)
return &perr
}
if p.Internal.Local && parent != nil && !parent.Internal.Local {
@ -730,21 +745,13 @@ func loadImport(ctx context.Context, pre *preload, path, srcDir string, parent *
ImportStack: stk.Copy(),
Err: err,
}
return setErrorPos(&perr, importPos)
perr.Error.setPos(importPos)
return &perr
}
return p
}
func setErrorPos(p *Package, importPos []token.Position) *Package {
if len(importPos) > 0 {
pos := importPos[0]
pos.Filename = base.ShortPath(pos.Filename)
p.Error.Pos = pos.String()
}
return p
}
// loadPackageData loads information needed to construct a *Package. The result
// is cached, and later calls to loadPackageData for the same package will return
// the same data.
@ -769,11 +776,7 @@ func loadPackageData(path, parentPath, parentDir, parentRoot string, parentIsStd
}
if strings.Contains(path, "@") {
if cfg.ModulesEnabled {
return nil, false, errors.New("can only use path@version syntax with 'go get'")
} else {
return nil, false, errors.New("cannot use path@version syntax in GOPATH mode")
}
return nil, false, errors.New("can only use path@version syntax with 'go get' and 'go install' in module-aware mode")
}
// Determine canonical package path and directory.
@ -1659,7 +1662,7 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor
// must be either in an explicit command-line argument,
// or on the importer side (indicated by a non-empty importPos).
if path != stk.Top() && len(importPos) > 0 {
p = setErrorPos(p, importPos)
p.Error.setPos(importPos)
}
}
}
@ -1669,11 +1672,6 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor
p.setLoadPackageDataError(err, path, stk, importPos)
}
p.EmbedFiles, p.Internal.Embed, err = p.resolveEmbed(p.EmbedPatterns)
if err != nil {
setError(err)
}
useBindir := p.Name == "main"
if !p.Standard {
switch cfg.BuildBuildmode {
@ -1809,9 +1807,20 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor
return
}
// Errors after this point are caused by this package, not the importing
// package. Pushing the path here prevents us from reporting the error
// with the position of the import declaration.
stk.Push(path)
defer stk.Pop()
p.EmbedFiles, p.Internal.Embed, err = resolveEmbed(p.Dir, p.EmbedPatterns)
if err != nil {
p.Incomplete = true
setError(err)
embedErr := err.(*EmbedError)
p.Error.setPos(p.Internal.Build.EmbedPatternPos[embedErr.Pattern])
}
// Check for case-insensitive collision of input files.
// To avoid problems on case-insensitive files, we reject any package
// where two different input files have equal names under a case-insensitive
@ -1915,35 +1924,62 @@ func (p *Package) load(ctx context.Context, path string, stk *ImportStack, impor
}
}
// An EmbedError indicates a problem with a go:embed directive.
type EmbedError struct {
Pattern string
Err error
}
func (e *EmbedError) Error() string {
return fmt.Sprintf("pattern %s: %v", e.Pattern, e.Err)
}
func (e *EmbedError) Unwrap() error {
return e.Err
}
// ResolveEmbed resolves //go:embed patterns and returns only the file list.
// For use by go list to compute p.TestEmbedFiles and p.XTestEmbedFiles.
func (p *Package) ResolveEmbed(patterns []string) []string {
files, _, _ := p.resolveEmbed(patterns)
return files
// For use by go mod vendor to find embedded files it should copy into the
// vendor directory.
// TODO(#42504): Once go mod vendor uses load.PackagesAndErrors, just
// call (*Package).ResolveEmbed
func ResolveEmbed(dir string, patterns []string) ([]string, error) {
files, _, err := resolveEmbed(dir, patterns)
return files, err
}
// resolveEmbed resolves //go:embed patterns to precise file lists.
// It sets files to the list of unique files matched (for go list),
// and it sets pmap to the more precise mapping from
// patterns to files.
// TODO(rsc): All these messages need position information for better error reports.
func (p *Package) resolveEmbed(patterns []string) (files []string, pmap map[string][]string, err error) {
func resolveEmbed(pkgdir string, patterns []string) (files []string, pmap map[string][]string, err error) {
var pattern string
defer func() {
if err != nil {
err = &EmbedError{
Pattern: pattern,
Err: err,
}
}
}()
// TODO(rsc): All these messages need position information for better error reports.
pmap = make(map[string][]string)
have := make(map[string]int)
dirOK := make(map[string]bool)
pid := 0 // pattern ID, to allow reuse of have map
for _, pattern := range patterns {
for _, pattern = range patterns {
pid++
// Check pattern is valid for //go:embed.
if _, err := path.Match(pattern, ""); err != nil || !validEmbedPattern(pattern) {
return nil, nil, fmt.Errorf("pattern %s: invalid pattern syntax", pattern)
return nil, nil, fmt.Errorf("invalid pattern syntax")
}
// Glob to find matches.
match, err := fsys.Glob(p.Dir + string(filepath.Separator) + filepath.FromSlash(pattern))
match, err := fsys.Glob(pkgdir + string(filepath.Separator) + filepath.FromSlash(pattern))
if err != nil {
return nil, nil, fmt.Errorf("pattern %s: %v", pattern, err)
return nil, nil, err
}
// Filter list of matches down to the ones that will still exist when
@ -1952,7 +1988,7 @@ func (p *Package) resolveEmbed(patterns []string) (files []string, pmap map[stri
// then there may be other things lying around, like symbolic links or .git directories.)
var list []string
for _, file := range match {
rel := filepath.ToSlash(file[len(p.Dir)+1:]) // file, relative to p.Dir
rel := filepath.ToSlash(file[len(pkgdir)+1:]) // file, relative to p.Dir
what := "file"
info, err := fsys.Lstat(file)
@ -1965,28 +2001,28 @@ func (p *Package) resolveEmbed(patterns []string) (files []string, pmap map[stri
// Check that directories along path do not begin a new module
// (do not contain a go.mod).
for dir := file; len(dir) > len(p.Dir)+1 && !dirOK[dir]; dir = filepath.Dir(dir) {
for dir := file; len(dir) > len(pkgdir)+1 && !dirOK[dir]; dir = filepath.Dir(dir) {
if _, err := fsys.Stat(filepath.Join(dir, "go.mod")); err == nil {
return nil, nil, fmt.Errorf("pattern %s: cannot embed %s %s: in different module", pattern, what, rel)
return nil, nil, fmt.Errorf("cannot embed %s %s: in different module", what, rel)
}
if dir != file {
if info, err := fsys.Lstat(dir); err == nil && !info.IsDir() {
return nil, nil, fmt.Errorf("pattern %s: cannot embed %s %s: in non-directory %s", pattern, what, rel, dir[len(p.Dir)+1:])
return nil, nil, fmt.Errorf("cannot embed %s %s: in non-directory %s", what, rel, dir[len(pkgdir)+1:])
}
}
dirOK[dir] = true
if elem := filepath.Base(dir); isBadEmbedName(elem) {
if dir == file {
return nil, nil, fmt.Errorf("pattern %s: cannot embed %s %s: invalid name %s", pattern, what, rel, elem)
return nil, nil, fmt.Errorf("cannot embed %s %s: invalid name %s", what, rel, elem)
} else {
return nil, nil, fmt.Errorf("pattern %s: cannot embed %s %s: in invalid directory %s", pattern, what, rel, elem)
return nil, nil, fmt.Errorf("cannot embed %s %s: in invalid directory %s", what, rel, elem)
}
}
}
switch {
default:
return nil, nil, fmt.Errorf("pattern %s: cannot embed irregular file %s", pattern, rel)
return nil, nil, fmt.Errorf("cannot embed irregular file %s", rel)
case info.Mode().IsRegular():
if have[rel] != pid {
@ -2002,7 +2038,7 @@ func (p *Package) resolveEmbed(patterns []string) (files []string, pmap map[stri
if err != nil {
return err
}
rel := filepath.ToSlash(path[len(p.Dir)+1:])
rel := filepath.ToSlash(path[len(pkgdir)+1:])
name := info.Name()
if path != file && (isBadEmbedName(name) || name[0] == '.' || name[0] == '_') {
// Ignore bad names, assuming they won't go into modules.
@ -2033,13 +2069,13 @@ func (p *Package) resolveEmbed(patterns []string) (files []string, pmap map[stri
return nil, nil, err
}
if count == 0 {
return nil, nil, fmt.Errorf("pattern %s: cannot embed directory %s: contains no embeddable files", pattern, rel)
return nil, nil, fmt.Errorf("cannot embed directory %s: contains no embeddable files", rel)
}
}
}
if len(list) == 0 {
return nil, nil, fmt.Errorf("pattern %s: no matching files found", pattern)
return nil, nil, fmt.Errorf("no matching files found")
}
sort.Strings(list)
pmap[pattern] = list

View File

@ -124,12 +124,14 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p
imports = append(imports, p1)
}
var err error
p.TestEmbedFiles, testEmbed, err = p.resolveEmbed(p.TestEmbedPatterns)
p.TestEmbedFiles, testEmbed, err = resolveEmbed(p.Dir, p.TestEmbedPatterns)
if err != nil && ptestErr == nil {
ptestErr = &PackageError{
ImportStack: stk.Copy(),
Err: err,
}
embedErr := err.(*EmbedError)
ptestErr.setPos(p.Internal.Build.TestEmbedPatternPos[embedErr.Pattern])
}
stk.Pop()
@ -145,12 +147,14 @@ func TestPackagesAndErrors(ctx context.Context, p *Package, cover *TestCover) (p
}
p.XTestImports[i] = p1.ImportPath
}
p.XTestEmbedFiles, xtestEmbed, err = p.resolveEmbed(p.XTestEmbedPatterns)
p.XTestEmbedFiles, xtestEmbed, err = resolveEmbed(p.Dir, p.XTestEmbedPatterns)
if err != nil && pxtestErr == nil {
pxtestErr = &PackageError{
ImportStack: stk.Copy(),
Err: err,
}
embedErr := err.(*EmbedError)
pxtestErr.setPos(p.Internal.Build.XTestEmbedPatternPos[embedErr.Pattern])
}
stk.Pop()

View File

@ -52,7 +52,9 @@ corresponding to this Go struct:
The -x flag causes download to print the commands download executes.
See 'go help modules' for more about module queries.
See https://golang.org/ref/mod#go-mod-download for more about 'go mod download'.
See https://golang.org/ref/mod#version-queries for more about version queries.
`,
}

View File

@ -95,6 +95,7 @@ writing it back to go.mod. The JSON output corresponds to these Go types:
Require []Require
Exclude []Module
Replace []Replace
Retract []Retract
}
type Require struct {
@ -121,9 +122,7 @@ Note that this only describes the go.mod file itself, not other modules
referred to indirectly. For the full set of modules available to a build,
use 'go list -m -json all'.
For example, a tool can obtain the go.mod as a data structure by
parsing the output of 'go mod edit -json' and can then make changes
by invoking 'go mod edit' with -require, -exclude, and so on.
See https://golang.org/ref/mod#go-mod-edit for more about 'go mod edit'.
`,
}

View File

@ -26,6 +26,8 @@ Graph prints the module requirement graph (with replacements applied)
in text form. Each line in the output has two space-separated fields: a module
and one of its requirements. Each module is identified as a string of the form
path@version, except for the main module, which has no @version suffix.
See https://golang.org/ref/mod#go-mod-graph for more about 'go mod graph'.
`,
Run: runGraph,
}

View File

@ -27,6 +27,8 @@ Gopkg.lock), and the current directory (if in GOPATH).
If a configuration file for a vendoring tool is present, init will attempt to
import module requirements from it.
See https://golang.org/ref/mod#go-mod-init for more about 'go mod init'.
`,
Run: runInit,
}

View File

@ -29,6 +29,8 @@ to standard error.
The -e flag causes tidy to attempt to proceed despite errors
encountered while loading packages.
See https://golang.org/ref/mod#go-mod-tidy for more about 'go mod tidy'.
`,
Run: runTidy,
}

View File

@ -7,7 +7,9 @@ package modcmd
import (
"bytes"
"context"
"errors"
"fmt"
"go/build"
"io"
"io/fs"
"os"
@ -19,7 +21,9 @@ import (
"cmd/go/internal/cfg"
"cmd/go/internal/fsys"
"cmd/go/internal/imports"
"cmd/go/internal/load"
"cmd/go/internal/modload"
"cmd/go/internal/str"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
@ -38,6 +42,8 @@ modules and packages to standard error.
The -e flag causes vendor to attempt to proceed despite errors
encountered while loading packages.
See https://golang.org/ref/mod#go-mod-vendor for more about 'go mod vendor'.
`,
Run: runVendor,
}
@ -180,19 +186,76 @@ func moduleLine(m, r module.Version) string {
}
func vendorPkg(vdir, pkg string) {
// TODO(#42504): Instead of calling modload.ImportMap then build.ImportDir,
// just call load.PackagesAndErrors. To do that, we need to add a good way
// to ignore build constraints.
realPath := modload.ImportMap(pkg)
if realPath != pkg && modload.ImportMap(realPath) != "" {
fmt.Fprintf(os.Stderr, "warning: %s imported as both %s and %s; making two copies.\n", realPath, realPath, pkg)
}
copiedFiles := make(map[string]bool)
dst := filepath.Join(vdir, pkg)
src := modload.PackageDir(realPath)
if src == "" {
fmt.Fprintf(os.Stderr, "internal error: no pkg for %s -> %s\n", pkg, realPath)
}
copyDir(dst, src, matchPotentialSourceFile)
copyDir(dst, src, matchPotentialSourceFile, copiedFiles)
if m := modload.PackageModule(realPath); m.Path != "" {
copyMetadata(m.Path, realPath, dst, src)
copyMetadata(m.Path, realPath, dst, src, copiedFiles)
}
ctx := build.Default
ctx.UseAllFiles = true
bp, err := ctx.ImportDir(src, build.IgnoreVendor)
// Because UseAllFiles is set on the build.Context, it's possible ta get
// a MultiplePackageError on an otherwise valid package: the package could
// have different names for GOOS=windows and GOOS=mac for example. On the
// other hand if there's a NoGoError, the package might have source files
// specifying "// +build ignore" those packages should be skipped because
// embeds from ignored files can't be used.
// TODO(#42504): Find a better way to avoid errors from ImportDir. We'll
// need to figure this out when we switch to PackagesAndErrors as per the
// TODO above.
var multiplePackageError *build.MultiplePackageError
var noGoError *build.NoGoError
if err != nil {
if errors.As(err, &noGoError) {
return // No source files in this package are built. Skip embeds in ignored files.
} else if !errors.As(err, &multiplePackageError) { // multiplePackgeErrors are okay, but others are not.
base.Fatalf("internal error: failed to find embedded files of %s: %v\n", pkg, err)
}
}
embedPatterns := str.StringList(bp.EmbedPatterns, bp.TestEmbedPatterns, bp.XTestEmbedPatterns)
embeds, err := load.ResolveEmbed(bp.Dir, embedPatterns)
if err != nil {
base.Fatalf("go mod vendor: %v", err)
}
for _, embed := range embeds {
embedDst := filepath.Join(dst, embed)
if copiedFiles[embedDst] {
continue
}
// Copy the file as is done by copyDir below.
r, err := os.Open(filepath.Join(src, embed))
if err != nil {
base.Fatalf("go mod vendor: %v", err)
}
if err := os.MkdirAll(filepath.Dir(embedDst), 0777); err != nil {
base.Fatalf("go mod vendor: %v", err)
}
w, err := os.Create(embedDst)
if err != nil {
base.Fatalf("go mod vendor: %v", err)
}
if _, err := io.Copy(w, r); err != nil {
base.Fatalf("go mod vendor: %v", err)
}
r.Close()
if err := w.Close(); err != nil {
base.Fatalf("go mod vendor: %v", err)
}
}
}
@ -205,14 +268,14 @@ var copiedMetadata = make(map[metakey]bool)
// copyMetadata copies metadata files from parents of src to parents of dst,
// stopping after processing the src parent for modPath.
func copyMetadata(modPath, pkg, dst, src string) {
func copyMetadata(modPath, pkg, dst, src string, copiedFiles map[string]bool) {
for parent := 0; ; parent++ {
if copiedMetadata[metakey{modPath, dst}] {
break
}
copiedMetadata[metakey{modPath, dst}] = true
if parent > 0 {
copyDir(dst, src, matchMetadata)
copyDir(dst, src, matchMetadata, copiedFiles)
}
if modPath == pkg {
break
@ -280,7 +343,7 @@ func matchPotentialSourceFile(dir string, info fs.DirEntry) bool {
}
// copyDir copies all regular files satisfying match(info) from src to dst.
func copyDir(dst, src string, match func(dir string, info fs.DirEntry) bool) {
func copyDir(dst, src string, match func(dir string, info fs.DirEntry) bool, copiedFiles map[string]bool) {
files, err := os.ReadDir(src)
if err != nil {
base.Fatalf("go mod vendor: %v", err)
@ -292,11 +355,14 @@ func copyDir(dst, src string, match func(dir string, info fs.DirEntry) bool) {
if file.IsDir() || !file.Type().IsRegular() || !match(src, file) {
continue
}
copiedFiles[file.Name()] = true
r, err := os.Open(filepath.Join(src, file.Name()))
if err != nil {
base.Fatalf("go mod vendor: %v", err)
}
w, err := os.Create(filepath.Join(dst, file.Name()))
dstPath := filepath.Join(dst, file.Name())
copiedFiles[dstPath] = true
w, err := os.Create(dstPath)
if err != nil {
base.Fatalf("go mod vendor: %v", err)
}

View File

@ -31,6 +31,8 @@ modified since being downloaded. If all the modules are unmodified,
verify prints "all modules verified." Otherwise it reports which
modules have been changed and causes 'go mod' to exit with a
non-zero status.
See https://golang.org/ref/mod#go-mod-verify for more about 'go mod verify'.
`,
Run: runVerify,
}

View File

@ -48,6 +48,8 @@ For example:
# golang.org/x/text/encoding
(main module does not need package golang.org/x/text/encoding)
$
See https://golang.org/ref/mod#go-mod-why for more about 'go mod why'.
`,
}

View File

@ -10,10 +10,10 @@ import (
"bytes"
"crypto/sha256"
"fmt"
exec "internal/execabs"
"io"
"io/fs"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"

View File

@ -8,11 +8,11 @@ import (
"bytes"
"errors"
"fmt"
exec "internal/execabs"
"io"
"io/fs"
"net/url"
"os"
"os/exec"
"path/filepath"
"sort"
"strconv"

View File

@ -768,90 +768,14 @@ var HelpModuleAuth = &base.Command{
UsageLine: "module-auth",
Short: "module authentication using go.sum",
Long: `
The go command tries to authenticate every downloaded module,
checking that the bits downloaded for a specific module version today
match bits downloaded yesterday. This ensures repeatable builds
and detects introduction of unexpected changes, malicious or not.
When the go command downloads a module zip file or go.mod file into the
module cache, it computes a cryptographic hash and compares it with a known
value to verify the file hasn't changed since it was first downloaded. Known
hashes are stored in a file in the module root directory named go.sum. Hashes
may also be downloaded from the checksum database depending on the values of
GOSUMDB, GOPRIVATE, and GONOSUMDB.
In each module's root, alongside go.mod, the go command maintains
a file named go.sum containing the cryptographic checksums of the
module's dependencies.
The form of each line in go.sum is three fields:
<module> <version>[/go.mod] <hash>
Each known module version results in two lines in the go.sum file.
The first line gives the hash of the module version's file tree.
The second line appends "/go.mod" to the version and gives the hash
of only the module version's (possibly synthesized) go.mod file.
The go.mod-only hash allows downloading and authenticating a
module version's go.mod file, which is needed to compute the
dependency graph, without also downloading all the module's source code.
The hash begins with an algorithm prefix of the form "h<N>:".
The only defined algorithm prefix is "h1:", which uses SHA-256.
Module authentication failures
The go command maintains a cache of downloaded packages and computes
and records the cryptographic checksum of each package at download time.
In normal operation, the go command checks the main module's go.sum file
against these precomputed checksums instead of recomputing them on
each command invocation. The 'go mod verify' command checks that
the cached copies of module downloads still match both their recorded
checksums and the entries in go.sum.
In day-to-day development, the checksum of a given module version
should never change. Each time a dependency is used by a given main
module, the go command checks its local cached copy, freshly
downloaded or not, against the main module's go.sum. If the checksums
don't match, the go command reports the mismatch as a security error
and refuses to run the build. When this happens, proceed with caution:
code changing unexpectedly means today's build will not match
yesterday's, and the unexpected change may not be beneficial.
If the go command reports a mismatch in go.sum, the downloaded code
for the reported module version does not match the one used in a
previous build of the main module. It is important at that point
to find out what the right checksum should be, to decide whether
go.sum is wrong or the downloaded code is wrong. Usually go.sum is right:
you want to use the same code you used yesterday.
If a downloaded module is not yet included in go.sum and it is a publicly
available module, the go command consults the Go checksum database to fetch
the expected go.sum lines. If the downloaded code does not match those
lines, the go command reports the mismatch and exits. Note that the
database is not consulted for module versions already listed in go.sum.
If a go.sum mismatch is reported, it is always worth investigating why
the code downloaded today differs from what was downloaded yesterday.
The GOSUMDB environment variable identifies the name of checksum database
to use and optionally its public key and URL, as in:
GOSUMDB="sum.golang.org"
GOSUMDB="sum.golang.org+<publickey>"
GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"
The go command knows the public key of sum.golang.org, and also that the name
sum.golang.google.cn (available inside mainland China) connects to the
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.
See https://sum.golang.org/privacy for the service's privacy policy.
If GOSUMDB is set to "off", or if "go get" is invoked with the -insecure flag,
the checksum database is not consulted, and all unrecognized modules are
accepted, at the cost of giving up the security guarantee of verified repeatable
downloads for all modules. A better way to bypass the checksum database
for specific modules is to use the GOPRIVATE or GONOSUMDB environment
variables. See 'go help private' for details.
The 'go env -w' command (see 'go help env') can be used to set these variables
for future go command invocations.
For details, see https://golang.org/ref/mod#authenticating.
`,
}
@ -865,8 +789,8 @@ regardless of source, against the public Go checksum database at sum.golang.org.
These defaults work well for publicly available source code.
The GOPRIVATE environment variable controls which modules the go command
considers to be private (not available publicly) and should therefore not use the
proxy or checksum database. The variable is a comma-separated list of
considers to be private (not available publicly) and should therefore not use
the proxy or checksum database. The variable is a comma-separated list of
glob patterns (in the syntax of Go's path.Match) of module path prefixes.
For example,
@ -876,10 +800,6 @@ causes the go command to treat as private any module with a path prefix
matching either pattern, including git.corp.example.com/xyzzy, rsc.io/private,
and rsc.io/private/quux.
The GOPRIVATE environment variable may be used by other tools as well to
identify non-public modules. For example, an editor could use GOPRIVATE
to decide whether to hyperlink a package import to a godoc.org page.
For fine-grained control over module download and validation, the GONOPROXY
and GONOSUMDB environment variables accept the same kind of glob list
and override GOPRIVATE for the specific decision of whether to use the proxy
@ -892,12 +812,6 @@ users would configure go using:
GOPROXY=proxy.example.com
GONOPROXY=none
This would tell the go command and other tools that modules beginning with
a corp.example.com subdomain are private but that the company proxy should
be used for downloading both public and private modules, because
GONOPROXY has been set to a pattern that won't match any modules,
overriding GOPRIVATE.
The GOPRIVATE variable is also used to define the "public" and "private"
patterns for the GOVCS variable; see 'go help vcs'. For that usage,
GOPRIVATE applies even in GOPATH mode. In that case, it matches import paths
@ -905,5 +819,7 @@ instead of module paths.
The 'go env -w' command (see 'go help env') can be used to set these variables
for future go command invocations.
For more details, see https://golang.org/ref/mod#private-modules.
`,
}

View File

@ -36,65 +36,8 @@ URLs of a specified form. The requests have no query parameters, so even
a site serving from a fixed file system (including a file:/// URL)
can be a module proxy.
The GET requests sent to a Go module proxy are:
GET $GOPROXY/<module>/@v/list returns a list of known versions of the given
module, one per line.
GET $GOPROXY/<module>/@v/<version>.info returns JSON-formatted metadata
about that version of the given module.
GET $GOPROXY/<module>/@v/<version>.mod returns the go.mod file
for that version of the given module.
GET $GOPROXY/<module>/@v/<version>.zip returns the zip archive
for that version of the given module.
GET $GOPROXY/<module>/@latest returns JSON-formatted metadata about the
latest known version of the given module in the same format as
<module>/@v/<version>.info. The latest version should be the version of
the module the go command may use if <module>/@v/list is empty or no
listed version is suitable. <module>/@latest is optional and may not
be implemented by a module proxy.
When resolving the latest version of a module, the go command will request
<module>/@v/list, then, if no suitable versions are found, <module>/@latest.
The go command prefers, in order: the semantically highest release version,
the semantically highest pre-release version, and the chronologically
most recent pseudo-version. In Go 1.12 and earlier, the go command considered
pseudo-versions in <module>/@v/list to be pre-release versions, but this is
no longer true since Go 1.13.
To avoid problems when serving from case-sensitive file systems,
the <module> and <version> elements are case-encoded, replacing every
uppercase letter with an exclamation mark followed by the corresponding
lower-case letter: github.com/Azure encodes as github.com/!azure.
The JSON-formatted metadata about a given module corresponds to
this Go data structure, which may be expanded in the future:
type Info struct {
Version string // version string
Time time.Time // commit time
}
The zip archive for a specific version of a given module is a
standard zip file that contains the file tree corresponding
to the module's source code and related files. The archive uses
slash-separated paths, and every file path in the archive must
begin with <module>@<version>/, where the module and version are
substituted directly, not case-encoded. The root of the module
file tree corresponds to the <module>@<version>/ prefix in the
archive.
Even when downloading directly from version control systems,
the go command synthesizes explicit info, mod, and zip files
and stores them in its local cache, $GOPATH/pkg/mod/cache/download,
the same as if it had downloaded them directly from a proxy.
The cache layout is the same as the proxy URL space, so
serving $GOPATH/pkg/mod/cache/download at (or copying it to)
https://example.com/proxy would let other users access those
cached module versions with GOPROXY=https://example.com/proxy.
For details on the GOPROXY protocol, see
https://golang.org/ref/mod#goproxy-protocol.
`,
}

View File

@ -56,85 +56,49 @@ var CmdGet = &base.Command{
UsageLine: "go get [-d] [-t] [-u] [-v] [-insecure] [build flags] [packages]",
Short: "add dependencies to current module and install them",
Long: `
Get resolves and adds dependencies to the current development module
and then builds and installs them.
Get resolves its command-line arguments to packages at specific module versions,
updates go.mod to require those versions, downloads source code into the
module cache, then builds and installs the named packages.
The first step is to resolve which dependencies to add.
To add a dependency for a package or upgrade it to its latest version:
For each named package or package pattern, get must decide which version of
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
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 looks up the latest
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.
go get example.com/pkg
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'.
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.
To upgrade or downgrade a package to a specific version:
For modules stored in source control repositories, the version suffix can
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'. 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.
go get example.com/pkg@v1.2.3
If a module under consideration is already a dependency of the current
development module, then get will update the required version.
Specifying a version earlier than the current required version is valid and
downgrades the dependency. The version suffix @none indicates that the
dependency should be removed entirely, downgrading or removing modules
depending on it as needed.
To remove a dependency on a module and downgrade modules that require it:
The version suffix @latest explicitly requests the latest minor release of
the module named by the given path. The suffix @upgrade is like @latest but
will not downgrade a module if it is already required at a revision or
pre-release version newer than the latest released version. The suffix
@patch requests the latest patch release: the latest released version
with the same major and minor version numbers as the currently required
version. Like @upgrade, @patch will not downgrade a module already required
at a newer version. If the path is not already required, @upgrade is
equivalent to @latest, and @patch is disallowed.
go get example.com/mod@none
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
dependencies. Instead it prefers to use the specific dependency versions
requested by that module. For example, if the latest A requires module
B v1.2.3, while B v1.2.4 and v1.3.1 are also available, then 'go get A'
will use the latest A but then use B v1.2.3, as requested by A. (If there
are competing requirements for a particular module, then 'go get' resolves
those requirements by taking the maximum requested version.)
See https://golang.org/ref/mod#go-get for details.
The 'go install' command may be used to build and install packages. When a
version is specified, 'go install' runs in module-aware mode and ignores
the go.mod file in the current directory. For example:
go install example.com/pkg@v1.2.3
go install example.com/pkg@latest
See 'go help install' or https://golang.org/ref/mod#go-install for details.
In addition to build flags (listed in 'go help build') 'go get' accepts the
following flags.
The -t flag instructs get to consider modules needed to build tests of
packages specified on the command line.
The -u flag instructs get to update modules providing dependencies
of packages named on the command line to use newer minor or patch
releases when available. Continuing the previous example, 'go get -u A'
will use the latest A with B v1.3.1 (not B v1.2.3). If B requires module C,
but C does not provide any packages needed to build packages in A
(not including tests), then C will not be updated.
releases when available.
The -u=patch flag (not -u patch) also instructs get to update dependencies,
but changes the default to select patch releases.
Continuing the previous example,
'go get -u=patch A@latest' will use the latest A with B v1.2.4 (not B v1.2.3),
while 'go get -u=patch A' will use a patch release of A instead.
When the -t and -u flags are used together, get will update
test dependencies as well.
In general, adding a new dependency may require upgrading
existing dependencies to keep a working build, and 'go get' does
this automatically. Similarly, downgrading one dependency may
require downgrading other dependencies, and 'go get' does
this automatically as well.
The -insecure flag permits fetching from repositories and resolving
custom domains using insecure schemes such as HTTP, and also bypassess
module sum validation using the checksum database. Use with caution.
@ -143,12 +107,8 @@ To permit the use of insecure schemes, use the GOINSECURE environment
variable instead. To bypass module sum validation, use GOPRIVATE or
GONOSUMDB. See 'go help environment' for details.
The second step is to download (if needed), build, and install
the named packages.
The -d flag instructs get to skip this step, downloading source code
needed to build the named packages and their dependencies, but not
building or installing.
The -d flag instructs get not to build or install packages. get will only
update go.mod and download source code needed to build packages.
Building and installing packages with get is deprecated. In a future release,
the -d flag will be enabled by default, and 'go get' will be only be used to
@ -157,31 +117,14 @@ dependencies from the current module, use 'go install'. To install a package
ignoring the current module, use 'go install' with an @version suffix like
"@latest" after each argument.
If an argument names a module but not a package (because there is no
Go source code in the module's root directory), then the install step
is skipped for that argument, instead of causing a build failure.
For example 'go get golang.org/x/perf' succeeds even though there
is no code corresponding to that import path.
Note that package patterns are allowed and are expanded after resolving
the module versions. For example, 'go get golang.org/x/perf/cmd/...'
adds the latest golang.org/x/perf and then installs the commands in that
latest version.
With no package arguments, 'go get' applies to Go package in the
current directory, if any. In particular, 'go get -u' and
'go get -u=patch' update all the dependencies of that package.
With no package arguments and also without -u, 'go get' is not much more
than 'go install', and 'go get -d' not much more than 'go list'.
For more about modules, see 'go help modules'.
For more about modules, see https://golang.org/ref/mod.
For more about specifying packages, see 'go help packages'.
This text describes the behavior of get using modules to manage source
code and dependencies. If instead the go command is running in GOPATH
mode, the details of get's flags and effects change, as does 'go help get'.
See 'go help modules' and 'go help gopath-get'.
See 'go help gopath-get'.
See also: go build, go install, go clean, go mod.
`,
@ -1558,7 +1501,7 @@ func (r *resolver) checkPackagesAndRetractions(ctx context.Context, pkgPatterns
}
}
if retractPath != "" {
fmt.Fprintf(os.Stderr, "go: run 'go get %s@latest' to switch to the latest unretracted version\n", retractPath)
fmt.Fprintf(os.Stderr, "go: to switch to the latest unretracted version, run:\n\tgo get %s@latest", retractPath)
}
}

View File

@ -281,14 +281,14 @@ func reportError(q *query, err error) {
// TODO(bcmills): Use errors.As to unpack these errors instead of parsing
// strings with regular expressions.
patternRE := regexp.MustCompile("(?m)(?:[ \t(\"`]|^)" + regexp.QuoteMeta(q.pattern) + "(?:[ @:)\"`]|$)")
patternRE := regexp.MustCompile("(?m)(?:[ \t(\"`]|^)" + regexp.QuoteMeta(q.pattern) + "(?:[ @:;)\"`]|$)")
if patternRE.MatchString(errStr) {
if q.rawVersion == "" {
base.Errorf("go get: %s", errStr)
return
}
versionRE := regexp.MustCompile("(?m)(?:[ @(\"`]|^)" + regexp.QuoteMeta(q.version) + "(?:[ :)\"`]|$)")
versionRE := regexp.MustCompile("(?m)(?:[ @(\"`]|^)" + regexp.QuoteMeta(q.version) + "(?:[ :;)\"`]|$)")
if versionRE.MatchString(errStr) {
base.Errorf("go get: %s", errStr)
return

View File

@ -28,6 +28,11 @@ import (
//
var buildList []module.Version
// additionalExplicitRequirements is a list of modules paths for which
// WriteGoMod should record explicit requirements, even if they would be
// selected without those requirements. Each path must also appear in buildList.
var additionalExplicitRequirements []string
// capVersionSlice returns s with its cap reduced to its length.
func capVersionSlice(s []module.Version) []module.Version {
return s[:len(s):len(s)]
@ -121,6 +126,12 @@ func EditBuildList(ctx context.Context, add, mustSelect []module.Version) error
if !inconsistent {
buildList = final
additionalExplicitRequirements = make([]string, 0, len(mustSelect))
for _, m := range mustSelect {
if m.Version != "none" {
additionalExplicitRequirements = append(additionalExplicitRequirements, m.Path)
}
}
return nil
}

View File

@ -12,395 +12,16 @@ var HelpModules = &base.Command{
UsageLine: "modules",
Short: "modules, module versions, and more",
Long: `
A module is a collection of related Go packages.
Modules are the unit of source code interchange and versioning.
The go command has direct support for working with modules,
including recording and resolving dependencies on other modules.
Modules replace the old GOPATH-based approach to specifying
which source files are used in a given build.
Modules are how Go manages dependencies.
Module support
A module is a collection of packages that are released, versioned, and
distributed together. Modules may be downloaded directly from version control
repositories or from module proxy servers.
The go command includes support for Go modules. Module-aware mode is active
by default whenever a go.mod file is found in the current directory or in
any parent directory.
For a series of tutorials on modules, see
https://golang.org/doc/tutorial/create-module.
The quickest way to take advantage of module support is to check out your
repository, create a go.mod file (described in the next section) there, and run
go commands from within that file tree.
For more fine-grained control, the go command continues to respect
a temporary environment variable, GO111MODULE, which can be set to one
of three string values: off, on, or auto (the default).
If GO111MODULE=on, then the go command requires the use of modules,
never consulting GOPATH. We refer to this as the command
being module-aware or running in "module-aware mode".
If GO111MODULE=off, then the go command never uses
module support. Instead it looks in vendor directories and GOPATH
to find dependencies; we now refer to this as "GOPATH mode."
If GO111MODULE=auto or is unset, then the go command enables or disables
module support based on the current directory.
Module support is enabled only when the current directory contains a
go.mod file or is below a directory containing a go.mod file.
In module-aware mode, GOPATH no longer defines the meaning of imports
during a build, but it still stores downloaded dependencies (in GOPATH/pkg/mod)
and installed commands (in GOPATH/bin, unless GOBIN is set).
Defining a module
A module is defined by a tree of Go source files with a go.mod file
in the tree's root directory. The directory containing the go.mod file
is called the module root. Typically the module root will also correspond
to a source code repository root (but in general it need not).
The module is the set of all Go packages in the module root and its
subdirectories, but excluding subtrees with their own go.mod files.
The "module path" is the import path prefix corresponding to the module root.
The go.mod file defines the module path and lists the specific versions
of other modules that should be used when resolving imports during a build,
by giving their module paths and versions.
For example, this go.mod declares that the directory containing it is the root
of the module with path example.com/m, and it also declares that the module
depends on specific versions of golang.org/x/text and gopkg.in/yaml.v2:
module example.com/m
require (
golang.org/x/text v0.3.0
gopkg.in/yaml.v2 v2.1.0
)
The go.mod file can also specify replacements and excluded versions
that only apply when building the module directly; they are ignored
when the module is incorporated into a larger build.
For more about the go.mod file, see 'go help go.mod'.
To start a new module, simply create a go.mod file in the root of the
module's directory tree, containing only a module statement.
The 'go mod init' command can be used to do this:
go mod init example.com/m
In a project already using an existing dependency management tool like
godep, glide, or dep, 'go mod init' will also add require statements
matching the existing configuration.
Once the go.mod file exists, no additional steps are required:
go commands like 'go build', 'go test', or even 'go list' will automatically
add new dependencies as needed to satisfy imports.
The main module and the build list
The "main module" is the module containing the directory where the go command
is run. The go command finds the module root by looking for a go.mod in the
current directory, or else the current directory's parent directory,
or else the parent's parent directory, and so on.
The main module's go.mod file defines the precise set of packages available
for use by the go command, through require, replace, and exclude statements.
Dependency modules, found by following require statements, also contribute
to the definition of that set of packages, but only through their go.mod
files' require statements: any replace and exclude statements in dependency
modules are ignored. The replace and exclude statements therefore allow the
main module complete control over its own build, without also being subject
to complete control by dependencies.
The set of modules providing packages to builds is called the "build list".
The build list initially contains only the main module. Then the go command
adds to the list the exact module versions required by modules already
on the list, recursively, until there is nothing left to add to the list.
If multiple versions of a particular module are added to the list,
then at the end only the latest version (according to semantic version
ordering) is kept for use in the build.
The 'go list' command provides information about the main module
and the build list. For example:
go list -m # print path of main module
go list -m -f={{.Dir}} # print root directory of main module
go list -m all # print build list
Maintaining module requirements
The go.mod file is meant to be readable and editable by both programmers and
tools. Most updates to dependencies can be performed using "go get" and
"go mod tidy". Other module-aware build commands may be invoked using the
-mod=mod flag to automatically add missing requirements and fix inconsistencies.
The "go get" command updates go.mod to change the module versions used in a
build. An upgrade of one module may imply upgrading others, and similarly a
downgrade of one module may imply downgrading others. The "go get" command
makes these implied changes as well. See "go help module-get".
The "go mod" command provides other functionality for use in maintaining
and understanding modules and go.mod files. See "go help mod", particularly
"go help mod tidy" and "go help mod edit".
As part of maintaining the require statements in go.mod, the go command
tracks which ones provide packages imported directly by the current module
and which ones provide packages only used indirectly by other module
dependencies. Requirements needed only for indirect uses are marked with a
"// indirect" comment in the go.mod file. Indirect requirements may be
automatically removed from the go.mod file once they are implied by other
direct requirements. Indirect requirements only arise when using modules
that fail to state some of their own dependencies or when explicitly
upgrading a module's dependencies ahead of its own stated requirements.
The -mod build flag provides additional control over the updating and use of
go.mod for commands that build packages like "go build" and "go test".
If invoked with -mod=readonly (the default in most situations), the go command
reports an error if a package named on the command line or an imported package
is not provided by any module in the build list computed from the main module's
requirements. The go command also reports an error if a module's checksum is
missing from go.sum (see Module downloading and verification). Either go.mod or
go.sum must be updated in these situations.
If invoked with -mod=mod, the go command automatically updates go.mod and
go.sum, fixing inconsistencies and adding missing requirements and checksums
as needed. If the go command finds an unfamiliar import, it looks up the
module containing that import and adds a requirement for the latest version
of that module to go.mod. In most cases, therefore, one may add an import to
source code and run "go build", "go test", or even "go list" with -mod=mod:
as part of analyzing the package, the go command will resolve the import and
update the go.mod file.
If invoked with -mod=vendor, the go command loads packages from the main
module's vendor directory instead of downloading modules to and loading packages
from the module cache. The go command assumes the vendor directory holds
correct copies of dependencies, and it does not compute the set of required
module versions from go.mod files. However, the go command does check that
vendor/modules.txt (generated by "go mod vendor") contains metadata consistent
with go.mod.
If the go command is not invoked with a -mod flag, and the vendor directory
is present, and the "go" version in go.mod is 1.14 or higher, the go command
will act as if it were invoked with -mod=vendor. Otherwise, the -mod flag
defaults to -mod=readonly.
Note that neither "go get" nor the "go mod" subcommands accept the -mod flag.
Pseudo-versions
The go.mod file and the go command more generally use semantic versions as
the standard form for describing module versions, so that versions can be
compared to determine which should be considered earlier or later than another.
A module version like v1.2.3 is introduced by tagging a revision in the
underlying source repository. Untagged revisions can be referred to
using a "pseudo-version" like v0.0.0-yyyymmddhhmmss-abcdefabcdef,
where the time is the commit time in UTC and the final suffix is the prefix
of the commit hash. The time portion ensures that two pseudo-versions can
be compared to determine which happened later, the commit hash identifes
the underlying commit, and the prefix (v0.0.0- in this example) is derived from
the most recent tagged version in the commit graph before this commit.
There are three pseudo-version forms:
vX.0.0-yyyymmddhhmmss-abcdefabcdef is used when there is no earlier
versioned commit with an appropriate major version before the target commit.
(This was originally the only form, so some older go.mod files use this form
even for commits that do follow tags.)
vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef is used when the most
recent versioned commit before the target commit is vX.Y.Z-pre.
vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef is used when the most
recent versioned commit before the target commit is vX.Y.Z.
Pseudo-versions never need to be typed by hand: the go command will accept
the plain commit hash and translate it into a pseudo-version (or a tagged
version if available) automatically. This conversion is an example of a
module query.
Module queries
The go command accepts a "module query" in place of a module version
both on the command line and in the main module's go.mod file.
(After evaluating a query found in the main module's go.mod file,
the go command updates the file to replace the query with its result.)
A fully-specified semantic version, such as "v1.2.3",
evaluates to that specific version.
A semantic version prefix, such as "v1" or "v1.2",
evaluates to the latest available tagged version with that prefix.
A semantic version comparison, such as "<v1.2.3" or ">=v1.5.6",
evaluates to the available tagged version nearest to the comparison target
(the latest version for < and <=, the earliest version for > and >=).
The string "latest" matches the latest available tagged version,
or else the underlying source repository's latest untagged revision.
The string "upgrade" is like "latest", but if the module is
currently required at a later version than the version "latest"
would select (for example, a newer pre-release version), "upgrade"
will select the later version instead.
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.
For example, "<v1.2.3" will prefer to return "v1.2.2"
instead of "v1.2.3-pre1", even though "v1.2.3-pre1" is nearer
to the comparison target.
Module versions disallowed by exclude statements in the
main module's go.mod are considered unavailable and cannot
be returned by queries.
For example, these commands are all valid:
go get github.com/gorilla/mux@latest # same (@latest is default for 'go get')
go get github.com/gorilla/mux@v1.6.2 # records v1.6.2
go get github.com/gorilla/mux@e3702bed2 # records v1.6.2
go get github.com/gorilla/mux@c856192 # records v0.0.0-20180517173623-c85619274f5d
go get github.com/gorilla/mux@master # records current meaning of master
Module compatibility and semantic versioning
The go command requires that modules use semantic versions and expects that
the versions accurately describe compatibility: it assumes that v1.5.4 is a
backwards-compatible replacement for v1.5.3, v1.4.0, and even v1.0.0.
More generally the go command expects that packages follow the
"import compatibility rule", which says:
"If an old package and a new package have the same import path,
the new package must be backwards compatible with the old package."
Because the go command assumes the import compatibility rule,
a module definition can only set the minimum required version of one
of its dependencies: it cannot set a maximum or exclude selected versions.
Still, the import compatibility rule is not a guarantee: it may be that
v1.5.4 is buggy and not a backwards-compatible replacement for v1.5.3.
Because of this, the go command never updates from an older version
to a newer version of a module unasked.
In semantic versioning, changing the major version number indicates a lack
of backwards compatibility with earlier versions. To preserve import
compatibility, the go command requires that modules with major version v2
or later use a module path with that major version as the final element.
For example, version v2.0.0 of example.com/m must instead use module path
example.com/m/v2, and packages in that module would use that path as
their import path prefix, as in example.com/m/v2/sub/pkg. Including the
major version number in the module path and import paths in this way is
called "semantic import versioning". Pseudo-versions for modules with major
version v2 and later begin with that major version instead of v0, as in
v2.0.0-20180326061214-4fc5987536ef.
As a special case, module paths beginning with gopkg.in/ continue to use the
conventions established on that system: the major version is always present,
and it is preceded by a dot instead of a slash: gopkg.in/yaml.v1
and gopkg.in/yaml.v2, not gopkg.in/yaml and gopkg.in/yaml/v2.
The go command treats modules with different module paths as unrelated:
it makes no connection between example.com/m and example.com/m/v2.
Modules with different major versions can be used together in a build
and are kept separate by the fact that their packages use different
import paths.
In semantic versioning, major version v0 is for initial development,
indicating no expectations of stability or backwards compatibility.
Major version v0 does not appear in the module path, because those
versions are preparation for v1.0.0, and v1 does not appear in the
module path either.
Code written before the semantic import versioning convention
was introduced may use major versions v2 and later to describe
the same set of unversioned import paths as used in v0 and v1.
To accommodate such code, if a source code repository has a
v2.0.0 or later tag for a file tree with no go.mod, the version is
considered to be part of the v1 module's available versions
and is given an +incompatible suffix when converted to a module
version, as in v2.0.0+incompatible. The +incompatible tag is also
applied to pseudo-versions derived from such versions, as in
v2.0.1-0.yyyymmddhhmmss-abcdefabcdef+incompatible.
In general, having a dependency in the build list (as reported by 'go list -m all')
on a v0 version, pre-release version, pseudo-version, or +incompatible version
is an indication that problems are more likely when upgrading that
dependency, since there is no expectation of compatibility for those.
See https://research.swtch.com/vgo-import for more information about
semantic import versioning, and see https://semver.org/ for more about
semantic versioning.
Module code layout
For now, see https://research.swtch.com/vgo-module for information
about how source code in version control systems is mapped to
module file trees.
Module downloading and verification
The go command can fetch modules from a proxy or connect to source control
servers directly, according to the setting of the GOPROXY environment
variable (see 'go help env'). The default setting for GOPROXY is
"https://proxy.golang.org,direct", which means to try the
Go module mirror run by Google and fall back to a direct connection
if the proxy reports that it does not have the module (HTTP error 404 or 410).
See https://proxy.golang.org/privacy for the service's privacy policy.
If GOPROXY is set to the string "direct", downloads use a direct connection to
source control servers. Setting GOPROXY to "off" disallows downloading modules
from any source. Otherwise, GOPROXY is expected to be list of module proxy URLs
separated by either comma (,) or pipe (|) characters, which control error
fallback behavior. For each request, the go command tries each proxy in
sequence. If there is an error, the go command will try the next proxy in the
list if the error is a 404 or 410 HTTP response or if the current proxy is
followed by a pipe character, indicating it is safe to fall back on any error.
The GOPRIVATE and GONOPROXY environment variables allow bypassing
the proxy for selected modules. See 'go help private' for details.
No matter the source of the modules, the go command checks downloads against
known checksums, to detect unexpected changes in the content of any specific
module version from one day to the next. This check first consults the current
module's go.sum file but falls back to the Go checksum database, controlled by
the GOSUMDB and GONOSUMDB environment variables. See 'go help module-auth'
for details.
See 'go help goproxy' for details about the proxy protocol and also
the format of the cached downloaded packages.
Modules and vendoring
When using modules, the go command typically satisfies dependencies by
downloading modules from their sources and using those downloaded copies
(after verification, as described in the previous section). Vendoring may
be used to allow interoperation with older versions of Go, or to ensure
that all files used for a build are stored together in a single file tree.
The command 'go mod vendor' constructs a directory named vendor in the main
module's root directory that contains copies of all packages needed to support
builds and tests of packages in the main module. 'go mod vendor' also
creates the file vendor/modules.txt that contains metadata about vendored
packages and module versions. This file should be kept consistent with go.mod:
when vendoring is used, 'go mod vendor' should be run after go.mod is updated.
If the vendor directory is present in the main module's root directory, it will
be used automatically if the "go" version in the main module's go.mod file is
1.14 or higher. Build commands like 'go build' and 'go test' will load packages
from the vendor directory instead of accessing the network or the local module
cache. To explicitly enable vendoring, invoke the go command with the flag
-mod=vendor. To disable vendoring, use the flag -mod=mod.
Unlike vendoring in GOPATH, the go command ignores vendor directories in
locations other than the main module's root directory.
For a detailed reference on modules, see https://golang.org/ref/mod.
`,
}
@ -413,87 +34,22 @@ file in its root. When the go command is run, it looks in the current
directory and then successive parent directories to find the go.mod
marking the root of the main (current) module.
The go.mod file itself is line-oriented, with // comments but
no /* */ comments. Each line holds a single directive, made up of a
verb followed by arguments. For example:
The go.mod file format is described in detail at
https://golang.org/ref/mod#go-mod-file.
module my/thing
go 1.12
require other/thing v1.0.2
require new/thing/v2 v2.3.4
exclude old/thing v1.2.3
replace bad/thing v1.4.5 => good/thing v1.4.5
retract v1.5.6
To create a new go.mod file, use 'go help init'. For details see
'go help mod init' or https://golang.org/ref/mod#go-mod-init.
The verbs are
module, to define the module path;
go, to set the expected language version;
require, to require a particular module at a given version or later;
exclude, to exclude a particular module version from use;
replace, to replace a module version with a different module version; and
retract, to indicate a previously released version should not be used.
Exclude and replace apply only in the main module's go.mod and are ignored
in dependencies. See https://golang.org/ref/mod for details.
To add missing module requirements or remove unneeded requirements,
use 'go mod tidy'. For details, see 'go help mod tidy' or
https://golang.org/ref/mod#go-mod-tidy.
The leading verb can be factored out of adjacent lines to create a block,
like in Go imports:
To add, upgrade, downgrade, or remove a specific module requirement, use
'go get'. For details, see 'go help module-get' or
https://golang.org/ref/mod#go-get.
require (
new/thing/v2 v2.3.4
old/thing v1.2.3
)
The go.mod file is designed both to be edited directly and to be
easily updated by tools. The 'go mod edit' command can be used to
parse and edit the go.mod file from programs and tools.
See 'go help mod edit'.
The go command automatically updates go.mod each time it uses the
module graph, to make sure go.mod always accurately reflects reality
and is properly formatted. For example, consider this go.mod file:
module M
require (
A v1
B v1.0.0
C v1.0.0
D v1.2.3
E dev
)
exclude D v1.2.3
The update rewrites non-canonical version identifiers to semver form,
so A's v1 becomes v1.0.0 and E's dev becomes the pseudo-version for the
latest commit on the dev branch, perhaps v0.0.0-20180523231146-b3f5c0f6e5f1.
The update modifies requirements to respect exclusions, so the
requirement on the excluded D v1.2.3 is updated to use the next
available version of D, perhaps D v1.2.4 or D v1.3.0.
The update removes redundant or misleading requirements.
For example, if A v1.0.0 itself requires B v1.2.0 and C v1.0.0,
then go.mod's requirement of B v1.0.0 is misleading (superseded by
A's need for v1.2.0), and its requirement of C v1.0.0 is redundant
(implied by A's need for the same version), so both will be removed.
If module M contains packages that directly import packages from B or
C, then the requirements will be kept but updated to the actual
versions being used.
Finally, the update reformats the go.mod in a canonical formatting, so
that future mechanical changes will result in minimal diffs.
Because the module graph defines the meaning of import statements, any
commands that load packages also use and therefore update go.mod,
including go build, go get, go install, go list, go test, go mod graph,
go mod tidy, and go mod why.
The expected language version, set by the go directive, determines
which language features are available when compiling the module.
Language features available in that version will be available for use.
Language features removed in earlier versions, or added in later versions,
will not be available. Note that the language version does not affect
build tags, which are determined by the Go release being used.
To make other changes or to parse go.mod as JSON for use by other tools,
use 'go mod edit'. See 'go help mod edit' or
https://golang.org/ref/mod#go-mod-edit.
`,
}

View File

@ -31,10 +31,6 @@ type ImportMissingError struct {
Module module.Version
QueryErr error
// inAll indicates whether Path is in the "all" package pattern,
// and thus would be added by 'go mod tidy'.
inAll bool
// isStd indicates whether we would expect to find the package in the standard
// library. This is normally true for all dotless import paths, but replace
// directives can cause us to treat the replaced paths as also being in
@ -58,7 +54,7 @@ func (e *ImportMissingError) Error() string {
if e.QueryErr != nil {
return fmt.Sprintf("cannot find module providing package %s: %v", e.Path, e.QueryErr)
}
if cfg.BuildMod == "mod" {
if cfg.BuildMod == "mod" || (cfg.BuildMod == "readonly" && allowMissingModuleImports) {
return "cannot find module providing package " + e.Path
}
@ -67,16 +63,14 @@ func (e *ImportMissingError) Error() string {
if !modfetch.IsZeroPseudoVersion(e.replaced.Version) {
suggestArg = e.replaced.String()
}
return fmt.Sprintf("module %s provides package %s and is replaced but not required; try 'go get -d %s' to add it", e.replaced.Path, e.Path, suggestArg)
return fmt.Sprintf("module %s provides package %s and is replaced but not required; to add it:\n\tgo get %s", e.replaced.Path, e.Path, suggestArg)
}
suggestion := ""
if !HasModRoot() {
suggestion = ": working directory is not part of a module"
} else if e.inAll {
suggestion = "; try 'go mod tidy' to add it"
} else {
suggestion = fmt.Sprintf("; try 'go get -d %s' to add it", e.Path)
suggestion = fmt.Sprintf("; to add it:\n\tgo get %s", e.Path)
}
return fmt.Sprintf("no required module provides package %s%s", e.Path, suggestion)
}
@ -136,24 +130,57 @@ func (e *AmbiguousImportError) Error() string {
}
// ImportMissingSumError is reported in readonly mode when we need to check
// if a module in the build list contains a package, but we don't have a sum
// for its .zip file.
// if a module contains a package, but we don't have a sum for its .zip file.
// We might need sums for multiple modules to verify the package is unique.
//
// TODO(#43653): consolidate multiple errors of this type into a single error
// that suggests a 'go get' command for root packages that transtively import
// packages from modules with missing sums. load.CheckPackageErrors would be
// a good place to consolidate errors, but we'll need to attach the import
// stack here.
type ImportMissingSumError struct {
importPath string
found, inAll bool
importPath string
found bool
mods []module.Version
importer, importerVersion string // optional, but used for additional context
importerIsTest bool
}
func (e *ImportMissingSumError) Error() string {
var importParen string
if e.importer != "" {
importParen = fmt.Sprintf(" (imported by %s)", e.importer)
}
var message string
if e.found {
message = fmt.Sprintf("missing go.sum entry needed to verify package %s is provided by exactly one module", e.importPath)
message = fmt.Sprintf("missing go.sum entry needed to verify package %s%s is provided by exactly one module", e.importPath, importParen)
} else {
message = fmt.Sprintf("missing go.sum entry for module providing package %s", e.importPath)
message = fmt.Sprintf("missing go.sum entry for module providing package %s%s", e.importPath, importParen)
}
if e.inAll {
return message + "; try 'go mod tidy' to add it"
var hint string
if e.importer == "" {
// Importing package is unknown, or the missing package was named on the
// command line. Recommend 'go mod download' for the modules that could
// provide the package, since that shouldn't change go.mod.
args := make([]string, len(e.mods))
for i, mod := range e.mods {
args[i] = mod.Path
}
hint = fmt.Sprintf("; to add:\n\tgo mod download %s", strings.Join(args, " "))
} else {
// Importing package is known (common case). Recommend 'go get' on the
// current version of the importing package.
tFlag := ""
if e.importerIsTest {
tFlag = " -t"
}
version := ""
if e.importerVersion != "" {
version = "@" + e.importerVersion
}
hint = fmt.Sprintf("; to add:\n\tgo get%s %s%s", tFlag, e.importer, version)
}
return message
return message + hint
}
func (e *ImportMissingSumError) ImportPath() string {
@ -244,7 +271,7 @@ func importFromBuildList(ctx context.Context, path string, buildList []module.Ve
// Check each module on the build list.
var dirs []string
var mods []module.Version
haveSumErr := false
var sumErrMods []module.Version
for _, m := range buildList {
if !maybeInModule(path, m.Path) {
// Avoid possibly downloading irrelevant modules.
@ -257,8 +284,9 @@ func importFromBuildList(ctx context.Context, path string, buildList []module.Ve
// We are missing a sum needed to fetch a module in the build list.
// We can't verify that the package is unique, and we may not find
// the package at all. Keep checking other modules to decide which
// error to report.
haveSumErr = true
// error to report. Multiple sums may be missing if we need to look in
// multiple nested modules to resolve the import.
sumErrMods = append(sumErrMods, m)
continue
}
// Report fetch error.
@ -279,8 +307,12 @@ func importFromBuildList(ctx context.Context, path string, buildList []module.Ve
if len(mods) > 1 {
return module.Version{}, "", &AmbiguousImportError{importPath: path, Dirs: dirs, Modules: mods}
}
if haveSumErr {
return module.Version{}, "", &ImportMissingSumError{importPath: path, found: len(mods) > 0}
if len(sumErrMods) > 0 {
return module.Version{}, "", &ImportMissingSumError{
importPath: path,
mods: sumErrMods,
found: len(mods) > 0,
}
}
if len(mods) == 1 {
return mods[0], dirs[0], nil
@ -365,7 +397,7 @@ func queryImport(ctx context.Context, path string) (module.Version, error) {
return module.Version{}, &ImportMissingError{Path: path, isStd: true}
}
if cfg.BuildMod == "readonly" {
if cfg.BuildMod == "readonly" && !allowMissingModuleImports {
// In readonly mode, we can't write go.mod, so we shouldn't try to look up
// the module. If readonly mode was enabled explicitly, include that in
// the error message.
@ -547,7 +579,7 @@ func fetch(ctx context.Context, mod module.Version, needSum bool) (dir string, i
mod = r
}
if cfg.BuildMod == "readonly" && needSum && !modfetch.HaveSum(mod) {
if HasModRoot() && cfg.BuildMod == "readonly" && needSum && !modfetch.HaveSum(mod) {
return "", false, module.VersionError(mod, &sumMissingError{})
}

View File

@ -58,10 +58,15 @@ var importTests = []struct {
func TestQueryImport(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
testenv.MustHaveExecPath(t, "git")
defer func(old bool) {
allowMissingModuleImports = old
}(allowMissingModuleImports)
AllowMissingModuleImports()
oldAllowMissingModuleImports := allowMissingModuleImports
oldRootMode := RootMode
defer func() {
allowMissingModuleImports = oldAllowMissingModuleImports
RootMode = oldRootMode
}()
allowMissingModuleImports = true
RootMode = NoRoot
ctx := context.Background()

View File

@ -15,6 +15,7 @@ import (
"os"
"path"
"path/filepath"
"sort"
"strconv"
"strings"
"sync"
@ -27,6 +28,7 @@ import (
"cmd/go/internal/modfetch"
"cmd/go/internal/mvs"
"cmd/go/internal/search"
"cmd/go/internal/str"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
@ -200,6 +202,8 @@ func Init() {
}
// We're in module mode. Set any global variables that need to be set.
cfg.ModulesEnabled = true
setDefaultBuildMod()
list := filepath.SplitList(cfg.BuildContext.GOPATH)
if len(list) == 0 || list[0] == "" {
base.Fatalf("missing $GOPATH")
@ -209,8 +213,6 @@ func Init() {
base.Fatalf("$GOPATH/go.mod exists but should not")
}
cfg.ModulesEnabled = true
if modRoot == "" {
// We're in module mode, but not inside a module.
//
@ -346,8 +348,8 @@ func die() {
// ensuring requirements are consistent. WriteGoMod should be called later to
// write changes out to disk or report errors in readonly mode.
//
// As a side-effect, LoadModFile sets a default for cfg.BuildMod if it does not
// already have an explicit value.
// As a side-effect, LoadModFile may change cfg.BuildMod to "vendor" if
// -mod wasn't set explicitly and automatic vendoring should be enabled.
func LoadModFile(ctx context.Context) {
if len(buildList) > 0 {
return
@ -378,14 +380,14 @@ func LoadModFile(ctx context.Context) {
if f.Module == nil {
// No module declaration. Must add module path.
base.Fatalf("go: no module declaration in go.mod.\n\tRun 'go mod edit -module=example.com/mod' to specify the module path.")
base.Fatalf("go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod")
}
if err := checkModulePathLax(f.Module.Mod.Path); err != nil {
base.Fatalf("go: %v", err)
}
setDefaultBuildMod()
setDefaultBuildMod() // possibly enable automatic vendoring
modFileToBuildList()
if cfg.BuildMod == "vendor" {
readVendorList()
@ -456,7 +458,7 @@ func CreateModFile(ctx context.Context, modPath string) {
}
}
if !empty {
fmt.Fprintf(os.Stderr, "go: run 'go mod tidy' to add module requirements and sums\n")
fmt.Fprintf(os.Stderr, "go: to add module requirements and sums:\n\tgo mod tidy\n")
}
}
@ -584,8 +586,8 @@ func modFileToBuildList() {
buildList = list
}
// setDefaultBuildMod sets a default value for cfg.BuildMod
// if it is currently empty.
// setDefaultBuildMod sets a default value for cfg.BuildMod if the -mod flag
// wasn't provided. setDefaultBuildMod may be called multiple times.
func setDefaultBuildMod() {
if cfg.BuildModExplicit {
// Don't override an explicit '-mod=' argument.
@ -606,7 +608,7 @@ func setDefaultBuildMod() {
if fi, err := fsys.Stat(filepath.Join(modRoot, "vendor")); err == nil && fi.IsDir() {
modGo := "unspecified"
if index.goVersionV != "" {
if index != nil && index.goVersionV != "" {
if semver.Compare(index.goVersionV, "v1.14") >= 0 {
// The Go version is at least 1.14, and a vendor directory exists.
// Set -mod=vendor by default.
@ -845,13 +847,15 @@ func AllowWriteGoMod() {
// MinReqs returns a Reqs with minimal additional dependencies of Target,
// as will be written to go.mod.
func MinReqs() mvs.Reqs {
var retain []string
retain := append([]string{}, additionalExplicitRequirements...)
for _, m := range buildList[1:] {
_, explicit := index.require[m]
if explicit || loaded.direct[m.Path] {
retain = append(retain, m.Path)
}
}
sort.Strings(retain)
str.Uniq(&retain)
min, err := mvs.Req(Target, retain, &mvsReqs{buildList: buildList})
if err != nil {
base.Fatalf("go: %v", err)
@ -903,7 +907,7 @@ func WriteGoMod() {
} else if cfg.BuildModReason != "" {
base.Fatalf("go: updates to go.mod needed, disabled by -mod=readonly\n\t(%s)", cfg.BuildModReason)
} else {
base.Fatalf("go: updates to go.mod needed; try 'go mod tidy' first")
base.Fatalf("go: updates to go.mod needed; to update it:\n\tgo mod tidy")
}
}
@ -972,9 +976,12 @@ func WriteGoMod() {
// It also contains entries for go.mod files needed for MVS (the version
// of these entries ends with "/go.mod").
//
// If addDirect is true, the set also includes sums for modules directly
// required by go.mod, as represented by the index, with replacements applied.
func keepSums(addDirect bool) map[module.Version]bool {
// If keepBuildListZips is true, the set also includes sums for zip files for
// all modules in the build list with replacements applied. 'go get' and
// 'go mod download' may add sums to this set when adding a requirement on a
// module without a root package or when downloading a direct or indirect
// dependency.
func keepSums(keepBuildListZips bool) map[module.Version]bool {
// Re-derive the build list using the current list of direct requirements.
// Keep the sum for the go.mod of each visited module version (or its
// replacement).
@ -1003,19 +1010,20 @@ func keepSums(addDirect bool) map[module.Version]bool {
panic(fmt.Sprintf("unexpected error reloading build list: %v", err))
}
actualMods := make(map[string]module.Version)
for _, m := range buildList[1:] {
if r := Replacement(m); r.Path != "" {
actualMods[m.Path] = r
} else {
actualMods[m.Path] = m
}
}
// Add entries for modules in the build list with paths that are prefixes of
// paths of loaded packages. We need to retain sums for modules needed to
// report ambiguous import errors. We use our re-derived build list,
// since the global build list may have been tidied.
if loaded != nil {
actualMods := make(map[string]module.Version)
for _, m := range buildList[1:] {
if r := Replacement(m); r.Path != "" {
actualMods[m.Path] = r
} else {
actualMods[m.Path] = m
}
}
for _, pkg := range loaded.pkgs {
if pkg.testOf != nil || pkg.inStd || module.CheckImportPath(pkg.path) != nil {
continue
@ -1028,17 +1036,13 @@ func keepSums(addDirect bool) map[module.Version]bool {
}
}
// Add entries for modules directly required by go.mod.
if addDirect {
for m := range index.require {
var kept module.Version
if r := Replacement(m); r.Path != "" {
kept = r
} else {
kept = m
}
keep[kept] = true
keep[module.Version{Path: kept.Path, Version: kept.Version + "/go.mod"}] = true
// Add entries for the zip of each module in the build list.
// We might not need all of these (tidy does not add them), but they may be
// added by a specific 'go get' or 'go mod download' command to resolve
// missing import sum errors.
if keepBuildListZips {
for _, m := range actualMods {
keep[m] = true
}
}
@ -1058,9 +1062,8 @@ func (r *keepSumReqs) Required(m module.Version) ([]module.Version, error) {
}
func TrimGoSum() {
// Don't retain sums for direct requirements in go.mod. When TrimGoSum is
// called, go.mod has not been updated, and it may contain requirements on
// modules deleted from the build list.
addDirect := false
modfetch.TrimGoSum(keepSums(addDirect))
// Don't retain sums for the zip file of every module in the build list.
// We may not need them all to build the main module's packages.
keepBuildListZips := false
modfetch.TrimGoSum(keepSums(keepBuildListZips))
}

View File

@ -280,11 +280,11 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
checkMultiplePaths()
for _, pkg := range loaded.pkgs {
if pkg.err != nil {
if pkg.flags.has(pkgInAll) {
if imErr := (*ImportMissingError)(nil); errors.As(pkg.err, &imErr) {
imErr.inAll = true
} else if sumErr := (*ImportMissingSumError)(nil); errors.As(pkg.err, &sumErr) {
sumErr.inAll = true
if sumErr := (*ImportMissingSumError)(nil); errors.As(pkg.err, &sumErr) {
if importer := pkg.stack; importer != nil {
sumErr.importer = importer.path
sumErr.importerVersion = importer.mod.Version
sumErr.importerIsTest = importer.testOf != nil
}
}
@ -863,12 +863,21 @@ func loadFromRoots(params loaderParams) *loader {
for _, pkg := range ld.pkgs {
if pkg.mod == Target {
for _, dep := range pkg.imports {
if dep.mod.Path != "" {
if dep.mod.Path != "" && dep.mod.Path != Target.Path && index != nil {
_, explicit := index.require[dep.mod]
if allowWriteGoMod && cfg.BuildMod == "readonly" && !explicit {
// TODO(#40775): attach error to package instead of using
// base.Errorf. Ideally, 'go list' should not fail because of this,
// but today, LoadPackages calls WriteGoMod unconditionally, which
// would fail with a less clear message.
base.Errorf("go: %[1]s: package %[2]s imported from implicitly required module; to add missing requirements, run:\n\tgo get %[2]s@%[3]s", pkg.path, dep.path, dep.mod.Version)
}
ld.direct[dep.mod.Path] = true
}
}
}
}
base.ExitIfErrors()
// If we didn't scan all of the imports from the main module, or didn't use
// imports.AnyTags, then we didn't necessarily load every package that

View File

@ -446,10 +446,10 @@ func goModSummary(m module.Version) (*modFileSummary, error) {
if actual.Path == "" {
actual = m
}
if cfg.BuildMod == "readonly" && actual.Version != "" {
if HasModRoot() && cfg.BuildMod == "readonly" && actual.Version != "" {
key := module.Version{Path: actual.Path, Version: actual.Version + "/go.mod"}
if !modfetch.HaveSum(key) {
suggestion := fmt.Sprintf("; try 'go mod download %s' to add it", m.Path)
suggestion := fmt.Sprintf("; to add it:\n\tgo mod download %s", m.Path)
return nil, module.VersionError(actual, &sumMissingError{suggestion: suggestion})
}
}

View File

@ -111,19 +111,3 @@ func (*mvsReqs) Previous(m module.Version) (module.Version, error) {
}
return module.Version{Path: m.Path, Version: "none"}, nil
}
// next returns the next version of m.Path after m.Version.
// It is only used by the exclusion processing in the Required method,
// not called directly by MVS.
func (*mvsReqs) next(m module.Version) (module.Version, error) {
// TODO(golang.org/issue/38714): thread tracing context through MVS.
list, err := versions(context.TODO(), m.Path, CheckAllowed)
if err != nil {
return module.Version{}, err
}
i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) > 0 })
if i < len(list) {
return module.Version{Path: m.Path, Version: list[i]}, nil
}
return module.Version{Path: m.Path, Version: "none"}, nil
}

View File

@ -21,6 +21,7 @@ import (
"cmd/go/internal/imports"
"cmd/go/internal/modfetch"
"cmd/go/internal/search"
"cmd/go/internal/str"
"cmd/go/internal/trace"
"golang.org/x/mod/module"
@ -1005,13 +1006,8 @@ func (rr *replacementRepo) Versions(prefix string) ([]string, error) {
sort.Slice(versions, func(i, j int) bool {
return semver.Compare(versions[i], versions[j]) < 0
})
uniq := versions[:1]
for _, v := range versions {
if v != uniq[len(uniq)-1] {
uniq = append(uniq, v)
}
}
return uniq, nil
str.Uniq(&versions)
return versions, nil
}
func (rr *replacementRepo) Stat(rev string) (*modfetch.RevInfo, error) {

View File

@ -214,6 +214,6 @@ func checkVendorConsistency() {
}
if vendErrors.Len() > 0 {
base.Fatalf("go: inconsistent vendoring in %s:%s\n\nrun 'go mod vendor' to sync, or use -mod=mod or -mod=readonly to ignore the vendor directory", modRoot, vendErrors)
base.Fatalf("go: inconsistent vendoring in %s:%s\n\n\tTo ignore the vendor directory, use -mod=readonly or -mod=mod.\n\tTo sync the vendor directory, run:\n\t\tgo mod vendor", modRoot, vendErrors)
}
}

View File

@ -96,6 +96,20 @@ func Contains(x []string, s string) bool {
return false
}
// Uniq removes consecutive duplicate strings from ss.
func Uniq(ss *[]string) {
if len(*ss) <= 1 {
return
}
uniq := (*ss)[:1]
for _, s := range *ss {
if s != uniq[len(uniq)-1] {
uniq = append(uniq, s)
}
}
*ss = uniq
}
func isSpaceByte(c byte) bool {
return c == ' ' || c == '\t' || c == '\n' || c == '\r'
}

View File

@ -9,9 +9,9 @@ package main
import (
"bytes"
"flag"
exec "internal/execabs"
"log"
"os"
"os/exec"
"strings"
"testing"
"text/template"

View File

@ -11,10 +11,10 @@ import (
"errors"
"fmt"
"go/build"
exec "internal/execabs"
"io"
"io/fs"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"

View File

@ -325,7 +325,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
if !testC {
buildFlag = "-i"
}
fmt.Fprintf(os.Stderr, "flag %s is not a 'go test' flag (unknown flags cannot be used with %s)\n", firstUnknownFlag, buildFlag)
fmt.Fprintf(os.Stderr, "go test: unknown flag %s cannot be used with %s\n", firstUnknownFlag, buildFlag)
exitWithUsage()
}

View File

@ -8,8 +8,9 @@ package tool
import (
"context"
"fmt"
exec "internal/execabs"
"os"
"os/exec"
"os/signal"
"sort"
"strings"
@ -85,7 +86,19 @@ func runTool(ctx context.Context, cmd *base.Command, args []string) {
Stdout: os.Stdout,
Stderr: os.Stderr,
}
err := toolCmd.Run()
err := toolCmd.Start()
if err == nil {
c := make(chan os.Signal, 100)
signal.Notify(c)
go func() {
for sig := range c {
toolCmd.Process.Signal(sig)
}
}()
err = toolCmd.Wait()
signal.Stop(c)
close(c)
}
if err != nil {
// Only print about the exit status if the command
// didn't even run (not an ExitError) or it didn't exit cleanly

View File

@ -8,13 +8,13 @@ import (
"encoding/json"
"errors"
"fmt"
exec "internal/execabs"
"internal/lazyregexp"
"internal/singleflight"
"io/fs"
"log"
urlpkg "net/url"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
@ -729,7 +729,7 @@ func checkGOVCS(vcs *Cmd, root string) error {
if private {
what = "private"
}
return fmt.Errorf("GOVCS disallows using %s for %s %s", vcs.Cmd, what, root)
return fmt.Errorf("GOVCS disallows using %s for %s %s; see 'go help vcs'", vcs.Cmd, what, root)
}
return nil

View File

@ -10,9 +10,9 @@ import (
"errors"
"flag"
"fmt"
exec "internal/execabs"
"log"
"os"
"os/exec"
"path/filepath"
"strings"

View File

@ -9,9 +9,9 @@ import (
"errors"
"fmt"
"go/build"
exec "internal/execabs"
"internal/goroot"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
@ -113,7 +113,10 @@ and test commands:
created with -buildmode=shared.
-mod mode
module download mode to use: readonly, vendor, or mod.
See 'go help modules' for more.
By default, if a vendor directory is present and the go version in go.mod
is 1.14 or higher, the go command acts as if -mod=vendor were set.
Otherwise, the go command acts as if -mod=readonly were set.
See https://golang.org/ref/mod#build-commands for details.
-modcacherw
leave newly-created directories in the module cache read-write
instead of making them read-only.

View File

@ -7,8 +7,8 @@ package work
import (
"bytes"
"fmt"
exec "internal/execabs"
"os"
"os/exec"
"strings"
"cmd/go/internal/base"

View File

@ -13,13 +13,13 @@ import (
"encoding/json"
"errors"
"fmt"
exec "internal/execabs"
"internal/lazyregexp"
"io"
"io/fs"
"log"
"math/rand"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
@ -1166,6 +1166,7 @@ func (b *Builder) vet(ctx context.Context, a *Action) error {
return err
}
// TODO(rsc): Why do we pass $GCCGO to go vet?
env := b.cCompilerEnv()
if cfg.BuildToolchainName == "gccgo" {
env = append(env, "GCCGO="+BuildToolchain.compiler())
@ -2046,6 +2047,9 @@ func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...interfa
var buf bytes.Buffer
cmd := exec.Command(cmdline[0], cmdline[1:]...)
if cmd.Path != "" {
cmd.Args[0] = cmd.Path
}
cmd.Stdout = &buf
cmd.Stderr = &buf
cleanup := passLongArgsInResponseFiles(cmd)
@ -2437,7 +2441,7 @@ func (b *Builder) fcExe() []string {
func (b *Builder) compilerExe(envValue string, def string) []string {
compiler := strings.Fields(envValue)
if len(compiler) == 0 {
compiler = []string{def}
compiler = strings.Fields(def)
}
return compiler
}
@ -2589,7 +2593,14 @@ func (b *Builder) gccArchArgs() []string {
case "386":
return []string{"-m32"}
case "amd64":
if cfg.Goos == "darwin" {
return []string{"-arch", "x86_64", "-m64"}
}
return []string{"-m64"}
case "arm64":
if cfg.Goos == "darwin" {
return []string{"-arch", "arm64"}
}
case "arm":
return []string{"-marm"} // not thumb
case "s390x":
@ -2721,7 +2732,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
for i, f := range cgoLDFLAGS {
flags[i] = strconv.Quote(f)
}
cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")}
cgoenv = append(cgoenv, "CGO_LDFLAGS="+strings.Join(flags, " "))
}
if cfg.BuildToolchainName == "gccgo" {

View File

@ -6,8 +6,8 @@ package work
import (
"fmt"
exec "internal/execabs"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
@ -93,6 +93,12 @@ func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg,
args = append(args, "-I", root)
}
}
if embedcfg != nil && b.gccSupportsFlag(args[:1], "-fgo-embedcfg=/dev/null") {
if err := b.writeFile(objdir+"embedcfg", embedcfg); err != nil {
return "", nil, err
}
args = append(args, "-fgo-embedcfg="+objdir+"embedcfg")
}
if b.gccSupportsFlag(args[:1], "-ffile-prefix-map=a=b") {
if cfg.BuildTrimpath {

View File

@ -25,7 +25,7 @@ import (
"io/fs"
"log"
"os"
"os/exec"
exec "internal/execabs"
"path/filepath"
"strings"

View File

@ -2,7 +2,7 @@
# embedded in a package, that is referenced by a Go assembly function.
# See issue 33139.
[!gc] skip
[!exec:cc] skip
[!cgo] skip
# External linking is not supported on linux/ppc64.
# See: https://github.com/golang/go/issues/8912

View File

@ -19,7 +19,7 @@ stderr 'malformed module path "x/y.z": missing dot in first path element'
! go build ./useappengine
stderr '^useappengine[/\\]x.go:2:8: cannot find package$'
! go build ./usenonexistent
stderr '^usenonexistent[/\\]x.go:2:8: no required module provides package nonexistent.rsc.io; try ''go mod tidy'' to add it$'
stderr '^usenonexistent[/\\]x.go:2:8: no required module provides package nonexistent.rsc.io; to add it:\n\tgo get nonexistent.rsc.io$'
# 'get -d' should be similarly definitive

View File

@ -21,6 +21,12 @@ cmpenv go.mod $WORK/go.mod.edit1
go mod edit -droprequire=x.1 -dropexclude=x.1@v1.2.1 -dropreplace=x.1@v1.3.0 -require=x.3@v1.99.0 -dropretract=v1.0.0 -dropretract=[v1.1.0,v1.2.0]
cmpenv go.mod $WORK/go.mod.edit2
# -exclude and -retract reject invalid versions.
! go mod edit -exclude=example.com/m@bad
stderr '^go mod: -exclude=example.com/m@bad: version "bad" invalid: must be of the form v1.2.3$'
! go mod edit -retract=bad
stderr '^go mod: -retract=bad: version "bad" invalid: must be of the form v1.2.3$'
# go mod edit -json
go mod edit -json
cmpenv stdout $WORK/go.mod.json

View File

@ -6,5 +6,5 @@ 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://proxy.golang.org/golang.org/x/tools/@v/list'
! stderr '# get https://golang.org'

View File

@ -19,7 +19,7 @@ exec $WORK/testimport$GOEXE other/x/y/z/w .
stdout w2.go
! exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
stderr 'no required module provides package gobuild.example.com/x/y/z/w; try ''go get -d gobuild.example.com/x/y/z/w'' to add it'
stderr 'no required module provides package gobuild.example.com/x/y/z/w; to add it:\n\tgo get gobuild.example.com/x/y/z/w'
cd z
exec $WORK/testimport$GOEXE other/x/y/z/w .

View File

@ -39,7 +39,7 @@ stdout example.com/notfound
# Listing the missing dependency directly should fail outright...
! go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}}' example.com/notfound
stderr 'no required module provides package example.com/notfound; try ''go get -d example.com/notfound'' to add it'
stderr 'no required module provides package example.com/notfound; to add it:\n\tgo get example.com/notfound'
! stdout error
! stdout incomplete

View File

@ -13,7 +13,7 @@ cmp go.mod go.mod.empty
# -mod=readonly should be set by default.
env GOFLAGS=
! go list all
stderr '^x.go:2:8: no required module provides package rsc\.io/quote; try ''go mod tidy'' to add it$'
stderr '^x.go:2:8: no required module provides package rsc\.io/quote; to add it:\n\tgo get rsc\.io/quote$'
cmp go.mod go.mod.empty
env GOFLAGS=-mod=readonly
@ -51,7 +51,7 @@ cmp go.mod go.mod.inconsistent
# We get a different message when -mod=readonly is used by default.
env GOFLAGS=
! go list
stderr '^go: updates to go.mod needed; try ''go mod tidy'' first$'
stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy'
# However, it should not reject files missing a 'go' directive,
# since that was not always required.
@ -75,15 +75,15 @@ cmp go.mod go.mod.indirect
cp go.mod.untidy go.mod
! go list all
stderr '^x.go:2:8: no required module provides package rsc.io/quote; try ''go mod tidy'' to add it$'
stderr '^x.go:2:8: no required module provides package rsc.io/quote; to add it:\n\tgo get rsc.io/quote$'
! go list -deps .
stderr '^x.go:2:8: no required module provides package rsc.io/quote; try ''go mod tidy'' to add it$'
stderr '^x.go:2:8: no required module provides package rsc.io/quote; to add it:\n\tgo get rsc.io/quote$'
# However, if we didn't see an import from the main module, we should suggest
# 'go get -d' instead, because we don't know whether 'go mod tidy' would add it.
! go list rsc.io/quote
stderr '^no required module provides package rsc.io/quote; try ''go get -d rsc.io/quote'' to add it$'
stderr '^no required module provides package rsc.io/quote; to add it:\n\tgo get rsc.io/quote$'
-- go.mod --

View File

@ -66,7 +66,7 @@ stderr '^go: inconsistent vendoring in '$WORK[/\\]auto':$'
stderr '^\texample.com/printversion@v1.0.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt'
stderr '^\texample.com/unused: is replaced in go.mod, but not marked as replaced in vendor/modules.txt'
stderr '^\texample.com/version@v1.2.0: is replaced in go.mod, but not marked as replaced in vendor/modules.txt'
stderr '\n\nrun .go mod vendor. to sync, or use -mod=mod or -mod=readonly to ignore the vendor directory$'
stderr '^\tTo ignore the vendor directory, use -mod=readonly or -mod=mod.\n\tTo sync the vendor directory, run:\n\t\tgo mod vendor$'
# Module-specific subcommands should continue to load the full module graph.
go mod graph
@ -135,7 +135,7 @@ stderr '^go: inconsistent vendoring in '$WORK[/\\]auto':$'
stderr '^\texample.com/printversion@v1.0.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt'
stderr '^\texample.com/unused: is replaced in go.mod, but not marked as replaced in vendor/modules.txt'
stderr '^\texample.com/version@v1.2.0: is replaced in go.mod, but not marked as replaced in vendor/modules.txt'
stderr '\n\nrun .go mod vendor. to sync, or use -mod=mod or -mod=readonly to ignore the vendor directory$'
stderr '^\tTo ignore the vendor directory, use -mod=readonly or -mod=mod.\n\tTo sync the vendor directory, run:\n\t\tgo mod vendor$'
# If -mod=vendor is set, limited consistency checks should apply even when
# the go version is 1.13 or earlier.
@ -151,7 +151,7 @@ cp $WORK/modules-bad-1.13.txt vendor/modules.txt
! go list -mod=vendor -f {{.Dir}} -tags tools all
stderr '^go: inconsistent vendoring in '$WORK[/\\]auto':$'
stderr '^\texample.com/printversion@v1.0.0: is explicitly required in go.mod, but vendor/modules.txt indicates example.com/printversion@v1.1.0$'
stderr '\n\nrun .go mod vendor. to sync, or use -mod=mod or -mod=readonly to ignore the vendor directory$'
stderr '^\tTo ignore the vendor directory, use -mod=readonly or -mod=mod.\n\tTo sync the vendor directory, run:\n\t\tgo mod vendor$'
# If the go version is still 1.13, 'go mod vendor' should write a
# matching vendor/modules.txt containing the corrected 1.13 data.

View File

@ -1,14 +1,14 @@
# Test rejection of pkg@version in GOPATH mode.
env GO111MODULE=off
! go get rsc.io/quote@v1.5.1
stderr 'cannot use path@version syntax in GOPATH mode'
stderr '^go: can only use path@version syntax with ''go get'' and ''go install'' in module-aware mode$'
! go build rsc.io/quote@v1.5.1
stderr 'cannot use path@version syntax in GOPATH mode'
stderr '^package rsc.io/quote@v1.5.1: can only use path@version syntax with ''go get'' and ''go install'' in module-aware mode$'
env GO111MODULE=on
cd x
! go build rsc.io/quote@v1.5.1
stderr 'can only use path@version syntax with ''go get'''
stderr '^package rsc.io/quote@v1.5.1: can only use path@version syntax with ''go get'' and ''go install'' in module-aware mode$'
-- x/go.mod --
module x

View File

@ -6,8 +6,8 @@
package browser
import (
exec "internal/execabs"
"os"
"os/exec"
"runtime"
"time"
)

View File

@ -6,7 +6,7 @@
//
// Usage:
//
// go tool test2json [-p pkg] [-t] [./pkg.test -test.v]
// go tool test2json [-p pkg] [-t] [./pkg.test -test.v [-test.paniconexit0]]
//
// Test2json runs the given test command and converts its output to JSON;
// with no command specified, test2json expects test output on standard input.
@ -18,6 +18,10 @@
//
// The -t flag requests that time stamps be added to each test event.
//
// The test must be invoked with -test.v. Additionally passing
// -test.paniconexit0 will cause test2json to exit with a non-zero
// status if one of the tests being run calls os.Exit(0).
//
// Note that test2json is only intended for converting a single test
// binary's output. To convert the output of a "go test" command,
// use "go test -json" instead of invoking test2json directly.
@ -82,9 +86,9 @@ package main
import (
"flag"
"fmt"
exec "internal/execabs"
"io"
"os"
"os/exec"
"cmd/internal/test2json"
)

View File

@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm
golang.org/x/crypto/ed25519
golang.org/x/crypto/ed25519/internal/edwards25519
golang.org/x/crypto/ssh/terminal
# golang.org/x/mod v0.4.0
# golang.org/x/mod v0.4.1
## explicit
golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/modfile
@ -44,7 +44,7 @@ golang.org/x/mod/zip
golang.org/x/sys/internal/unsafeheader
golang.org/x/sys/unix
golang.org/x/sys/windows
# golang.org/x/tools v0.0.0-20201211025543-abf6a1d87e11
# golang.org/x/tools v0.0.0-20210107193943-4ed967dd8eff
## explicit
golang.org/x/tools/go/analysis
golang.org/x/tools/go/analysis/internal/analysisflags

View File

@ -386,10 +386,11 @@ func p224Invert(out, in *p224FieldElement) {
// p224Contract converts a FieldElement to its unique, minimal form.
//
// On entry, in[i] < 2**29
// On exit, in[i] < 2**28
// On exit, out[i] < 2**28 and out < p
func p224Contract(out, in *p224FieldElement) {
copy(out[:], in[:])
// First, carry the bits above 28 to the higher limb.
for i := 0; i < 7; i++ {
out[i+1] += out[i] >> 28
out[i] &= bottom28Bits
@ -397,10 +398,13 @@ func p224Contract(out, in *p224FieldElement) {
top := out[7] >> 28
out[7] &= bottom28Bits
// Use the reduction identity to carry the overflow.
//
// a + top * 2²²⁴ = a + top * 2⁹⁶ - top
out[0] -= top
out[3] += top << 12
// We may just have made out[i] negative. So we carry down. If we made
// We may just have made out[0] negative. So we carry down. If we made
// out[0] negative then we know that out[3] is sufficiently positive
// because we just added to it.
for i := 0; i < 3; i++ {
@ -425,13 +429,12 @@ func p224Contract(out, in *p224FieldElement) {
// There are two cases to consider for out[3]:
// 1) The first time that we eliminated top, we didn't push out[3] over
// 2**28. In this case, the partial carry chain didn't change any values
// and top is zero.
// and top is now zero.
// 2) We did push out[3] over 2**28 the first time that we eliminated top.
// The first value of top was in [0..16), therefore, prior to eliminating
// the first top, 0xfff1000 <= out[3] <= 0xfffffff. Therefore, after
// overflowing and being reduced by the second carry chain, out[3] <=
// 0xf000. Thus it cannot have overflowed when we eliminated top for the
// second time.
// The first value of top was in [0..2], therefore, after overflowing
// and being reduced by the second carry chain, out[3] <= 2<<12 - 1.
// In both cases, out[3] cannot have overflowed when we eliminated top for
// the second time.
// Again, we may just have made out[0] negative, so do the same carry down.
// As before, if we made out[0] negative then we know that out[3] is
@ -470,12 +473,11 @@ func p224Contract(out, in *p224FieldElement) {
bottom3NonZero |= bottom3NonZero >> 1
bottom3NonZero = uint32(int32(bottom3NonZero<<31) >> 31)
// Everything depends on the value of out[3].
// If it's > 0xffff000 and top4AllOnes != 0 then the whole value is >= p
// If it's = 0xffff000 and top4AllOnes != 0 and bottom3NonZero != 0,
// then the whole value is >= p
// Assuming top4AllOnes != 0, everything depends on the value of out[3].
// If it's > 0xffff000 then the whole value is > p
// If it's = 0xffff000 and bottom3NonZero != 0, then the whole value is >= p
// If it's < 0xffff000, then the whole value is < p
n := out[3] - 0xffff000
n := 0xffff000 - out[3]
out3Equal := n
out3Equal |= out3Equal >> 16
out3Equal |= out3Equal >> 8
@ -484,8 +486,8 @@ func p224Contract(out, in *p224FieldElement) {
out3Equal |= out3Equal >> 1
out3Equal = ^uint32(int32(out3Equal<<31) >> 31)
// If out[3] > 0xffff000 then n's MSB will be zero.
out3GT := ^uint32(int32(n) >> 31)
// If out[3] > 0xffff000 then n's MSB will be one.
out3GT := uint32(int32(n) >> 31)
mask := top4AllOnes & ((out3Equal & bottom3NonZero) | out3GT)
out[0] -= 1 & mask
@ -494,6 +496,15 @@ func p224Contract(out, in *p224FieldElement) {
out[5] -= 0xfffffff & mask
out[6] -= 0xfffffff & mask
out[7] -= 0xfffffff & mask
// Do one final carry down, in case we made out[0] negative. One of
// out[0..3] needs to be positive and able to absorb the -1 or the value
// would have been < p, and the subtraction wouldn't have happened.
for i := 0; i < 3; i++ {
mask := uint32(int32(out[i]) >> 31)
out[i] += (1 << 28) & mask
out[i+1] -= 1 & mask
}
}
// Group element functions.

View File

@ -6,7 +6,11 @@ package elliptic
import (
"math/big"
"math/bits"
"math/rand"
"reflect"
"testing"
"testing/quick"
)
var toFromBigTests = []string{
@ -21,16 +25,16 @@ func p224AlternativeToBig(in *p224FieldElement) *big.Int {
ret := new(big.Int)
tmp := new(big.Int)
for i := uint(0); i < 8; i++ {
for i := len(in) - 1; i >= 0; i-- {
ret.Lsh(ret, 28)
tmp.SetInt64(int64(in[i]))
tmp.Lsh(tmp, 28*i)
ret.Add(ret, tmp)
}
ret.Mod(ret, p224.P)
ret.Mod(ret, P224().Params().P)
return ret
}
func TestToFromBig(t *testing.T) {
func TestP224ToFromBig(t *testing.T) {
for i, test := range toFromBigTests {
n, _ := new(big.Int).SetString(test, 16)
var x p224FieldElement
@ -41,7 +45,270 @@ func TestToFromBig(t *testing.T) {
}
q := p224AlternativeToBig(&x)
if n.Cmp(q) != 0 {
t.Errorf("#%d: %x != %x (alternative)", i, n, m)
t.Errorf("#%d: %x != %x (alternative)", i, n, q)
}
}
}
// quickCheckConfig32 will make each quickcheck test run (32 * -quickchecks)
// times. The default value of -quickchecks is 100.
var quickCheckConfig32 = &quick.Config{MaxCountScale: 32}
// weirdLimbs can be combined to generate a range of edge-case field elements.
var weirdLimbs = [...]uint32{
0, 1, (1 << 29) - 1,
(1 << 12), (1 << 12) - 1,
(1 << 28), (1 << 28) - 1,
}
func generateLimb(rand *rand.Rand) uint32 {
const bottom29Bits = 0x1fffffff
n := rand.Intn(len(weirdLimbs) + 3)
switch n {
case len(weirdLimbs):
// Random value.
return uint32(rand.Int31n(1 << 29))
case len(weirdLimbs) + 1:
// Sum of two values.
k := generateLimb(rand) + generateLimb(rand)
return k & bottom29Bits
case len(weirdLimbs) + 2:
// Difference of two values.
k := generateLimb(rand) - generateLimb(rand)
return k & bottom29Bits
default:
return weirdLimbs[n]
}
}
func (p224FieldElement) Generate(rand *rand.Rand, size int) reflect.Value {
return reflect.ValueOf(p224FieldElement{
generateLimb(rand),
generateLimb(rand),
generateLimb(rand),
generateLimb(rand),
generateLimb(rand),
generateLimb(rand),
generateLimb(rand),
generateLimb(rand),
})
}
func isInBounds(x *p224FieldElement) bool {
return bits.Len32(x[0]) <= 29 &&
bits.Len32(x[1]) <= 29 &&
bits.Len32(x[2]) <= 29 &&
bits.Len32(x[3]) <= 29 &&
bits.Len32(x[4]) <= 29 &&
bits.Len32(x[5]) <= 29 &&
bits.Len32(x[6]) <= 29 &&
bits.Len32(x[7]) <= 29
}
func TestP224Mul(t *testing.T) {
mulMatchesBigInt := func(a, b, out p224FieldElement) bool {
var tmp p224LargeFieldElement
p224Mul(&out, &a, &b, &tmp)
exp := new(big.Int).Mul(p224AlternativeToBig(&a), p224AlternativeToBig(&b))
exp.Mod(exp, P224().Params().P)
got := p224AlternativeToBig(&out)
if exp.Cmp(got) != 0 || !isInBounds(&out) {
t.Logf("a = %x", a)
t.Logf("b = %x", b)
t.Logf("p224Mul(a, b) = %x = %v", out, got)
t.Logf("a * b = %v", exp)
return false
}
return true
}
a := p224FieldElement{0xfffffff, 0xfffffff, 0xf00ffff, 0x20f, 0x0, 0x0, 0x0, 0x0}
b := p224FieldElement{1, 0, 0, 0, 0, 0, 0, 0}
if !mulMatchesBigInt(a, b, p224FieldElement{}) {
t.Fail()
}
if err := quick.Check(mulMatchesBigInt, quickCheckConfig32); err != nil {
t.Error(err)
}
}
func TestP224Square(t *testing.T) {
squareMatchesBigInt := func(a, out p224FieldElement) bool {
var tmp p224LargeFieldElement
p224Square(&out, &a, &tmp)
exp := p224AlternativeToBig(&a)
exp.Mul(exp, exp)
exp.Mod(exp, P224().Params().P)
got := p224AlternativeToBig(&out)
if exp.Cmp(got) != 0 || !isInBounds(&out) {
t.Logf("a = %x", a)
t.Logf("p224Square(a, b) = %x = %v", out, got)
t.Logf("a * a = %v", exp)
return false
}
return true
}
if err := quick.Check(squareMatchesBigInt, quickCheckConfig32); err != nil {
t.Error(err)
}
}
func TestP224Add(t *testing.T) {
addMatchesBigInt := func(a, b, out p224FieldElement) bool {
p224Add(&out, &a, &b)
exp := new(big.Int).Add(p224AlternativeToBig(&a), p224AlternativeToBig(&b))
exp.Mod(exp, P224().Params().P)
got := p224AlternativeToBig(&out)
if exp.Cmp(got) != 0 {
t.Logf("a = %x", a)
t.Logf("b = %x", b)
t.Logf("p224Add(a, b) = %x = %v", out, got)
t.Logf("a + b = %v", exp)
return false
}
return true
}
if err := quick.Check(addMatchesBigInt, quickCheckConfig32); err != nil {
t.Error(err)
}
}
func TestP224Reduce(t *testing.T) {
reduceMatchesBigInt := func(a p224FieldElement) bool {
out := a
// TODO: generate higher values for functions like p224Reduce that are
// expected to work with higher input bounds.
p224Reduce(&out)
exp := p224AlternativeToBig(&a)
got := p224AlternativeToBig(&out)
if exp.Cmp(got) != 0 || !isInBounds(&out) {
t.Logf("a = %x = %v", a, exp)
t.Logf("p224Reduce(a) = %x = %v", out, got)
return false
}
return true
}
if err := quick.Check(reduceMatchesBigInt, quickCheckConfig32); err != nil {
t.Error(err)
}
}
func TestP224Contract(t *testing.T) {
contractMatchesBigInt := func(a, out p224FieldElement) bool {
p224Contract(&out, &a)
exp := p224AlternativeToBig(&a)
got := p224AlternativeToBig(&out)
if exp.Cmp(got) != 0 {
t.Logf("a = %x = %v", a, exp)
t.Logf("p224Contract(a) = %x = %v", out, got)
return false
}
// Check that out < P.
for i := range p224P {
k := 8 - i - 1
if out[k] > p224P[k] {
t.Logf("p224Contract(a) = %x", out)
return false
}
if out[k] < p224P[k] {
return true
}
}
t.Logf("p224Contract(a) = %x", out)
return false
}
if !contractMatchesBigInt(p224P, p224FieldElement{}) {
t.Error("p224Contract(p) is broken")
}
pMinus1 := p224FieldElement{0, 0, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
if !contractMatchesBigInt(pMinus1, p224FieldElement{}) {
t.Error("p224Contract(p - 1) is broken")
}
// Check that we can handle input above p, but lowest limb zero.
a := p224FieldElement{0, 1, 0, 0xffff000, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
if !contractMatchesBigInt(a, p224FieldElement{}) {
t.Error("p224Contract(p + 2²⁸) is broken")
}
// Check that we can handle input above p, but lowest three limbs zero.
b := p224FieldElement{0, 0, 0, 0xffff001, 0xfffffff, 0xfffffff, 0xfffffff, 0xfffffff}
if !contractMatchesBigInt(b, p224FieldElement{}) {
t.Error("p224Contract(p + 2⁸⁴) is broken")
}
if err := quick.Check(contractMatchesBigInt, quickCheckConfig32); err != nil {
t.Error(err)
}
}
func TestP224IsZero(t *testing.T) {
if got := p224IsZero(&p224FieldElement{}); got != 1 {
t.Errorf("p224IsZero(0) = %d, expected 1", got)
}
if got := p224IsZero((*p224FieldElement)(&p224P)); got != 1 {
t.Errorf("p224IsZero(p) = %d, expected 1", got)
}
if got := p224IsZero(&p224FieldElement{1}); got != 0 {
t.Errorf("p224IsZero(1) = %d, expected 0", got)
}
isZeroMatchesBigInt := func(a p224FieldElement) bool {
isZero := p224IsZero(&a)
big := p224AlternativeToBig(&a)
if big.Sign() == 0 && isZero != 1 {
return false
}
if big.Sign() != 0 && isZero != 0 {
return false
}
return true
}
if err := quick.Check(isZeroMatchesBigInt, quickCheckConfig32); err != nil {
t.Error(err)
}
}
func TestP224Invert(t *testing.T) {
var out p224FieldElement
p224Invert(&out, &p224FieldElement{})
if got := p224IsZero(&out); got != 1 {
t.Errorf("p224Invert(0) = %x, expected 0", out)
}
p224Invert(&out, (*p224FieldElement)(&p224P))
if got := p224IsZero(&out); got != 1 {
t.Errorf("p224Invert(p) = %x, expected 0", out)
}
p224Invert(&out, &p224FieldElement{1})
p224Contract(&out, &out)
if out != (p224FieldElement{1}) {
t.Errorf("p224Invert(1) = %x, expected 1", out)
}
var tmp p224LargeFieldElement
a := p224FieldElement{1, 2, 3, 4, 5, 6, 7, 8}
p224Invert(&out, &a)
p224Mul(&out, &out, &a, &tmp)
p224Contract(&out, &out)
if out != (p224FieldElement{1}) {
t.Errorf("p224Invert(a) * a = %x, expected 1", out)
}
}

View File

@ -8,8 +8,8 @@
package rand
import (
"internal/syscall/windows"
"os"
"syscall"
)
func init() { Reader = &rngReader{} }
@ -24,7 +24,7 @@ func (r *rngReader) Read(b []byte) (n int, err error) {
return 0, nil
}
err = syscall.RtlGenRandom(&b[0], inputLen)
err = windows.RtlGenRandom(b)
if err != nil {
return 0, os.NewSyscallError("RtlGenRandom", err)
}

View File

@ -7,7 +7,6 @@ package tls
import (
"bytes"
"container/list"
"context"
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
@ -444,16 +443,6 @@ type ClientHelloInfo struct {
// config is embedded by the GetCertificate or GetConfigForClient caller,
// for use with SupportsCertificate.
config *Config
// ctx is the context of the handshake that is in progress.
ctx context.Context
}
// Context returns the context of the handshake that is in progress.
// This context is a child of the context passed to HandshakeContext,
// if any, and is canceled when the handshake concludes.
func (c *ClientHelloInfo) Context() context.Context {
return c.ctx
}
// CertificateRequestInfo contains information from a server's
@ -472,16 +461,6 @@ type CertificateRequestInfo struct {
// Version is the TLS version that was negotiated for this connection.
Version uint16
// ctx is the context of the handshake that is in progress.
ctx context.Context
}
// Context returns the context of the handshake that is in progress.
// This context is a child of the context passed to HandshakeContext,
// if any, and is canceled when the handshake concludes.
func (c *CertificateRequestInfo) Context() context.Context {
return c.ctx
}
// RenegotiationSupport enumerates the different levels of support for TLS

View File

@ -8,7 +8,6 @@ package tls
import (
"bytes"
"context"
"crypto/cipher"
"crypto/subtle"
"crypto/x509"
@ -28,7 +27,7 @@ type Conn struct {
// constant
conn net.Conn
isClient bool
handshakeFn func(context.Context) error // (*Conn).clientHandshake or serverHandshake
handshakeFn func() error // (*Conn).clientHandshake or serverHandshake
// handshakeStatus is 1 if the connection is currently transferring
// application data (i.e. is not currently processing a handshake).
@ -1191,7 +1190,7 @@ func (c *Conn) handleRenegotiation() error {
defer c.handshakeMutex.Unlock()
atomic.StoreUint32(&c.handshakeStatus, 0)
if c.handshakeErr = c.clientHandshake(context.Background()); c.handshakeErr == nil {
if c.handshakeErr = c.clientHandshake(); c.handshakeErr == nil {
c.handshakes++
}
return c.handshakeErr
@ -1374,61 +1373,8 @@ func (c *Conn) closeNotify() error {
// first Read or Write will call it automatically.
//
// For control over canceling or setting a timeout on a handshake, use
// HandshakeContext or the Dialer's DialContext method instead.
// the Dialer's DialContext method.
func (c *Conn) Handshake() error {
return c.HandshakeContext(context.Background())
}
// HandshakeContext runs the client or server handshake
// protocol if it has not yet been run.
//
// The provided Context must be non-nil. If the context is canceled before
// the handshake is complete, the handshake is interrupted and an error is returned.
// Once the handshake has completed, cancellation of the context will not affect the
// connection.
//
// Most uses of this package need not call HandshakeContext explicitly: the
// first Read or Write will call it automatically.
func (c *Conn) HandshakeContext(ctx context.Context) error {
// Delegate to unexported method for named return
// without confusing documented signature.
return c.handshakeContext(ctx)
}
func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
handshakeCtx, cancel := context.WithCancel(ctx)
// Note: defer this before starting the "interrupter" goroutine
// so that we can tell the difference between the input being canceled and
// this cancellation. In the former case, we need to close the connection.
defer cancel()
// Start the "interrupter" goroutine, if this context might be canceled.
// (The background context cannot).
//
// The interrupter goroutine waits for the input context to be done and
// closes the connection if this happens before the function returns.
if ctx.Done() != nil {
done := make(chan struct{})
interruptRes := make(chan error, 1)
defer func() {
close(done)
if ctxErr := <-interruptRes; ctxErr != nil {
// Return context error to user.
ret = ctxErr
}
}()
go func() {
select {
case <-handshakeCtx.Done():
// Close the connection, discarding the error
_ = c.conn.Close()
interruptRes <- handshakeCtx.Err()
case <-done:
interruptRes <- nil
}
}()
}
c.handshakeMutex.Lock()
defer c.handshakeMutex.Unlock()
@ -1442,7 +1388,7 @@ func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
c.in.Lock()
defer c.in.Unlock()
c.handshakeErr = c.handshakeFn(handshakeCtx)
c.handshakeErr = c.handshakeFn()
if c.handshakeErr == nil {
c.handshakes++
} else {

View File

@ -6,7 +6,6 @@ package tls
import (
"bytes"
"context"
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
@ -25,7 +24,6 @@ import (
type clientHandshakeState struct {
c *Conn
ctx context.Context
serverHello *serverHelloMsg
hello *clientHelloMsg
suite *cipherSuite
@ -136,7 +134,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) {
return hello, params, nil
}
func (c *Conn) clientHandshake(ctx context.Context) (err error) {
func (c *Conn) clientHandshake() (err error) {
if c.config == nil {
c.config = defaultConfig()
}
@ -200,7 +198,6 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) {
if c.vers == VersionTLS13 {
hs := &clientHandshakeStateTLS13{
c: c,
ctx: ctx,
serverHello: serverHello,
hello: hello,
ecdheParams: ecdheParams,
@ -215,7 +212,6 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) {
hs := &clientHandshakeState{
c: c,
ctx: ctx,
serverHello: serverHello,
hello: hello,
session: session,
@ -544,7 +540,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
certRequested = true
hs.finishedHash.Write(certReq.marshal())
cri := certificateRequestInfoFromMsg(hs.ctx, c.vers, certReq)
cri := certificateRequestInfoFromMsg(c.vers, certReq)
if chainToSend, err = c.getClientCertificate(cri); err != nil {
c.sendAlert(alertInternalError)
return err
@ -884,11 +880,10 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
// certificateRequestInfoFromMsg generates a CertificateRequestInfo from a TLS
// <= 1.2 CertificateRequest, making an effort to fill in missing information.
func certificateRequestInfoFromMsg(ctx context.Context, vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo {
func certificateRequestInfoFromMsg(vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo {
cri := &CertificateRequestInfo{
AcceptableCAs: certReq.certificateAuthorities,
Version: vers,
ctx: ctx,
}
var rsaAvail, ecAvail bool

View File

@ -6,7 +6,6 @@ package tls
import (
"bytes"
"context"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
@ -21,7 +20,6 @@ import (
"os/exec"
"path/filepath"
"reflect"
"runtime"
"strconv"
"strings"
"testing"
@ -2513,37 +2511,3 @@ func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) {
serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps)
}
}
func TestClientHandshakeContextCancellation(t *testing.T) {
c, s := localPipe(t)
serverConfig := testConfig.Clone()
serverErr := make(chan error, 1)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
defer close(serverErr)
defer s.Close()
conn := Server(s, serverConfig)
_, err := conn.readClientHello(ctx)
cancel()
serverErr <- err
}()
cli := Client(c, testConfig)
err := cli.HandshakeContext(ctx)
if err == nil {
t.Fatal("Client handshake did not error when the context was canceled")
}
if err != context.Canceled {
t.Errorf("Unexpected client handshake error: %v", err)
}
if err := <-serverErr; err != nil {
t.Errorf("Unexpected server error: %v", err)
}
if runtime.GOARCH == "wasm" {
t.Skip("conn.Close does not error as expected when called multiple times on WASM")
}
err = cli.Close()
if err == nil {
t.Error("Client connection was not closed when the context was canceled")
}
}

View File

@ -6,7 +6,6 @@ package tls
import (
"bytes"
"context"
"crypto"
"crypto/hmac"
"crypto/rsa"
@ -18,7 +17,6 @@ import (
type clientHandshakeStateTLS13 struct {
c *Conn
ctx context.Context
serverHello *serverHelloMsg
hello *clientHelloMsg
ecdheParams ecdheParameters
@ -557,7 +555,6 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error {
AcceptableCAs: hs.certReq.certificateAuthorities,
SignatureSchemes: hs.certReq.supportedSignatureAlgorithms,
Version: c.vers,
ctx: hs.ctx,
})
if err != nil {
return err

View File

@ -5,7 +5,6 @@
package tls
import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
@ -24,7 +23,6 @@ import (
// It's discarded once the handshake has completed.
type serverHandshakeState struct {
c *Conn
ctx context.Context
clientHello *clientHelloMsg
hello *serverHelloMsg
suite *cipherSuite
@ -39,8 +37,8 @@ type serverHandshakeState struct {
}
// serverHandshake performs a TLS handshake as a server.
func (c *Conn) serverHandshake(ctx context.Context) error {
clientHello, err := c.readClientHello(ctx)
func (c *Conn) serverHandshake() error {
clientHello, err := c.readClientHello()
if err != nil {
return err
}
@ -48,7 +46,6 @@ func (c *Conn) serverHandshake(ctx context.Context) error {
if c.vers == VersionTLS13 {
hs := serverHandshakeStateTLS13{
c: c,
ctx: ctx,
clientHello: clientHello,
}
return hs.handshake()
@ -56,7 +53,6 @@ func (c *Conn) serverHandshake(ctx context.Context) error {
hs := serverHandshakeState{
c: c,
ctx: ctx,
clientHello: clientHello,
}
return hs.handshake()
@ -128,7 +124,7 @@ func (hs *serverHandshakeState) handshake() error {
}
// readClientHello reads a ClientHello message and selects the protocol version.
func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) {
func (c *Conn) readClientHello() (*clientHelloMsg, error) {
msg, err := c.readHandshake()
if err != nil {
return nil, err
@ -142,7 +138,7 @@ func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) {
var configForClient *Config
originalConfig := c.config
if c.config.GetConfigForClient != nil {
chi := clientHelloInfo(ctx, c, clientHello)
chi := clientHelloInfo(c, clientHello)
if configForClient, err = c.config.GetConfigForClient(chi); err != nil {
c.sendAlert(alertInternalError)
return nil, err
@ -224,7 +220,7 @@ func (hs *serverHandshakeState) processClientHello() error {
}
}
hs.cert, err = c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello))
hs.cert, err = c.config.getCertificate(clientHelloInfo(c, hs.clientHello))
if err != nil {
if err == errNoCertificates {
c.sendAlert(alertUnrecognizedName)
@ -832,7 +828,7 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
return nil
}
func clientHelloInfo(ctx context.Context, c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo {
func clientHelloInfo(c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo {
supportedVersions := clientHello.supportedVersions
if len(clientHello.supportedVersions) == 0 {
supportedVersions = supportedVersionsFromMax(clientHello.vers)
@ -848,6 +844,5 @@ func clientHelloInfo(ctx context.Context, c *Conn, clientHello *clientHelloMsg)
SupportedVersions: supportedVersions,
Conn: c.conn,
config: c.config,
ctx: ctx,
}
}

View File

@ -6,7 +6,6 @@ package tls
import (
"bytes"
"context"
"crypto"
"crypto/elliptic"
"crypto/x509"
@ -18,7 +17,6 @@ import (
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
"time"
@ -40,12 +38,10 @@ func testClientHelloFailure(t *testing.T, serverConfig *Config, m handshakeMessa
cli.writeRecord(recordTypeHandshake, m.marshal())
c.Close()
}()
ctx := context.Background()
conn := Server(s, serverConfig)
ch, err := conn.readClientHello(ctx)
ch, err := conn.readClientHello()
hs := serverHandshakeState{
c: conn,
ctx: ctx,
clientHello: ch,
}
if err == nil {
@ -1425,11 +1421,9 @@ func TestSNIGivenOnFailure(t *testing.T) {
c.Close()
}()
conn := Server(s, serverConfig)
ctx := context.Background()
ch, err := conn.readClientHello(ctx)
ch, err := conn.readClientHello()
hs := serverHandshakeState{
c: conn,
ctx: ctx,
clientHello: ch,
}
if err == nil {
@ -1683,46 +1677,6 @@ func TestMultipleCertificates(t *testing.T) {
}
}
func TestServerHandshakeContextCancellation(t *testing.T) {
c, s := localPipe(t)
clientConfig := testConfig.Clone()
clientErr := make(chan error, 1)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
defer close(clientErr)
defer c.Close()
clientHello := &clientHelloMsg{
vers: VersionTLS10,
random: make([]byte, 32),
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone},
}
cli := Client(c, clientConfig)
_, err := cli.writeRecord(recordTypeHandshake, clientHello.marshal())
cancel()
clientErr <- err
}()
conn := Server(s, testConfig)
err := conn.HandshakeContext(ctx)
if err == nil {
t.Fatal("Server handshake did not error when the context was canceled")
}
if err != context.Canceled {
t.Errorf("Unexpected server handshake error: %v", err)
}
if err := <-clientErr; err != nil {
t.Errorf("Unexpected client error: %v", err)
}
if runtime.GOARCH == "wasm" {
t.Skip("conn.Close does not error as expected when called multiple times on WASM")
}
err = conn.Close()
if err == nil {
t.Error("Server connection was not closed when the context was canceled")
}
}
func TestAESCipherReordering(t *testing.T) {
currentAESSupport := hasAESGCMHardwareSupport
defer func() { hasAESGCMHardwareSupport = currentAESSupport; initDefaultCipherSuites() }()

View File

@ -6,7 +6,6 @@ package tls
import (
"bytes"
"context"
"crypto"
"crypto/hmac"
"crypto/rsa"
@ -24,7 +23,6 @@ const maxClientPSKIdentities = 5
type serverHandshakeStateTLS13 struct {
c *Conn
ctx context.Context
clientHello *clientHelloMsg
hello *serverHelloMsg
sentDummyCCS bool
@ -376,7 +374,7 @@ func (hs *serverHandshakeStateTLS13) pickCertificate() error {
return c.sendAlert(alertMissingExtension)
}
certificate, err := c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello))
certificate, err := c.config.getCertificate(clientHelloInfo(c, hs.clientHello))
if err != nil {
if err == errNoCertificates {
c.sendAlert(alertUnrecognizedName)

View File

@ -25,6 +25,7 @@ import (
"net"
"os"
"strings"
"time"
)
// Server returns a new TLS server side connection
@ -115,16 +116,28 @@ func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*
}
func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, config *Config) (*Conn, error) {
if netDialer.Timeout != 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, netDialer.Timeout)
defer cancel()
}
// We want the Timeout and Deadline values from dialer to cover the
// whole process: TCP connection and TLS handshake. This means that we
// also need to start our own timers now.
timeout := netDialer.Timeout
if !netDialer.Deadline.IsZero() {
var cancel context.CancelFunc
ctx, cancel = context.WithDeadline(ctx, netDialer.Deadline)
defer cancel()
deadlineTimeout := time.Until(netDialer.Deadline)
if timeout == 0 || deadlineTimeout < timeout {
timeout = deadlineTimeout
}
}
// hsErrCh is non-nil if we might not wait for Handshake to complete.
var hsErrCh chan error
if timeout != 0 || ctx.Done() != nil {
hsErrCh = make(chan error, 2)
}
if timeout != 0 {
timer := time.AfterFunc(timeout, func() {
hsErrCh <- timeoutError{}
})
defer timer.Stop()
}
rawConn, err := netDialer.DialContext(ctx, network, addr)
@ -151,10 +164,34 @@ func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, conf
}
conn := Client(rawConn, config)
if err := conn.HandshakeContext(ctx); err != nil {
if hsErrCh == nil {
err = conn.Handshake()
} else {
go func() {
hsErrCh <- conn.Handshake()
}()
select {
case <-ctx.Done():
err = ctx.Err()
case err = <-hsErrCh:
if err != nil {
// If the error was due to the context
// closing, prefer the context's error, rather
// than some random network teardown error.
if e := ctx.Err(); e != nil {
err = e
}
}
}
}
if err != nil {
rawConn.Close()
return nil, err
}
return conn, nil
}

View File

@ -4,7 +4,11 @@
package x509
//go:generate go run root_ios_gen.go -version 55161.140.3
// To update the embedded iOS root store, update the -version
// argument to the latest security_certificates version from
// https://opensource.apple.com/source/security_certificates/
// and run "go generate". See https://golang.org/issue/38843.
//go:generate go run root_ios_gen.go -version 55188.40.9
import "sync"

View File

@ -1,4 +1,4 @@
// Code generated by root_ios_gen.go -version 55161.140.3; DO NOT EDIT.
// Code generated by root_ios_gen.go -version 55188.40.9; DO NOT EDIT.
// Update the version in root.go and regenerate with "go generate".
// +build ios
@ -116,61 +116,6 @@ ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU
LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT
LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
-----END CERTIFICATE-----
# "AddTrust Class 1 CA Root"
# 8C 72 09 27 9A C0 4E 27 5E 16 D0 7F D3 B7 75 E8
# 01 54 B5 96 80 46 E3 1F 52 DD 25 76 63 24 E9 A7
-----BEGIN CERTIFICATE-----
MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU
MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw
MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD
VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul
CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n
tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl
dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch
PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC
+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O
BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E
BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl
MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk
ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB
IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X
7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz
43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl
pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA
WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
-----END CERTIFICATE-----
# "AddTrust External CA Root"
# 68 7F A4 51 38 22 78 FF F0 C8 B1 1F 8D 43 D5 76
# 67 1C 6E B2 BC EA B4 13 FB 83 D9 65 D0 6D 2F F2
-----BEGIN CERTIFICATE-----
MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
-----END CERTIFICATE-----
# "Admin-Root-CA"
# A3 1F 09 30 53 BD 12 C1 F5 C3 C6 EF D4 98 02 3F
# D2 91 4D 77 58 D0 5D 69 8C E0 84 B5 06 26 E0 E5
@ -1249,31 +1194,6 @@ Bvt9YAretIpjsJyp8qS5UwGH0GikJ3+r/+n6yUA4iGe0OcaEb1fJU9u6ju7AQ7L4
CYNu/2bPPu8Xs1gYJQk0XuPL1hS27PKSb3TkL4Eq1ZKR4OCXPDJoBYVL0fdX4lId
kxpUnwVwwEpxYB5DC2Ae/qPOgRnhCzU=
-----END CERTIFICATE-----
# "Class 2 Primary CA"
# 0F 99 3C 8A EF 97 BA AF 56 87 14 0E D5 9A D1 82
# 1B B4 AF AC F0 AA 9A 58 B5 D5 7A 33 8A 3A FB CB
-----BEGIN CERTIFICATE-----
MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw
PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz
cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9
MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz
IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ
ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR
VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL
kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd
EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas
H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0
HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud
DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4
QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu
Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/
AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8
yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR
FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA
ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB
kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
l7+ijrRU
-----END CERTIFICATE-----
# "COMODO Certification Authority"
# 0C 2C D6 3D F7 80 6F A3 99 ED E8 09 11 6B 57 5B
# F8 79 89 F0 65 18 F9 80 8C 86 05 03 17 8B AF 66
@ -1529,31 +1449,6 @@ CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na
xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX
KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1
-----END CERTIFICATE-----
# "Deutsche Telekom Root CA 2"
# B6 19 1A 50 D0 C3 97 7F 7D A9 9B CD AA C8 6A 22
# 7D AE B9 67 9E C7 0B A3 B0 C9 D9 22 71 C1 70 D3
-----BEGIN CERTIFICATE-----
MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc
MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj
IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB
IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE
RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl
U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290
IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU
ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC
QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr
rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S
NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc
QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH
txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP
BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC
AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp
tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa
IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl
6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+
xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
Cm26OWMohpLzGITY+9HPBVZkVw==
-----END CERTIFICATE-----
# "Developer ID Certification Authority"
# 7A FC 9D 01 A6 2F 03 A2 DE 96 37 93 6D 4A FE 68
# 09 0D 2D E1 8D 03 F2 9C 88 CF B0 B1 BA 63 58 7F
@ -1801,29 +1696,6 @@ R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----
# "DST Root CA X4"
# 9A 73 92 9A 50 0F 1A 0B F4 9D CB 04 6E 80 39 16
# 96 96 55 73 45 E9 F8 13 F1 0F F9 38 0D B2 26 95
-----BEGIN CERTIFICATE-----
MIIDOzCCAiOgAwIBAgIRANAeRlAAACmMAAAAAgAAAAIwDQYJKoZIhvcNAQEFBQAw
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYNDAeFw0wMDA5MTMwNjIyNTBaFw0yMDA5MTMwNjIyNTBa
MD8xJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEXMBUGA1UE
AxMORFNUIFJvb3QgQ0EgWDQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQCthX3OFEYY8gSeIYur0O4ypOT68HnDrjLfIutL5PZHRwQGjzCPb9PFo/ihboJ8
RvfGhBAqpQCo47zwYEhpWm1jB+L/OE/dBBiyn98krfU2NiBKSom2J58RBeAwHGEy
cO+lewyjVvbDDLUy4CheY059vfMjPAftCRXjqSZIolQb9FdPcAoa90mFwB7rKniE
J7vppdrUScSS0+eBrHSUPLdvwyn4RGp+lSwbWYcbg5EpSpE0GRJdchic0YDjvIoC
YHpe7Rkj93PYRTQyU4bhC88ck8tMqbvRYqMRqR+vobbkrj5LLCOQCHV5WEoxWh+0
E2SpIFe7RkV++MmpIAc0h1tZAgMBAAGjMjAwMA8GA1UdEwEB/wQFMAMBAf8wHQYD
VR0OBBYEFPCD6nPIP1ubWzdf9UyPWvf0hki9MA0GCSqGSIb3DQEBBQUAA4IBAQCE
G85wl5eEWd7adH6XW/ikGN5salvpq/Fix6yVTzE6CrhlP5LBdkf6kx1bSPL18M45
g0rw2zA/MWOhJ3+S6U+BE0zPGCuu8YQaZibR7snm3HiHUaZNMu5c8D0x0bcMxDjY
AVVcHCoNiL53Q4PLW27nbY6wwG0ffFKmgV3blxrYWfuUDgGpyPwHwkfVFvz9qjaV
mf12VJffL6W8omBPtgteb6UaT/k1oJ7YI0ldGf+ngpVbRhD+LC3cUtT6GO/BEPZu
8YTV/hbiDH5v3khVqMIeKT6o8IuXGG7F6a6vKwP1F1FwTXf4UC/ivhme7vdUH7B/
Vv4AEbT8dNfEeFxrkDbh
-----END CERTIFICATE-----
# "E-Tugra Certification Authority"
# B0 BF D5 2B B0 D7 D9 BD 92 BF 5D 4D C1 3D A2 55
# C0 2C 54 2F 37 83 65 EA 89 39 11 F5 5E 55 F2 3C
@ -2671,39 +2543,6 @@ EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO
fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi
AmvZWg==
-----END CERTIFICATE-----
# "I.CA - Qualified Certification Authority, 09/2009"
# C0 C0 5A 8D 8D A5 5E AF 27 AA 9B 91 0B 0A 6E F0
# D8 BB DE D3 46 92 8D B8 72 E1 82 C2 07 3E 98 02
-----BEGIN CERTIFICATE-----
MIIFHjCCBAagAwIBAgIEAKA3oDANBgkqhkiG9w0BAQsFADCBtzELMAkGA1UEBhMC
Q1oxOjA4BgNVBAMMMUkuQ0EgLSBRdWFsaWZpZWQgQ2VydGlmaWNhdGlvbiBBdXRo
b3JpdHksIDA5LzIwMDkxLTArBgNVBAoMJFBydm7DrSBjZXJ0aWZpa2HEjW7DrSBh
dXRvcml0YSwgYS5zLjE9MDsGA1UECww0SS5DQSAtIEFjY3JlZGl0ZWQgUHJvdmlk
ZXIgb2YgQ2VydGlmaWNhdGlvbiBTZXJ2aWNlczAeFw0wOTA5MDEwMDAwMDBaFw0x
OTA5MDEwMDAwMDBaMIG3MQswCQYDVQQGEwJDWjE6MDgGA1UEAwwxSS5DQSAtIFF1
YWxpZmllZCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSwgMDkvMjAwOTEtMCsGA1UE
CgwkUHJ2bsOtIGNlcnRpZmlrYcSNbsOtIGF1dG9yaXRhLCBhLnMuMT0wOwYDVQQL
DDRJLkNBIC0gQWNjcmVkaXRlZCBQcm92aWRlciBvZiBDZXJ0aWZpY2F0aW9uIFNl
cnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtTaEy0KC8M9l
4lSaWHMs4+sVV1LwzyJYiIQNeCrv1HHm/YpGIdY/Z640ceankjQvIX7m23BK4OSC
6KO8kZYA3zopOz6GFCOKV2PvLukbc+c2imF6kLHEv6qNA8WxhPbR3xKwlHDwB2yh
Wzo7V3QVgDRG83sugqQntKYC3LnlTGbJpNP+Az72gpO9AHUn/IBhFk4ksc8lYS2L
9GCy9CsmdKSBP78p9w8Lx7vDLqkDgt1/zBrcUWmSSb7AE/BPEeMryQV1IdI6nlGn
BhWkXOYf6GSdayJw86btuxC7viDKNrbp44HjQRaSxnp6O3eto1x4DfiYdw/YbJFe
7EjkxSQBywIDAQABo4IBLjCCASowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
BAMCAQYwgecGA1UdIASB3zCB3DCB2QYEVR0gADCB0DCBzQYIKwYBBQUHAgIwgcAa
gb1UZW50byBjZXJ0aWZpa2F0IGplIHZ5ZGFuIGpha28ga3ZhbGlmaWtvdmFueSBz
eXN0ZW1vdnkgY2VydGlmaWthdCBwb2RsZSB6YWtvbmEgYy4gMjI3LzIwMDAgU2Iu
IHYgcGxhdG5lbSB6bmVuaS9UaGlzIGlzIHF1YWxpZmllZCBzeXN0ZW0gY2VydGlm
aWNhdGUgYWNjb3JkaW5nIHRvIEN6ZWNoIEFjdCBOby4gMjI3LzIwMDAgQ29sbC4w
HQYDVR0OBBYEFHnL0CPpOmdwkXRP01Hi4CD94Sj7MA0GCSqGSIb3DQEBCwUAA4IB
AQB9laU214hYaBHPZftbDS/2dIGLWdmdSbj1OZbJ8LIPBMxYjPoEMqzAR74tw96T
i6aWRa5WdOWaS6I/qibEKFZhJAVXX5mkx2ewGFLJ+0Go+eTxnjLOnhVF2V2s+57b
m8c8j6/bS6Ij6DspcHEYpfjjh64hE2r0aSpZDjGzKFM6YpqsCJN8qYe2X1qmGMLQ
wvNdjG+nPzCJOOuUEypIWt555ZDLXqS5F7ZjBjlfyDZjEfS2Es9Idok8alf563Mi
9/o+Ba46wMYOkk3P1IlU0RqCajdbliioACKDztAqubONU1guZVzV8tuMASVzbJeL
/GAB7ECTwe1RuKrLYtglMKI9
-----END CERTIFICATE-----
# "IdenTrust Commercial Root CA 1"
# 5D 56 49 9B E4 D2 E0 8B CF CA D0 8A 3E 38 72 3D
# 50 50 3B DE 70 69 48 E4 2F 55 60 30 19 E5 28 AE
@ -4722,123 +4561,6 @@ VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
jjxDah2nGN59PRbxYvnKkKj9
-----END CERTIFICATE-----
# "UTN - DATACorp SGC"
# 85 FB 2F 91 DD 12 27 5A 01 45 B6 36 53 4F 84 02
# 4A D6 8B 69 B8 EE 88 68 4F F7 11 37 58 05 B3 48
-----BEGIN CERTIFICATE-----
MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB
kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw
IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG
EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD
VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu
dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6
E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ
D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK
4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq
lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW
bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB
o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT
MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js
LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr
BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB
AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft
Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj
j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH
KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv
2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3
mfnGV/TJVTl4uix5yaaIK/QI
-----END CERTIFICATE-----
# "UTN-USERFirst-Client Authentication and Email"
# 43 F2 57 41 2D 44 0D 62 74 76 97 4F 87 7D A8 F1
# FC 24 44 56 5A 36 7A E6 0E DD C2 7A 41 25 31 AE
-----BEGIN CERTIFICATE-----
MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCB
rjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0BgNVBAMTLVVUTi1VU0VSRmlyc3Qt
Q2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05OTA3MDkxNzI4NTBa
Fw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAV
BgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5l
dHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UE
AxMtVVROLVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWls
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3B
YHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIxB8dOtINknS4p1aJkxIW9
hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8om+rWV6l
L8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLm
SGHGTPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM
1tZUOt4KpLoDd7NlyP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws
6wIDAQABo4G5MIG2MAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
DgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNVHR8EUTBPME2gS6BJhkdodHRw
Oi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGllbnRBdXRoZW50
aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH
AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u
7mFVbwQ+zznexRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0
xtcgBEXkzYABurorbs6q15L+5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQ
rfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarVNZ1yQAOJujEdxRBoUp7fooXFXAim
eOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZw7JHpsIyYdfHb0gk
USeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ=
-----END CERTIFICATE-----
# "UTN-USERFirst-Hardware"
# 6E A5 47 41 D0 04 66 7E ED 1B 48 16 63 4A A3 A7
# 9E 6E 4B 96 95 0F 82 79 DA FC 8D 9B D8 81 21 37
-----BEGIN CERTIFICATE-----
MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB
lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG
A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe
MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v
d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh
cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn
0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ
M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a
MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd
oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI
DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy
oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD
VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0
dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy
bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF
BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli
CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE
CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t
3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS
KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA==
-----END CERTIFICATE-----
# "UTN-USERFirst-Object"
# 6F FF 78 E4 00 A7 0C 11 01 1C D8 59 77 C4 59 FB
# 5A F9 6A 3D F0 54 08 20 D0 F4 B8 60 78 75 E5 8F
-----BEGIN CERTIFICATE-----
MIIEZjCCA06gAwIBAgIQRL4Mi1AAJLQR0zYt4LNfGzANBgkqhkiG9w0BAQUFADCB
lTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAbBgNVBAMTFFVUTi1VU0VSRmlyc3Qt
T2JqZWN0MB4XDTk5MDcwOTE4MzEyMFoXDTE5MDcwOTE4NDAzNlowgZUxCzAJBgNV
BAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxHjAc
BgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3
dy51c2VydHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdDCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6qgT+jo2F4qjEAVZURnicP
HxzfOpuCaDDASmEd8S8O+r5596Uj71VRloTN2+O5bj4x2AogZ8f02b+U60cEPgLO
KqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQw5ujm9M89RKZd7G3CeBo
5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbHd2pBnqcP1/vulBe3/IW+
pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh2JU022R5KP+6LhHC5ehb
kkj7RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzTbafc8H9vg2XiaquHhnUC
AwEAAaOBrzCBrDALBgNVHQ8EBAMCAcYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
FgQU2u1kdBScFDyr3ZmpvVsoTYs8ydgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDov
L2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmlyc3QtT2JqZWN0LmNybDApBgNV
HSUEIjAgBggrBgEFBQcDAwYIKwYBBQUHAwgGCisGAQQBgjcKAwQwDQYJKoZIhvcN
AQEFBQADggEBAAgfUrE3RHjb/c652pWWmKpVZIC1WkDdIaXFwfNfLEzIR1pp6ujw
NTX00CXzyKakh0q9G7FzCL3Uw8q2NbtZhncxzaeAFK4T7/yxSPlrJSUtUbYsbUXB
mMiKVl0+7kNOPmsnjtA6S4ULX9Ptaqd1y9Fahy85dRNacrACgZ++8A+EVCBibGnU
4U3GDZlDAQ0Slox4nb9QorFEqmrPF3rPbw/U+CRVX/A0FklmPlBGyWNxODFiuGK5
81OtbLUrohKqGU8J2l7nk8aOFAj+8DCAGKCGhU3IfdeLA/5u1fedFqySLKAj5ZyR
Uh+U3xeUc8OzwcFxBSAAeL0TUh2oPs0AH8g=
-----END CERTIFICATE-----
# "VeriSign Class 1 Public Primary Certification Authority - G3"
# CB B5 AF 18 5E 94 2A 24 02 F9 EA CB C0 ED 5B B8
# 76 EE A3 C1 22 36 23 D0 04 47 E4 F3 BA 55 4B 65

View File

@ -1997,49 +1997,6 @@ func buildCSRExtensions(template *CertificateRequest) ([]pkix.Extension, error)
})
}
if template.KeyUsage != 0 &&
!oidInExtensions(oidExtensionKeyUsage, template.ExtraExtensions) {
ext, err := marshalKeyUsage(template.KeyUsage)
if err != nil {
return nil, err
}
ret = append(ret, ext)
}
if (len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0) &&
!oidInExtensions(oidExtensionExtendedKeyUsage, template.ExtraExtensions) {
ext, err := marshalExtKeyUsage(template.ExtKeyUsage, template.UnknownExtKeyUsage)
if err != nil {
return nil, err
}
ret = append(ret, ext)
}
if template.BasicConstraintsValid && !oidInExtensions(oidExtensionBasicConstraints, template.ExtraExtensions) {
ext, err := marshalBasicConstraints(template.IsCA, template.MaxPathLen, template.MaxPathLenZero)
if err != nil {
return nil, err
}
ret = append(ret, ext)
}
if len(template.SubjectKeyId) > 0 && !oidInExtensions(oidExtensionSubjectKeyId, template.ExtraExtensions) {
skidBytes, err := asn1.Marshal(template.SubjectKeyId)
if err != nil {
return nil, err
}
ret = append(ret, pkix.Extension{Id: oidExtensionSubjectKeyId, Value: skidBytes})
}
if len(template.PolicyIdentifiers) > 0 &&
!oidInExtensions(oidExtensionCertificatePolicies, template.ExtraExtensions) {
ext, err := marshalCertificatePolicies(template.PolicyIdentifiers)
if err != nil {
return nil, err
}
ret = append(ret, ext)
}
return append(ret, template.ExtraExtensions...), nil
}
@ -2405,7 +2362,6 @@ type CertificateRequest struct {
Version int
Signature []byte
SignatureAlgorithm SignatureAlgorithm
KeyUsage KeyUsage
PublicKeyAlgorithm PublicKeyAlgorithm
PublicKey interface{}
@ -2438,37 +2394,6 @@ type CertificateRequest struct {
EmailAddresses []string
IPAddresses []net.IP
URIs []*url.URL
ExtKeyUsage []ExtKeyUsage // Sequence of extended key usages.
UnknownExtKeyUsage []asn1.ObjectIdentifier // Encountered extended key usages unknown to this package.
// BasicConstraintsValid indicates whether IsCA, MaxPathLen,
// and MaxPathLenZero are valid.
BasicConstraintsValid bool
IsCA bool
// MaxPathLen and MaxPathLenZero indicate the presence and
// value of the BasicConstraints' "pathLenConstraint".
//
// When parsing a certificate, a positive non-zero MaxPathLen
// means that the field was specified, -1 means it was unset,
// and MaxPathLenZero being true mean that the field was
// explicitly set to zero. The case of MaxPathLen==0 with MaxPathLenZero==false
// should be treated equivalent to -1 (unset).
//
// When generating a certificate, an unset pathLenConstraint
// can be requested with either MaxPathLen == -1 or using the
// zero value for both MaxPathLen and MaxPathLenZero.
MaxPathLen int
// MaxPathLenZero indicates that BasicConstraintsValid==true
// and MaxPathLen==0 should be interpreted as an actual
// maximum path length of zero. Otherwise, that combination is
// interpreted as MaxPathLen not being set.
MaxPathLenZero bool
SubjectKeyId []byte
PolicyIdentifiers []asn1.ObjectIdentifier
}
// These structures reflect the ASN.1 structure of X.509 certificate
@ -2566,15 +2491,6 @@ func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error)
// - EmailAddresses
// - IPAddresses
// - URIs
// - KeyUsage
// - ExtKeyUsage
// - UnknownExtKeyUsage
// - BasicConstraintsValid
// - IsCA
// - MaxPathLen
// - MaxPathLenZero
// - SubjectKeyId
// - PolicyIdentifiers
// - ExtraExtensions
// - Attributes (deprecated)
//
@ -2799,30 +2715,6 @@ func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error
if err != nil {
return nil, err
}
case extension.Id.Equal(oidExtensionKeyUsage):
out.KeyUsage, err = parseKeyUsageExtension(extension.Value)
case extension.Id.Equal(oidExtensionExtendedKeyUsage):
out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(extension.Value)
if err != nil {
return nil, err
}
case extension.Id.Equal(oidExtensionBasicConstraints):
out.IsCA, out.MaxPathLen, err = parseBasicConstraintsExtension(extension.Value)
if err != nil {
return nil, err
}
out.BasicConstraintsValid = true
out.MaxPathLenZero = out.MaxPathLen == 0
case extension.Id.Equal(oidExtensionSubjectKeyId):
out.SubjectKeyId, err = parseSubjectKeyIdExtension(extension.Value)
if err != nil {
return nil, err
}
case extension.Id.Equal(oidExtensionCertificatePolicies):
out.PolicyIdentifiers, err = parseCertificatePoliciesExtension(extension.Value)
if err != nil {
return nil, err
}
}
}

View File

@ -2964,44 +2964,34 @@ func certPoolEqual(a, b *CertPool) bool {
}
func TestCertificateRequestRoundtripFields(t *testing.T) {
urlA, err := url.Parse("https://example.com/_")
if err != nil {
t.Fatal(err)
}
urlB, err := url.Parse("https://example.org/_")
if err != nil {
t.Fatal(err)
}
in := &CertificateRequest{
KeyUsage: KeyUsageCertSign,
ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageAny},
UnknownExtKeyUsage: []asn1.ObjectIdentifier{{1, 2, 3}},
BasicConstraintsValid: true,
IsCA: true,
MaxPathLen: 0,
MaxPathLenZero: true,
SubjectKeyId: []byte{1, 2, 3},
PolicyIdentifiers: []asn1.ObjectIdentifier{{1, 2, 3}},
DNSNames: []string{"example.com", "example.org"},
EmailAddresses: []string{"a@example.com", "b@example.com"},
IPAddresses: []net.IP{net.IPv4(192, 0, 2, 0), net.IPv6loopback},
URIs: []*url.URL{urlA, urlB},
}
out := marshalAndParseCSR(t, in)
if in.KeyUsage != out.KeyUsage {
t.Fatalf("Unexpected KeyUsage: got %v, want %v", out.KeyUsage, in.KeyUsage)
if !reflect.DeepEqual(in.DNSNames, out.DNSNames) {
t.Fatalf("Unexpected DNSNames: got %v, want %v", out.DNSNames, in.DNSNames)
}
if !reflect.DeepEqual(in.ExtKeyUsage, out.ExtKeyUsage) {
t.Fatalf("Unexpected ExtKeyUsage: got %v, want %v", out.ExtKeyUsage, in.ExtKeyUsage)
if !reflect.DeepEqual(in.EmailAddresses, out.EmailAddresses) {
t.Fatalf("Unexpected EmailAddresses: got %v, want %v", out.EmailAddresses, in.EmailAddresses)
}
if !reflect.DeepEqual(in.UnknownExtKeyUsage, out.UnknownExtKeyUsage) {
t.Fatalf("Unexpected UnknownExtKeyUsage: got %v, want %v", out.UnknownExtKeyUsage, in.UnknownExtKeyUsage)
if len(in.IPAddresses) != len(out.IPAddresses) ||
!in.IPAddresses[0].Equal(out.IPAddresses[0]) ||
!in.IPAddresses[1].Equal(out.IPAddresses[1]) {
t.Fatalf("Unexpected IPAddresses: got %v, want %v", out.IPAddresses, in.IPAddresses)
}
if in.BasicConstraintsValid != out.BasicConstraintsValid {
t.Fatalf("Unexpected BasicConstraintsValid: got %v, want %v", out.BasicConstraintsValid, in.BasicConstraintsValid)
}
if in.IsCA != out.IsCA {
t.Fatalf("Unexpected IsCA: got %v, want %v", out.IsCA, in.IsCA)
}
if in.MaxPathLen != out.MaxPathLen {
t.Fatalf("Unexpected MaxPathLen: got %v, want %v", out.MaxPathLen, in.MaxPathLen)
}
if in.MaxPathLenZero != out.MaxPathLenZero {
t.Fatalf("Unexpected MaxPathLenZero: got %v, want %v", out.MaxPathLenZero, in.MaxPathLenZero)
}
if !reflect.DeepEqual(in.SubjectKeyId, out.SubjectKeyId) {
t.Fatalf("Unexpected SubjectKeyId: got %v, want %v", out.SubjectKeyId, in.SubjectKeyId)
}
if !reflect.DeepEqual(in.PolicyIdentifiers, out.PolicyIdentifiers) {
t.Fatalf("Unexpected PolicyIdentifiers: got %v, want %v", out.PolicyIdentifiers, in.PolicyIdentifiers)
if !reflect.DeepEqual(in.URIs, out.URIs) {
t.Fatalf("Unexpected URIs: got %v, want %v", out.URIs, in.URIs)
}
}

View File

@ -244,6 +244,9 @@ func (f FS) lookup(name string) *file {
if name == "." {
return dotFile
}
if f.files == nil {
return nil
}
// Binary search to find where name would be in the list,
// and then check if name is at that position.
@ -261,6 +264,9 @@ func (f FS) lookup(name string) *file {
// readDir returns the list of files corresponding to the directory dir.
func (f FS) readDir(dir string) []file {
if f.files == nil {
return nil
}
// Binary search to find where dir starts and ends in the list
// and then return that slice of the list.
files := *f.files

View File

@ -73,24 +73,11 @@ func TestGlobal(t *testing.T) {
testString(t, string(glass), "glass", "I can eat glass and it doesn't hurt me.\n")
}
func TestLocal(t *testing.T) {
//go:embed testdata/k*.txt
var local embed.FS
testFiles(t, local, "testdata/ken.txt", "If a program is too slow, it must have a loop.\n")
//go:embed testdata/k*.txt
var s string
testString(t, s, "local variable s", "If a program is too slow, it must have a loop.\n")
//go:embed testdata/h*.txt
var b []byte
testString(t, string(b), "local variable b", "hello, world\n")
}
//go:embed testdata
var testDirAll embed.FS
func TestDir(t *testing.T) {
//go:embed testdata
var all embed.FS
all := testDirAll
testFiles(t, all, "testdata/hello.txt", "hello, world\n")
testFiles(t, all, "testdata/i/i18n.txt", "internationalization\n")
testFiles(t, all, "testdata/i/j/k/k8s.txt", "kubernetes\n")
@ -102,12 +89,15 @@ func TestDir(t *testing.T) {
testDir(t, all, "testdata/i/j/k", "k8s.txt")
}
func TestHidden(t *testing.T) {
//go:embed testdata
var dir embed.FS
//go:embed testdata
var testHiddenDir embed.FS
//go:embed testdata/*
var star embed.FS
//go:embed testdata/*
var testHiddenStar embed.FS
func TestHidden(t *testing.T) {
dir := testHiddenDir
star := testHiddenStar
t.Logf("//go:embed testdata")
@ -122,3 +112,20 @@ func TestHidden(t *testing.T) {
testDir(t, star, "testdata/.hidden",
"fortune.txt", "more/") // but not .more or _more
}
func TestUninitialized(t *testing.T) {
var uninitialized embed.FS
testDir(t, uninitialized, ".")
f, err := uninitialized.Open(".")
if err != nil {
t.Fatal(err)
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
t.Fatal(err)
}
if !fi.IsDir() {
t.Errorf("in uninitialized embed.FS, . is not a directory")
}
}

View File

@ -90,17 +90,3 @@ func TestXGlobal(t *testing.T) {
}
bbig[0] = old
}
func TestXLocal(t *testing.T) {
//go:embed testdata/*o.txt
var local embed.FS
testFiles(t, local, "testdata/hello.txt", "hello, world\n")
//go:embed testdata/k*.txt
var s string
testString(t, s, "local variable s", "If a program is too slow, it must have a loop.\n")
//go:embed testdata/h*.txt
var b []byte
testString(t, string(b), "local variable b", "hello, world\n")
}

View File

@ -1067,6 +1067,15 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
// set causes a SET, rather than a SEQUENCE type to be expected
// tag:x specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC
//
// When decoding an ASN.1 value with an IMPLICIT tag into a string field,
// Unmarshal will default to a PrintableString, which doesn't support
// characters such as '@' and '&'. To force other encodings, use the following
// tags:
//
// ia5 causes strings to be unmarshaled as ASN.1 IA5String values
// numeric causes strings to be unmarshaled as ASN.1 NumericString values
// utf8 causes strings to be unmarshaled as ASN.1 UTF8String values
//
// If the type of the first field of a structure is RawContent then the raw
// ASN1 contents of the struct will be stored in it.
//

View File

@ -11,13 +11,13 @@ import (
"go/ast"
"go/doc"
"go/token"
exec "internal/execabs"
"internal/goroot"
"internal/goversion"
"io"
"io/fs"
"io/ioutil"
"os"
"os/exec"
pathpkg "path"
"path/filepath"
"runtime"
@ -451,9 +451,12 @@ type Package struct {
// //go:embed a* b.c
// then the list will contain those two strings as separate entries.
// (See package embed for more details about //go:embed.)
EmbedPatterns []string // patterns from GoFiles, CgoFiles
TestEmbedPatterns []string // patterns from TestGoFiles
XTestEmbedPatterns []string // patterns from XTestGoFiles
EmbedPatterns []string // patterns from GoFiles, CgoFiles
EmbedPatternPos map[string][]token.Position // line information for EmbedPatterns
TestEmbedPatterns []string // patterns from TestGoFiles
TestEmbedPatternPos map[string][]token.Position // line information for TestEmbedPatterns
XTestEmbedPatterns []string // patterns from XTestGoFiles
XTestEmbedPatternPos map[string][]token.Position // line information for XTestEmbedPatternPos
}
// IsCommand reports whether the package is considered a
@ -796,10 +799,12 @@ Found:
var badGoError error
var Sfiles []string // files with ".S"(capital S)/.sx(capital s equivalent for case insensitive filesystems)
var firstFile, firstCommentFile string
var embeds, testEmbeds, xTestEmbeds []string
imported := make(map[string][]token.Position)
testImported := make(map[string][]token.Position)
xTestImported := make(map[string][]token.Position)
embedPos := make(map[string][]token.Position)
testEmbedPos := make(map[string][]token.Position)
xTestEmbedPos := make(map[string][]token.Position)
importPos := make(map[string][]token.Position)
testImportPos := make(map[string][]token.Position)
xTestImportPos := make(map[string][]token.Position)
allTags := make(map[string]bool)
fset := token.NewFileSet()
for _, d := range dirs {
@ -922,31 +927,31 @@ Found:
}
}
var fileList, embedList *[]string
var importMap map[string][]token.Position
var fileList *[]string
var importMap, embedMap map[string][]token.Position
switch {
case isCgo:
allTags["cgo"] = true
if ctxt.CgoEnabled {
fileList = &p.CgoFiles
importMap = imported
embedList = &embeds
importMap = importPos
embedMap = embedPos
} else {
// Ignore imports from cgo files if cgo is disabled.
// Ignore imports and embeds from cgo files if cgo is disabled.
fileList = &p.IgnoredGoFiles
}
case isXTest:
fileList = &p.XTestGoFiles
importMap = xTestImported
embedList = &xTestEmbeds
importMap = xTestImportPos
embedMap = xTestEmbedPos
case isTest:
fileList = &p.TestGoFiles
importMap = testImported
embedList = &testEmbeds
importMap = testImportPos
embedMap = testEmbedPos
default:
fileList = &p.GoFiles
importMap = imported
embedList = &embeds
importMap = importPos
embedMap = embedPos
}
*fileList = append(*fileList, name)
if importMap != nil {
@ -954,8 +959,10 @@ Found:
importMap[imp.path] = append(importMap[imp.path], fset.Position(imp.pos))
}
}
if embedList != nil {
*embedList = append(*embedList, info.embeds...)
if embedMap != nil {
for _, emb := range info.embeds {
embedMap[emb.pattern] = append(embedMap[emb.pattern], emb.pos)
}
}
}
@ -964,13 +971,13 @@ Found:
}
sort.Strings(p.AllTags)
p.EmbedPatterns = uniq(embeds)
p.TestEmbedPatterns = uniq(testEmbeds)
p.XTestEmbedPatterns = uniq(xTestEmbeds)
p.EmbedPatterns, p.EmbedPatternPos = cleanDecls(embedPos)
p.TestEmbedPatterns, p.TestEmbedPatternPos = cleanDecls(testEmbedPos)
p.XTestEmbedPatterns, p.XTestEmbedPatternPos = cleanDecls(xTestEmbedPos)
p.Imports, p.ImportPos = cleanImports(imported)
p.TestImports, p.TestImportPos = cleanImports(testImported)
p.XTestImports, p.XTestImportPos = cleanImports(xTestImported)
p.Imports, p.ImportPos = cleanDecls(importPos)
p.TestImports, p.TestImportPos = cleanDecls(testImportPos)
p.XTestImports, p.XTestImportPos = cleanDecls(xTestImportPos)
// add the .S/.sx files only if we are using cgo
// (which means gcc will compile them).
@ -1342,7 +1349,7 @@ type fileInfo struct {
parsed *ast.File
parseErr error
imports []fileImport
embeds []string
embeds []fileEmbed
embedErr error
}
@ -1352,6 +1359,11 @@ type fileImport struct {
doc *ast.CommentGroup
}
type fileEmbed struct {
pattern string
pos token.Position
}
// matchFile determines whether the file with the given name in the given directory
// should be included in the package being constructed.
// If the file should be included, matchFile returns a non-nil *fileInfo (and a nil error).
@ -1426,7 +1438,7 @@ func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binary
return info, nil
}
func cleanImports(m map[string][]token.Position) ([]string, map[string][]token.Position) {
func cleanDecls(m map[string][]token.Position) ([]string, map[string][]token.Position) {
all := make([]string, 0, len(m))
for path := range m {
all = append(all, path)

View File

@ -28,6 +28,7 @@ func TestMatch(t *testing.T) {
ctxt := Default
what := "default"
match := func(tag string, want map[string]bool) {
t.Helper()
m := make(map[string]bool)
if !ctxt.match(tag, m) {
t.Errorf("%s context should match %s, does not", what, tag)
@ -37,6 +38,7 @@ func TestMatch(t *testing.T) {
}
}
nomatch := func(tag string, want map[string]bool) {
t.Helper()
m := make(map[string]bool)
if ctxt.match(tag, m) {
t.Errorf("%s context should NOT match %s, does", what, tag)
@ -57,7 +59,6 @@ func TestMatch(t *testing.T) {
nomatch(runtime.GOOS+","+runtime.GOARCH+",!foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
match(runtime.GOOS+","+runtime.GOARCH+",!bar", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "bar": true})
nomatch(runtime.GOOS+","+runtime.GOARCH+",bar", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "bar": true})
nomatch("!", map[string]bool{})
}
func TestDotSlashImport(t *testing.T) {

View File

@ -0,0 +1,574 @@
// Copyright 2020 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 constraint implements parsing and evaluation of build constraint lines.
// See https://golang.org/cmd/go/#hdr-Build_constraints for documentation about build constraints themselves.
//
// This package parses both the original “// +build” syntax and the “//go:build” syntax that will be added in Go 1.17.
// The parser is being included in Go 1.16 to allow tools that need to process Go 1.17 source code
// to still be built against the Go 1.16 release.
// See https://golang.org/design/draft-gobuild for details about the “//go:build” syntax.
package constraint
import (
"errors"
"strings"
"unicode"
"unicode/utf8"
)
// An Expr is a build tag constraint expression.
// The underlying concrete type is *AndExpr, *OrExpr, *NotExpr, or *TagExpr.
type Expr interface {
// String returns the string form of the expression,
// using the boolean syntax used in //go:build lines.
String() string
// Eval reports whether the expression evaluates to true.
// It calls ok(tag) as needed to find out whether a given build tag
// is satisfied by the current build configuration.
Eval(ok func(tag string) bool) bool
// The presence of an isExpr method explicitly marks the type as an Expr.
// Only implementations in this package should be used as Exprs.
isExpr()
}
// A TagExpr is an Expr for the single tag Tag.
type TagExpr struct {
Tag string // for example, “linux” or “cgo”
}
func (x *TagExpr) isExpr() {}
func (x *TagExpr) Eval(ok func(tag string) bool) bool {
return ok(x.Tag)
}
func (x *TagExpr) String() string {
return x.Tag
}
func tag(tag string) Expr { return &TagExpr{tag} }
// A NotExpr represents the expression !X (the negation of X).
type NotExpr struct {
X Expr
}
func (x *NotExpr) isExpr() {}
func (x *NotExpr) Eval(ok func(tag string) bool) bool {
return !x.X.Eval(ok)
}
func (x *NotExpr) String() string {
s := x.X.String()
switch x.X.(type) {
case *AndExpr, *OrExpr:
s = "(" + s + ")"
}
return "!" + s
}
func not(x Expr) Expr { return &NotExpr{x} }
// An AndExpr represents the expression X && Y.
type AndExpr struct {
X, Y Expr
}
func (x *AndExpr) isExpr() {}
func (x *AndExpr) Eval(ok func(tag string) bool) bool {
// Note: Eval both, to make sure ok func observes all tags.
xok := x.X.Eval(ok)
yok := x.Y.Eval(ok)
return xok && yok
}
func (x *AndExpr) String() string {
return andArg(x.X) + " && " + andArg(x.Y)
}
func andArg(x Expr) string {
s := x.String()
if _, ok := x.(*OrExpr); ok {
s = "(" + s + ")"
}
return s
}
func and(x, y Expr) Expr {
return &AndExpr{x, y}
}
// An OrExpr represents the expression X || Y.
type OrExpr struct {
X, Y Expr
}
func (x *OrExpr) isExpr() {}
func (x *OrExpr) Eval(ok func(tag string) bool) bool {
// Note: Eval both, to make sure ok func observes all tags.
xok := x.X.Eval(ok)
yok := x.Y.Eval(ok)
return xok || yok
}
func (x *OrExpr) String() string {
return orArg(x.X) + " || " + orArg(x.Y)
}
func orArg(x Expr) string {
s := x.String()
if _, ok := x.(*AndExpr); ok {
s = "(" + s + ")"
}
return s
}
func or(x, y Expr) Expr {
return &OrExpr{x, y}
}
// A SyntaxError reports a syntax error in a parsed build expression.
type SyntaxError struct {
Offset int // byte offset in input where error was detected
Err string // description of error
}
func (e *SyntaxError) Error() string {
return e.Err
}
var errNotConstraint = errors.New("not a build constraint")
// Parse parses a single build constraint line of the form “//go:build ...” or “// +build ...”
// and returns the corresponding boolean expression.
func Parse(line string) (Expr, error) {
if text, ok := splitGoBuild(line); ok {
return parseExpr(text)
}
if text, ok := splitPlusBuild(line); ok {
return parsePlusBuildExpr(text), nil
}
return nil, errNotConstraint
}
// IsGoBuild reports whether the line of text is a “//go:build” constraint.
// It only checks the prefix of the text, not that the expression itself parses.
func IsGoBuild(line string) bool {
_, ok := splitGoBuild(line)
return ok
}
// splitGoBuild splits apart the leading //go:build prefix in line from the build expression itself.
// It returns "", false if the input is not a //go:build line or if the input contains multiple lines.
func splitGoBuild(line string) (expr string, ok bool) {
// A single trailing newline is OK; otherwise multiple lines are not.
if len(line) > 0 && line[len(line)-1] == '\n' {
line = line[:len(line)-1]
}
if strings.Contains(line, "\n") {
return "", false
}
if !strings.HasPrefix(line, "//go:build") {
return "", false
}
line = strings.TrimSpace(line)
line = line[len("//go:build"):]
// If strings.TrimSpace finds more to trim after removing the //go:build prefix,
// it means that the prefix was followed by a space, making this a //go:build line
// (as opposed to a //go:buildsomethingelse line).
// If line is empty, we had "//go:build" by itself, which also counts.
trim := strings.TrimSpace(line)
if len(line) == len(trim) && line != "" {
return "", false
}
return trim, true
}
// An exprParser holds state for parsing a build expression.
type exprParser struct {
s string // input string
i int // next read location in s
tok string // last token read
isTag bool
pos int // position (start) of last token
}
// parseExpr parses a boolean build tag expression.
func parseExpr(text string) (x Expr, err error) {
defer func() {
if e := recover(); e != nil {
if e, ok := e.(*SyntaxError); ok {
err = e
return
}
panic(e) // unreachable unless parser has a bug
}
}()
p := &exprParser{s: text}
x = p.or()
if p.tok != "" {
panic(&SyntaxError{Offset: p.pos, Err: "unexpected token " + p.tok})
}
return x, nil
}
// or parses a sequence of || expressions.
// On entry, the next input token has not yet been lexed.
// On exit, the next input token has been lexed and is in p.tok.
func (p *exprParser) or() Expr {
x := p.and()
for p.tok == "||" {
x = or(x, p.and())
}
return x
}
// and parses a sequence of && expressions.
// On entry, the next input token has not yet been lexed.
// On exit, the next input token has been lexed and is in p.tok.
func (p *exprParser) and() Expr {
x := p.not()
for p.tok == "&&" {
x = and(x, p.not())
}
return x
}
// not parses a ! expression.
// On entry, the next input token has not yet been lexed.
// On exit, the next input token has been lexed and is in p.tok.
func (p *exprParser) not() Expr {
p.lex()
if p.tok == "!" {
p.lex()
if p.tok == "!" {
panic(&SyntaxError{Offset: p.pos, Err: "double negation not allowed"})
}
return not(p.atom())
}
return p.atom()
}
// atom parses a tag or a parenthesized expression.
// On entry, the next input token HAS been lexed.
// On exit, the next input token has been lexed and is in p.tok.
func (p *exprParser) atom() Expr {
// first token already in p.tok
if p.tok == "(" {
pos := p.pos
defer func() {
if e := recover(); e != nil {
if e, ok := e.(*SyntaxError); ok && e.Err == "unexpected end of expression" {
e.Err = "missing close paren"
}
panic(e)
}
}()
x := p.or()
if p.tok != ")" {
panic(&SyntaxError{Offset: pos, Err: "missing close paren"})
}
p.lex()
return x
}
if !p.isTag {
if p.tok == "" {
panic(&SyntaxError{Offset: p.pos, Err: "unexpected end of expression"})
}
panic(&SyntaxError{Offset: p.pos, Err: "unexpected token " + p.tok})
}
tok := p.tok
p.lex()
return tag(tok)
}
// lex finds and consumes the next token in the input stream.
// On return, p.tok is set to the token text,
// p.isTag reports whether the token was a tag,
// and p.pos records the byte offset of the start of the token in the input stream.
// If lex reaches the end of the input, p.tok is set to the empty string.
// For any other syntax error, lex panics with a SyntaxError.
func (p *exprParser) lex() {
p.isTag = false
for p.i < len(p.s) && (p.s[p.i] == ' ' || p.s[p.i] == '\t') {
p.i++
}
if p.i >= len(p.s) {
p.tok = ""
p.pos = p.i
return
}
switch p.s[p.i] {
case '(', ')', '!':
p.pos = p.i
p.i++
p.tok = p.s[p.pos:p.i]
return
case '&', '|':
if p.i+1 >= len(p.s) || p.s[p.i+1] != p.s[p.i] {
panic(&SyntaxError{Offset: p.i, Err: "invalid syntax at " + string(rune(p.s[p.i]))})
}
p.pos = p.i
p.i += 2
p.tok = p.s[p.pos:p.i]
return
}
tag := p.s[p.i:]
for i, c := range tag {
if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
tag = tag[:i]
break
}
}
if tag == "" {
c, _ := utf8.DecodeRuneInString(p.s[p.i:])
panic(&SyntaxError{Offset: p.i, Err: "invalid syntax at " + string(c)})
}
p.pos = p.i
p.i += len(tag)
p.tok = p.s[p.pos:p.i]
p.isTag = true
return
}
// IsPlusBuild reports whether the line of text is a “// +build” constraint.
// It only checks the prefix of the text, not that the expression itself parses.
func IsPlusBuild(line string) bool {
_, ok := splitPlusBuild(line)
return ok
}
// splitGoBuild splits apart the leading //go:build prefix in line from the build expression itself.
// It returns "", false if the input is not a //go:build line or if the input contains multiple lines.
func splitPlusBuild(line string) (expr string, ok bool) {
// A single trailing newline is OK; otherwise multiple lines are not.
if len(line) > 0 && line[len(line)-1] == '\n' {
line = line[:len(line)-1]
}
if strings.Contains(line, "\n") {
return "", false
}
if !strings.HasPrefix(line, "//") {
return "", false
}
line = line[len("//"):]
// Note the space is optional; "//+build" is recognized too.
line = strings.TrimSpace(line)
if !strings.HasPrefix(line, "+build") {
return "", false
}
line = line[len("+build"):]
// If strings.TrimSpace finds more to trim after removing the +build prefix,
// it means that the prefix was followed by a space, making this a +build line
// (as opposed to a +buildsomethingelse line).
// If line is empty, we had "// +build" by itself, which also counts.
trim := strings.TrimSpace(line)
if len(line) == len(trim) && line != "" {
return "", false
}
return trim, true
}
// parsePlusBuildExpr parses a legacy build tag expression (as used with “// +build”).
func parsePlusBuildExpr(text string) Expr {
var x Expr
for _, clause := range strings.Fields(text) {
var y Expr
for _, lit := range strings.Split(clause, ",") {
var z Expr
var neg bool
if strings.HasPrefix(lit, "!!") || lit == "!" {
z = tag("ignore")
} else {
if strings.HasPrefix(lit, "!") {
neg = true
lit = lit[len("!"):]
}
if isValidTag(lit) {
z = tag(lit)
} else {
z = tag("ignore")
}
if neg {
z = not(z)
}
}
if y == nil {
y = z
} else {
y = and(y, z)
}
}
if x == nil {
x = y
} else {
x = or(x, y)
}
}
return x
}
// isValidTag reports whether the word is a valid build tag.
// Tags must be letters, digits, underscores or dots.
// Unlike in Go identifiers, all digits are fine (e.g., "386").
func isValidTag(word string) bool {
if word == "" {
return false
}
for _, c := range word {
if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
return false
}
}
return true
}
var errComplex = errors.New("expression too complex for // +build lines")
// PlusBuildLines returns a sequence of “// +build” lines that evaluate to the build expression x.
// If the expression is too complex to convert directly to “// +build” lines, PlusBuildLines returns an error.
func PlusBuildLines(x Expr) ([]string, error) {
// Push all NOTs to the expression leaves, so that //go:build !(x && y) can be treated as !x || !y.
// This rewrite is both efficient and commonly needed, so it's worth doing.
// Essentially all other possible rewrites are too expensive and too rarely needed.
x = pushNot(x, false)
// Split into AND of ORs of ANDs of literals (tag or NOT tag).
var split [][][]Expr
for _, or := range appendSplitAnd(nil, x) {
var ands [][]Expr
for _, and := range appendSplitOr(nil, or) {
var lits []Expr
for _, lit := range appendSplitAnd(nil, and) {
switch lit.(type) {
case *TagExpr, *NotExpr:
lits = append(lits, lit)
default:
return nil, errComplex
}
}
ands = append(ands, lits)
}
split = append(split, ands)
}
// If all the ORs have length 1 (no actual OR'ing going on),
// push the top-level ANDs to the bottom level, so that we get
// one // +build line instead of many.
maxOr := 0
for _, or := range split {
if maxOr < len(or) {
maxOr = len(or)
}
}
if maxOr == 1 {
var lits []Expr
for _, or := range split {
lits = append(lits, or[0]...)
}
split = [][][]Expr{{lits}}
}
// Prepare the +build lines.
var lines []string
for _, or := range split {
line := "// +build"
for _, and := range or {
clause := ""
for i, lit := range and {
if i > 0 {
clause += ","
}
clause += lit.String()
}
line += " " + clause
}
lines = append(lines, line)
}
return lines, nil
}
// pushNot applies DeMorgan's law to push negations down the expression,
// so that only tags are negated in the result.
// (It applies the rewrites !(X && Y) => (!X || !Y) and !(X || Y) => (!X && !Y).)
func pushNot(x Expr, not bool) Expr {
switch x := x.(type) {
default:
// unreachable
return x
case *NotExpr:
if _, ok := x.X.(*TagExpr); ok && !not {
return x
}
return pushNot(x.X, !not)
case *TagExpr:
if not {
return &NotExpr{X: x}
}
return x
case *AndExpr:
x1 := pushNot(x.X, not)
y1 := pushNot(x.Y, not)
if not {
return or(x1, y1)
}
if x1 == x.X && y1 == x.Y {
return x
}
return and(x1, y1)
case *OrExpr:
x1 := pushNot(x.X, not)
y1 := pushNot(x.Y, not)
if not {
return and(x1, y1)
}
if x1 == x.X && y1 == x.Y {
return x
}
return or(x1, y1)
}
}
// appendSplitAnd appends x to list while splitting apart any top-level && expressions.
// For example, appendSplitAnd({W}, X && Y && Z) = {W, X, Y, Z}.
func appendSplitAnd(list []Expr, x Expr) []Expr {
if x, ok := x.(*AndExpr); ok {
list = appendSplitAnd(list, x.X)
list = appendSplitAnd(list, x.Y)
return list
}
return append(list, x)
}
// appendSplitOr appends x to list while splitting apart any top-level || expressions.
// For example, appendSplitOr({W}, X || Y || Z) = {W, X, Y, Z}.
func appendSplitOr(list []Expr, x Expr) []Expr {
if x, ok := x.(*OrExpr); ok {
list = appendSplitOr(list, x.X)
list = appendSplitOr(list, x.Y)
return list
}
return append(list, x)
}

View File

@ -0,0 +1,317 @@
// Copyright 2020 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 constraint
import (
"fmt"
"reflect"
"strings"
"testing"
)
var exprStringTests = []struct {
x Expr
out string
}{
{
x: tag("abc"),
out: "abc",
},
{
x: not(tag("abc")),
out: "!abc",
},
{
x: not(and(tag("abc"), tag("def"))),
out: "!(abc && def)",
},
{
x: and(tag("abc"), or(tag("def"), tag("ghi"))),
out: "abc && (def || ghi)",
},
{
x: or(and(tag("abc"), tag("def")), tag("ghi")),
out: "(abc && def) || ghi",
},
}
func TestExprString(t *testing.T) {
for i, tt := range exprStringTests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
s := tt.x.String()
if s != tt.out {
t.Errorf("String() mismatch:\nhave %s\nwant %s", s, tt.out)
}
})
}
}
var lexTests = []struct {
in string
out string
}{
{"", ""},
{"x", "x"},
{"x.y", "x.y"},
{"x_y", "x_y"},
{"αx", "αx"},
{"αx²", "αx err: invalid syntax at ²"},
{"go1.2", "go1.2"},
{"x y", "x y"},
{"x!y", "x ! y"},
{"&&||!()xy yx ", "&& || ! ( ) xy yx"},
{"x~", "x err: invalid syntax at ~"},
{"x ~", "x err: invalid syntax at ~"},
{"x &", "x err: invalid syntax at &"},
{"x &y", "x err: invalid syntax at &"},
}
func TestLex(t *testing.T) {
for i, tt := range lexTests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
p := &exprParser{s: tt.in}
out := ""
for {
tok, err := lexHelp(p)
if tok == "" && err == nil {
break
}
if out != "" {
out += " "
}
if err != nil {
out += "err: " + err.Error()
break
}
out += tok
}
if out != tt.out {
t.Errorf("lex(%q):\nhave %s\nwant %s", tt.in, out, tt.out)
}
})
}
}
func lexHelp(p *exprParser) (tok string, err error) {
defer func() {
if e := recover(); e != nil {
if e, ok := e.(*SyntaxError); ok {
err = e
return
}
panic(e)
}
}()
p.lex()
return p.tok, nil
}
var parseExprTests = []struct {
in string
x Expr
}{
{"x", tag("x")},
{"x&&y", and(tag("x"), tag("y"))},
{"x||y", or(tag("x"), tag("y"))},
{"(x)", tag("x")},
{"x||y&&z", or(tag("x"), and(tag("y"), tag("z")))},
{"x&&y||z", or(and(tag("x"), tag("y")), tag("z"))},
{"x&&(y||z)", and(tag("x"), or(tag("y"), tag("z")))},
{"(x||y)&&z", and(or(tag("x"), tag("y")), tag("z"))},
{"!(x&&y)", not(and(tag("x"), tag("y")))},
}
func TestParseExpr(t *testing.T) {
for i, tt := range parseExprTests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
x, err := parseExpr(tt.in)
if err != nil {
t.Fatal(err)
}
if x.String() != tt.x.String() {
t.Errorf("parseExpr(%q):\nhave %s\nwant %s", tt.in, x, tt.x)
}
})
}
}
var parseExprErrorTests = []struct {
in string
err error
}{
{"x && ", &SyntaxError{Offset: 5, Err: "unexpected end of expression"}},
{"x && (", &SyntaxError{Offset: 6, Err: "missing close paren"}},
{"x && ||", &SyntaxError{Offset: 5, Err: "unexpected token ||"}},
{"x && !", &SyntaxError{Offset: 6, Err: "unexpected end of expression"}},
{"x && !!", &SyntaxError{Offset: 6, Err: "double negation not allowed"}},
{"x !", &SyntaxError{Offset: 2, Err: "unexpected token !"}},
{"x && (y", &SyntaxError{Offset: 5, Err: "missing close paren"}},
}
func TestParseError(t *testing.T) {
for i, tt := range parseExprErrorTests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
x, err := parseExpr(tt.in)
if err == nil {
t.Fatalf("parseExpr(%q) = %v, want error", tt.in, x)
}
if !reflect.DeepEqual(err, tt.err) {
t.Fatalf("parseExpr(%q): wrong error:\nhave %#v\nwant %#v", tt.in, err, tt.err)
}
})
}
}
var exprEvalTests = []struct {
in string
ok bool
tags string
}{
{"x", false, "x"},
{"x && y", false, "x y"},
{"x || y", false, "x y"},
{"!x && yes", true, "x yes"},
{"yes || y", true, "y yes"},
}
func TestExprEval(t *testing.T) {
for i, tt := range exprEvalTests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
x, err := parseExpr(tt.in)
if err != nil {
t.Fatal(err)
}
tags := make(map[string]bool)
wantTags := make(map[string]bool)
for _, tag := range strings.Fields(tt.tags) {
wantTags[tag] = true
}
hasTag := func(tag string) bool {
tags[tag] = true
return tag == "yes"
}
ok := x.Eval(hasTag)
if ok != tt.ok || !reflect.DeepEqual(tags, wantTags) {
t.Errorf("Eval(%#q):\nhave ok=%v, tags=%v\nwant ok=%v, tags=%v",
tt.in, ok, tags, tt.ok, wantTags)
}
})
}
}
var parsePlusBuildExprTests = []struct {
in string
x Expr
}{
{"x", tag("x")},
{"x,y", and(tag("x"), tag("y"))},
{"x y", or(tag("x"), tag("y"))},
{"x y,z", or(tag("x"), and(tag("y"), tag("z")))},
{"x,y z", or(and(tag("x"), tag("y")), tag("z"))},
{"x,!y !z", or(and(tag("x"), not(tag("y"))), not(tag("z")))},
{"!! x", or(tag("ignore"), tag("x"))},
{"!!x", tag("ignore")},
{"!x", not(tag("x"))},
{"!", tag("ignore")},
}
func TestParsePlusBuildExpr(t *testing.T) {
for i, tt := range parsePlusBuildExprTests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
x := parsePlusBuildExpr(tt.in)
if x.String() != tt.x.String() {
t.Errorf("parsePlusBuildExpr(%q):\nhave %v\nwant %v", tt.in, x, tt.x)
}
})
}
}
var constraintTests = []struct {
in string
x Expr
err error
}{
{"//+build x y", or(tag("x"), tag("y")), nil},
{"// +build x y \n", or(tag("x"), tag("y")), nil},
{"// +build x y \n ", nil, errNotConstraint},
{"// +build x y \nmore", nil, errNotConstraint},
{" //+build x y", nil, errNotConstraint},
{"//go:build x && y", and(tag("x"), tag("y")), nil},
{"//go:build x && y\n", and(tag("x"), tag("y")), nil},
{"//go:build x && y\n ", nil, errNotConstraint},
{"//go:build x && y\nmore", nil, errNotConstraint},
{" //go:build x && y", nil, errNotConstraint},
}
func TestParse(t *testing.T) {
for i, tt := range constraintTests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
x, err := Parse(tt.in)
if err != nil {
if tt.err == nil {
t.Errorf("Constraint(%q): unexpected error: %v", tt.in, err)
} else if tt.err != err {
t.Errorf("Constraint(%q): error %v, want %v", tt.in, err, tt.err)
}
return
}
if tt.err != nil {
t.Errorf("Constraint(%q) = %v, want error %v", tt.in, x, tt.err)
return
}
if x.String() != tt.x.String() {
t.Errorf("Constraint(%q):\nhave %v\nwant %v", tt.in, x, tt.x)
}
})
}
}
var plusBuildLinesTests = []struct {
in string
out []string
err error
}{
{"x", []string{"x"}, nil},
{"x && !y", []string{"x,!y"}, nil},
{"x || y", []string{"x y"}, nil},
{"x && (y || z)", []string{"x", "y z"}, nil},
{"!(x && y)", []string{"!x !y"}, nil},
{"x || (y && z)", []string{"x y,z"}, nil},
{"w && (x || (y && z))", []string{"w", "x y,z"}, nil},
{"v || (w && (x || (y && z)))", nil, errComplex},
}
func TestPlusBuildLines(t *testing.T) {
for i, tt := range plusBuildLinesTests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
x, err := parseExpr(tt.in)
if err != nil {
t.Fatal(err)
}
lines, err := PlusBuildLines(x)
if err != nil {
if tt.err == nil {
t.Errorf("PlusBuildLines(%q): unexpected error: %v", tt.in, err)
} else if tt.err != err {
t.Errorf("PlusBuildLines(%q): error %v, want %v", tt.in, err, tt.err)
}
return
}
if tt.err != nil {
t.Errorf("PlusBuildLines(%q) = %v, want error %v", tt.in, lines, tt.err)
return
}
var want []string
for _, line := range tt.out {
want = append(want, "// +build "+line)
}
if !reflect.DeepEqual(lines, want) {
t.Errorf("PlusBuildLines(%q):\nhave %q\nwant %q", tt.in, lines, want)
}
})
}
}

View File

@ -10,6 +10,7 @@ package build
import (
"bytes"
"fmt"
"go/token"
"internal/testenv"
"io/fs"
"os"
@ -162,6 +163,9 @@ var depsRules = `
< os
< os/signal;
io/fs
< embed;
unicode, fmt !< os, os/signal;
os/signal, STR
@ -174,7 +178,7 @@ var depsRules = `
reflect !< OS;
OS
< golang.org/x/sys/cpu, internal/goroot;
< golang.org/x/sys/cpu;
# FMT is OS (which includes string routines) plus reflect and fmt.
# It does not include package log, which should be avoided in core packages.
@ -190,6 +194,12 @@ var depsRules = `
log !< FMT;
OS, FMT
< internal/execabs;
OS, internal/execabs
< internal/goroot;
# Misc packages needing only FMT.
FMT
< flag,
@ -278,6 +288,9 @@ var depsRules = `
container/heap, go/constant, go/parser
< go/types;
FMT
< go/build/constraint;
go/doc, go/parser, internal/goroot, internal/goversion
< go/build;
@ -602,6 +615,7 @@ func findImports(pkg string) ([]string, error) {
}
var imports []string
var haveImport = map[string]bool{}
fset := token.NewFileSet()
for _, file := range files {
name := file.Name()
if name == "slice_go14.go" || name == "slice_go18.go" {
@ -611,8 +625,10 @@ func findImports(pkg string) ([]string, error) {
if !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") {
continue
}
var info fileInfo
info.name = filepath.Join(dir, name)
info := fileInfo{
name: filepath.Join(dir, name),
fset: fset,
}
f, err := os.Open(info.name)
if err != nil {
return nil, err
@ -840,3 +856,28 @@ func TestStdlibLowercase(t *testing.T) {
}
}
}
// TestFindImports tests that findImports works. See #43249.
func TestFindImports(t *testing.T) {
if !testenv.HasSrc() {
// Tests run in a limited file system and we do not
// provide access to every source file.
t.Skipf("skipping on %s/%s, missing full GOROOT", runtime.GOOS, runtime.GOARCH)
}
imports, err := findImports("go/build")
if err != nil {
t.Fatal(err)
}
t.Logf("go/build imports %q", imports)
want := []string{"bytes", "os", "path/filepath", "strings"}
wantLoop:
for _, w := range want {
for _, imp := range imports {
if imp == w {
continue wantLoop
}
}
t.Errorf("expected to find %q in import list", w)
}
}

View File

@ -10,6 +10,7 @@ import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"io"
"strconv"
"strings"
@ -24,6 +25,18 @@ type importReader struct {
err error
eof bool
nerr int
pos token.Position
}
func newImportReader(name string, r io.Reader) *importReader {
return &importReader{
b: bufio.NewReader(r),
pos: token.Position{
Filename: name,
Line: 1,
Column: 1,
},
}
}
func isIdent(c byte) bool {
@ -66,22 +79,32 @@ func (r *importReader) readByte() byte {
// readByteNoBuf is like readByte but doesn't buffer the byte.
// It exhausts r.buf before reading from r.b.
func (r *importReader) readByteNoBuf() byte {
var c byte
var err error
if len(r.buf) > 0 {
c := r.buf[0]
c = r.buf[0]
r.buf = r.buf[1:]
return c
}
c, err := r.b.ReadByte()
if err == nil && c == 0 {
err = errNUL
} else {
c, err = r.b.ReadByte()
if err == nil && c == 0 {
err = errNUL
}
}
if err != nil {
if err == io.EOF {
r.eof = true
} else if r.err == nil {
r.err = err
}
c = 0
return 0
}
r.pos.Offset++
if c == '\n' {
r.pos.Line++
r.pos.Column = 1
} else {
r.pos.Column++
}
return c
}
@ -171,6 +194,41 @@ func (r *importReader) findEmbed(first bool) bool {
case ' ', '\t':
// leave startLine alone
case '"':
startLine = false
for r.err == nil {
if r.eof {
r.syntaxError()
}
c = r.readByteNoBuf()
if c == '\\' {
r.readByteNoBuf()
if r.err != nil {
r.syntaxError()
return false
}
continue
}
if c == '"' {
c = r.readByteNoBuf()
goto Reswitch
}
}
goto Reswitch
case '`':
startLine = false
for r.err == nil {
if r.eof {
r.syntaxError()
}
c = r.readByteNoBuf()
if c == '`' {
c = r.readByteNoBuf()
goto Reswitch
}
}
case '/':
c = r.readByteNoBuf()
switch c {
@ -288,7 +346,7 @@ func (r *importReader) readImport() {
// readComments is like io.ReadAll, except that it only reads the leading
// block of comments in the file.
func readComments(f io.Reader) ([]byte, error) {
r := &importReader{b: bufio.NewReader(f)}
r := newImportReader("", f)
r.peekByte(true)
if r.err == nil && !r.eof {
// Didn't reach EOF, so must have found a non-space byte. Remove it.
@ -305,7 +363,7 @@ func readComments(f io.Reader) ([]byte, error) {
// It only returns an error if there are problems reading the file,
// not for syntax errors in the file itself.
func readGoInfo(f io.Reader, info *fileInfo) error {
r := &importReader{b: bufio.NewReader(f)}
r := newImportReader(info.name, f)
r.readKeyword("package")
r.readIdent()
@ -393,6 +451,7 @@ func readGoInfo(f io.Reader, info *fileInfo) error {
var line []byte
for first := true; r.findEmbed(first); first = false {
line = line[:0]
pos := r.pos
for {
c := r.readByteNoBuf()
if c == '\n' || r.err != nil || r.eof {
@ -403,9 +462,9 @@ func readGoInfo(f io.Reader, info *fileInfo) error {
// Add args if line is well-formed.
// Ignore badly-formed lines - the compiler will report them when it finds them,
// and we can pretend they are not there to help go list succeed with what it knows.
args, err := parseGoEmbed(string(line))
embs, err := parseGoEmbed(string(line), pos)
if err == nil {
info.embeds = append(info.embeds, args...)
info.embeds = append(info.embeds, embs...)
}
}
}
@ -415,11 +474,23 @@ func readGoInfo(f io.Reader, info *fileInfo) error {
// parseGoEmbed parses the text following "//go:embed" to extract the glob patterns.
// It accepts unquoted space-separated patterns as well as double-quoted and back-quoted Go strings.
// There is a copy of this code in cmd/compile/internal/gc/noder.go as well.
func parseGoEmbed(args string) ([]string, error) {
var list []string
for args = strings.TrimSpace(args); args != ""; args = strings.TrimSpace(args) {
// This is based on a similar function in cmd/compile/internal/gc/noder.go;
// this version calculates position information as well.
func parseGoEmbed(args string, pos token.Position) ([]fileEmbed, error) {
trimBytes := func(n int) {
pos.Offset += n
pos.Column += utf8.RuneCountInString(args[:n])
args = args[n:]
}
trimSpace := func() {
trim := strings.TrimLeftFunc(args, unicode.IsSpace)
trimBytes(len(args) - len(trim))
}
var list []fileEmbed
for trimSpace(); args != ""; trimSpace() {
var path string
pathPos := pos
Switch:
switch args[0] {
default:
@ -431,7 +502,7 @@ func parseGoEmbed(args string) ([]string, error) {
}
}
path = args[:i]
args = args[i:]
trimBytes(i)
case '`':
i := strings.Index(args[1:], "`")
@ -439,7 +510,7 @@ func parseGoEmbed(args string) ([]string, error) {
return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
}
path = args[1 : 1+i]
args = args[1+i+1:]
trimBytes(1 + i + 1)
case '"':
i := 1
@ -454,7 +525,7 @@ func parseGoEmbed(args string) ([]string, error) {
return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args[:i+1])
}
path = q
args = args[i+1:]
trimBytes(i + 1)
break Switch
}
}
@ -469,7 +540,7 @@ func parseGoEmbed(args string) ([]string, error) {
return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
}
}
list = append(list, path)
list = append(list, fileEmbed{path, pathPos})
}
return list, nil
}

View File

@ -5,9 +5,9 @@
package build
import (
"fmt"
"go/token"
"io"
"reflect"
"strings"
"testing"
)
@ -228,55 +228,94 @@ func TestReadFailuresIgnored(t *testing.T) {
}
var readEmbedTests = []struct {
in string
out []string
in, out string
}{
{
"package p\n",
nil,
"",
},
{
"package p\nimport \"embed\"\nvar i int\n//go:embed x y z\nvar files embed.FS",
[]string{"x", "y", "z"},
`test:4:12:x
test:4:14:y
test:4:16:z`,
},
{
"package p\nimport \"embed\"\nvar i int\n//go:embed x \"\\x79\" `z`\nvar files embed.FS",
[]string{"x", "y", "z"},
`test:4:12:x
test:4:14:y
test:4:21:z`,
},
{
"package p\nimport \"embed\"\nvar i int\n//go:embed x y\n//go:embed z\nvar files embed.FS",
[]string{"x", "y", "z"},
`test:4:12:x
test:4:14:y
test:5:12:z`,
},
{
"package p\nimport \"embed\"\nvar i int\n\t //go:embed x y\n\t //go:embed z\n\t var files embed.FS",
[]string{"x", "y", "z"},
`test:4:14:x
test:4:16:y
test:5:14:z`,
},
{
"package p\nimport \"embed\"\n//go:embed x y z\nvar files embed.FS",
[]string{"x", "y", "z"},
`test:3:12:x
test:3:14:y
test:3:16:z`,
},
{
"package p\nimport \"embed\"\nvar s = \"/*\"\n//go:embed x\nvar files embed.FS",
`test:4:12:x`,
},
{
`package p
import "embed"
var s = "\"\\\\"
//go:embed x
var files embed.FS`,
`test:4:15:x`,
},
{
"package p\nimport \"embed\"\nvar s = `/*`\n//go:embed x\nvar files embed.FS",
`test:4:12:x`,
},
{
"package p\nimport \"embed\"\nvar s = z/ *y\n//go:embed pointer\nvar pointer embed.FS",
"test:4:12:pointer",
},
{
"package p\n//go:embed x y z\n", // no import, no scan
nil,
"",
},
{
"package p\n//go:embed x y z\nvar files embed.FS", // no import, no scan
nil,
"",
},
}
func TestReadEmbed(t *testing.T) {
fset := token.NewFileSet()
for i, tt := range readEmbedTests {
var info fileInfo
info.fset = fset
info := fileInfo{
name: "test",
fset: fset,
}
err := readGoInfo(strings.NewReader(tt.in), &info)
if err != nil {
t.Errorf("#%d: %v", i, err)
continue
}
if !reflect.DeepEqual(info.embeds, tt.out) {
t.Errorf("#%d: embeds=%v, want %v", i, info.embeds, tt.out)
b := &strings.Builder{}
sep := ""
for _, emb := range info.embeds {
fmt.Fprintf(b, "%s%v:%s", sep, emb.pos, emb.pattern)
sep = "\n"
}
got := b.String()
want := strings.Join(strings.Fields(tt.out), "\n")
if got != want {
t.Errorf("#%d: embeds:\n%s\nwant:\n%s", i, got, want)
}
}
}

View File

@ -7,8 +7,8 @@ package gccgoimporter
import (
"bufio"
"go/types"
exec "internal/execabs"
"os"
"os/exec"
"path/filepath"
"strings"
)

View File

@ -13,9 +13,9 @@ import (
"go/parser"
"go/token"
"go/types"
exec "internal/execabs"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"

Some files were not shown because too many files have changed in this diff Show More