mirror of
https://github.com/golang/go
synced 2024-11-23 19:30:05 -07:00
cmd/go: refine definition of 'standard' import paths to include vendored code
The vendored copy of golang.org/x/net/http/hpack was being treated as not standard, which in turn was making it not subject to the mtime exception for rebuilding the standard library in a release, which in turn was making net/http look out of date. One fix and three tests: - Fix the definition of standard. - Test that everything in $GOROOT/src/ is standard during 'go test cmd/go'. (In general there can be non-standard things in $GOROOT/src/, but this test implies that you can do that or you can run 'go test cmd/go', but not both. That's fine.) - Test that 'go list std cmd' shows our vendored code. - Enforce that no standard package can depend on a non-standard one. Also fix a few error printing nits. Fixes #13713. Change-Id: I1f943f1c354174c199e9b52075c11ee44198e81b Reviewed-on: https://go-review.googlesource.com/18978 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
1023d63f7f
commit
4223675913
@ -666,10 +666,41 @@ func TestGoBuildDashAInReleaseBranch(t *testing.T) {
|
|||||||
|
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
tg.run("install", "math") // should be up to date already but just in case
|
tg.run("install", "math", "net/http") // should be up to date already but just in case
|
||||||
tg.setenv("TESTGO_IS_GO_RELEASE", "1")
|
tg.setenv("TESTGO_IS_GO_RELEASE", "1")
|
||||||
tg.run("build", "-v", "-a", "math")
|
tg.run("install", "-v", "-a", "math")
|
||||||
tg.grepStderr("runtime", "testgo build -a math in dev branch did not build runtime, but should have")
|
tg.grepStderr("runtime", "testgo build -a math in release branch DID NOT build runtime, but should have")
|
||||||
|
|
||||||
|
// Now runtime.a is updated (newer mtime), so everything would look stale if not for being a release.
|
||||||
|
//
|
||||||
|
tg.run("build", "-v", "net/http")
|
||||||
|
tg.grepStderrNot("strconv", "testgo build -v net/http in release branch with newer runtime.a DID build strconv but should not have")
|
||||||
|
tg.grepStderrNot("golang.org/x/net/http2/hpack", "testgo build -v net/http in release branch with newer runtime.a DID build .../golang.org/x/net/http2/hpack but should not have")
|
||||||
|
tg.grepStderrNot("net/http", "testgo build -v net/http in release branch with newer runtime.a DID build net/http but should not have")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGoListStandard(t *testing.T) {
|
||||||
|
tg := testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
tg.cd(runtime.GOROOT() + "/src")
|
||||||
|
tg.run("list", "-f", "{{if not .Standard}}{{.ImportPath}}{{end}}", "./...")
|
||||||
|
stdout := tg.getStdout()
|
||||||
|
for _, line := range strings.Split(stdout, "\n") {
|
||||||
|
if strings.HasPrefix(line, "_/") && strings.HasSuffix(line, "/src") {
|
||||||
|
// $GOROOT/src shows up if there are any .go files there.
|
||||||
|
// We don't care.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if line == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.Errorf("package in GOROOT not listed as standard: %v", line)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Similarly, expanding std should include some of our vendored code.
|
||||||
|
tg.run("list", "std", "cmd")
|
||||||
|
tg.grepStdout("golang.org/x/net/http2/hpack", "list std cmd did not mention vendored hpack")
|
||||||
|
tg.grepStdout("golang.org/x/arch/x86/x86asm", "list std cmd did not mention vendored x86asm")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGoInstallCleansUpAfterGoBuild(t *testing.T) {
|
func TestGoInstallCleansUpAfterGoBuild(t *testing.T) {
|
||||||
|
@ -588,10 +588,9 @@ func matchPackages(pattern string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
name := filepath.ToSlash(path[len(src):])
|
name := filepath.ToSlash(path[len(src):])
|
||||||
if pattern == "std" && (strings.Contains(name, ".") || name == "cmd") {
|
if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") {
|
||||||
// The name "std" is only the standard library.
|
// The name "std" is only the standard library.
|
||||||
// If the name has a dot, assume it's a domain name for go get,
|
// If the name is cmd, it's the root of the command tree.
|
||||||
// and if the name is cmd, it's the root of the command tree.
|
|
||||||
return filepath.SkipDir
|
return filepath.SkipDir
|
||||||
}
|
}
|
||||||
if !treeCanMatch(name) {
|
if !treeCanMatch(name) {
|
||||||
|
@ -153,7 +153,7 @@ func (p *Package) copyBuild(pp *build.Package) {
|
|||||||
p.ConflictDir = pp.ConflictDir
|
p.ConflictDir = pp.ConflictDir
|
||||||
// TODO? Target
|
// TODO? Target
|
||||||
p.Goroot = pp.Goroot
|
p.Goroot = pp.Goroot
|
||||||
p.Standard = p.Goroot && p.ImportPath != "" && !strings.Contains(p.ImportPath, ".")
|
p.Standard = p.Goroot && p.ImportPath != "" && isStandardImportPath(p.ImportPath)
|
||||||
p.GoFiles = pp.GoFiles
|
p.GoFiles = pp.GoFiles
|
||||||
p.CgoFiles = pp.CgoFiles
|
p.CgoFiles = pp.CgoFiles
|
||||||
p.IgnoredGoFiles = pp.IgnoredGoFiles
|
p.IgnoredGoFiles = pp.IgnoredGoFiles
|
||||||
@ -177,6 +177,19 @@ func (p *Package) copyBuild(pp *build.Package) {
|
|||||||
p.XTestImports = pp.XTestImports
|
p.XTestImports = pp.XTestImports
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isStandardImportPath reports whether $GOROOT/src/path should be considered
|
||||||
|
// part of the standard distribution. For historical reasons we allow people to add
|
||||||
|
// their own code to $GOROOT instead of using $GOPATH, but we assume that
|
||||||
|
// code will start with a domain name (dot in the first element).
|
||||||
|
func isStandardImportPath(path string) bool {
|
||||||
|
i := strings.Index(path, "/")
|
||||||
|
if i < 0 {
|
||||||
|
i = len(path)
|
||||||
|
}
|
||||||
|
elem := path[:i]
|
||||||
|
return !strings.Contains(elem, ".")
|
||||||
|
}
|
||||||
|
|
||||||
// A PackageError describes an error loading information about a package.
|
// A PackageError describes an error loading information about a package.
|
||||||
type PackageError struct {
|
type PackageError struct {
|
||||||
ImportStack []string // shortest path from package named on command line to this one
|
ImportStack []string // shortest path from package named on command line to this one
|
||||||
@ -362,7 +375,7 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
|
|||||||
err = fmt.Errorf("code in directory %s expects import %q", bp.Dir, bp.ImportComment)
|
err = fmt.Errorf("code in directory %s expects import %q", bp.Dir, bp.ImportComment)
|
||||||
}
|
}
|
||||||
p.load(stk, bp, err)
|
p.load(stk, bp, err)
|
||||||
if p.Error != nil && len(importPos) > 0 {
|
if p.Error != nil && p.Error.Pos == "" && len(importPos) > 0 {
|
||||||
pos := importPos[0]
|
pos := importPos[0]
|
||||||
pos.Filename = shortPath(pos.Filename)
|
pos.Filename = shortPath(pos.Filename)
|
||||||
p.Error.Pos = pos.String()
|
p.Error.Pos = pos.String()
|
||||||
@ -933,6 +946,17 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if p.Standard && !p1.Standard && p.Error == nil {
|
||||||
|
p.Error = &PackageError{
|
||||||
|
ImportStack: stk.copy(),
|
||||||
|
Err: fmt.Sprintf("non-standard import %q in standard package %q", path, p.ImportPath),
|
||||||
|
}
|
||||||
|
pos := p.build.ImportPos[path]
|
||||||
|
if len(pos) > 0 {
|
||||||
|
p.Error.Pos = pos[0].String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
path = p1.ImportPath
|
path = p1.ImportPath
|
||||||
importPaths[i] = path
|
importPaths[i] = path
|
||||||
if i < len(p.Imports) {
|
if i < len(p.Imports) {
|
||||||
|
@ -89,9 +89,19 @@ func runRun(cmd *Command, args []string) {
|
|||||||
fatalf("%s", p.Error)
|
fatalf("%s", p.Error)
|
||||||
}
|
}
|
||||||
p.omitDWARF = true
|
p.omitDWARF = true
|
||||||
|
if len(p.DepsErrors) > 0 {
|
||||||
|
// Since these are errors in dependencies,
|
||||||
|
// the same error might show up multiple times,
|
||||||
|
// once in each package that depends on it.
|
||||||
|
// Only print each once.
|
||||||
|
printed := map[*PackageError]bool{}
|
||||||
for _, err := range p.DepsErrors {
|
for _, err := range p.DepsErrors {
|
||||||
|
if !printed[err] {
|
||||||
|
printed[err] = true
|
||||||
errorf("%s", err)
|
errorf("%s", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
exitIfErrors()
|
exitIfErrors()
|
||||||
if p.Name != "main" {
|
if p.Name != "main" {
|
||||||
fatalf("go run: cannot run non-main package")
|
fatalf("go run: cannot run non-main package")
|
||||||
|
Loading…
Reference in New Issue
Block a user