vgo: initial copy of cmd/go, adapted to build and run standalone No vgo-specific changes yet.
diff --git a/main.go b/main.go new file mode 100644 index 0000000..dde0b98 --- /dev/null +++ b/main.go
@@ -0,0 +1,11 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import Main "cmd/go" + +func main() { + Main.Main() +}
diff --git a/vendor/cmd/go/alldocs.go b/vendor/cmd/go/alldocs.go new file mode 100644 index 0000000..5231eb7 --- /dev/null +++ b/vendor/cmd/go/alldocs.go
@@ -0,0 +1,1824 @@ +// Copyright 2011 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. + +// DO NOT EDIT THIS FILE. GENERATED BY mkalldocs.sh. +// Edit the documentation in other files and rerun mkalldocs.sh to generate this one. + +// Go is a tool for managing Go source code. +// +// Usage: +// +// go command [arguments] +// +// The commands are: +// +// bug start a bug report +// build compile packages and dependencies +// clean remove object files and cached files +// doc show documentation for package or symbol +// env print Go environment information +// fix update packages to use new APIs +// fmt gofmt (reformat) package sources +// generate generate Go files by processing source +// get download and install packages and dependencies +// install compile and install packages and dependencies +// list list packages +// run compile and run Go program +// test test packages +// tool run specified go tool +// version print Go version +// vet report likely mistakes in packages +// +// Use "go help [command]" for more information about a command. +// +// Additional help topics: +// +// buildmode build modes +// c calling between Go and C +// cache build and test caching +// environment environment variables +// filetype file types +// gopath GOPATH environment variable +// importpath import path syntax +// packages package lists +// testflag testing flags +// testfunc testing functions +// +// Use "go help [topic]" for more information about that topic. +// +// +// Start a bug report +// +// Usage: +// +// go bug +// +// Bug opens the default browser and starts a new bug report. +// The report includes useful system information. +// +// +// Compile packages and dependencies +// +// Usage: +// +// go build [-o output] [-i] [build flags] [packages] +// +// Build compiles the packages named by the import paths, +// along with their dependencies, but it does not install the results. +// +// If the arguments to build are a list of .go files, build treats +// them as a list of source files specifying a single package. +// +// When compiling a single main package, build writes +// the resulting executable to an output file named after +// the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe') +// or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe'). +// The '.exe' suffix is added when writing a Windows executable. +// +// When compiling multiple packages or a single non-main package, +// build compiles the packages but discards the resulting object, +// serving only as a check that the packages can be built. +// +// When compiling packages, build ignores files that end in '_test.go'. +// +// The -o flag, only allowed when compiling a single package, +// forces build to write the resulting executable or object +// to the named output file, instead of the default behavior described +// in the last two paragraphs. +// +// The -i flag installs the packages that are dependencies of the target. +// +// The build flags are shared by the build, clean, get, install, list, run, +// and test commands: +// +// -a +// force rebuilding of packages that are already up-to-date. +// -n +// print the commands but do not run them. +// -p n +// the number of programs, such as build commands or +// test binaries, that can be run in parallel. +// The default is the number of CPUs available. +// -race +// enable data race detection. +// Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. +// -msan +// enable interoperation with memory sanitizer. +// Supported only on linux/amd64, +// and only with Clang/LLVM as the host C compiler. +// -v +// print the names of packages as they are compiled. +// -work +// print the name of the temporary work directory and +// do not delete it when exiting. +// -x +// print the commands. +// +// -asmflags '[pattern=]arg list' +// arguments to pass on each go tool asm invocation. +// -buildmode mode +// build mode to use. See 'go help buildmode' for more. +// -compiler name +// name of compiler to use, as in runtime.Compiler (gccgo or gc). +// -gccgoflags '[pattern=]arg list' +// arguments to pass on each gccgo compiler/linker invocation. +// -gcflags '[pattern=]arg list' +// arguments to pass on each go tool compile invocation. +// -installsuffix suffix +// a suffix to use in the name of the package installation directory, +// in order to keep output separate from default builds. +// If using the -race flag, the install suffix is automatically set to race +// or, if set explicitly, has _race appended to it. Likewise for the -msan +// flag. Using a -buildmode option that requires non-default compile flags +// has a similar effect. +// -ldflags '[pattern=]arg list' +// arguments to pass on each go tool link invocation. +// -linkshared +// link against shared libraries previously created with +// -buildmode=shared. +// -pkgdir dir +// install and load all packages from dir instead of the usual locations. +// For example, when building with a non-standard configuration, +// use -pkgdir to keep generated packages in a separate location. +// -tags 'tag list' +// a space-separated list of build tags to consider satisfied during the +// build. For more information about build tags, see the description of +// build constraints in the documentation for the go/build package. +// -toolexec 'cmd args' +// a program to use to invoke toolchain programs like vet and asm. +// For example, instead of running asm, the go command will run +// 'cmd args /path/to/asm <arguments for asm>'. +// +// The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a +// space-separated list of arguments to pass to an underlying tool +// during the build. To embed spaces in an element in the list, surround +// it with either single or double quotes. The argument list may be +// preceded by a package pattern and an equal sign, which restricts +// the use of that argument list to the building of packages matching +// that pattern (see 'go help packages' for a description of package +// patterns). Without a pattern, the argument list applies only to the +// packages named on the command line. The flags may be repeated +// with different patterns in order to specify different arguments for +// different sets of packages. If a package matches patterns given in +// multiple flags, the latest match on the command line wins. +// For example, 'go build -gcflags=-S fmt' prints the disassembly +// only for package fmt, while 'go build -gcflags=all=-S fmt' +// prints the disassembly for fmt and all its dependencies. +// +// For more about specifying packages, see 'go help packages'. +// For more about where packages and binaries are installed, +// run 'go help gopath'. +// For more about calling between Go and C/C++, run 'go help c'. +// +// Note: Build adheres to certain conventions such as those described +// by 'go help gopath'. Not all projects can follow these conventions, +// however. Installations that have their own conventions or that use +// a separate software build system may choose to use lower-level +// invocations such as 'go tool compile' and 'go tool link' to avoid +// some of the overheads and design decisions of the build tool. +// +// See also: go install, go get, go clean. +// +// +// Remove object files and cached files +// +// Usage: +// +// go clean [-i] [-r] [-n] [-x] [-cache] [-testcache] [build flags] [packages] +// +// Clean removes object files from package source directories. +// The go command builds most objects in a temporary directory, +// so go clean is mainly concerned with object files left by other +// tools or by manual invocations of go build. +// +// Specifically, clean removes the following files from each of the +// source directories corresponding to the import paths: +// +// _obj/ old object directory, left from Makefiles +// _test/ old test directory, left from Makefiles +// _testmain.go old gotest file, left from Makefiles +// test.out old test log, left from Makefiles +// build.out old test log, left from Makefiles +// *.[568ao] object files, left from Makefiles +// +// DIR(.exe) from go build +// DIR.test(.exe) from go test -c +// MAINFILE(.exe) from go build MAINFILE.go +// *.so from SWIG +// +// In the list, DIR represents the final path element of the +// directory, and MAINFILE is the base name of any Go source +// file in the directory that is not included when building +// the package. +// +// The -i flag causes clean to remove the corresponding installed +// archive or binary (what 'go install' would create). +// +// The -n flag causes clean to print the remove commands it would execute, +// but not run them. +// +// The -r flag causes clean to be applied recursively to all the +// dependencies of the packages named by the import paths. +// +// The -x flag causes clean to print remove commands as it executes them. +// +// The -cache flag causes clean to remove the entire go build cache. +// +// The -testcache flag causes clean to expire all test results in the +// go build cache. +// +// For more about build flags, see 'go help build'. +// +// For more about specifying packages, see 'go help packages'. +// +// +// Show documentation for package or symbol +// +// Usage: +// +// go doc [-u] [-c] [package|[package.]symbol[.methodOrField]] +// +// Doc prints the documentation comments associated with the item identified by its +// arguments (a package, const, func, type, var, method, or struct field) +// followed by a one-line summary of each of the first-level items "under" +// that item (package-level declarations for a package, methods for a type, +// etc.). +// +// Doc accepts zero, one, or two arguments. +// +// Given no arguments, that is, when run as +// +// go doc +// +// it prints the package documentation for the package in the current directory. +// If the package is a command (package main), the exported symbols of the package +// are elided from the presentation unless the -cmd flag is provided. +// +// When run with one argument, the argument is treated as a Go-syntax-like +// representation of the item to be documented. What the argument selects depends +// on what is installed in GOROOT and GOPATH, as well as the form of the argument, +// which is schematically one of these: +// +// go doc <pkg> +// go doc <sym>[.<methodOrField>] +// go doc [<pkg>.]<sym>[.<methodOrField>] +// go doc [<pkg>.][<sym>.]<methodOrField> +// +// The first item in this list matched by the argument is the one whose documentation +// is printed. (See the examples below.) However, if the argument starts with a capital +// letter it is assumed to identify a symbol or method in the current directory. +// +// For packages, the order of scanning is determined lexically in breadth-first order. +// That is, the package presented is the one that matches the search and is nearest +// the root and lexically first at its level of the hierarchy. The GOROOT tree is +// always scanned in its entirety before GOPATH. +// +// If there is no package specified or matched, the package in the current +// directory is selected, so "go doc Foo" shows the documentation for symbol Foo in +// the current package. +// +// The package path must be either a qualified path or a proper suffix of a +// path. The go tool's usual package mechanism does not apply: package path +// elements like . and ... are not implemented by go doc. +// +// When run with two arguments, the first must be a full package path (not just a +// suffix), and the second is a symbol, or symbol with method or struct field. +// This is similar to the syntax accepted by godoc: +// +// go doc <pkg> <sym>[.<methodOrField>] +// +// In all forms, when matching symbols, lower-case letters in the argument match +// either case but upper-case letters match exactly. This means that there may be +// multiple matches of a lower-case argument in a package if different symbols have +// different cases. If this occurs, documentation for all matches is printed. +// +// Examples: +// go doc +// Show documentation for current package. +// go doc Foo +// Show documentation for Foo in the current package. +// (Foo starts with a capital letter so it cannot match +// a package path.) +// go doc encoding/json +// Show documentation for the encoding/json package. +// go doc json +// Shorthand for encoding/json. +// go doc json.Number (or go doc json.number) +// Show documentation and method summary for json.Number. +// go doc json.Number.Int64 (or go doc json.number.int64) +// Show documentation for json.Number's Int64 method. +// go doc cmd/doc +// Show package docs for the doc command. +// go doc -cmd cmd/doc +// Show package docs and exported symbols within the doc command. +// go doc template.new +// Show documentation for html/template's New function. +// (html/template is lexically before text/template) +// go doc text/template.new # One argument +// Show documentation for text/template's New function. +// go doc text/template new # Two arguments +// Show documentation for text/template's New function. +// +// At least in the current tree, these invocations all print the +// documentation for json.Decoder's Decode method: +// +// go doc json.Decoder.Decode +// go doc json.decoder.decode +// go doc json.decode +// cd go/src/encoding/json; go doc decode +// +// Flags: +// -c +// Respect case when matching symbols. +// -cmd +// Treat a command (package main) like a regular package. +// Otherwise package main's exported symbols are hidden +// when showing the package's top-level documentation. +// -u +// Show documentation for unexported as well as exported +// symbols, methods, and fields. +// +// +// Print Go environment information +// +// Usage: +// +// go env [-json] [var ...] +// +// Env prints Go environment information. +// +// By default env prints information as a shell script +// (on Windows, a batch file). If one or more variable +// names is given as arguments, env prints the value of +// each named variable on its own line. +// +// The -json flag prints the environment in JSON format +// instead of as a shell script. +// +// For more about environment variables, see 'go help environment'. +// +// +// Update packages to use new APIs +// +// Usage: +// +// go fix [packages] +// +// Fix runs the Go fix command on the packages named by the import paths. +// +// For more about fix, see 'go doc cmd/fix'. +// For more about specifying packages, see 'go help packages'. +// +// To run fix with specific options, run 'go tool fix'. +// +// See also: go fmt, go vet. +// +// +// Gofmt (reformat) package sources +// +// Usage: +// +// go fmt [-n] [-x] [packages] +// +// Fmt runs the command 'gofmt -l -w' on the packages named +// by the import paths. It prints the names of the files that are modified. +// +// For more about gofmt, see 'go doc cmd/gofmt'. +// For more about specifying packages, see 'go help packages'. +// +// The -n flag prints commands that would be executed. +// The -x flag prints commands as they are executed. +// +// To run gofmt with specific options, run gofmt itself. +// +// See also: go fix, go vet. +// +// +// Generate Go files by processing source +// +// Usage: +// +// go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages] +// +// Generate runs commands described by directives within existing +// files. Those commands can run any process but the intent is to +// create or update Go source files. +// +// Go generate is never run automatically by go build, go get, go test, +// and so on. It must be run explicitly. +// +// Go generate scans the file for directives, which are lines of +// the form, +// +// //go:generate command argument... +// +// (note: no leading spaces and no space in "//go") where command +// is the generator to be run, corresponding to an executable file +// 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. +// +// 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. +// +// The arguments to the directive are space-separated tokens or +// double-quoted strings passed to the generator as individual +// 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. +// +// Go generate sets several variables when it runs the generator: +// +// $GOARCH +// The execution architecture (arm, amd64, etc.) +// $GOOS +// The execution operating system (linux, windows, etc.) +// $GOFILE +// The base name of the file. +// $GOLINE +// The line number of the directive in the source file. +// $GOPACKAGE +// The name of the package of the file containing the directive. +// $DOLLAR +// A dollar sign. +// +// Other than variable substitution and quoted-string evaluation, no +// special processing such as "globbing" is performed on the command +// line. +// +// As a last step before running the command, any invocations of any +// environment variables with alphanumeric names, such as $GOFILE or +// $HOME, are expanded throughout the command line. The syntax for +// variable expansion is $NAME on all operating systems. Due to the +// order of evaluation, variables are expanded even inside quoted +// strings. If the variable NAME is not set, $NAME expands to the +// empty string. +// +// A directive of the form, +// +// //go:generate -command xxx args... +// +// specifies, for the remainder of this source file only, that the +// string xxx represents the command identified by the arguments. This +// can be used to create aliases or to handle multiword generators. +// For example, +// +// //go:generate -command foo go tool foo +// +// specifies that the command "foo" represents the generator +// "go tool foo". +// +// Generate processes packages in the order given on the command line, +// one at a time. If the command line lists .go files, they are treated +// as a single package. Within a package, generate processes the +// source files in a package in file name order, one at a time. Within +// a source file, generate runs generators in the order they appear +// in the file, one at a time. +// +// If any generator returns an error exit status, "go generate" skips +// all further processing for that package. +// +// The generator is run in the package's source directory. +// +// Go generate accepts one specific flag: +// +// -run="" +// if non-empty, specifies a regular expression to select +// directives whose full original source text (excluding +// any trailing spaces and final newline) matches the +// expression. +// +// It also accepts the standard build flags including -v, -n, and -x. +// The -v flag prints the names of packages and files as they are +// processed. +// The -n flag prints commands that would be executed. +// The -x flag prints commands as they are executed. +// +// For more about build flags, see 'go help build'. +// +// For more about specifying packages, see 'go help packages'. +// +// +// Download and install packages and dependencies +// +// Usage: +// +// go get [-d] [-f] [-fix] [-insecure] [-t] [-u] [-v] [build flags] [packages] +// +// Get downloads the packages named by the import paths, along with their +// dependencies. It then installs the named packages, like 'go install'. +// +// The -d flag instructs get to stop after downloading the packages; that is, +// it instructs get not to install the packages. +// +// The -f flag, valid only when -u is set, forces get -u not to verify that +// each package has been checked out from the source control repository +// implied by its import path. This can be useful if the source is a local fork +// of the original. +// +// The -fix flag instructs get to run the fix tool on the downloaded packages +// before resolving dependencies or building the code. +// +// The -insecure flag permits fetching from repositories and resolving +// custom domains using insecure schemes such as HTTP. Use with caution. +// +// The -t flag instructs get to also download the packages required to build +// the tests for the specified packages. +// +// The -u flag instructs get to use the network to update the named packages +// and their dependencies. By default, get uses the network to check out +// missing packages but does not use it to look for updates to existing packages. +// +// The -v flag enables verbose progress and debug output. +// +// Get also accepts build flags to control the installation. See 'go help build'. +// +// When checking out a new package, get creates the target directory +// GOPATH/src/<import-path>. If the GOPATH contains multiple entries, +// get uses the first one. For more details see: 'go help gopath'. +// +// When checking out or updating a package, get looks for a branch or tag +// that matches the locally installed version of Go. The most important +// rule is that if the local installation is running version "go1", get +// searches for a branch or tag named "go1". If no such version exists +// it retrieves the default branch of the package. +// +// When go get checks out or updates a Git repository, +// it also updates any git submodules referenced by the repository. +// +// Get never checks out or updates code stored in vendor directories. +// +// For more about specifying packages, see 'go help packages'. +// +// For more about how 'go get' finds source code to +// download, see 'go help importpath'. +// +// See also: go build, go install, go clean. +// +// +// Compile and install packages and dependencies +// +// Usage: +// +// go install [-i] [build flags] [packages] +// +// Install compiles and installs the packages named by the import paths. +// +// The -i flag installs the dependencies of the named packages as well. +// +// For more about the build flags, see 'go help build'. +// For more about specifying packages, see 'go help packages'. +// +// See also: go build, go get, go clean. +// +// +// List packages +// +// Usage: +// +// go list [-e] [-f format] [-json] [build flags] [packages] +// +// List lists the packages named by the import paths, one per line. +// +// The default output shows the package import path: +// +// bytes +// encoding/json +// github.com/gorilla/mux +// golang.org/x/net/html +// +// The -f flag specifies an alternate format for the list, using the +// syntax of package template. The default output is equivalent to -f +// '{{.ImportPath}}'. The struct being passed to the template is: +// +// type Package struct { +// Dir string // directory containing package sources +// ImportPath string // import path of package in dir +// ImportComment string // path in import comment on package statement +// Name string // package name +// Doc string // package documentation string +// Target string // install path +// Shlib string // the shared library that contains this package (only set when -linkshared) +// Goroot bool // is this package in the Go root? +// Standard bool // is this package part of the standard Go library? +// Stale bool // would 'go install' do anything for this package? +// StaleReason string // explanation for Stale==true +// Root string // Go root or Go path dir containing this package +// ConflictDir string // this directory shadows Dir in $GOPATH +// BinaryOnly bool // binary-only package: cannot be recompiled from sources +// +// // Source files +// GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) +// CgoFiles []string // .go sources files that import "C" +// IgnoredGoFiles []string // .go sources ignored due to build constraints +// CFiles []string // .c source files +// CXXFiles []string // .cc, .cxx and .cpp source files +// MFiles []string // .m source files +// HFiles []string // .h, .hh, .hpp and .hxx source files +// FFiles []string // .f, .F, .for and .f90 Fortran source files +// SFiles []string // .s source files +// SwigFiles []string // .swig files +// SwigCXXFiles []string // .swigcxx files +// SysoFiles []string // .syso object files to add to archive +// TestGoFiles []string // _test.go files in package +// XTestGoFiles []string // _test.go files outside package +// +// // Cgo directives +// CgoCFLAGS []string // cgo: flags for C compiler +// CgoCPPFLAGS []string // cgo: flags for C preprocessor +// CgoCXXFLAGS []string // cgo: flags for C++ compiler +// CgoFFLAGS []string // cgo: flags for Fortran compiler +// CgoLDFLAGS []string // cgo: flags for linker +// CgoPkgConfig []string // cgo: pkg-config names +// +// // Dependency information +// Imports []string // import paths used by this package +// Deps []string // all (recursively) imported dependencies +// TestImports []string // imports from TestGoFiles +// XTestImports []string // imports from XTestGoFiles +// +// // Error information +// Incomplete bool // this package or a dependency has an error +// Error *PackageError // error loading package +// DepsErrors []*PackageError // errors loading dependencies +// } +// +// Packages stored in vendor directories report an ImportPath that includes the +// path to the vendor directory (for example, "d/vendor/p" instead of "p"), +// so that the ImportPath uniquely identifies a given copy of a package. +// The Imports, Deps, TestImports, and XTestImports lists also contain these +// expanded imports paths. See golang.org/s/go15vendor for more about vendoring. +// +// The error information, if any, is +// +// type PackageError struct { +// ImportStack []string // shortest path from package named on command line to this one +// Pos string // position of error (if present, file:line:col) +// Err string // the error itself +// } +// +// The template function "join" calls strings.Join. +// +// The template function "context" returns the build context, defined as: +// +// type Context struct { +// GOARCH string // target architecture +// GOOS string // target operating system +// GOROOT string // Go root +// GOPATH string // Go path +// CgoEnabled bool // whether cgo can be used +// UseAllFiles bool // use files regardless of +build lines, file names +// Compiler string // compiler to assume when computing target paths +// BuildTags []string // build constraints to match in +build lines +// ReleaseTags []string // releases the current release is compatible with +// InstallSuffix string // suffix to use in the name of the install dir +// } +// +// For more information about the meaning of these fields see the documentation +// for the go/build package's Context type. +// +// The -json flag causes the package data to be printed in JSON format +// instead of using the template format. +// +// The -e flag changes the handling of erroneous packages, those that +// cannot be found or are malformed. By default, the list command +// prints an error to standard error for each erroneous package and +// omits the packages from consideration during the usual printing. +// With the -e flag, the list command never prints errors to standard +// error and instead processes the erroneous packages with the usual +// printing. Erroneous packages will have a non-empty ImportPath and +// a non-nil Error field; other information may or may not be missing +// (zeroed). +// +// For more about build flags, see 'go help build'. +// +// For more about specifying packages, see 'go help packages'. +// +// +// Compile and run Go program +// +// Usage: +// +// go run [build flags] [-exec xprog] gofiles... [arguments...] +// +// Run compiles and runs the main package comprising the named Go source files. +// A Go source file is defined to be a file ending in a literal ".go" suffix. +// +// By default, 'go run' runs the compiled binary directly: 'a.out arguments...'. +// If the -exec flag is given, 'go run' invokes the binary using xprog: +// 'xprog a.out arguments...'. +// If the -exec flag is not given, GOOS or GOARCH is different from the system +// default, and a program named go_$GOOS_$GOARCH_exec can be found +// on the current search path, 'go run' invokes the binary using that program, +// for example 'go_nacl_386_exec a.out arguments...'. This allows execution of +// cross-compiled programs when a simulator or other execution method is +// available. +// +// For more about build flags, see 'go help build'. +// +// See also: go build. +// +// +// Test packages +// +// Usage: +// +// go test [build/test flags] [packages] [build/test flags & test binary flags] +// +// 'Go test' automates testing the packages named by the import paths. +// It prints a summary of the test results in the format: +// +// ok archive/tar 0.011s +// FAIL archive/zip 0.022s +// ok compress/gzip 0.033s +// ... +// +// followed by detailed output for each failed package. +// +// 'Go test' recompiles each package along with any files with names matching +// the file pattern "*_test.go". +// These additional files can contain test functions, benchmark functions, and +// example functions. See 'go help testfunc' for more. +// Each listed package causes the execution of a separate test binary. +// Files whose names begin with "_" (including "_test.go") or "." are ignored. +// +// Test files that declare a package with the suffix "_test" will be compiled as a +// separate package, and then linked and run with the main test binary. +// +// The go tool will ignore a directory named "testdata", making it available +// to hold ancillary data needed by the tests. +// +// As part of building a test binary, go test runs go vet on the package +// and its test source files to identify significant problems. If go vet +// finds any problems, go test reports those and does not run the test binary. +// Only a high-confidence subset of the default go vet checks are used. +// To disable the running of go vet, use the -vet=off flag. +// +// All test output and summary lines are printed to the go command's +// standard output, even if the test printed them to its own standard +// error. (The go command's standard error is reserved for printing +// errors building the tests.) +// +// Go test runs in two different modes: +// +// The first, called local directory mode, occurs when go test is +// invoked with no package arguments (for example, 'go test' or 'go +// test -v'). In this mode, go test compiles the package sources and +// tests found in the current directory and then runs the resulting +// test binary. In this mode, caching (discussed below) is disabled. +// After the package test finishes, go test prints a summary line +// showing the test status ('ok' or 'FAIL'), package name, and elapsed +// time. +// +// The second, called package list mode, occurs when go test is invoked +// with explicit package arguments (for example 'go test math', 'go +// test ./...', and even 'go test .'). In this mode, go test compiles +// and tests each of the packages listed on the command line. If a +// package test passes, go test prints only the final 'ok' summary +// line. If a package test fails, go test prints the full test output. +// If invoked with the -bench or -v flag, go test prints the full +// output even for passing package tests, in order to display the +// requested benchmark results or verbose logging. +// +// In package list mode only, go test caches successful package test +// results to avoid unnecessary repeated running of tests. When the +// result of a test can be recovered from the cache, go test will +// redisplay the previous output instead of running the test binary +// again. When this happens, go test prints '(cached)' in place of the +// elapsed time in the summary line. +// +// The rule for a match in the cache is that the run involves the same +// test binary and the flags on the command line come entirely from a +// restricted set of 'cacheable' test flags, defined as -cpu, -list, +// -parallel, -run, -short, and -v. If a run of go test has any test +// or non-test flags outside this set, the result is not cached. To +// disable test caching, use any test flag or argument other than the +// cacheable flags. The idiomatic way to disable test caching explicitly +// is to use -count=1. Tests that open files within the package's source +// root (usually $GOPATH) or that consult environment variables only +// match future runs in which the files and environment variables are unchanged. +// A cached test result is treated as executing in no time at all, +// so a successful package test result will be cached and reused +// regardless of -timeout setting. +// +// In addition to the build flags, the flags handled by 'go test' itself are: +// +// -args +// Pass the remainder of the command line (everything after -args) +// to the test binary, uninterpreted and unchanged. +// Because this flag consumes the remainder of the command line, +// the package list (if present) must appear before this flag. +// +// -c +// Compile the test binary to pkg.test but do not run it +// (where pkg is the last element of the package's import path). +// The file name can be changed with the -o flag. +// +// -exec xprog +// Run the test binary using xprog. The behavior is the same as +// in 'go run'. See 'go help run' for details. +// +// -i +// Install packages that are dependencies of the test. +// Do not run the test. +// +// -json +// Convert test output to JSON suitable for automated processing. +// See 'go doc test2json' for the encoding details. +// +// -o file +// Compile the test binary to the named file. +// The test still runs (unless -c or -i is specified). +// +// The test binary also accepts flags that control execution of the test; these +// flags are also accessible by 'go test'. See 'go help testflag' for details. +// +// For more about build flags, see 'go help build'. +// For more about specifying packages, see 'go help packages'. +// +// See also: go build, go vet. +// +// +// Run specified go tool +// +// Usage: +// +// go tool [-n] command [args...] +// +// Tool runs the go tool command identified by the arguments. +// With no arguments it prints the list of known tools. +// +// The -n flag causes tool to print the command that would be +// executed but not execute it. +// +// For more about each tool command, see 'go doc cmd/<command>'. +// +// +// Print Go version +// +// Usage: +// +// go version +// +// Version prints the Go version, as reported by runtime.Version. +// +// +// Report likely mistakes in packages +// +// Usage: +// +// go vet [-n] [-x] [build flags] [vet flags] [packages] +// +// Vet runs the Go vet command on the packages named by the import paths. +// +// For more about vet and its flags, see 'go doc cmd/vet'. +// For more about specifying packages, see 'go help packages'. +// +// The -n flag prints commands that would be executed. +// The -x flag prints commands as they are executed. +// +// The build flags supported by go vet are those that control package resolution +// and execution, such as -n, -x, -v, -tags, and -toolexec. +// For more about these flags, see 'go help build'. +// +// See also: go fmt, go fix. +// +// +// Build modes +// +// The 'go build' and 'go install' commands take a -buildmode argument which +// indicates which kind of object file is to be built. Currently supported values +// are: +// +// -buildmode=archive +// Build the listed non-main packages into .a files. Packages named +// main are ignored. +// +// -buildmode=c-archive +// Build the listed main package, plus all packages it imports, +// into a C archive file. The only callable symbols will be those +// functions exported using a cgo //export comment. Requires +// exactly one main package to be listed. +// +// -buildmode=c-shared +// Build the listed main package, plus all packages it imports, +// into a C shared library. The only callable symbols will +// be those functions exported using a cgo //export comment. +// Requires exactly one main package to be listed. +// +// -buildmode=default +// Listed main packages are built into executables and listed +// non-main packages are built into .a files (the default +// behavior). +// +// -buildmode=shared +// Combine all the listed non-main packages into a single shared +// library that will be used when building with the -linkshared +// option. Packages named main are ignored. +// +// -buildmode=exe +// Build the listed main packages and everything they import into +// executables. Packages not named main are ignored. +// +// -buildmode=pie +// Build the listed main packages and everything they import into +// position independent executables (PIE). Packages not named +// main are ignored. +// +// -buildmode=plugin +// Build the listed main packages, plus all packages that they +// import, into a Go plugin. Packages not named main are ignored. +// +// +// Calling between Go and C +// +// There are two different ways to call between Go and C/C++ code. +// +// The first is the cgo tool, which is part of the Go distribution. For +// information on how to use it see the cgo documentation (go doc cmd/cgo). +// +// The second is the SWIG program, which is a general tool for +// interfacing between languages. For information on SWIG see +// http://swig.org/. When running go build, any file with a .swig +// extension will be passed to SWIG. Any file with a .swigcxx extension +// will be passed to SWIG with the -c++ option. +// +// When either cgo or SWIG is used, go build will pass any .c, .m, .s, +// or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++ +// compiler. The CC or CXX environment variables may be set to determine +// the C or C++ compiler, respectively, to use. +// +// +// Build and test caching +// +// The go command caches build outputs for reuse in future builds. +// The default location for cache data is a subdirectory named go-build +// in the standard user cache directory for the current operating system. +// Setting the GOCACHE environment variable overrides this default, +// and running 'go env GOCACHE' prints the current cache directory. +// +// The go command periodically deletes cached data that has not been +// used recently. Running 'go clean -cache' deletes all cached data. +// +// The build cache correctly accounts for changes to Go source files, +// compilers, compiler options, and so on: cleaning the cache explicitly +// should not be necessary in typical use. However, the build cache +// does not detect changes to C libraries imported with cgo. +// If you have made changes to the C libraries on your system, you +// will need to clean the cache explicitly or else use the -a build flag +// (see 'go help build') to force rebuilding of packages that +// depend on the updated C libraries. +// +// The go command also caches successful package test results. +// See 'go help test' for details. Running 'go clean -testcache' removes +// all cached test results (but not cached build results). +// +// The GODEBUG environment variable can enable printing of debugging +// information about the state of the cache: +// +// GODEBUG=gocacheverify=1 causes the go command to bypass the +// use of any cache entries and instead rebuild everything and check +// that the results match existing cache entries. +// +// GODEBUG=gocachehash=1 causes the go command to print the inputs +// for all of the content hashes it uses to construct cache lookup keys. +// The output is voluminous but can be useful for debugging the cache. +// +// GODEBUG=gocachetest=1 causes the go command to print details of its +// decisions about whether to reuse a cached test result. +// +// +// Environment variables +// +// The go command, and the tools it invokes, examine a few different +// environment variables. For many of these, you can see the default +// value of on your system by running 'go env NAME', where NAME is the +// name of the variable. +// +// General-purpose environment variables: +// +// GCCGO +// The gccgo command to run for 'go build -compiler=gccgo'. +// GOARCH +// The architecture, or processor, for which to compile code. +// Examples are amd64, 386, arm, ppc64. +// GOBIN +// The directory where 'go install' will install a command. +// GOOS +// The operating system for which to compile code. +// Examples are linux, darwin, windows, netbsd. +// GOPATH +// For more details see: 'go help gopath'. +// GORACE +// Options for the race detector. +// See https://golang.org/doc/articles/race_detector.html. +// GOROOT +// The root of the go tree. +// GOTMPDIR +// The directory where the go command will write +// temporary source files, packages, and binaries. +// GOCACHE +// The directory where the go command will store +// cached information for reuse in future builds. +// +// Environment variables for use with cgo: +// +// CC +// The command to use to compile C code. +// CGO_ENABLED +// Whether the cgo command is supported. Either 0 or 1. +// CGO_CFLAGS +// Flags that cgo will pass to the compiler when compiling +// C code. +// CGO_CFLAGS_ALLOW +// A regular expression specifying additional flags to allow +// to appear in #cgo CFLAGS source code directives. +// Does not apply to the CGO_CFLAGS environment variable. +// CGO_CFLAGS_DISALLOW +// A regular expression specifying flags that must be disallowed +// from appearing in #cgo CFLAGS source code directives. +// Does not apply to the CGO_CFLAGS environment variable. +// CGO_CPPFLAGS, CGO_CPPFLAGS_ALLOW, CGO_CPPFLAGS_DISALLOW +// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, +// but for the C preprocessor. +// CGO_CXXFLAGS, CGO_CXXFLAGS_ALLOW, CGO_CXXFLAGS_DISALLOW +// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, +// but for the C++ compiler. +// CGO_FFLAGS, CGO_FFLAGS_ALLOW, CGO_FFLAGS_DISALLOW +// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, +// but for the Fortran compiler. +// CGO_LDFLAGS, CGO_LDFLAGS_ALLOW, CGO_LDFLAGS_DISALLOW +// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, +// but for the linker. +// CXX +// The command to use to compile C++ code. +// PKG_CONFIG +// Path to pkg-config tool. +// +// Architecture-specific environment variables: +// +// GOARM +// For GOARCH=arm, the ARM architecture for which to compile. +// Valid values are 5, 6, 7. +// GO386 +// For GOARCH=386, the floating point instruction set. +// Valid values are 387, sse2. +// GOMIPS +// For GOARCH=mips{,le}, whether to use floating point instructions. +// Valid values are hardfloat (default), softfloat. +// +// Special-purpose environment variables: +// +// GOROOT_FINAL +// The root of the installed Go tree, when it is +// installed in a location other than where it is built. +// File names in stack traces are rewritten from GOROOT to +// GOROOT_FINAL. +// GO_EXTLINK_ENABLED +// Whether the linker should use external linking mode +// when using -linkmode=auto with code that uses cgo. +// Set to 0 to disable external linking mode, 1 to enable it. +// GIT_ALLOW_PROTOCOL +// Defined by Git. A colon-separated list of schemes that are allowed to be used +// with git fetch/clone. If set, any scheme not explicitly mentioned will be +// considered insecure by 'go get'. +// +// +// File types +// +// The go command examines the contents of a restricted set of files +// in each directory. It identifies which files to examine based on +// the extension of the file name. These extensions are: +// +// .go +// Go source files. +// .c, .h +// C source files. +// If the package uses cgo or SWIG, these will be compiled with the +// OS-native compiler (typically gcc); otherwise they will +// trigger an error. +// .cc, .cpp, .cxx, .hh, .hpp, .hxx +// C++ source files. Only useful with cgo or SWIG, and always +// compiled with the OS-native compiler. +// .m +// Objective-C source files. Only useful with cgo, and always +// compiled with the OS-native compiler. +// .s, .S +// Assembler source files. +// If the package uses cgo or SWIG, these will be assembled with the +// OS-native assembler (typically gcc (sic)); otherwise they +// will be assembled with the Go assembler. +// .swig, .swigcxx +// SWIG definition files. +// .syso +// System object files. +// +// Files of each of these types except .syso may contain build +// constraints, but the go command stops scanning for build constraints +// at the first item in the file that is not a blank line or //-style +// line comment. See the go/build package documentation for +// more details. +// +// Non-test Go source files can also include a //go:binary-only-package +// comment, indicating that the package sources are included +// for documentation only and must not be used to build the +// package binary. This enables distribution of Go packages in +// their compiled form alone. Even binary-only packages require +// accurate import blocks listing required dependencies, so that +// those dependencies can be supplied when linking the resulting +// command. +// +// +// GOPATH environment variable +// +// The Go path is used to resolve import statements. +// It is implemented by and documented in the go/build package. +// +// The GOPATH environment variable lists places to look for Go code. +// On Unix, the value is a colon-separated string. +// On Windows, the value is a semicolon-separated string. +// On Plan 9, the value is a list. +// +// If the environment variable is unset, GOPATH defaults +// to a subdirectory named "go" in the user's home directory +// ($HOME/go on Unix, %USERPROFILE%\go on Windows), +// unless that directory holds a Go distribution. +// Run "go env GOPATH" to see the current GOPATH. +// +// See https://golang.org/wiki/SettingGOPATH to set a custom GOPATH. +// +// Each directory listed in GOPATH must have a prescribed structure: +// +// The src directory holds source code. The path below src +// determines the import path or executable name. +// +// The pkg directory holds installed package objects. +// As in the Go tree, each target operating system and +// architecture pair has its own subdirectory of pkg +// (pkg/GOOS_GOARCH). +// +// If DIR is a directory listed in the GOPATH, a package with +// source in DIR/src/foo/bar can be imported as "foo/bar" and +// has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a". +// +// The bin directory holds compiled commands. +// Each command is named for its source directory, but only +// the final element, not the entire path. That is, the +// command with source in DIR/src/foo/quux is installed into +// DIR/bin/quux, not DIR/bin/foo/quux. The "foo/" prefix is stripped +// so that you can add DIR/bin to your PATH to get at the +// installed commands. If the GOBIN environment variable is +// set, commands are installed to the directory it names instead +// of DIR/bin. GOBIN must be an absolute path. +// +// Here's an example directory layout: +// +// GOPATH=/home/user/go +// +// /home/user/go/ +// src/ +// foo/ +// bar/ (go code in package bar) +// x.go +// quux/ (go code in package main) +// y.go +// bin/ +// quux (installed command) +// pkg/ +// linux_amd64/ +// foo/ +// bar.a (installed package object) +// +// Go searches each directory listed in GOPATH to find source code, +// but new packages are always downloaded into the first directory +// in the list. +// +// See https://golang.org/doc/code.html for an example. +// +// Internal Directories +// +// Code in or below a directory named "internal" is importable only +// by code in the directory tree rooted at the parent of "internal". +// Here's an extended version of the directory layout above: +// +// /home/user/go/ +// src/ +// crash/ +// bang/ (go code in package bang) +// b.go +// foo/ (go code in package foo) +// f.go +// bar/ (go code in package bar) +// x.go +// internal/ +// baz/ (go code in package baz) +// z.go +// quux/ (go code in package main) +// y.go +// +// +// The code in z.go is imported as "foo/internal/baz", but that +// import statement can only appear in source files in the subtree +// rooted at foo. The source files foo/f.go, foo/bar/x.go, and +// foo/quux/y.go can all import "foo/internal/baz", but the source file +// crash/bang/b.go cannot. +// +// See https://golang.org/s/go14internal for details. +// +// Vendor Directories +// +// Go 1.6 includes support for using local copies of external dependencies +// to satisfy imports of those dependencies, often referred to as vendoring. +// +// Code below a directory named "vendor" is importable only +// by code in the directory tree rooted at the parent of "vendor", +// and only using an import path that omits the prefix up to and +// including the vendor element. +// +// Here's the example from the previous section, +// but with the "internal" directory renamed to "vendor" +// and a new foo/vendor/crash/bang directory added: +// +// /home/user/go/ +// src/ +// crash/ +// bang/ (go code in package bang) +// b.go +// foo/ (go code in package foo) +// f.go +// bar/ (go code in package bar) +// x.go +// vendor/ +// crash/ +// bang/ (go code in package bang) +// b.go +// baz/ (go code in package baz) +// z.go +// quux/ (go code in package main) +// y.go +// +// The same visibility rules apply as for internal, but the code +// in z.go is imported as "baz", not as "foo/vendor/baz". +// +// Code in vendor directories deeper in the source tree shadows +// code in higher directories. Within the subtree rooted at foo, an import +// of "crash/bang" resolves to "foo/vendor/crash/bang", not the +// top-level "crash/bang". +// +// Code in vendor directories is not subject to import path +// checking (see 'go help importpath'). +// +// When 'go get' checks out or updates a git repository, it now also +// updates submodules. +// +// Vendor directories do not affect the placement of new repositories +// being checked out for the first time by 'go get': those are always +// placed in the main GOPATH, never in a vendor subtree. +// +// See https://golang.org/s/go15vendor for details. +// +// +// Import path syntax +// +// An import path (see 'go help packages') denotes a package stored in the local +// file system. In general, an import path denotes either a standard package (such +// as "unicode/utf8") or a package found in one of the work spaces (For more +// details see: 'go help gopath'). +// +// Relative import paths +// +// An import path beginning with ./ or ../ is called a relative path. +// The toolchain supports relative import paths as a shortcut in two ways. +// +// First, a relative path can be used as a shorthand on the command line. +// If you are working in the directory containing the code imported as +// "unicode" and want to run the tests for "unicode/utf8", you can type +// "go test ./utf8" instead of needing to specify the full path. +// Similarly, in the reverse situation, "go test .." will test "unicode" from +// the "unicode/utf8" directory. Relative patterns are also allowed, like +// "go test ./..." to test all subdirectories. See 'go help packages' for details +// on the pattern syntax. +// +// Second, if you are compiling a Go program not in a work space, +// you can use a relative path in an import statement in that program +// to refer to nearby code also not in a work space. +// This makes it easy to experiment with small multipackage programs +// outside of the usual work spaces, but such programs cannot be +// installed with "go install" (there is no work space in which to install them), +// so they are rebuilt from scratch each time they are built. +// To avoid ambiguity, Go programs cannot use relative import paths +// within a work space. +// +// Remote import paths +// +// Certain import paths also +// describe how to obtain the source code for the package using +// a revision control system. +// +// A few common code hosting sites have special syntax: +// +// Bitbucket (Git, Mercurial) +// +// import "bitbucket.org/user/project" +// import "bitbucket.org/user/project/sub/directory" +// +// GitHub (Git) +// +// import "github.com/user/project" +// import "github.com/user/project/sub/directory" +// +// Launchpad (Bazaar) +// +// import "launchpad.net/project" +// import "launchpad.net/project/series" +// import "launchpad.net/project/series/sub/directory" +// +// import "launchpad.net/~user/project/branch" +// import "launchpad.net/~user/project/branch/sub/directory" +// +// IBM DevOps Services (Git) +// +// import "hub.jazz.net/git/user/project" +// import "hub.jazz.net/git/user/project/sub/directory" +// +// For code hosted on other servers, import paths may either be qualified +// with the version control type, or the go tool can dynamically fetch +// the import path over https/http and discover where the code resides +// from a <meta> tag in the HTML. +// +// To declare the code location, an import path of the form +// +// repository.vcs/path +// +// specifies the given repository, with or without the .vcs suffix, +// using the named version control system, and then the path inside +// that repository. The supported version control systems are: +// +// Bazaar .bzr +// Git .git +// Mercurial .hg +// Subversion .svn +// +// For example, +// +// import "example.org/user/foo.hg" +// +// denotes the root directory of the Mercurial repository at +// example.org/user/foo or foo.hg, and +// +// import "example.org/repo.git/foo/bar" +// +// denotes the foo/bar directory of the Git repository at +// example.org/repo or repo.git. +// +// When a version control system supports multiple protocols, +// each is tried in turn when downloading. For example, a Git +// download tries https://, then git+ssh://. +// +// By default, downloads are restricted to known secure protocols +// (e.g. https, ssh). To override this setting for Git downloads, the +// GIT_ALLOW_PROTOCOL environment variable can be set (For more details see: +// 'go help environment'). +// +// If the import path is not a known code hosting site and also lacks a +// version control qualifier, the go tool attempts to fetch the import +// over https/http and looks for a <meta> tag in the document's HTML +// <head>. +// +// The meta tag has the form: +// +// <meta name="go-import" content="import-prefix vcs repo-root"> +// +// The import-prefix is the import path corresponding to the repository +// root. It must be a prefix or an exact match of the package being +// fetched with "go get". If it's not an exact match, another http +// request is made at the prefix to verify the <meta> tags match. +// +// The meta tag should appear as early in the file as possible. +// In particular, it should appear before any raw JavaScript or CSS, +// to avoid confusing the go command's restricted parser. +// +// The vcs is one of "git", "hg", "svn", etc, +// +// The repo-root is the root of the version control system +// containing a scheme and not containing a .vcs qualifier. +// +// For example, +// +// import "example.org/pkg/foo" +// +// will result in the following requests: +// +// https://example.org/pkg/foo?go-get=1 (preferred) +// http://example.org/pkg/foo?go-get=1 (fallback, only with -insecure) +// +// If that page contains the meta tag +// +// <meta name="go-import" content="example.org git https://code.org/r/p/exproj"> +// +// the go tool will verify that https://example.org/?go-get=1 contains the +// same meta tag and then git clone https://code.org/r/p/exproj into +// GOPATH/src/example.org. +// +// New downloaded packages are written to the first directory listed in the GOPATH +// environment variable (For more details see: 'go help gopath'). +// +// The go command attempts to download the version of the +// package appropriate for the Go release being used. +// Run 'go help get' for more. +// +// Import path checking +// +// When the custom import path feature described above redirects to a +// known code hosting site, each of the resulting packages has two possible +// import paths, using the custom domain or the known hosting site. +// +// A package statement is said to have an "import comment" if it is immediately +// followed (before the next newline) by a comment of one of these two forms: +// +// package math // import "path" +// package math /* import "path" */ +// +// The go command will refuse to install a package with an import comment +// unless it is being referred to by that import path. In this way, import comments +// let package authors make sure the custom import path is used and not a +// direct path to the underlying code hosting site. +// +// Import path checking is disabled for code found within vendor trees. +// This makes it possible to copy code into alternate locations in vendor trees +// without needing to update import comments. +// +// See https://golang.org/s/go14customimport for details. +// +// +// Package lists +// +// Many commands apply to a set of packages: +// +// go action [packages] +// +// Usually, [packages] is a list of import paths. +// +// An import path that is a rooted path or that begins with +// a . or .. element is interpreted as a file system path and +// denotes the package in that directory. +// +// Otherwise, the import path P denotes the package found in +// the directory DIR/src/P for some DIR listed in the GOPATH +// environment variable (For more details see: 'go help gopath'). +// +// If no import paths are given, the action applies to the +// package in the current directory. +// +// There are four reserved names for paths that should not be used +// for packages to be built with the go tool: +// +// - "main" denotes the top-level package in a stand-alone executable. +// +// - "all" expands to all package directories found in all the GOPATH +// trees. For example, 'go list all' lists all the packages on the local +// system. +// +// - "std" is like all but expands to just the packages in the standard +// Go library. +// +// - "cmd" expands to the Go repository's commands and their +// internal libraries. +// +// Import paths beginning with "cmd/" only match source code in +// the Go repository. +// +// An import path is a pattern if it includes one or more "..." wildcards, +// each of which can match any string, including the empty string and +// strings containing slashes. Such a pattern expands to all package +// directories found in the GOPATH trees with names matching the +// patterns. +// +// To make common patterns more convenient, there are two special cases. +// First, /... at the end of the pattern can match an empty string, +// so that net/... matches both net and packages in its subdirectories, like net/http. +// Second, any slash-separated pattern element containing a wildcard never +// participates in a match of the "vendor" element in the path of a vendored +// package, so that ./... does not match packages in subdirectories of +// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do. +// Note, however, that a directory named vendor that itself contains code +// is not a vendored package: cmd/vendor would be a command named vendor, +// and the pattern cmd/... matches it. +// See golang.org/s/go15vendor for more about vendoring. +// +// An import path can also name a package to be downloaded from +// a remote repository. Run 'go help importpath' for details. +// +// Every package in a program must have a unique import path. +// By convention, this is arranged by starting each path with a +// unique prefix that belongs to you. For example, paths used +// internally at Google all begin with 'google', and paths +// denoting remote repositories begin with the path to the code, +// such as 'github.com/user/repo'. +// +// Packages in a program need not have unique package names, +// but there are two reserved package names with special meaning. +// The name main indicates a command, not a library. +// Commands are built into binaries and cannot be imported. +// The name documentation indicates documentation for +// a non-Go program in the directory. Files in package documentation +// are ignored by the go command. +// +// As a special case, if the package list is a list of .go files from a +// single directory, the command is applied to a single synthesized +// package made up of exactly those files, ignoring any build constraints +// in those files and ignoring any other files in the directory. +// +// Directory and file names that begin with "." or "_" are ignored +// by the go tool, as are directories named "testdata". +// +// +// Testing flags +// +// The 'go test' command takes both flags that apply to 'go test' itself +// and flags that apply to the resulting test binary. +// +// Several of the flags control profiling and write an execution profile +// suitable for "go tool pprof"; run "go tool pprof -h" for more +// information. The --alloc_space, --alloc_objects, and --show_bytes +// options of pprof control how the information is presented. +// +// The following flags are recognized by the 'go test' command and +// control the execution of any test: +// +// -bench regexp +// Run only those benchmarks matching a regular expression. +// By default, no benchmarks are run. +// To run all benchmarks, use '-bench .' or '-bench=.'. +// The regular expression is split by unbracketed slash (/) +// characters into a sequence of regular expressions, and each +// part of a benchmark's identifier must match the corresponding +// element in the sequence, if any. Possible parents of matches +// are run with b.N=1 to identify sub-benchmarks. For example, +// given -bench=X/Y, top-level benchmarks matching X are run +// with b.N=1 to find any sub-benchmarks matching Y, which are +// then run in full. +// +// -benchtime t +// Run enough iterations of each benchmark to take t, specified +// as a time.Duration (for example, -benchtime 1h30s). +// The default is 1 second (1s). +// +// -count n +// Run each test and benchmark n times (default 1). +// If -cpu is set, run n times for each GOMAXPROCS value. +// Examples are always run once. +// +// -cover +// Enable coverage analysis. +// Note that because coverage works by annotating the source +// code before compilation, compilation and test failures with +// coverage enabled may report line numbers that don't correspond +// to the original sources. +// +// -covermode set,count,atomic +// Set the mode for coverage analysis for the package[s] +// being tested. The default is "set" unless -race is enabled, +// in which case it is "atomic". +// The values: +// set: bool: does this statement run? +// count: int: how many times does this statement run? +// atomic: int: count, but correct in multithreaded tests; +// significantly more expensive. +// Sets -cover. +// +// -coverpkg pattern1,pattern2,pattern3 +// Apply coverage analysis in each test to packages matching the patterns. +// The default is for each test to analyze only the package being tested. +// See 'go help packages' for a description of package patterns. +// Sets -cover. +// +// -cpu 1,2,4 +// Specify a list of GOMAXPROCS values for which the tests or +// benchmarks should be executed. The default is the current value +// of GOMAXPROCS. +// +// -failfast +// Do not start new tests after the first test failure. +// +// -list regexp +// List tests, benchmarks, or examples matching the regular expression. +// No tests, benchmarks or examples will be run. This will only +// list top-level tests. No subtest or subbenchmarks will be shown. +// +// -parallel n +// Allow parallel execution of test functions that call t.Parallel. +// The value of this flag is the maximum number of tests to run +// simultaneously; by default, it is set to the value of GOMAXPROCS. +// Note that -parallel only applies within a single test binary. +// The 'go test' command may run tests for different packages +// in parallel as well, according to the setting of the -p flag +// (see 'go help build'). +// +// -run regexp +// Run only those tests and examples matching the regular expression. +// For tests, the regular expression is split by unbracketed slash (/) +// characters into a sequence of regular expressions, and each part +// of a test's identifier must match the corresponding element in +// the sequence, if any. Note that possible parents of matches are +// run too, so that -run=X/Y matches and runs and reports the result +// of all tests matching X, even those without sub-tests matching Y, +// because it must run them to look for those sub-tests. +// +// -short +// Tell long-running tests to shorten their run time. +// It is off by default but set during all.bash so that installing +// the Go tree can run a sanity check but not spend time running +// exhaustive tests. +// +// -timeout d +// If a test binary runs longer than duration d, panic. +// If d is 0, the timeout is disabled. +// The default is 10 minutes (10m). +// +// -v +// Verbose output: log all tests as they are run. Also print all +// text from Log and Logf calls even if the test succeeds. +// +// -vet list +// Configure the invocation of "go vet" during "go test" +// to use the comma-separated list of vet checks. +// If list is empty, "go test" runs "go vet" with a curated list of +// checks believed to be always worth addressing. +// If list is "off", "go test" does not run "go vet" at all. +// +// The following flags are also recognized by 'go test' and can be used to +// profile the tests during execution: +// +// -benchmem +// Print memory allocation statistics for benchmarks. +// +// -blockprofile block.out +// Write a goroutine blocking profile to the specified file +// when all tests are complete. +// Writes test binary as -c would. +// +// -blockprofilerate n +// Control the detail provided in goroutine blocking profiles by +// calling runtime.SetBlockProfileRate with n. +// See 'go doc runtime.SetBlockProfileRate'. +// The profiler aims to sample, on average, one blocking event every +// n nanoseconds the program spends blocked. By default, +// if -test.blockprofile is set without this flag, all blocking events +// are recorded, equivalent to -test.blockprofilerate=1. +// +// -coverprofile cover.out +// Write a coverage profile to the file after all tests have passed. +// Sets -cover. +// +// -cpuprofile cpu.out +// Write a CPU profile to the specified file before exiting. +// Writes test binary as -c would. +// +// -memprofile mem.out +// Write a memory profile to the file after all tests have passed. +// Writes test binary as -c would. +// +// -memprofilerate n +// Enable more precise (and expensive) memory profiles by setting +// runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'. +// To profile all memory allocations, use -test.memprofilerate=1 +// and pass --alloc_space flag to the pprof tool. +// +// -mutexprofile mutex.out +// Write a mutex contention profile to the specified file +// when all tests are complete. +// Writes test binary as -c would. +// +// -mutexprofilefraction n +// Sample 1 in n stack traces of goroutines holding a +// contended mutex. +// +// -outputdir directory +// Place output files from profiling in the specified directory, +// by default the directory in which "go test" is running. +// +// -trace trace.out +// Write an execution trace to the specified file before exiting. +// +// Each of these flags is also recognized with an optional 'test.' prefix, +// as in -test.v. When invoking the generated test binary (the result of +// 'go test -c') directly, however, the prefix is mandatory. +// +// The 'go test' command rewrites or removes recognized flags, +// as appropriate, both before and after the optional package list, +// before invoking the test binary. +// +// For instance, the command +// +// go test -v -myflag testdata -cpuprofile=prof.out -x +// +// will compile the test binary and then run it as +// +// pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out +// +// (The -x flag is removed because it applies only to the go command's +// execution, not to the test itself.) +// +// The test flags that generate profiles (other than for coverage) also +// leave the test binary in pkg.test for use when analyzing the profiles. +// +// When 'go test' runs a test binary, it does so from within the +// corresponding package's source code directory. Depending on the test, +// it may be necessary to do the same when invoking a generated test +// binary directly. +// +// The command-line package list, if present, must appear before any +// flag not known to the go test command. Continuing the example above, +// the package list would have to appear before -myflag, but could appear +// on either side of -v. +// +// To keep an argument for a test binary from being interpreted as a +// known flag or a package name, use -args (see 'go help test') which +// passes the remainder of the command line through to the test binary +// uninterpreted and unaltered. +// +// For instance, the command +// +// go test -v -args -x -v +// +// will compile the test binary and then run it as +// +// pkg.test -test.v -x -v +// +// Similarly, +// +// go test -args math +// +// will compile the test binary and then run it as +// +// pkg.test math +// +// In the first example, the -x and the second -v are passed through to the +// test binary unchanged and with no effect on the go command itself. +// In the second example, the argument math is passed through to the test +// binary, instead of being interpreted as the package list. +// +// +// Testing functions +// +// The 'go test' command expects to find test, benchmark, and example functions +// in the "*_test.go" files corresponding to the package under test. +// +// A test function is one named TestXxx (where Xxx does not start with a +// lower case letter) and should have the signature, +// +// func TestXxx(t *testing.T) { ... } +// +// A benchmark function is one named BenchmarkXxx and should have the signature, +// +// func BenchmarkXxx(b *testing.B) { ... } +// +// An example function is similar to a test function but, instead of using +// *testing.T to report success or failure, prints output to os.Stdout. +// If the last comment in the function starts with "Output:" then the output +// is compared exactly against the comment (see examples below). If the last +// comment begins with "Unordered output:" then the output is compared to the +// comment, however the order of the lines is ignored. An example with no such +// comment is compiled but not executed. An example with no text after +// "Output:" is compiled, executed, and expected to produce no output. +// +// Godoc displays the body of ExampleXxx to demonstrate the use +// of the function, constant, or variable Xxx. An example of a method M with +// receiver type T or *T is named ExampleT_M. There may be multiple examples +// for a given function, constant, or variable, distinguished by a trailing _xxx, +// where xxx is a suffix not beginning with an upper case letter. +// +// Here is an example of an example: +// +// func ExamplePrintln() { +// Println("The output of\nthis example.") +// // Output: The output of +// // this example. +// } +// +// Here is another example where the ordering of the output is ignored: +// +// func ExamplePerm() { +// for _, value := range Perm(4) { +// fmt.Println(value) +// } +// +// // Unordered output: 4 +// // 2 +// // 1 +// // 3 +// // 0 +// } +// +// The entire test file is presented as the example when it contains a single +// example function, at least one other function, type, variable, or constant +// declaration, and no test or benchmark functions. +// +// See the documentation of the testing package for more information. +// +// +package Main
diff --git a/vendor/cmd/go/go11.go b/vendor/cmd/go/go11.go new file mode 100644 index 0000000..fa641f2 --- /dev/null +++ b/vendor/cmd/go/go11.go
@@ -0,0 +1,10 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.1 + +package Main + +// Test that go1.1 tag above is included in builds. main.go refers to this definition. +const go11tag = true
diff --git a/vendor/cmd/go/go_test.go b/vendor/cmd/go/go_test.go new file mode 100644 index 0000000..371f3d8 --- /dev/null +++ b/vendor/cmd/go/go_test.go
@@ -0,0 +1,5906 @@ +// Copyright 2015 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 Main_test + +import ( + "bytes" + "debug/elf" + "debug/macho" + "fmt" + "go/format" + "internal/testenv" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "regexp" + "runtime" + "strconv" + "strings" + "testing" + "time" +) + +const raceEnabled = false + +var ( + canRun = true // whether we can run go or ./testgo + canRace = false // whether we can run the race detector + canCgo = false // whether we can use cgo + canMSan = false // whether we can run the memory sanitizer + + exeSuffix string // ".exe" on Windows + + skipExternal = false // skip external tests +) + +func tooSlow(t *testing.T) { + if testing.Short() { + // In -short mode; skip test, except run it on the {darwin,linux,windows}/amd64 builders. + if testenv.Builder() != "" && runtime.GOARCH == "amd64" && (runtime.GOOS == "linux" || runtime.GOOS == "darwin" || runtime.GOOS == "windows") { + return + } + t.Skip("skipping test in -short mode") + } +} + +func init() { + switch runtime.GOOS { + case "android", "nacl": + canRun = false + case "darwin": + switch runtime.GOARCH { + case "arm", "arm64": + canRun = false + } + case "linux": + switch runtime.GOARCH { + case "arm": + // many linux/arm machines are too slow to run + // the full set of external tests. + skipExternal = true + case "mips", "mipsle", "mips64", "mips64le": + // Also slow. + skipExternal = true + if testenv.Builder() != "" { + // On the builders, skip the cmd/go + // tests. They're too slow and already + // covered by other ports. There's + // nothing os/arch specific in the + // tests. + canRun = false + } + } + case "freebsd": + switch runtime.GOARCH { + case "arm": + // many freebsd/arm machines are too slow to run + // the full set of external tests. + skipExternal = true + canRun = false + } + case "plan9": + switch runtime.GOARCH { + case "arm": + // many plan9/arm machines are too slow to run + // the full set of external tests. + skipExternal = true + } + case "windows": + exeSuffix = ".exe" + } +} + +// testGOROOT is the GOROOT to use when running testgo, a cmd/go binary +// build from this process's current GOROOT, but run from a different +// (temp) directory. +var testGOROOT string + +var testCC string + +// The TestMain function creates a go command for testing purposes and +// deletes it after the tests have been run. +func TestMain(m *testing.M) { + if os.Getenv("GO_GCFLAGS") != "" { + fmt.Fprintf(os.Stderr, "testing: warning: no tests to run\n") // magic string for cmd/go + fmt.Printf("cmd/go test is not compatible with $GO_GCFLAGS being set\n") + fmt.Printf("SKIP\n") + return + } + os.Unsetenv("GOROOT_FINAL") + + if canRun { + args := []string{"build", "-tags", "testgo", "-o", "testgo" + exeSuffix, "../../.."} + if raceEnabled { + args = append(args, "-race") + } + gotool, err := testenv.GoTool() + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(2) + } + + goEnv := func(name string) string { + out, err := exec.Command(gotool, "env", name).CombinedOutput() + if err != nil { + fmt.Fprintf(os.Stderr, "go env %s: %v\n%s", name, err, out) + os.Exit(2) + } + return strings.TrimSpace(string(out)) + } + testGOROOT = goEnv("GOROOT") + + // The whole GOROOT/pkg tree was installed using the GOHOSTOS/GOHOSTARCH + // toolchain (installed in GOROOT/pkg/tool/GOHOSTOS_GOHOSTARCH). + // The testgo.exe we are about to create will be built for GOOS/GOARCH, + // which means it will use the GOOS/GOARCH toolchain + // (installed in GOROOT/pkg/tool/GOOS_GOARCH). + // If these are not the same toolchain, then the entire standard library + // will look out of date (the compilers in those two different tool directories + // are built for different architectures and have different buid IDs), + // which will cause many tests to do unnecessary rebuilds and some + // tests to attempt to overwrite the installed standard library. + // Bail out entirely in this case. + hostGOOS := goEnv("GOHOSTOS") + hostGOARCH := goEnv("GOHOSTARCH") + if hostGOOS != runtime.GOOS || hostGOARCH != runtime.GOARCH { + fmt.Fprintf(os.Stderr, "testing: warning: no tests to run\n") // magic string for cmd/go + fmt.Printf("cmd/go test is not compatible with GOOS/GOARCH != GOHOSTOS/GOHOSTARCH (%s/%s != %s/%s)\n", runtime.GOOS, runtime.GOARCH, hostGOOS, hostGOARCH) + fmt.Printf("SKIP\n") + return + } + + out, err := exec.Command(gotool, args...).CombinedOutput() + if err != nil { + fmt.Fprintf(os.Stderr, "building testgo failed: %v\n%s", err, out) + os.Exit(2) + } + + out, err = exec.Command(gotool, "env", "CC").CombinedOutput() + if err != nil { + fmt.Fprintf(os.Stderr, "could not find testing CC: %v\n%s", err, out) + os.Exit(2) + } + testCC = strings.TrimSpace(string(out)) + + if out, err := exec.Command("./testgo"+exeSuffix, "env", "CGO_ENABLED").Output(); err != nil { + fmt.Fprintf(os.Stderr, "running testgo failed: %v\n", err) + canRun = false + } else { + canCgo, err = strconv.ParseBool(strings.TrimSpace(string(out))) + if err != nil { + fmt.Fprintf(os.Stderr, "can't parse go env CGO_ENABLED output: %v\n", strings.TrimSpace(string(out))) + } + } + + // As of Sept 2017, MSan is only supported on linux/amd64. + // https://github.com/google/sanitizers/wiki/MemorySanitizer#getting-memorysanitizer + canMSan = canCgo && runtime.GOOS == "linux" && runtime.GOARCH == "amd64" + + switch runtime.GOOS { + case "linux", "darwin", "freebsd", "windows": + // The race detector doesn't work on Alpine Linux: + // golang.org/issue/14481 + canRace = canCgo && runtime.GOARCH == "amd64" && !isAlpineLinux() + } + } + // Don't let these environment variables confuse the test. + os.Unsetenv("GOBIN") + os.Unsetenv("GOPATH") + os.Unsetenv("GIT_ALLOW_PROTOCOL") + if home, ccacheDir := os.Getenv("HOME"), os.Getenv("CCACHE_DIR"); home != "" && ccacheDir == "" { + // On some systems the default C compiler is ccache. + // Setting HOME to a non-existent directory will break + // those systems. Set CCACHE_DIR to cope. Issue 17668. + os.Setenv("CCACHE_DIR", filepath.Join(home, ".ccache")) + } + os.Setenv("HOME", "/test-go-home-does-not-exist") + if os.Getenv("GOCACHE") == "" { + os.Setenv("GOCACHE", "off") // because $HOME is gone + } + + r := m.Run() + + if canRun { + os.Remove("testgo" + exeSuffix) + } + + os.Exit(r) +} + +func isAlpineLinux() bool { + if runtime.GOOS != "linux" { + return false + } + fi, err := os.Lstat("/etc/alpine-release") + return err == nil && fi.Mode().IsRegular() +} + +// The length of an mtime tick on this system. This is an estimate of +// how long we need to sleep to ensure that the mtime of two files is +// different. +// We used to try to be clever but that didn't always work (see golang.org/issue/12205). +var mtimeTick time.Duration = 1 * time.Second + +// Manage a single run of the testgo binary. +type testgoData struct { + t *testing.T + temps []string + wd string + env []string + tempdir string + ran bool + inParallel bool + stdout, stderr bytes.Buffer +} + +// testgo sets up for a test that runs testgo. +func testgo(t *testing.T) *testgoData { + t.Helper() + testenv.MustHaveGoBuild(t) + + if skipExternal { + t.Skipf("skipping external tests on %s/%s", runtime.GOOS, runtime.GOARCH) + } + + return &testgoData{t: t} +} + +// must gives a fatal error if err is not nil. +func (tg *testgoData) must(err error) { + tg.t.Helper() + if err != nil { + tg.t.Fatal(err) + } +} + +// check gives a test non-fatal error if err is not nil. +func (tg *testgoData) check(err error) { + tg.t.Helper() + if err != nil { + tg.t.Error(err) + } +} + +// parallel runs the test in parallel by calling t.Parallel. +func (tg *testgoData) parallel() { + tg.t.Helper() + if tg.ran { + tg.t.Fatal("internal testsuite error: call to parallel after run") + } + if tg.wd != "" { + tg.t.Fatal("internal testsuite error: call to parallel after cd") + } + for _, e := range tg.env { + if strings.HasPrefix(e, "GOROOT=") || strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "GOBIN=") { + val := e[strings.Index(e, "=")+1:] + if strings.HasPrefix(val, "testdata") || strings.HasPrefix(val, "./testdata") { + tg.t.Fatalf("internal testsuite error: call to parallel with testdata in environment (%s)", e) + } + } + } + tg.inParallel = true + tg.t.Parallel() +} + +// pwd returns the current directory. +func (tg *testgoData) pwd() string { + tg.t.Helper() + wd, err := os.Getwd() + if err != nil { + tg.t.Fatalf("could not get working directory: %v", err) + } + return wd +} + +// cd changes the current directory to the named directory. Note that +// using this means that the test must not be run in parallel with any +// other tests. +func (tg *testgoData) cd(dir string) { + tg.t.Helper() + if tg.inParallel { + tg.t.Fatal("internal testsuite error: changing directory when running in parallel") + } + if tg.wd == "" { + tg.wd = tg.pwd() + } + abs, err := filepath.Abs(dir) + tg.must(os.Chdir(dir)) + if err == nil { + tg.setenv("PWD", abs) + } +} + +// sleep sleeps for one tick, where a tick is a conservative estimate +// of how long it takes for a file modification to get a different +// mtime. +func (tg *testgoData) sleep() { + time.Sleep(mtimeTick) +} + +// setenv sets an environment variable to use when running the test go +// command. +func (tg *testgoData) setenv(name, val string) { + tg.t.Helper() + if tg.inParallel && (name == "GOROOT" || name == "GOPATH" || name == "GOBIN") && (strings.HasPrefix(val, "testdata") || strings.HasPrefix(val, "./testdata")) { + tg.t.Fatalf("internal testsuite error: call to setenv with testdata (%s=%s) after parallel", name, val) + } + tg.unsetenv(name) + tg.env = append(tg.env, name+"="+val) +} + +// unsetenv removes an environment variable. +func (tg *testgoData) unsetenv(name string) { + if tg.env == nil { + tg.env = append([]string(nil), os.Environ()...) + } + for i, v := range tg.env { + if strings.HasPrefix(v, name+"=") { + tg.env = append(tg.env[:i], tg.env[i+1:]...) + break + } + } +} + +func (tg *testgoData) goTool() string { + if tg.wd == "" { + return "./testgo" + exeSuffix + } + return filepath.Join(tg.wd, "testgo"+exeSuffix) +} + +// doRun runs the test go command, recording stdout and stderr and +// returning exit status. +func (tg *testgoData) doRun(args []string) error { + tg.t.Helper() + if !canRun { + panic("testgoData.doRun called but canRun false") + } + if tg.inParallel { + for _, arg := range args { + if strings.HasPrefix(arg, "testdata") || strings.HasPrefix(arg, "./testdata") { + tg.t.Fatal("internal testsuite error: parallel run using testdata") + } + } + } + + hasGoroot := false + for _, v := range tg.env { + if strings.HasPrefix(v, "GOROOT=") { + hasGoroot = true + break + } + } + prog := tg.goTool() + if !hasGoroot { + tg.setenv("GOROOT", testGOROOT) + } + + tg.t.Logf("running testgo %v", args) + cmd := exec.Command(prog, args...) + tg.stdout.Reset() + tg.stderr.Reset() + cmd.Stdout = &tg.stdout + cmd.Stderr = &tg.stderr + cmd.Env = tg.env + status := cmd.Run() + if tg.stdout.Len() > 0 { + tg.t.Log("standard output:") + tg.t.Log(tg.stdout.String()) + } + if tg.stderr.Len() > 0 { + tg.t.Log("standard error:") + tg.t.Log(tg.stderr.String()) + } + tg.ran = true + return status +} + +// run runs the test go command, and expects it to succeed. +func (tg *testgoData) run(args ...string) { + tg.t.Helper() + if status := tg.doRun(args); status != nil { + tg.t.Logf("go %v failed unexpectedly: %v", args, status) + tg.t.FailNow() + } +} + +// runFail runs the test go command, and expects it to fail. +func (tg *testgoData) runFail(args ...string) { + tg.t.Helper() + if status := tg.doRun(args); status == nil { + tg.t.Fatal("testgo succeeded unexpectedly") + } else { + tg.t.Log("testgo failed as expected:", status) + } +} + +// runGit runs a git command, and expects it to succeed. +func (tg *testgoData) runGit(dir string, args ...string) { + tg.t.Helper() + cmd := exec.Command("git", args...) + tg.stdout.Reset() + tg.stderr.Reset() + cmd.Stdout = &tg.stdout + cmd.Stderr = &tg.stderr + cmd.Dir = dir + cmd.Env = tg.env + status := cmd.Run() + if tg.stdout.Len() > 0 { + tg.t.Log("git standard output:") + tg.t.Log(tg.stdout.String()) + } + if tg.stderr.Len() > 0 { + tg.t.Log("git standard error:") + tg.t.Log(tg.stderr.String()) + } + if status != nil { + tg.t.Logf("git %v failed unexpectedly: %v", args, status) + tg.t.FailNow() + } +} + +// getStdout returns standard output of the testgo run as a string. +func (tg *testgoData) getStdout() string { + tg.t.Helper() + if !tg.ran { + tg.t.Fatal("internal testsuite error: stdout called before run") + } + return tg.stdout.String() +} + +// getStderr returns standard error of the testgo run as a string. +func (tg *testgoData) getStderr() string { + tg.t.Helper() + if !tg.ran { + tg.t.Fatal("internal testsuite error: stdout called before run") + } + return tg.stderr.String() +} + +// doGrepMatch looks for a regular expression in a buffer, and returns +// whether it is found. The regular expression is matched against +// each line separately, as with the grep command. +func (tg *testgoData) doGrepMatch(match string, b *bytes.Buffer) bool { + tg.t.Helper() + if !tg.ran { + tg.t.Fatal("internal testsuite error: grep called before run") + } + re := regexp.MustCompile(match) + for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) { + if re.Match(ln) { + return true + } + } + return false +} + +// doGrep looks for a regular expression in a buffer and fails if it +// is not found. The name argument is the name of the output we are +// searching, "output" or "error". The msg argument is logged on +// failure. +func (tg *testgoData) doGrep(match string, b *bytes.Buffer, name, msg string) { + tg.t.Helper() + if !tg.doGrepMatch(match, b) { + tg.t.Log(msg) + tg.t.Logf("pattern %v not found in standard %s", match, name) + tg.t.FailNow() + } +} + +// grepStdout looks for a regular expression in the test run's +// standard output and fails, logging msg, if it is not found. +func (tg *testgoData) grepStdout(match, msg string) { + tg.t.Helper() + tg.doGrep(match, &tg.stdout, "output", msg) +} + +// grepStderr looks for a regular expression in the test run's +// standard error and fails, logging msg, if it is not found. +func (tg *testgoData) grepStderr(match, msg string) { + tg.t.Helper() + tg.doGrep(match, &tg.stderr, "error", msg) +} + +// grepBoth looks for a regular expression in the test run's standard +// output or stand error and fails, logging msg, if it is not found. +func (tg *testgoData) grepBoth(match, msg string) { + tg.t.Helper() + if !tg.doGrepMatch(match, &tg.stdout) && !tg.doGrepMatch(match, &tg.stderr) { + tg.t.Log(msg) + tg.t.Logf("pattern %v not found in standard output or standard error", match) + tg.t.FailNow() + } +} + +// doGrepNot looks for a regular expression in a buffer and fails if +// it is found. The name and msg arguments are as for doGrep. +func (tg *testgoData) doGrepNot(match string, b *bytes.Buffer, name, msg string) { + tg.t.Helper() + if tg.doGrepMatch(match, b) { + tg.t.Log(msg) + tg.t.Logf("pattern %v found unexpectedly in standard %s", match, name) + tg.t.FailNow() + } +} + +// grepStdoutNot looks for a regular expression in the test run's +// standard output and fails, logging msg, if it is found. +func (tg *testgoData) grepStdoutNot(match, msg string) { + tg.t.Helper() + tg.doGrepNot(match, &tg.stdout, "output", msg) +} + +// grepStderrNot looks for a regular expression in the test run's +// standard error and fails, logging msg, if it is found. +func (tg *testgoData) grepStderrNot(match, msg string) { + tg.t.Helper() + tg.doGrepNot(match, &tg.stderr, "error", msg) +} + +// grepBothNot looks for a regular expression in the test run's +// standard output or stand error and fails, logging msg, if it is +// found. +func (tg *testgoData) grepBothNot(match, msg string) { + tg.t.Helper() + if tg.doGrepMatch(match, &tg.stdout) || tg.doGrepMatch(match, &tg.stderr) { + tg.t.Log(msg) + tg.t.Fatalf("pattern %v found unexpectedly in standard output or standard error", match) + } +} + +// doGrepCount counts the number of times a regexp is seen in a buffer. +func (tg *testgoData) doGrepCount(match string, b *bytes.Buffer) int { + tg.t.Helper() + if !tg.ran { + tg.t.Fatal("internal testsuite error: doGrepCount called before run") + } + re := regexp.MustCompile(match) + c := 0 + for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) { + if re.Match(ln) { + c++ + } + } + return c +} + +// grepCountBoth returns the number of times a regexp is seen in both +// standard output and standard error. +func (tg *testgoData) grepCountBoth(match string) int { + tg.t.Helper() + return tg.doGrepCount(match, &tg.stdout) + tg.doGrepCount(match, &tg.stderr) +} + +// creatingTemp records that the test plans to create a temporary file +// or directory. If the file or directory exists already, it will be +// removed. When the test completes, the file or directory will be +// removed if it exists. +func (tg *testgoData) creatingTemp(path string) { + tg.t.Helper() + if filepath.IsAbs(path) && !strings.HasPrefix(path, tg.tempdir) { + tg.t.Fatalf("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path) + } + // If we have changed the working directory, make sure we have + // an absolute path, because we are going to change directory + // back before we remove the temporary. + if tg.wd != "" && !filepath.IsAbs(path) { + path = filepath.Join(tg.pwd(), path) + } + tg.must(os.RemoveAll(path)) + tg.temps = append(tg.temps, path) +} + +// makeTempdir makes a temporary directory for a run of testgo. If +// the temporary directory was already created, this does nothing. +func (tg *testgoData) makeTempdir() { + tg.t.Helper() + if tg.tempdir == "" { + var err error + tg.tempdir, err = ioutil.TempDir("", "gotest") + tg.must(err) + } +} + +// tempFile adds a temporary file for a run of testgo. +func (tg *testgoData) tempFile(path, contents string) { + tg.t.Helper() + tg.makeTempdir() + tg.must(os.MkdirAll(filepath.Join(tg.tempdir, filepath.Dir(path)), 0755)) + bytes := []byte(contents) + if strings.HasSuffix(path, ".go") { + formatted, err := format.Source(bytes) + if err == nil { + bytes = formatted + } + } + tg.must(ioutil.WriteFile(filepath.Join(tg.tempdir, path), bytes, 0644)) +} + +// tempDir adds a temporary directory for a run of testgo. +func (tg *testgoData) tempDir(path string) { + tg.t.Helper() + tg.makeTempdir() + if err := os.MkdirAll(filepath.Join(tg.tempdir, path), 0755); err != nil && !os.IsExist(err) { + tg.t.Fatal(err) + } +} + +// path returns the absolute pathname to file with the temporary +// directory. +func (tg *testgoData) path(name string) string { + tg.t.Helper() + if tg.tempdir == "" { + tg.t.Fatalf("internal testsuite error: path(%q) with no tempdir", name) + } + if name == "." { + return tg.tempdir + } + return filepath.Join(tg.tempdir, name) +} + +// mustExist fails if path does not exist. +func (tg *testgoData) mustExist(path string) { + tg.t.Helper() + if _, err := os.Stat(path); err != nil { + if os.IsNotExist(err) { + tg.t.Fatalf("%s does not exist but should", path) + } + tg.t.Fatalf("%s stat failed: %v", path, err) + } +} + +// mustNotExist fails if path exists. +func (tg *testgoData) mustNotExist(path string) { + tg.t.Helper() + if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) { + tg.t.Fatalf("%s exists but should not (%v)", path, err) + } +} + +// mustHaveContent succeeds if filePath is a path to a file, +// and that file is readable and not empty. +func (tg *testgoData) mustHaveContent(filePath string) { + tg.mustExist(filePath) + f, err := os.Stat(filePath) + if err != nil { + tg.t.Fatal(err) + } + if f.Size() == 0 { + tg.t.Fatalf("expected %s to have data, but is empty", filePath) + } +} + +// wantExecutable fails with msg if path is not executable. +func (tg *testgoData) wantExecutable(path, msg string) { + tg.t.Helper() + if st, err := os.Stat(path); err != nil { + if !os.IsNotExist(err) { + tg.t.Log(err) + } + tg.t.Fatal(msg) + } else { + if runtime.GOOS != "windows" && st.Mode()&0111 == 0 { + tg.t.Fatalf("binary %s exists but is not executable", path) + } + } +} + +// wantArchive fails if path is not an archive. +func (tg *testgoData) wantArchive(path string) { + tg.t.Helper() + f, err := os.Open(path) + if err != nil { + tg.t.Fatal(err) + } + buf := make([]byte, 100) + io.ReadFull(f, buf) + f.Close() + if !bytes.HasPrefix(buf, []byte("!<arch>\n")) { + tg.t.Fatalf("file %s exists but is not an archive", path) + } +} + +// isStale reports whether pkg is stale, and why +func (tg *testgoData) isStale(pkg string) (bool, string) { + tg.t.Helper() + tg.run("list", "-f", "{{.Stale}}:{{.StaleReason}}", pkg) + v := strings.TrimSpace(tg.getStdout()) + f := strings.SplitN(v, ":", 2) + if len(f) == 2 { + switch f[0] { + case "true": + return true, f[1] + case "false": + return false, f[1] + } + } + tg.t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v) + panic("unreachable") +} + +// wantStale fails with msg if pkg is not stale. +func (tg *testgoData) wantStale(pkg, reason, msg string) { + tg.t.Helper() + stale, why := tg.isStale(pkg) + if !stale { + tg.t.Fatal(msg) + } + if reason == "" && why != "" || !strings.Contains(why, reason) { + tg.t.Errorf("wrong reason for Stale=true: %q, want %q", why, reason) + } +} + +// wantNotStale fails with msg if pkg is stale. +func (tg *testgoData) wantNotStale(pkg, reason, msg string) { + tg.t.Helper() + stale, why := tg.isStale(pkg) + if stale { + tg.t.Fatal(msg) + } + if reason == "" && why != "" || !strings.Contains(why, reason) { + tg.t.Errorf("wrong reason for Stale=false: %q, want %q", why, reason) + } +} + +// cleanup cleans up a test that runs testgo. +func (tg *testgoData) cleanup() { + tg.t.Helper() + if tg.wd != "" { + if err := os.Chdir(tg.wd); err != nil { + // We are unlikely to be able to continue. + fmt.Fprintln(os.Stderr, "could not restore working directory, crashing:", err) + os.Exit(2) + } + } + for _, path := range tg.temps { + tg.check(os.RemoveAll(path)) + } + if tg.tempdir != "" { + tg.check(os.RemoveAll(tg.tempdir)) + } +} + +// failSSH puts an ssh executable in the PATH that always fails. +// This is to stub out uses of ssh by go get. +func (tg *testgoData) failSSH() { + tg.t.Helper() + wd, err := os.Getwd() + if err != nil { + tg.t.Fatal(err) + } + fail := filepath.Join(wd, "testdata/failssh") + tg.setenv("PATH", fmt.Sprintf("%v%c%v", fail, filepath.ListSeparator, os.Getenv("PATH"))) +} + +func TestBuildComplex(t *testing.T) { + // Simple smoke test for build configuration. + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("build", "-x", "-o", os.DevNull, "complex") + + if _, err := exec.LookPath("gccgo"); err == nil { + t.Skip("golang.org/issue/22472") + tg.run("build", "-x", "-o", os.DevNull, "-compiler=gccgo", "complex") + } +} + +func TestFileLineInErrorMessages(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("err.go", `package main; import "bar"`) + path := tg.path("err.go") + tg.runFail("run", path) + shortPath := path + if rel, err := filepath.Rel(tg.pwd(), path); err == nil && len(rel) < len(path) { + shortPath = rel + } + tg.grepStderr("^"+regexp.QuoteMeta(shortPath)+":", "missing file:line in error message") +} + +func TestProgramNameInCrashMessages(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("triv.go", `package main; func main() {}`) + tg.runFail("build", "-ldflags", "-crash_for_testing", tg.path("triv.go")) + tg.grepStderr(`[/\\]tool[/\\].*[/\\]link`, "missing linker name in error message") +} + +func TestBrokenTestsWithoutTestFunctionsAllFail(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.runFail("test", "./testdata/src/badtest/...") + tg.grepBothNot("^ok", "test passed unexpectedly") + tg.grepBoth("FAIL.*badtest/badexec", "test did not run everything") + tg.grepBoth("FAIL.*badtest/badsyntax", "test did not run everything") + tg.grepBoth("FAIL.*badtest/badvar", "test did not run everything") +} + +func TestGoBuildDashAInDevBranch(t *testing.T) { + t.Skip("broken in standard distribution") + + if testing.Short() { + t.Skip("don't rebuild the standard library in short mode") + } + + tg := testgo(t) + defer tg.cleanup() + tg.run("install", "math") // should be up to date already but just in case + tg.setenv("TESTGO_IS_GO_RELEASE", "0") + tg.run("build", "-v", "-a", "math") + tg.grepStderr("runtime", "testgo build -a math in dev branch DID NOT build runtime, but should have") + + // Everything is out of date. Rebuild to leave things in a better state. + tg.run("install", "std") +} + +func TestGoBuildDashAInReleaseBranch(t *testing.T) { + t.Skip("broken in standard distribution") + + if testing.Short() { + t.Skip("don't rebuild the standard library in short mode") + } + + tg := testgo(t) + defer tg.cleanup() + tg.run("install", "math", "net/http") // should be up to date already but just in case + tg.setenv("TESTGO_IS_GO_RELEASE", "1") + tg.run("install", "-v", "-a", "math") + tg.grepStderr("runtime", "testgo build -a math in release branch DID NOT build runtime, but should have") + + // Now runtime.a is updated (newer mtime), so everything would look stale if not for being a release. + tg.run("build", "-v", "net/http") + tg.grepStderrNot("strconv", "testgo build -v net/http in release branch with newer runtime.a DID build strconv but should not have") + tg.grepStderrNot("golang.org/x/net/http2/hpack", "testgo build -v net/http in release branch with newer runtime.a DID build .../golang.org/x/net/http2/hpack but should not have") + tg.grepStderrNot("net/http", "testgo build -v net/http in release branch with newer runtime.a DID build net/http but should not have") + + // Everything is out of date. Rebuild to leave things in a better state. + tg.run("install", "std") +} + +func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) { + t.Skip("broken in standard distribution") + + if testing.Short() { + t.Skip("don't rebuild the standard library in short mode") + } + + tg := testgo(t) + defer tg.cleanup() + + addNL := func(name string) (restore func()) { + data, err := ioutil.ReadFile(name) + if err != nil { + t.Fatal(err) + } + old := data + data = append(data, '\n') + if err := ioutil.WriteFile(name, append(data, '\n'), 0666); err != nil { + t.Fatal(err) + } + tg.sleep() + return func() { + if err := ioutil.WriteFile(name, old, 0666); err != nil { + t.Fatal(err) + } + } + } + + tg.tempFile("d1/src/p1/p1.go", `package p1`) + tg.setenv("GOPATH", tg.path("d1")) + tg.run("install", "-a", "p1") + tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, before any changes") + + // Changing mtime of runtime/internal/sys/sys.go + // should have no effect: only the content matters. + // In fact this should be true even outside a release branch. + sys := runtime.GOROOT() + "/src/runtime/internal/sys/sys.go" + tg.sleep() + restore := addNL(sys) + restore() + tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after updating mtime of runtime/internal/sys/sys.go") + + // But changing content of any file should have an effect. + // Previously zversion.go was the only one that mattered; + // now they all matter, so keep using sys.go. + restore = addNL(sys) + defer restore() + tg.wantStale("p1", "stale dependency: runtime/internal/sys", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go") + restore() + tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after changing back to old release") + addNL(sys) + tg.wantStale("p1", "stale dependency: runtime/internal/sys", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go again") + tg.run("install", "p1") + tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with new release") + + // Restore to "old" release. + restore() + tg.wantStale("p1", "stale dependency: runtime/internal/sys", "./testgo list claims p1 is NOT stale, incorrectly, after restoring sys.go") + tg.run("install", "p1") + tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with old release") + + // Everything is out of date. Rebuild to leave things in a better state. + tg.run("install", "std") +} + +func TestGoListStandard(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.cd(runtime.GOROOT() + "/src") + tg.run("list", "-f", "{{if not .Standard}}{{.ImportPath}}{{end}}", "./...") + stdout := tg.getStdout() + for _, line := range strings.Split(stdout, "\n") { + if strings.HasPrefix(line, "_/") && strings.HasSuffix(line, "/src") { + // $GOROOT/src shows up if there are any .go files there. + // We don't care. + continue + } + if line == "" { + continue + } + t.Errorf("package in GOROOT not listed as standard: %v", line) + } + + // Similarly, expanding std should include some of our vendored code. + tg.run("list", "std", "cmd") + tg.grepStdout("golang.org/x/net/http2/hpack", "list std cmd did not mention vendored hpack") + tg.grepStdout("golang.org/x/arch/x86/x86asm", "list std cmd did not mention vendored x86asm") +} + +func TestGoInstallCleansUpAfterGoBuild(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.tempFile("src/mycmd/main.go", `package main; func main(){}`) + tg.setenv("GOPATH", tg.path(".")) + tg.cd(tg.path("src/mycmd")) + + doesNotExist := func(file, msg string) { + if _, err := os.Stat(file); err == nil { + t.Fatal(msg) + } else if !os.IsNotExist(err) { + t.Fatal(msg, "error:", err) + } + } + + tg.run("build") + tg.wantExecutable("mycmd"+exeSuffix, "testgo build did not write command binary") + tg.run("install") + doesNotExist("mycmd"+exeSuffix, "testgo install did not remove command binary") + tg.run("build") + tg.wantExecutable("mycmd"+exeSuffix, "testgo build did not write command binary (second time)") + // Running install with arguments does not remove the target, + // even in the same directory. + tg.run("install", "mycmd") + tg.wantExecutable("mycmd"+exeSuffix, "testgo install mycmd removed command binary when run in mycmd") + tg.run("build") + tg.wantExecutable("mycmd"+exeSuffix, "testgo build did not write command binary (third time)") + // And especially not outside the directory. + tg.cd(tg.path(".")) + if data, err := ioutil.ReadFile("src/mycmd/mycmd" + exeSuffix); err != nil { + t.Fatal("could not read file:", err) + } else { + if err := ioutil.WriteFile("mycmd"+exeSuffix, data, 0555); err != nil { + t.Fatal("could not write file:", err) + } + } + tg.run("install", "mycmd") + tg.wantExecutable("src/mycmd/mycmd"+exeSuffix, "testgo install mycmd removed command binary from its source dir when run outside mycmd") + tg.wantExecutable("mycmd"+exeSuffix, "testgo install mycmd removed command binary from current dir when run outside mycmd") +} + +func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("d1/src/p1/p1.go", `package p1 + import "p2" + func F() { p2.F() }`) + tg.tempFile("d2/src/p2/p2.go", `package p2 + func F() {}`) + sep := string(filepath.ListSeparator) + tg.setenv("GOPATH", tg.path("d1")+sep+tg.path("d2")) + tg.run("install", "-i", "p1") + tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly") + tg.wantNotStale("p2", "", "./testgo list claims p2 is stale, incorrectly") + tg.sleep() + if f, err := os.OpenFile(tg.path("d2/src/p2/p2.go"), os.O_WRONLY|os.O_APPEND, 0); err != nil { + t.Fatal(err) + } else if _, err = f.WriteString(`func G() {}`); err != nil { + t.Fatal(err) + } else { + tg.must(f.Close()) + } + tg.wantStale("p2", "build ID mismatch", "./testgo list claims p2 is NOT stale, incorrectly") + tg.wantStale("p1", "stale dependency: p2", "./testgo list claims p1 is NOT stale, incorrectly") + + tg.run("install", "-i", "p1") + tg.wantNotStale("p2", "", "./testgo list claims p2 is stale after reinstall, incorrectly") + tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after reinstall, incorrectly") +} + +func TestGoInstallDetectsRemovedFiles(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("src/mypkg/x.go", `package mypkg`) + tg.tempFile("src/mypkg/y.go", `package mypkg`) + tg.tempFile("src/mypkg/z.go", `// +build missingtag + + package mypkg`) + tg.setenv("GOPATH", tg.path(".")) + tg.run("install", "mypkg") + tg.wantNotStale("mypkg", "", "./testgo list mypkg claims mypkg is stale, incorrectly") + // z.go was not part of the build; removing it is okay. + tg.must(os.Remove(tg.path("src/mypkg/z.go"))) + tg.wantNotStale("mypkg", "", "./testgo list mypkg claims mypkg is stale after removing z.go; should not be stale") + // y.go was part of the package; removing it should be detected. + tg.must(os.Remove(tg.path("src/mypkg/y.go"))) + tg.wantStale("mypkg", "build ID mismatch", "./testgo list mypkg claims mypkg is NOT stale after removing y.go; should be stale") +} + +func TestWildcardMatchesSyntaxErrorDirs(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.tempFile("src/mypkg/x.go", `package mypkg`) + tg.tempFile("src/mypkg/y.go", `pkg mypackage`) + tg.setenv("GOPATH", tg.path(".")) + tg.cd(tg.path("src/mypkg")) + tg.runFail("list", "./...") + tg.runFail("build", "./...") + tg.runFail("install", "./...") +} + +func TestGoListWithTags(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.tempFile("src/mypkg/x.go", "// +build thetag\n\npackage mypkg\n") + tg.setenv("GOPATH", tg.path(".")) + tg.cd(tg.path("./src")) + tg.run("list", "-tags=thetag", "./my...") + tg.grepStdout("mypkg", "did not find mypkg") +} + +func TestGoInstallErrorOnCrossCompileToBin(t *testing.T) { + if testing.Short() { + t.Skip("don't install into GOROOT in short mode") + } + + tg := testgo(t) + defer tg.cleanup() + tg.tempFile("src/mycmd/x.go", `package main + func main() {}`) + tg.setenv("GOPATH", tg.path(".")) + tg.cd(tg.path("src/mycmd")) + + tg.run("build", "mycmd") + + goarch := "386" + if runtime.GOARCH == "386" { + goarch = "amd64" + } + tg.setenv("GOOS", "linux") + tg.setenv("GOARCH", goarch) + tg.run("install", "mycmd") + tg.setenv("GOBIN", tg.path(".")) + tg.runFail("install", "mycmd") + tg.run("install", "cmd/pack") +} + +func TestGoInstallDetectsRemovedFilesInPackageMain(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("src/mycmd/x.go", `package main + func main() {}`) + tg.tempFile("src/mycmd/y.go", `package main`) + tg.tempFile("src/mycmd/z.go", `// +build missingtag + + package main`) + tg.setenv("GOPATH", tg.path(".")) + tg.run("install", "mycmd") + tg.wantNotStale("mycmd", "", "./testgo list mypkg claims mycmd is stale, incorrectly") + // z.go was not part of the build; removing it is okay. + tg.must(os.Remove(tg.path("src/mycmd/z.go"))) + tg.wantNotStale("mycmd", "", "./testgo list mycmd claims mycmd is stale after removing z.go; should not be stale") + // y.go was part of the package; removing it should be detected. + tg.must(os.Remove(tg.path("src/mycmd/y.go"))) + tg.wantStale("mycmd", "build ID mismatch", "./testgo list mycmd claims mycmd is NOT stale after removing y.go; should be stale") +} + +func testLocalRun(tg *testgoData, exepath, local, match string) { + tg.t.Helper() + out, err := exec.Command(exepath).Output() + if err != nil { + tg.t.Fatalf("error running %v: %v", exepath, err) + } + if !regexp.MustCompile(match).Match(out) { + tg.t.Log(string(out)) + tg.t.Errorf("testdata/%s/easy.go did not generate expected output", local) + } +} + +func testLocalEasy(tg *testgoData, local string) { + tg.t.Helper() + exepath := "./easy" + exeSuffix + tg.creatingTemp(exepath) + tg.run("build", "-o", exepath, filepath.Join("testdata", local, "easy.go")) + testLocalRun(tg, exepath, local, `(?m)^easysub\.Hello`) +} + +func testLocalEasySub(tg *testgoData, local string) { + tg.t.Helper() + exepath := "./easysub" + exeSuffix + tg.creatingTemp(exepath) + tg.run("build", "-o", exepath, filepath.Join("testdata", local, "easysub", "main.go")) + testLocalRun(tg, exepath, local, `(?m)^easysub\.Hello`) +} + +func testLocalHard(tg *testgoData, local string) { + tg.t.Helper() + exepath := "./hard" + exeSuffix + tg.creatingTemp(exepath) + tg.run("build", "-o", exepath, filepath.Join("testdata", local, "hard.go")) + testLocalRun(tg, exepath, local, `(?m)^sub\.Hello`) +} + +func testLocalInstall(tg *testgoData, local string) { + tg.t.Helper() + tg.runFail("install", filepath.Join("testdata", local, "easy.go")) +} + +func TestLocalImportsEasy(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + testLocalEasy(tg, "local") +} + +func TestLocalImportsEasySub(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + testLocalEasySub(tg, "local") +} + +func TestLocalImportsHard(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + testLocalHard(tg, "local") +} + +func TestLocalImportsGoInstallShouldFail(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + testLocalInstall(tg, "local") +} + +const badDirName = `#$%:, &()*;<=>?\^{}` + +func copyBad(tg *testgoData) { + tg.t.Helper() + if runtime.GOOS == "windows" { + tg.t.Skipf("skipping test because %q is an invalid directory name", badDirName) + } + + tg.must(filepath.Walk("testdata/local", + func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.IsDir() { + return nil + } + var data []byte + data, err = ioutil.ReadFile(path) + if err != nil { + return err + } + newpath := strings.Replace(path, "local", badDirName, 1) + tg.tempFile(newpath, string(data)) + return nil + })) + tg.cd(tg.path(".")) +} + +func TestBadImportsEasy(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + copyBad(tg) + testLocalEasy(tg, badDirName) +} + +func TestBadImportsEasySub(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + copyBad(tg) + testLocalEasySub(tg, badDirName) +} + +func TestBadImportsHard(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + copyBad(tg) + testLocalHard(tg, badDirName) +} + +func TestBadImportsGoInstallShouldFail(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + copyBad(tg) + testLocalInstall(tg, badDirName) +} + +func TestInternalPackagesInGOROOTAreRespected(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.runFail("build", "-v", "./testdata/testinternal") + tg.grepBoth(`testinternal(\/|\\)p\.go\:3\:8\: use of internal package not allowed`, "wrong error message for testdata/testinternal") +} + +func TestInternalPackagesOutsideGOROOTAreRespected(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.runFail("build", "-v", "./testdata/testinternal2") + tg.grepBoth(`testinternal2(\/|\\)p\.go\:3\:8\: use of internal package not allowed`, "wrote error message for testdata/testinternal2") +} + +func TestRunInternal(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + dir := filepath.Join(tg.pwd(), "testdata") + tg.setenv("GOPATH", dir) + tg.run("run", filepath.Join(dir, "src/run/good.go")) + tg.runFail("run", filepath.Join(dir, "src/run/bad.go")) + tg.grepStderr(`testdata(\/|\\)src(\/|\\)run(\/|\\)bad\.go\:3\:8\: use of internal package not allowed`, "unexpected error for run/bad.go") +} + +func testMove(t *testing.T, vcs, url, base, config string) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempDir("src") + tg.setenv("GOPATH", tg.path(".")) + tg.run("get", "-d", url) + tg.run("get", "-d", "-u", url) + switch vcs { + case "svn": + // SVN doesn't believe in text files so we can't just edit the config. + // Check out a different repo into the wrong place. + tg.must(os.RemoveAll(tg.path("src/code.google.com/p/rsc-svn"))) + tg.run("get", "-d", "-u", "code.google.com/p/rsc-svn2/trunk") + tg.must(os.Rename(tg.path("src/code.google.com/p/rsc-svn2"), tg.path("src/code.google.com/p/rsc-svn"))) + default: + path := tg.path(filepath.Join("src", config)) + data, err := ioutil.ReadFile(path) + tg.must(err) + data = bytes.Replace(data, []byte(base), []byte(base+"XXX"), -1) + tg.must(ioutil.WriteFile(path, data, 0644)) + } + if vcs == "git" { + // git will ask for a username and password when we + // run go get -d -f -u. An empty username and + // password will work. Prevent asking by setting + // GIT_ASKPASS. + tg.creatingTemp("sink" + exeSuffix) + tg.tempFile("src/sink/sink.go", `package main; func main() {}`) + tg.run("build", "-o", "sink"+exeSuffix, "sink") + tg.setenv("GIT_ASKPASS", filepath.Join(tg.pwd(), "sink"+exeSuffix)) + } + tg.runFail("get", "-d", "-u", url) + tg.grepStderr("is a custom import path for", "go get -d -u "+url+" failed for wrong reason") + tg.runFail("get", "-d", "-f", "-u", url) + tg.grepStderr("validating server certificate|[nN]ot [fF]ound", "go get -d -f -u "+url+" failed for wrong reason") +} + +func TestInternalPackageErrorsAreHandled(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.run("list", "./testdata/testinternal3") +} + +func TestInternalCache(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testinternal4")) + tg.runFail("build", "p") + tg.grepStderr("internal", "did not fail to build p") +} + +func TestMoveGit(t *testing.T) { + testMove(t, "git", "rsc.io/pdf", "pdf", "rsc.io/pdf/.git/config") +} + +func TestMoveHG(t *testing.T) { + testMove(t, "hg", "vcs-test.golang.org/go/custom-hg-hello", "custom-hg-hello", "vcs-test.golang.org/go/custom-hg-hello/.hg/hgrc") +} + +// TODO(rsc): Set up a test case on SourceForge (?) for svn. +// func testMoveSVN(t *testing.T) { +// testMove(t, "svn", "code.google.com/p/rsc-svn/trunk", "-", "-") +// } + +func TestImportCommandMatch(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/importcom")) + tg.run("build", "./testdata/importcom/works.go") +} + +func TestImportCommentMismatch(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/importcom")) + tg.runFail("build", "./testdata/importcom/wrongplace.go") + tg.grepStderr(`wrongplace expects import "my/x"`, "go build did not mention incorrect import") +} + +func TestImportCommentSyntaxError(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/importcom")) + tg.runFail("build", "./testdata/importcom/bad.go") + tg.grepStderr("cannot parse import comment", "go build did not mention syntax error") +} + +func TestImportCommentConflict(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/importcom")) + tg.runFail("build", "./testdata/importcom/conflict.go") + tg.grepStderr("found import comments", "go build did not mention comment conflict") +} + +// cmd/go: custom import path checking should not apply to Go packages without import comment. +func TestIssue10952(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + if _, err := exec.LookPath("git"); err != nil { + t.Skip("skipping because git binary not found") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempDir("src") + tg.setenv("GOPATH", tg.path(".")) + const importPath = "github.com/zombiezen/go-get-issue-10952" + tg.run("get", "-d", "-u", importPath) + repoDir := tg.path("src/" + importPath) + tg.runGit(repoDir, "remote", "set-url", "origin", "https://"+importPath+".git") + tg.run("get", "-d", "-u", importPath) +} + +func TestIssue16471(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + if _, err := exec.LookPath("git"); err != nil { + t.Skip("skipping because git binary not found") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempDir("src") + tg.setenv("GOPATH", tg.path(".")) + tg.must(os.MkdirAll(tg.path("src/rsc.io/go-get-issue-10952"), 0755)) + tg.runGit(tg.path("src/rsc.io"), "clone", "https://github.com/zombiezen/go-get-issue-10952") + tg.runFail("get", "-u", "rsc.io/go-get-issue-10952") + tg.grepStderr("rsc.io/go-get-issue-10952 is a custom import path for https://github.com/rsc/go-get-issue-10952, but .* is checked out from https://github.com/zombiezen/go-get-issue-10952", "did not detect updated import path") +} + +// Test git clone URL that uses SCP-like syntax and custom import path checking. +func TestIssue11457(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + if _, err := exec.LookPath("git"); err != nil { + t.Skip("skipping because git binary not found") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempDir("src") + tg.setenv("GOPATH", tg.path(".")) + const importPath = "rsc.io/go-get-issue-11457" + tg.run("get", "-d", "-u", importPath) + repoDir := tg.path("src/" + importPath) + tg.runGit(repoDir, "remote", "set-url", "origin", "git@github.com:rsc/go-get-issue-11457") + + // At this time, custom import path checking compares remotes verbatim (rather than + // just the host and path, skipping scheme and user), so we expect go get -u to fail. + // However, the goal of this test is to verify that gitRemoteRepo correctly parsed + // the SCP-like syntax, and we expect it to appear in the error message. + tg.runFail("get", "-d", "-u", importPath) + want := " is checked out from ssh://git@github.com/rsc/go-get-issue-11457" + if !strings.HasSuffix(strings.TrimSpace(tg.getStderr()), want) { + t.Error("expected clone URL to appear in stderr") + } +} + +func TestGetGitDefaultBranch(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + if _, err := exec.LookPath("git"); err != nil { + t.Skip("skipping because git binary not found") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempDir("src") + tg.setenv("GOPATH", tg.path(".")) + + // This repo has two branches, master and another-branch. + // The another-branch is the default that you get from 'git clone'. + // The go get command variants should not override this. + const importPath = "github.com/rsc/go-get-default-branch" + + tg.run("get", "-d", importPath) + repoDir := tg.path("src/" + importPath) + tg.runGit(repoDir, "branch", "--contains", "HEAD") + tg.grepStdout(`\* another-branch`, "not on correct default branch") + + tg.run("get", "-d", "-u", importPath) + tg.runGit(repoDir, "branch", "--contains", "HEAD") + tg.grepStdout(`\* another-branch`, "not on correct default branch") +} + +func TestAccidentalGitCheckout(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + if _, err := exec.LookPath("git"); err != nil { + t.Skip("skipping because git binary not found") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempDir("src") + tg.setenv("GOPATH", tg.path(".")) + + tg.runFail("get", "-u", "vcs-test.golang.org/go/test1-svn-git") + tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason") + + tg.runFail("get", "-u", "vcs-test.golang.org/go/test2-svn-git/test2main") + tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason") +} + +func TestErrorMessageForSyntaxErrorInTestGoFileSaysFAIL(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("test", "syntaxerror") + tg.grepStderr("FAIL", "go test did not say FAIL") +} + +func TestWildcardsDoNotLookInUselessDirectories(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("list", "...") + tg.grepBoth("badpkg", "go list ... failure does not mention badpkg") + tg.run("list", "m...") +} + +func TestRelativeImportsGoTest(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "./testdata/testimport") +} + +func TestRelativeImportsGoTestDashI(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + + // don't let test -i overwrite runtime + tg.wantNotStale("runtime", "", "must be non-stale before test -i") + + tg.run("test", "-i", "./testdata/testimport") +} + +func TestRelativeImportsInCommandLinePackage(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + files, err := filepath.Glob("./testdata/testimport/*.go") + tg.must(err) + tg.run(append([]string{"test"}, files...)...) +} + +func TestNonCanonicalImportPaths(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("build", "canonical/d") + tg.grepStderr("package canonical/d", "did not report canonical/d") + tg.grepStderr("imports canonical/b", "did not report canonical/b") + tg.grepStderr("imports canonical/a/: non-canonical", "did not report canonical/a/") +} + +func TestVersionControlErrorMessageIncludesCorrectDirectory(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/shadow/root1")) + tg.runFail("get", "-u", "foo") + + // TODO(iant): We should not have to use strconv.Quote here. + // The code in vcs.go should be changed so that it is not required. + quoted := strconv.Quote(filepath.Join("testdata", "shadow", "root1", "src", "foo")) + quoted = quoted[1 : len(quoted)-1] + + tg.grepStderr(regexp.QuoteMeta(quoted), "go get -u error does not mention shadow/root1/src/foo") +} + +func TestInstallFailsWithNoBuildableFiles(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.setenv("CGO_ENABLED", "0") + tg.runFail("install", "cgotest") + tg.grepStderr("build constraints exclude all Go files", "go install cgotest did not report 'build constraints exclude all Go files'") +} + +// Issue 21895 +func TestMSanAndRaceRequireCgo(t *testing.T) { + if !canMSan && !canRace { + t.Skip("skipping because both msan and the race detector are not supported") + } + + tg := testgo(t) + defer tg.cleanup() + tg.tempFile("triv.go", `package main; func main() {}`) + tg.setenv("CGO_ENABLED", "0") + if canRace { + tg.runFail("install", "-race", "triv.go") + tg.grepStderr("-race requires cgo", "did not correctly report that -race requires cgo") + tg.grepStderrNot("-msan", "reported that -msan instead of -race requires cgo") + } + if canMSan { + tg.runFail("install", "-msan", "triv.go") + tg.grepStderr("-msan requires cgo", "did not correctly report that -msan requires cgo") + tg.grepStderrNot("-race", "reported that -race instead of -msan requires cgo") + } +} + +func TestRelativeGOBINFail(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.tempFile("triv.go", `package main; func main() {}`) + tg.setenv("GOBIN", ".") + tg.runFail("install") + tg.grepStderr("cannot install, GOBIN must be an absolute path", "go install must fail if $GOBIN is a relative path") +} + +// Test that without $GOBIN set, binaries get installed +// into the GOPATH bin directory. +func TestInstallIntoGOPATH(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.creatingTemp("testdata/bin/go-cmd-test" + exeSuffix) + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("install", "go-cmd-test") + tg.wantExecutable("testdata/bin/go-cmd-test"+exeSuffix, "go install go-cmd-test did not write to testdata/bin/go-cmd-test") +} + +// Issue 12407 +func TestBuildOutputToDevNull(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("build", "-o", os.DevNull, "go-cmd-test") +} + +func TestPackageMainTestImportsArchiveNotBinary(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + gobin := filepath.Join(tg.pwd(), "testdata", "bin") + tg.creatingTemp(gobin) + tg.setenv("GOBIN", gobin) + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.must(os.Chtimes("./testdata/src/main_test/m.go", time.Now(), time.Now())) + tg.sleep() + tg.run("test", "main_test") + tg.run("install", "main_test") + tg.wantNotStale("main_test", "", "after go install, main listed as stale") + tg.run("test", "main_test") +} + +func TestPackageMainTestCompilerFlags(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.tempFile("src/p1/p1.go", "package main\n") + tg.tempFile("src/p1/p1_test.go", "package main\nimport \"testing\"\nfunc Test(t *testing.T){}\n") + tg.run("test", "-c", "-n", "p1") + tg.grepBothNot(`[\\/]compile.* -p main.*p1\.go`, "should not have run compile -p main p1.go") + tg.grepStderr(`[\\/]compile.* -p p1.*p1\.go`, "should have run compile -p p1 p1.go") +} + +// The runtime version string takes one of two forms: +// "go1.X[.Y]" for Go releases, and "devel +hash" at tip. +// Determine whether we are in a released copy by +// inspecting the version. +var isGoRelease = strings.HasPrefix(runtime.Version(), "go1") + +// Issue 12690 +func TestPackageNotStaleWithTrailingSlash(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + + // Make sure the packages below are not stale. + tg.wantNotStale("runtime", "", "must be non-stale before test runs") + tg.wantNotStale("os", "", "must be non-stale before test runs") + tg.wantNotStale("io", "", "must be non-stale before test runs") + + goroot := runtime.GOROOT() + tg.setenv("GOROOT", goroot+"/") + + tg.wantNotStale("runtime", "", "with trailing slash in GOROOT, runtime listed as stale") + tg.wantNotStale("os", "", "with trailing slash in GOROOT, os listed as stale") + tg.wantNotStale("io", "", "with trailing slash in GOROOT, io listed as stale") +} + +// With $GOBIN set, binaries get installed to $GOBIN. +func TestInstallIntoGOBIN(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + gobin := filepath.Join(tg.pwd(), "testdata", "bin1") + tg.creatingTemp(gobin) + tg.setenv("GOBIN", gobin) + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("install", "go-cmd-test") + tg.wantExecutable("testdata/bin1/go-cmd-test"+exeSuffix, "go install go-cmd-test did not write to testdata/bin1/go-cmd-test") +} + +// Issue 11065 +func TestInstallToCurrentDirectoryCreatesExecutable(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + pkg := filepath.Join(tg.pwd(), "testdata", "src", "go-cmd-test") + tg.creatingTemp(filepath.Join(pkg, "go-cmd-test"+exeSuffix)) + tg.setenv("GOBIN", pkg) + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.cd(pkg) + tg.run("install") + tg.wantExecutable("go-cmd-test"+exeSuffix, "go install did not write to current directory") +} + +// Without $GOBIN set, installing a program outside $GOPATH should fail +// (there is nowhere to install it). +func TestInstallWithoutDestinationFails(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.runFail("install", "testdata/src/go-cmd-test/helloworld.go") + tg.grepStderr("no install location for .go files listed on command line", "wrong error") +} + +// With $GOBIN set, should install there. +func TestInstallToGOBINCommandLinePackage(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + gobin := filepath.Join(tg.pwd(), "testdata", "bin1") + tg.creatingTemp(gobin) + tg.setenv("GOBIN", gobin) + tg.run("install", "testdata/src/go-cmd-test/helloworld.go") + tg.wantExecutable("testdata/bin1/helloworld"+exeSuffix, "go install testdata/src/go-cmd-test/helloworld.go did not write testdata/bin1/helloworld") +} + +func TestGoGetNonPkg(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.tempDir("gobin") + tg.setenv("GOPATH", tg.path(".")) + tg.setenv("GOBIN", tg.path("gobin")) + tg.runFail("get", "-d", "golang.org/x/tools") + tg.grepStderr("golang.org/x/tools: no Go files", "missing error") + tg.runFail("get", "-d", "-u", "golang.org/x/tools") + tg.grepStderr("golang.org/x/tools: no Go files", "missing error") + tg.runFail("get", "-d", "golang.org/x/tools") + tg.grepStderr("golang.org/x/tools: no Go files", "missing error") +} + +func TestGoGetTestOnlyPkg(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.tempDir("gopath") + tg.setenv("GOPATH", tg.path("gopath")) + tg.run("get", "golang.org/x/tour/content") + tg.run("get", "-t", "golang.org/x/tour/content") +} + +func TestInstalls(t *testing.T) { + if testing.Short() { + t.Skip("don't install into GOROOT in short mode") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempDir("gobin") + tg.setenv("GOPATH", tg.path(".")) + goroot := runtime.GOROOT() + tg.setenv("GOROOT", goroot) + + // cmd/fix installs into tool + tg.run("env", "GOOS") + goos := strings.TrimSpace(tg.getStdout()) + tg.setenv("GOOS", goos) + tg.run("env", "GOARCH") + goarch := strings.TrimSpace(tg.getStdout()) + tg.setenv("GOARCH", goarch) + fixbin := filepath.Join(goroot, "pkg", "tool", goos+"_"+goarch, "fix") + exeSuffix + tg.must(os.RemoveAll(fixbin)) + tg.run("install", "cmd/fix") + tg.wantExecutable(fixbin, "did not install cmd/fix to $GOROOT/pkg/tool") + tg.must(os.Remove(fixbin)) + tg.setenv("GOBIN", tg.path("gobin")) + tg.run("install", "cmd/fix") + tg.wantExecutable(fixbin, "did not install cmd/fix to $GOROOT/pkg/tool with $GOBIN set") + tg.unsetenv("GOBIN") + + // gopath program installs into GOBIN + tg.tempFile("src/progname/p.go", `package main; func main() {}`) + tg.setenv("GOBIN", tg.path("gobin")) + tg.run("install", "progname") + tg.unsetenv("GOBIN") + tg.wantExecutable(tg.path("gobin/progname")+exeSuffix, "did not install progname to $GOBIN/progname") + + // gopath program installs into GOPATH/bin + tg.run("install", "progname") + tg.wantExecutable(tg.path("bin/progname")+exeSuffix, "did not install progname to $GOPATH/bin/progname") +} + +func TestRejectRelativeDotPathInGOPATHCommandLinePackage(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", ".") + tg.runFail("build", "testdata/src/go-cmd-test/helloworld.go") + tg.grepStderr("GOPATH entry is relative", "expected an error message rejecting relative GOPATH entries") +} + +func TestRejectRelativePathsInGOPATH(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + sep := string(filepath.ListSeparator) + tg.setenv("GOPATH", sep+filepath.Join(tg.pwd(), "testdata")+sep+".") + tg.runFail("build", "go-cmd-test") + tg.grepStderr("GOPATH entry is relative", "expected an error message rejecting relative GOPATH entries") +} + +func TestRejectRelativePathsInGOPATHCommandLinePackage(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", "testdata") + tg.runFail("build", "testdata/src/go-cmd-test/helloworld.go") + tg.grepStderr("GOPATH entry is relative", "expected an error message rejecting relative GOPATH entries") +} + +// Issue 21928. +func TestRejectBlankPathsInGOPATH(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + sep := string(filepath.ListSeparator) + tg.setenv("GOPATH", " "+sep+filepath.Join(tg.pwd(), "testdata")) + tg.runFail("build", "go-cmd-test") + tg.grepStderr("GOPATH entry is relative", "expected an error message rejecting relative GOPATH entries") +} + +// Issue 21928. +func TestIgnoreEmptyPathsInGOPATH(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.creatingTemp("testdata/bin/go-cmd-test" + exeSuffix) + sep := string(filepath.ListSeparator) + tg.setenv("GOPATH", ""+sep+filepath.Join(tg.pwd(), "testdata")) + tg.run("install", "go-cmd-test") + tg.wantExecutable("testdata/bin/go-cmd-test"+exeSuffix, "go install go-cmd-test did not write to testdata/bin/go-cmd-test") +} + +// Issue 4104. +func TestGoTestWithPackageListedMultipleTimes(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.run("test", "errors", "errors", "errors", "errors", "errors") + if strings.Contains(strings.TrimSpace(tg.getStdout()), "\n") { + t.Error("go test errors errors errors errors errors tested the same package multiple times") + } +} + +func TestGoListHasAConsistentOrder(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.run("list", "std") + first := tg.getStdout() + tg.run("list", "std") + if first != tg.getStdout() { + t.Error("go list std ordering is inconsistent") + } +} + +func TestGoListStdDoesNotIncludeCommands(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.run("list", "std") + tg.grepStdoutNot("cmd/", "go list std shows commands") +} + +func TestGoListCmdOnlyShowsCommands(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.run("list", "cmd") + out := strings.TrimSpace(tg.getStdout()) + for _, line := range strings.Split(out, "\n") { + if !strings.Contains(line, "cmd/") { + t.Error("go list cmd shows non-commands") + break + } + } +} + +func TestGoListDedupsPackages(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("list", "xtestonly", "./testdata/src/xtestonly/...") + got := strings.TrimSpace(tg.getStdout()) + const want = "xtestonly" + if got != want { + t.Errorf("got %q; want %q", got, want) + } +} + +func TestGoListDeps(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempDir("src/p1/p2/p3/p4") + tg.setenv("GOPATH", tg.path(".")) + tg.tempFile("src/p1/p.go", "package p1\nimport _ \"p1/p2\"\n") + tg.tempFile("src/p1/p2/p.go", "package p2\nimport _ \"p1/p2/p3\"\n") + tg.tempFile("src/p1/p2/p3/p.go", "package p3\nimport _ \"p1/p2/p3/p4\"\n") + tg.tempFile("src/p1/p2/p3/p4/p.go", "package p4\n") + tg.run("list", "-f", "{{.Deps}}", "p1") + tg.grepStdout("p1/p2/p3/p4", "Deps(p1) does not mention p4") +} + +// Issue 4096. Validate the output of unsuccessful go install foo/quxx. +func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.runFail("install", "foo/quxx") + if tg.grepCountBoth(`cannot find package "foo/quxx" in any of`) != 1 { + t.Error(`go install foo/quxx expected error: .*cannot find package "foo/quxx" in any of`) + } +} + +func TestGOROOTSearchFailureReporting(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.runFail("install", "foo/quxx") + if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("foo", "quxx"))+` \(from \$GOROOT\)$`) != 1 { + t.Error(`go install foo/quxx expected error: .*foo/quxx (from $GOROOT)`) + } +} + +func TestMultipleGOPATHEntriesReportedSeparately(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + sep := string(filepath.ListSeparator) + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b")) + tg.runFail("install", "foo/quxx") + if tg.grepCountBoth(`testdata[/\\].[/\\]src[/\\]foo[/\\]quxx`) != 2 { + t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)\n.*testdata/b/src/foo/quxx`) + } +} + +// Test (from $GOPATH) annotation is reported for the first GOPATH entry, +func TestMentionGOPATHInFirstGOPATHEntry(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + sep := string(filepath.ListSeparator) + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b")) + tg.runFail("install", "foo/quxx") + if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "a", "src", "foo", "quxx"))+` \(from \$GOPATH\)$`) != 1 { + t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)`) + } +} + +// but not on the second. +func TestMentionGOPATHNotOnSecondEntry(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + sep := string(filepath.ListSeparator) + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b")) + tg.runFail("install", "foo/quxx") + if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "b", "src", "foo", "quxx"))+`$`) != 1 { + t.Error(`go install foo/quxx expected error: .*testdata/b/src/foo/quxx`) + } +} + +func homeEnvName() string { + switch runtime.GOOS { + case "windows": + return "USERPROFILE" + case "plan9": + return "home" + default: + return "HOME" + } +} + +func TestDefaultGOPATH(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempDir("home/go") + tg.setenv(homeEnvName(), tg.path("home")) + + tg.run("env", "GOPATH") + tg.grepStdout(regexp.QuoteMeta(tg.path("home/go")), "want GOPATH=$HOME/go") + + tg.setenv("GOROOT", tg.path("home/go")) + tg.must(os.MkdirAll(tg.path("home/go/src/cmd/internal/objabi"), 0777)) + tg.must(copyFile(filepath.Join(runtime.GOROOT(), "src/cmd/internal/objabi/zbootstrap.go"), tg.path("home/go/src/cmd/internal/objabi/zbootstrap.go"), 0666)) // for vgo + + tg.run("env", "GOPATH") + tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go") + + tg.setenv("GOROOT", tg.path("home/go")+"/") + tg.run("env", "GOPATH") + tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go/") +} + +func TestDefaultGOPATHGet(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", "") + tg.tempDir("home") + tg.setenv(homeEnvName(), tg.path("home")) + + // warn for creating directory + tg.run("get", "-v", "github.com/golang/example/hello") + tg.grepStderr("created GOPATH="+regexp.QuoteMeta(tg.path("home/go"))+"; see 'go help gopath'", "did not create GOPATH") + + // no warning if directory already exists + tg.must(os.RemoveAll(tg.path("home/go"))) + tg.tempDir("home/go") + tg.run("get", "github.com/golang/example/hello") + tg.grepStderrNot(".", "expected no output on standard error") + + // error if $HOME/go is a file + tg.must(os.RemoveAll(tg.path("home/go"))) + tg.tempFile("home/go", "") + tg.runFail("get", "github.com/golang/example/hello") + tg.grepStderr(`mkdir .*[/\\]go: .*(not a directory|cannot find the path)`, "expected error because $HOME/go is a file") +} + +func TestDefaultGOPATHPrintedSearchList(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", "") + tg.tempDir("home") + tg.setenv(homeEnvName(), tg.path("home")) + + tg.runFail("install", "github.com/golang/example/hello") + tg.grepStderr(regexp.QuoteMeta(tg.path("home/go/src/github.com/golang/example/hello"))+`.*from \$GOPATH`, "expected default GOPATH") +} + +// Issue 4186. go get cannot be used to download packages to $GOROOT. +// Test that without GOPATH set, go get should fail. +func TestGoGetIntoGOROOT(t *testing.T) { + t.Skip("vgo detects fake GOROOT") + + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempDir("src") + + // Fails because GOROOT=GOPATH + tg.setenv("GOPATH", tg.path(".")) + tg.setenv("GOROOT", tg.path(".")) + tg.runFail("get", "-d", "github.com/golang/example/hello") + tg.grepStderr("warning: GOPATH set to GOROOT", "go should detect GOPATH=GOROOT") + tg.grepStderr(`\$GOPATH must not be set to \$GOROOT`, "go should detect GOPATH=GOROOT") + + // Fails because GOROOT=GOPATH after cleaning. + tg.setenv("GOPATH", tg.path(".")+"/") + tg.setenv("GOROOT", tg.path(".")) + tg.runFail("get", "-d", "github.com/golang/example/hello") + tg.grepStderr("warning: GOPATH set to GOROOT", "go should detect GOPATH=GOROOT") + tg.grepStderr(`\$GOPATH must not be set to \$GOROOT`, "go should detect GOPATH=GOROOT") + + tg.setenv("GOPATH", tg.path(".")) + tg.setenv("GOROOT", tg.path(".")+"/") + tg.runFail("get", "-d", "github.com/golang/example/hello") + tg.grepStderr("warning: GOPATH set to GOROOT", "go should detect GOPATH=GOROOT") + tg.grepStderr(`\$GOPATH must not be set to \$GOROOT`, "go should detect GOPATH=GOROOT") + + // Fails because GOROOT=$HOME/go so default GOPATH unset. + tg.tempDir("home/go") + tg.setenv(homeEnvName(), tg.path("home")) + tg.setenv("GOPATH", "") + tg.setenv("GOROOT", tg.path("home/go")) + tg.runFail("get", "-d", "github.com/golang/example/hello") + tg.grepStderr(`\$GOPATH not set`, "expected GOPATH not set") + + tg.setenv(homeEnvName(), tg.path("home")+"/") + tg.setenv("GOPATH", "") + tg.setenv("GOROOT", tg.path("home/go")) + tg.runFail("get", "-d", "github.com/golang/example/hello") + tg.grepStderr(`\$GOPATH not set`, "expected GOPATH not set") + + tg.setenv(homeEnvName(), tg.path("home")) + tg.setenv("GOPATH", "") + tg.setenv("GOROOT", tg.path("home/go")+"/") + tg.runFail("get", "-d", "github.com/golang/example/hello") + tg.grepStderr(`\$GOPATH not set`, "expected GOPATH not set") +} + +func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("main.go", `package main + var extern string + func main() { + println(extern) + }`) + tg.run("run", "-ldflags", `-X "main.extern=hello world"`, tg.path("main.go")) + tg.grepStderr("^hello world", `ldflags -X "main.extern=hello world"' failed`) +} + +func TestGoTestCpuprofileLeavesBinaryBehind(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.makeTempdir() + tg.cd(tg.path(".")) + tg.run("test", "-cpuprofile", "errors.prof", "errors") + tg.wantExecutable("errors.test"+exeSuffix, "go test -cpuprofile did not create errors.test") +} + +func TestGoTestCpuprofileDashOControlsBinaryLocation(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.makeTempdir() + tg.cd(tg.path(".")) + tg.run("test", "-cpuprofile", "errors.prof", "-o", "myerrors.test"+exeSuffix, "errors") + tg.wantExecutable("myerrors.test"+exeSuffix, "go test -cpuprofile -o myerrors.test did not create myerrors.test") +} + +func TestGoTestMutexprofileLeavesBinaryBehind(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.makeTempdir() + tg.cd(tg.path(".")) + tg.run("test", "-mutexprofile", "errors.prof", "errors") + tg.wantExecutable("errors.test"+exeSuffix, "go test -mutexprofile did not create errors.test") +} + +func TestGoTestMutexprofileDashOControlsBinaryLocation(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.makeTempdir() + tg.cd(tg.path(".")) + tg.run("test", "-mutexprofile", "errors.prof", "-o", "myerrors.test"+exeSuffix, "errors") + tg.wantExecutable("myerrors.test"+exeSuffix, "go test -mutexprofile -o myerrors.test did not create myerrors.test") +} + +func TestGoBuildNonMain(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("build", "-buildmode=exe", "-o", "not_main"+exeSuffix, "not_main") + tg.grepStderr("-buildmode=exe requires exactly one main package", "go build with -o and -buildmode=exe should on a non-main package should throw an error") + tg.mustNotExist("not_main" + exeSuffix) +} + +func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.run("test", "-c", "-o", tg.path("myerrors.test"+exeSuffix), "errors") + tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -c -o myerrors.test did not create myerrors.test") +} + +func TestGoTestDashOWritesBinary(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.run("test", "-o", tg.path("myerrors.test"+exeSuffix), "errors") + tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test") +} + +func TestGoTestDashIDashOWritesBinary(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + + // don't let test -i overwrite runtime + tg.wantNotStale("runtime", "", "must be non-stale before test -i") + + tg.run("test", "-v", "-i", "-o", tg.path("myerrors.test"+exeSuffix), "errors") + tg.grepBothNot("PASS|FAIL", "test should not have run") + tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test") +} + +// Issue 4568. +func TestSymlinksList(t *testing.T) { + testenv.MustHaveSymlink(t) + + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.tempDir("src") + tg.must(os.Symlink(tg.path("."), tg.path("src/dir1"))) + tg.tempFile("src/dir1/p.go", "package p") + tg.setenv("GOPATH", tg.path(".")) + tg.cd(tg.path("src")) + tg.run("list", "-f", "{{.Root}}", "dir1") + if strings.TrimSpace(tg.getStdout()) != tg.path(".") { + t.Error("confused by symlinks") + } +} + +// Issue 14054. +func TestSymlinksVendor(t *testing.T) { + testenv.MustHaveSymlink(t) + + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.tempDir("gopath/src/dir1/vendor/v") + tg.tempFile("gopath/src/dir1/p.go", "package main\nimport _ `v`\nfunc main(){}") + tg.tempFile("gopath/src/dir1/vendor/v/v.go", "package v") + tg.must(os.Symlink(tg.path("gopath/src/dir1"), tg.path("symdir1"))) + tg.setenv("GOPATH", tg.path("gopath")) + tg.cd(tg.path("symdir1")) + tg.run("list", "-f", "{{.Root}}", ".") + if strings.TrimSpace(tg.getStdout()) != tg.path("gopath") { + t.Error("list confused by symlinks") + } + + // All of these should succeed, not die in vendor-handling code. + tg.run("run", "p.go") + tg.run("build") + tg.run("install") +} + +// Issue 15201. +func TestSymlinksVendor15201(t *testing.T) { + testenv.MustHaveSymlink(t) + + tg := testgo(t) + defer tg.cleanup() + + tg.tempDir("gopath/src/x/y/_vendor/src/x") + tg.must(os.Symlink("../../..", tg.path("gopath/src/x/y/_vendor/src/x/y"))) + tg.tempFile("gopath/src/x/y/w/w.go", "package w\nimport \"x/y/z\"\n") + tg.must(os.Symlink("../_vendor/src", tg.path("gopath/src/x/y/w/vendor"))) + tg.tempFile("gopath/src/x/y/z/z.go", "package z\n") + + tg.setenv("GOPATH", tg.path("gopath/src/x/y/_vendor")+string(filepath.ListSeparator)+tg.path("gopath")) + tg.cd(tg.path("gopath/src")) + tg.run("list", "./...") +} + +func TestSymlinksInternal(t *testing.T) { + testenv.MustHaveSymlink(t) + + tg := testgo(t) + defer tg.cleanup() + tg.tempDir("gopath/src/dir1/internal/v") + tg.tempFile("gopath/src/dir1/p.go", "package main\nimport _ `dir1/internal/v`\nfunc main(){}") + tg.tempFile("gopath/src/dir1/internal/v/v.go", "package v") + tg.must(os.Symlink(tg.path("gopath/src/dir1"), tg.path("symdir1"))) + tg.setenv("GOPATH", tg.path("gopath")) + tg.cd(tg.path("symdir1")) + tg.run("list", "-f", "{{.Root}}", ".") + if strings.TrimSpace(tg.getStdout()) != tg.path("gopath") { + t.Error("list confused by symlinks") + } + + // All of these should succeed, not die in internal-handling code. + tg.run("run", "p.go") + tg.run("build") + tg.run("install") +} + +// Issue 4515. +func TestInstallWithTags(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempDir("bin") + tg.tempFile("src/example/a/main.go", `package main + func main() {}`) + tg.tempFile("src/example/b/main.go", `// +build mytag + + package main + func main() {}`) + tg.setenv("GOPATH", tg.path(".")) + tg.run("install", "-tags", "mytag", "example/a", "example/b") + tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/a example/b did not install binaries") + tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/a example/b did not install binaries") + tg.must(os.Remove(tg.path("bin/a" + exeSuffix))) + tg.must(os.Remove(tg.path("bin/b" + exeSuffix))) + tg.run("install", "-tags", "mytag", "example/...") + tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/... did not install binaries") + tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/... did not install binaries") + tg.run("list", "-tags", "mytag", "example/b...") + if strings.TrimSpace(tg.getStdout()) != "example/b" { + t.Error("go list example/b did not find example/b") + } +} + +// Issue 4773 +func TestCaseCollisions(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempDir("src/example/a/pkg") + tg.tempDir("src/example/a/Pkg") + tg.tempDir("src/example/b") + tg.setenv("GOPATH", tg.path(".")) + tg.tempFile("src/example/a/a.go", `package p + import ( + _ "example/a/pkg" + _ "example/a/Pkg" + )`) + tg.tempFile("src/example/a/pkg/pkg.go", `package pkg`) + tg.tempFile("src/example/a/Pkg/pkg.go", `package pkg`) + tg.run("list", "-json", "example/a") + tg.grepStdout("case-insensitive import collision", "go list -json example/a did not report import collision") + tg.runFail("build", "example/a") + tg.grepStderr("case-insensitive import collision", "go build example/a did not report import collision") + tg.tempFile("src/example/b/file.go", `package b`) + tg.tempFile("src/example/b/FILE.go", `package b`) + f, err := os.Open(tg.path("src/example/b")) + tg.must(err) + names, err := f.Readdirnames(0) + tg.must(err) + tg.check(f.Close()) + args := []string{"list"} + if len(names) == 2 { + // case-sensitive file system, let directory read find both files + args = append(args, "example/b") + } else { + // case-insensitive file system, list files explicitly on command line + args = append(args, tg.path("src/example/b/file.go"), tg.path("src/example/b/FILE.go")) + } + tg.runFail(args...) + tg.grepStderr("case-insensitive file name collision", "go list example/b did not report file name collision") + + tg.runFail("list", "example/a/pkg", "example/a/Pkg") + tg.grepStderr("case-insensitive import collision", "go list example/a/pkg example/a/Pkg did not report import collision") + tg.run("list", "-json", "-e", "example/a/pkg", "example/a/Pkg") + tg.grepStdout("case-insensitive import collision", "go list -json -e example/a/pkg example/a/Pkg did not report import collision") + tg.runFail("build", "example/a/pkg", "example/a/Pkg") + tg.grepStderr("case-insensitive import collision", "go build example/a/pkg example/a/Pkg did not report import collision") +} + +// Issue 17451, 17662. +func TestSymlinkWarning(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + + tg.tempDir("src/example/xx") + tg.tempDir("yy/zz") + tg.tempFile("yy/zz/zz.go", "package zz\n") + if err := os.Symlink(tg.path("yy"), tg.path("src/example/xx/yy")); err != nil { + t.Skipf("symlink failed: %v", err) + } + tg.run("list", "example/xx/z...") + tg.grepStdoutNot(".", "list should not have matched anything") + tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages") + tg.grepStderrNot("symlink", "list should not have reported symlink") + + tg.run("list", "example/xx/...") + tg.grepStdoutNot(".", "list should not have matched anything") + tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages") + tg.grepStderr("ignoring symlink", "list should have reported symlink") +} + +// Issue 8181. +func TestGoGetDashTIssue8181(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.run("get", "-v", "-t", "github.com/rsc/go-get-issue-8181/a", "github.com/rsc/go-get-issue-8181/b") + tg.run("list", "...") + tg.grepStdout("x/build/gerrit", "missing expected x/build/gerrit") +} + +func TestIssue11307(t *testing.T) { + // go get -u was not working except in checkout directory + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.run("get", "github.com/rsc/go-get-issue-11307") + tg.run("get", "-u", "github.com/rsc/go-get-issue-11307") // was failing +} + +func TestShadowingLogic(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + pwd := tg.pwd() + sep := string(filepath.ListSeparator) + tg.setenv("GOPATH", filepath.Join(pwd, "testdata", "shadow", "root1")+sep+filepath.Join(pwd, "testdata", "shadow", "root2")) + + // The math in root1 is not "math" because the standard math is. + tg.run("list", "-f", "({{.ImportPath}}) ({{.ConflictDir}})", "./testdata/shadow/root1/src/math") + pwdForwardSlash := strings.Replace(pwd, string(os.PathSeparator), "/", -1) + if !strings.HasPrefix(pwdForwardSlash, "/") { + pwdForwardSlash = "/" + pwdForwardSlash + } + // The output will have makeImportValid applies, but we only + // bother to deal with characters we might reasonably see. + for _, r := range " :" { + pwdForwardSlash = strings.Replace(pwdForwardSlash, string(r), "_", -1) + } + want := "(_" + pwdForwardSlash + "/testdata/shadow/root1/src/math) (" + filepath.Join(runtime.GOROOT(), "src", "math") + ")" + if strings.TrimSpace(tg.getStdout()) != want { + t.Error("shadowed math is not shadowed; looking for", want) + } + + // The foo in root1 is "foo". + tg.run("list", "-f", "({{.ImportPath}}) ({{.ConflictDir}})", "./testdata/shadow/root1/src/foo") + if strings.TrimSpace(tg.getStdout()) != "(foo) ()" { + t.Error("unshadowed foo is shadowed") + } + + // The foo in root2 is not "foo" because the foo in root1 got there first. + tg.run("list", "-f", "({{.ImportPath}}) ({{.ConflictDir}})", "./testdata/shadow/root2/src/foo") + want = "(_" + pwdForwardSlash + "/testdata/shadow/root2/src/foo) (" + filepath.Join(pwd, "testdata", "shadow", "root1", "src", "foo") + ")" + if strings.TrimSpace(tg.getStdout()) != want { + t.Error("shadowed foo is not shadowed; looking for", want) + } + + // The error for go install should mention the conflicting directory. + tg.runFail("install", "./testdata/shadow/root2/src/foo") + want = "go install: no install location for " + filepath.Join(pwd, "testdata", "shadow", "root2", "src", "foo") + ": hidden by " + filepath.Join(pwd, "testdata", "shadow", "root1", "src", "foo") + if strings.TrimSpace(tg.getStderr()) != want { + t.Error("wrong shadowed install error; looking for", want) + } +} + +// Only succeeds if source order is preserved. +func TestSourceFileNameOrderPreserved(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "testdata/example1_test.go", "testdata/example2_test.go") +} + +// Check that coverage analysis works at all. +// Don't worry about the exact numbers but require not 0.0%. +func checkCoverage(tg *testgoData, data string) { + tg.t.Helper() + if regexp.MustCompile(`[^0-9]0\.0%`).MatchString(data) { + tg.t.Error("some coverage results are 0.0%") + } +} + +func TestCoverageRuns(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "-short", "-coverpkg=strings", "strings", "regexp") + data := tg.getStdout() + tg.getStderr() + tg.run("test", "-short", "-cover", "strings", "math", "regexp") + data += tg.getStdout() + tg.getStderr() + checkCoverage(tg, data) +} + +func TestCoverageDotImport(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("test", "-coverpkg=coverdot1,coverdot2", "coverdot2") + data := tg.getStdout() + tg.getStderr() + checkCoverage(tg, data) +} + +// Check that coverage analysis uses set mode. +// Also check that coverage profiles merge correctly. +func TestCoverageUsesSetMode(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.creatingTemp("testdata/cover.out") + tg.run("test", "-short", "-cover", "encoding/binary", "errors", "-coverprofile=testdata/cover.out") + data := tg.getStdout() + tg.getStderr() + if out, err := ioutil.ReadFile("testdata/cover.out"); err != nil { + t.Error(err) + } else { + if !bytes.Contains(out, []byte("mode: set")) { + t.Error("missing mode: set") + } + if !bytes.Contains(out, []byte("errors.go")) { + t.Error("missing errors.go") + } + if !bytes.Contains(out, []byte("binary.go")) { + t.Error("missing binary.go") + } + if bytes.Count(out, []byte("mode: set")) != 1 { + t.Error("too many mode: set") + } + } + checkCoverage(tg, data) +} + +func TestCoverageUsesAtomicModeForRace(t *testing.T) { + tooSlow(t) + if !canRace { + t.Skip("skipping because race detector not supported") + } + + tg := testgo(t) + defer tg.cleanup() + tg.creatingTemp("testdata/cover.out") + tg.run("test", "-short", "-race", "-cover", "encoding/binary", "-coverprofile=testdata/cover.out") + data := tg.getStdout() + tg.getStderr() + if out, err := ioutil.ReadFile("testdata/cover.out"); err != nil { + t.Error(err) + } else { + if !bytes.Contains(out, []byte("mode: atomic")) { + t.Error("missing mode: atomic") + } + } + checkCoverage(tg, data) +} + +func TestCoverageSyncAtomicImport(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("test", "-short", "-cover", "-covermode=atomic", "-coverpkg=coverdep/p1", "coverdep") +} + +func TestCoverageDepLoop(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + // coverdep2/p1's xtest imports coverdep2/p2 which imports coverdep2/p1. + // Make sure that coverage on coverdep2/p2 recompiles coverdep2/p2. + tg.run("test", "-short", "-cover", "coverdep2/p1") + tg.grepStdout("coverage: 100.0% of statements", "expected 100.0% coverage") +} + +func TestCoverageImportMainLoop(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("test", "importmain/test") + tg.grepStderr("not an importable package", "did not detect import main") + tg.runFail("test", "-cover", "importmain/test") + tg.grepStderr("not an importable package", "did not detect import main") +} + +func TestCoveragePattern(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + + // If coverpkg=sleepy... expands by package loading + // (as opposed to pattern matching on deps) + // then it will try to load sleepybad, which does not compile, + // and the test command will fail. + tg.run("test", "-coverprofile="+tg.path("cover.out"), "-coverpkg=sleepy...", "-run=^$", "sleepy1") +} + +func TestCoverageErrorLine(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.setenv("GOTMPDIR", tg.tempdir) + + tg.runFail("test", "coverbad") + tg.grepStderr(`coverbad[\\/]p\.go:4`, "did not find coverbad/p.go:4") + if canCgo { + tg.grepStderr(`coverbad[\\/]p1\.go:6`, "did not find coverbad/p1.go:6") + } + tg.grepStderrNot(regexp.QuoteMeta(tg.tempdir), "found temporary directory in error") + stderr := tg.getStderr() + + tg.runFail("test", "-cover", "coverbad") + stderr2 := tg.getStderr() + + // It's OK that stderr2 drops the character position in the error, + // because of the //line directive (see golang.org/issue/22662). + stderr = strings.Replace(stderr, "p.go:4:2:", "p.go:4:", -1) + if stderr != stderr2 { + t.Logf("test -cover changed error messages:\nbefore:\n%s\n\nafter:\n%s", stderr, stderr2) + t.Skip("golang.org/issue/22660") + t.FailNow() + } +} + +func TestTestBuildFailureOutput(t *testing.T) { + tooSlow(t) + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + + // Doesn't build, -x output should not claim to run test. + tg.runFail("test", "-x", "coverbad") + tg.grepStderrNot(`[\\/]coverbad\.test( |$)`, "claimed to run test") +} + +func TestCoverageFunc(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + + tg.run("test", "-outputdir="+tg.tempdir, "-coverprofile=cover.out", "coverasm") + tg.run("tool", "cover", "-func="+tg.path("cover.out")) + tg.grepStdout(`\tg\t*100.0%`, "did not find g 100% covered") + tg.grepStdoutNot(`\tf\t*[0-9]`, "reported coverage for assembly function f") +} + +func TestPluginNonMain(t *testing.T) { + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + pkg := filepath.Join(wd, "testdata", "testdep", "p2") + + tg := testgo(t) + defer tg.cleanup() + + tg.runFail("build", "-buildmode=plugin", pkg) +} + +func TestTestEmpty(t *testing.T) { + if !canRace { + t.Skip("no race detector") + } + + wd, _ := os.Getwd() + testdata := filepath.Join(wd, "testdata") + for _, dir := range []string{"pkg", "test", "xtest", "pkgtest", "pkgxtest", "pkgtestxtest", "testxtest"} { + t.Run(dir, func(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", testdata) + tg.cd(filepath.Join(testdata, "src/empty/"+dir)) + tg.run("test", "-cover", "-coverpkg=.", "-race") + }) + if testing.Short() { + break + } + } +} + +func TestNoGoError(t *testing.T) { + wd, _ := os.Getwd() + testdata := filepath.Join(wd, "testdata") + for _, dir := range []string{"empty/test", "empty/xtest", "empty/testxtest", "exclude", "exclude/ignore", "exclude/empty"} { + t.Run(dir, func(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", testdata) + tg.cd(filepath.Join(testdata, "src")) + tg.runFail("build", "./"+dir) + var want string + if strings.Contains(dir, "test") { + want = "no non-test Go files in " + } else if dir == "exclude" { + want = "build constraints exclude all Go files in " + } else { + want = "no Go files in " + } + tg.grepStderr(want, "wrong reason for failure") + }) + } +} + +func TestTestRaceInstall(t *testing.T) { + if !canRace { + t.Skip("no race detector") + } + tooSlow(t) + + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + + tg.tempDir("pkg") + pkgdir := tg.path("pkg") + tg.run("install", "-race", "-pkgdir="+pkgdir, "std") + tg.run("test", "-race", "-pkgdir="+pkgdir, "-i", "-v", "empty/pkg") + if tg.getStderr() != "" { + t.Error("go test -i -race: rebuilds cached packages") + } +} + +func TestBuildDryRunWithCgo(t *testing.T) { + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + + tg := testgo(t) + defer tg.cleanup() + tg.tempFile("foo.go", `package main + +/* +#include <limits.h> +*/ +import "C" + +func main() { + println(C.INT_MAX) +}`) + tg.run("build", "-n", tg.path("foo.go")) + tg.grepStderrNot(`os.Stat .* no such file or directory`, "unexpected stat of archive file") +} + +func TestCoverageWithCgo(t *testing.T) { + tooSlow(t) + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + + for _, dir := range []string{"cgocover", "cgocover2", "cgocover3", "cgocover4"} { + t.Run(dir, func(t *testing.T) { + tg := testgo(t) + tg.parallel() + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("test", "-short", "-cover", dir) + data := tg.getStdout() + tg.getStderr() + checkCoverage(tg, data) + }) + } +} + +func TestCgoAsmError(t *testing.T) { + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + + tg := testgo(t) + tg.parallel() + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("build", "cgoasm") + tg.grepBoth("package using cgo has Go assembly file", "did not detect Go assembly file") +} + +func TestCgoDependsOnSyscall(t *testing.T) { + if testing.Short() { + t.Skip("skipping test that removes $GOROOT/pkg/*_race in short mode") + } + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + if !canRace { + t.Skip("skipping because race detector not supported") + } + + tg := testgo(t) + defer tg.cleanup() + files, err := filepath.Glob(filepath.Join(runtime.GOROOT(), "pkg", "*_race")) + tg.must(err) + for _, file := range files { + tg.check(os.RemoveAll(file)) + } + tg.tempFile("src/foo/foo.go", ` + package foo + //#include <stdio.h> + import "C"`) + tg.setenv("GOPATH", tg.path(".")) + tg.run("build", "-race", "foo") +} + +func TestCgoShowsFullPathNames(t *testing.T) { + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("src/x/y/dirname/foo.go", ` + package foo + import "C" + func f() {`) + tg.setenv("GOPATH", tg.path(".")) + tg.runFail("build", "x/y/dirname") + tg.grepBoth("x/y/dirname", "error did not use full path") +} + +func TestCgoHandlesWlORIGIN(t *testing.T) { + tooSlow(t) + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("src/origin/origin.go", `package origin + // #cgo !darwin LDFLAGS: -Wl,-rpath,$ORIGIN + // void f(void) {} + import "C" + func f() { C.f() }`) + tg.setenv("GOPATH", tg.path(".")) + tg.run("build", "origin") +} + +func TestCgoPkgConfig(t *testing.T) { + tooSlow(t) + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + + tg.run("env", "PKG_CONFIG") + pkgConfig := strings.TrimSpace(tg.getStdout()) + if out, err := exec.Command(pkgConfig, "--atleast-pkgconfig-version", "0.24").CombinedOutput(); err != nil { + t.Skipf("%s --atleast-pkgconfig-version 0.24: %v\n%s", pkgConfig, err, out) + } + + // OpenBSD's pkg-config is strict about whitespace and only + // supports backslash-escaped whitespace. It does not support + // quotes, which the normal freedesktop.org pkg-config does + // support. See http://man.openbsd.org/pkg-config.1 + tg.tempFile("foo.pc", ` +Name: foo +Description: The foo library +Version: 1.0.0 +Cflags: -Dhello=10 -Dworld=+32 -DDEFINED_FROM_PKG_CONFIG=hello\ world +`) + tg.tempFile("foo.go", `package main + +/* +#cgo pkg-config: foo +int value() { + return DEFINED_FROM_PKG_CONFIG; +} +*/ +import "C" +import "os" + +func main() { + if C.value() != 42 { + println("value() =", C.value(), "wanted 42") + os.Exit(1) + } +} +`) + tg.setenv("PKG_CONFIG_PATH", tg.path(".")) + tg.run("run", tg.path("foo.go")) +} + +// "go test -c -test.bench=XXX errors" should not hang. +// "go test -c" should also produce reproducible binaries. +// "go test -c" should also appear to write a new binary every time, +// even if it's really just updating the mtime on an existing up-to-date binary. +func TestIssue6480(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.makeTempdir() + tg.cd(tg.path(".")) + tg.run("test", "-c", "-test.bench=XXX", "errors") + tg.run("test", "-c", "-o", "errors2.test", "errors") + + data1, err := ioutil.ReadFile("errors.test" + exeSuffix) + tg.must(err) + data2, err := ioutil.ReadFile("errors2.test") // no exeSuffix because -o above doesn't have it + tg.must(err) + if !bytes.Equal(data1, data2) { + t.Fatalf("go test -c errors produced different binaries when run twice") + } + + start := time.Now() + tg.run("test", "-x", "-c", "-test.bench=XXX", "errors") + tg.grepStderrNot(`[\\/]link|gccgo`, "incorrectly relinked up-to-date test binary") + info, err := os.Stat("errors.test" + exeSuffix) + if err != nil { + t.Fatal(err) + } + start = truncateLike(start, info.ModTime()) + if info.ModTime().Before(start) { + t.Fatalf("mtime of errors.test predates test -c command (%v < %v)", info.ModTime(), start) + } + + start = time.Now() + tg.run("test", "-x", "-c", "-o", "errors2.test", "errors") + tg.grepStderrNot(`[\\/]link|gccgo`, "incorrectly relinked up-to-date test binary") + info, err = os.Stat("errors2.test") + if err != nil { + t.Fatal(err) + } + start = truncateLike(start, info.ModTime()) + if info.ModTime().Before(start) { + t.Fatalf("mtime of errors2.test predates test -c command (%v < %v)", info.ModTime(), start) + } +} + +// truncateLike returns the result of truncating t to the apparent precision of p. +func truncateLike(t, p time.Time) time.Time { + nano := p.UnixNano() + d := 1 * time.Nanosecond + for nano%int64(d) == 0 && d < 1*time.Second { + d *= 10 + } + for nano%int64(d) == 0 && d < 2*time.Second { + d *= 2 + } + return t.Truncate(d) +} + +// cmd/cgo: undefined reference when linking a C-library using gccgo +func TestIssue7573(t *testing.T) { + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + if _, err := exec.LookPath("gccgo"); err != nil { + t.Skip("skipping because no gccgo compiler found") + } + t.Skip("golang.org/issue/22472") + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("src/cgoref/cgoref.go", ` +package main +// #cgo LDFLAGS: -L alibpath -lalib +// void f(void) {} +import "C" + +func main() { C.f() }`) + tg.setenv("GOPATH", tg.path(".")) + tg.run("build", "-n", "-compiler", "gccgo", "cgoref") + tg.grepStderr(`gccgo.*\-L [^ ]*alibpath \-lalib`, `no Go-inline "#cgo LDFLAGS:" ("-L alibpath -lalib") passed to gccgo linking stage`) +} + +func TestListTemplateContextFunction(t *testing.T) { + t.Parallel() + for _, tt := range []struct { + v string + want string + }{ + {"GOARCH", runtime.GOARCH}, + {"GOOS", runtime.GOOS}, + {"GOROOT", filepath.Clean(runtime.GOROOT())}, + {"GOPATH", os.Getenv("GOPATH")}, + {"CgoEnabled", ""}, + {"UseAllFiles", ""}, + {"Compiler", ""}, + {"BuildTags", ""}, + {"ReleaseTags", ""}, + {"InstallSuffix", ""}, + } { + tt := tt + t.Run(tt.v, func(t *testing.T) { + tg := testgo(t) + tg.parallel() + defer tg.cleanup() + tmpl := "{{context." + tt.v + "}}" + tg.run("list", "-f", tmpl) + if tt.want == "" { + return + } + if got := strings.TrimSpace(tg.getStdout()); got != tt.want { + t.Errorf("go list -f %q: got %q; want %q", tmpl, got, tt.want) + } + }) + } +} + +// cmd/go: "go test" should fail if package does not build +func TestIssue7108(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("test", "notest") +} + +// cmd/go: go test -a foo does not rebuild regexp. +func TestIssue6844(t *testing.T) { + if testing.Short() { + t.Skip("don't rebuild the standard library in short mode") + } + + tg := testgo(t) + defer tg.cleanup() + tg.creatingTemp("deps.test" + exeSuffix) + tg.run("test", "-x", "-a", "-c", "testdata/dep_test.go") + tg.grepStderr("regexp", "go test -x -a -c testdata/dep-test.go did not rebuild regexp") +} + +func TestBuildDashIInstallsDependencies(t *testing.T) { + tooSlow(t) + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("src/x/y/foo/foo.go", `package foo + func F() {}`) + tg.tempFile("src/x/y/bar/bar.go", `package bar + import "x/y/foo" + func F() { foo.F() }`) + tg.setenv("GOPATH", tg.path(".")) + + // don't let build -i overwrite runtime + tg.wantNotStale("runtime", "", "must be non-stale before build -i") + + checkbar := func(desc string) { + tg.run("build", "-v", "-i", "x/y/bar") + tg.grepBoth("x/y/foo", "first build -i "+desc+" did not build x/y/foo") + tg.run("build", "-v", "-i", "x/y/bar") + tg.grepBothNot("x/y/foo", "second build -i "+desc+" built x/y/foo") + } + checkbar("pkg") + + tg.creatingTemp("bar" + exeSuffix) + tg.sleep() + tg.tempFile("src/x/y/foo/foo.go", `package foo + func F() { F() }`) + tg.tempFile("src/x/y/bar/bar.go", `package main + import "x/y/foo" + func main() { foo.F() }`) + checkbar("cmd") +} + +func TestGoBuildInTestOnlyDirectoryFailsWithAGoodError(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.runFail("build", "./testdata/testonly") + tg.grepStderr("no non-test Go files in", "go build ./testdata/testonly produced unexpected error") +} + +func TestGoTestDetectsTestOnlyImportCycles(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("test", "-c", "testcycle/p3") + tg.grepStderr("import cycle not allowed in test", "go test testcycle/p3 produced unexpected error") + + tg.runFail("test", "-c", "testcycle/q1") + tg.grepStderr("import cycle not allowed in test", "go test testcycle/q1 produced unexpected error") +} + +func TestGoTestFooTestWorks(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "testdata/standalone_test.go") +} + +// Issue 22388 +func TestGoTestMainWithWrongSignature(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.runFail("test", "testdata/standalone_main_wrong_test.go") + tg.grepStderr(`wrong signature for TestMain, must be: func TestMain\(m \*testing.M\)`, "detected wrong error message") +} + +func TestGoTestMainAsNormalTest(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "testdata/standalone_main_normal_test.go") + tg.grepBoth(okPattern, "go test did not say ok") +} + +func TestGoTestMainTwice(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOCACHE", tg.tempdir) + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("test", "-v", "multimain") + if strings.Count(tg.getStdout(), "notwithstanding") != 2 { + t.Fatal("tests did not run twice") + } +} + +func TestGoTestFlagsAfterPackage(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "testdata/flag_test.go", "-v", "-args", "-v=7") // Two distinct -v flags. + tg.run("test", "-v", "testdata/flag_test.go", "-args", "-v=7") // Two distinct -v flags. +} + +func TestGoTestXtestonlyWorks(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("clean", "-i", "xtestonly") + tg.run("test", "xtestonly") +} + +func TestGoTestBuildsAnXtestContainingOnlyNonRunnableExamples(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "-v", "./testdata/norunexample") + tg.grepStdout("File with non-runnable example was built.", "file with non-runnable example was not built") +} + +func TestGoGenerateHandlesSimpleCommand(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("skipping because windows has no echo command") + } + + tg := testgo(t) + defer tg.cleanup() + tg.run("generate", "./testdata/generate/test1.go") + tg.grepStdout("Success", "go generate ./testdata/generate/test1.go generated wrong output") +} + +func TestGoGenerateHandlesCommandAlias(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("skipping because windows has no echo command") + } + + tg := testgo(t) + defer tg.cleanup() + tg.run("generate", "./testdata/generate/test2.go") + tg.grepStdout("Now is the time for all good men", "go generate ./testdata/generate/test2.go generated wrong output") +} + +func TestGoGenerateVariableSubstitution(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("skipping because windows has no echo command") + } + + tg := testgo(t) + defer tg.cleanup() + tg.run("generate", "./testdata/generate/test3.go") + tg.grepStdout(runtime.GOARCH+" test3.go:7 pabc xyzp/test3.go/123", "go generate ./testdata/generate/test3.go generated wrong output") +} + +func TestGoGenerateRunFlag(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("skipping because windows has no echo command") + } + + tg := testgo(t) + defer tg.cleanup() + tg.run("generate", "-run", "y.s", "./testdata/generate/test4.go") + tg.grepStdout("yes", "go generate -run yes ./testdata/generate/test4.go did not select yes") + tg.grepStdoutNot("no", "go generate -run yes ./testdata/generate/test4.go selected no") +} + +func TestGoGenerateEnv(t *testing.T) { + switch runtime.GOOS { + case "plan9", "windows": + t.Skipf("skipping because %s does not have the env command", runtime.GOOS) + } + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("env.go", "package main\n\n//go:generate env") + tg.run("generate", tg.path("env.go")) + for _, v := range []string{"GOARCH", "GOOS", "GOFILE", "GOLINE", "GOPACKAGE", "DOLLAR"} { + tg.grepStdout("^"+v+"=", "go generate environment missing "+v) + } +} + +func TestGoGenerateBadImports(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("skipping because windows has no echo command") + } + + // This package has an invalid import causing an import cycle, + // but go generate is supposed to still run. + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("generate", "gencycle") + tg.grepStdout("hello world", "go generate gencycle did not run generator") +} + +func TestGoGetCustomDomainWildcard(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.run("get", "-u", "rsc.io/pdf/...") + tg.wantExecutable(tg.path("bin/pdfpasswd"+exeSuffix), "did not build rsc/io/pdf/pdfpasswd") +} + +func TestGoGetInternalWildcard(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + // used to fail with errors about internal packages + tg.run("get", "github.com/rsc/go-get-issue-11960/...") +} + +func TestGoVetWithExternalTests(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("vet", "vetpkg") + tg.grepBoth("Printf", "go vet vetpkg did not find missing argument for Printf") +} + +func TestGoVetWithTags(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("vet", "-tags", "tagtest", "vetpkg") + tg.grepBoth(`c\.go.*Printf`, "go vet vetpkg did not run scan tagged file") +} + +func TestGoVetWithFlagsOn(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("vet", "-printf", "vetpkg") + tg.grepBoth("Printf", "go vet -printf vetpkg did not find missing argument for Printf") +} + +func TestGoVetWithFlagsOff(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("vet", "-printf=false", "vetpkg") +} + +// Issue 23395. +func TestGoVetWithOnlyTestFiles(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("src/p/p_test.go", "package p; import \"testing\"; func TestMe(*testing.T) {}") + tg.setenv("GOPATH", tg.path(".")) + tg.run("vet", "p") +} + +// Issue 9767, 19769. +func TestGoGetDotSlashDownload(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.tempDir("src/rsc.io") + tg.setenv("GOPATH", tg.path(".")) + tg.cd(tg.path("src/rsc.io")) + tg.run("get", "./pprof_mac_fix") +} + +// Issue 13037: Was not parsing <meta> tags in 404 served over HTTPS +func TestGoGetHTTPS404(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + switch runtime.GOOS { + case "darwin", "linux", "freebsd": + default: + t.Skipf("test case does not work on %s", runtime.GOOS) + } + + tg := testgo(t) + defer tg.cleanup() + tg.tempDir("src") + tg.setenv("GOPATH", tg.path(".")) + tg.run("get", "bazil.org/fuse/fs/fstestutil") +} + +// Test that you cannot import a main package. +// See golang.org/issue/4210 and golang.org/issue/17475. +func TestImportMain(t *testing.T) { + tooSlow(t) + + tg := testgo(t) + tg.parallel() + defer tg.cleanup() + + // Importing package main from that package main's test should work. + tg.tempFile("src/x/main.go", `package main + var X int + func main() {}`) + tg.tempFile("src/x/main_test.go", `package main_test + import xmain "x" + import "testing" + var _ = xmain.X + func TestFoo(t *testing.T) {} + `) + tg.setenv("GOPATH", tg.path(".")) + tg.creatingTemp("x" + exeSuffix) + tg.run("build", "x") + tg.run("test", "x") + + // Importing package main from another package should fail. + tg.tempFile("src/p1/p.go", `package p1 + import xmain "x" + var _ = xmain.X + `) + tg.runFail("build", "p1") + tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main") + + // ... even in that package's test. + tg.tempFile("src/p2/p.go", `package p2 + `) + tg.tempFile("src/p2/p_test.go", `package p2 + import xmain "x" + import "testing" + var _ = xmain.X + func TestFoo(t *testing.T) {} + `) + tg.run("build", "p2") + tg.runFail("test", "p2") + tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main") + + // ... even if that package's test is an xtest. + tg.tempFile("src/p3/p.go", `package p + `) + tg.tempFile("src/p3/p_test.go", `package p_test + import xmain "x" + import "testing" + var _ = xmain.X + func TestFoo(t *testing.T) {} + `) + tg.run("build", "p3") + tg.runFail("test", "p3") + tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main") + + // ... even if that package is a package main + tg.tempFile("src/p4/p.go", `package main + func main() {} + `) + tg.tempFile("src/p4/p_test.go", `package main + import xmain "x" + import "testing" + var _ = xmain.X + func TestFoo(t *testing.T) {} + `) + tg.creatingTemp("p4" + exeSuffix) + tg.run("build", "p4") + tg.runFail("test", "p4") + tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main") + + // ... even if that package is a package main using an xtest. + tg.tempFile("src/p5/p.go", `package main + func main() {} + `) + tg.tempFile("src/p5/p_test.go", `package main_test + import xmain "x" + import "testing" + var _ = xmain.X + func TestFoo(t *testing.T) {} + `) + tg.creatingTemp("p5" + exeSuffix) + tg.run("build", "p5") + tg.runFail("test", "p5") + tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main") +} + +// Test that you cannot use a local import in a package +// accessed by a non-local import (found in a GOPATH/GOROOT). +// See golang.org/issue/17475. +func TestImportLocal(t *testing.T) { + tooSlow(t) + + tg := testgo(t) + tg.parallel() + defer tg.cleanup() + + tg.tempFile("src/dir/x/x.go", `package x + var X int + `) + tg.setenv("GOPATH", tg.path(".")) + tg.run("build", "dir/x") + + // Ordinary import should work. + tg.tempFile("src/dir/p0/p.go", `package p0 + import "dir/x" + var _ = x.X + `) + tg.run("build", "dir/p0") + + // Relative import should not. + tg.tempFile("src/dir/p1/p.go", `package p1 + import "../x" + var _ = x.X + `) + tg.runFail("build", "dir/p1") + tg.grepStderr("local import.*in non-local package", "did not diagnose local import") + + // ... even in a test. + tg.tempFile("src/dir/p2/p.go", `package p2 + `) + tg.tempFile("src/dir/p2/p_test.go", `package p2 + import "../x" + import "testing" + var _ = x.X + func TestFoo(t *testing.T) {} + `) + tg.run("build", "dir/p2") + tg.runFail("test", "dir/p2") + tg.grepStderr("local import.*in non-local package", "did not diagnose local import") + + // ... even in an xtest. + tg.tempFile("src/dir/p2/p_test.go", `package p2_test + import "../x" + import "testing" + var _ = x.X + func TestFoo(t *testing.T) {} + `) + tg.run("build", "dir/p2") + tg.runFail("test", "dir/p2") + tg.grepStderr("local import.*in non-local package", "did not diagnose local import") + + // Relative import starting with ./ should not work either. + tg.tempFile("src/dir/d.go", `package dir + import "./x" + var _ = x.X + `) + tg.runFail("build", "dir") + tg.grepStderr("local import.*in non-local package", "did not diagnose local import") + + // ... even in a test. + tg.tempFile("src/dir/d.go", `package dir + `) + tg.tempFile("src/dir/d_test.go", `package dir + import "./x" + import "testing" + var _ = x.X + func TestFoo(t *testing.T) {} + `) + tg.run("build", "dir") + tg.runFail("test", "dir") + tg.grepStderr("local import.*in non-local package", "did not diagnose local import") + + // ... even in an xtest. + tg.tempFile("src/dir/d_test.go", `package dir_test + import "./x" + import "testing" + var _ = x.X + func TestFoo(t *testing.T) {} + `) + tg.run("build", "dir") + tg.runFail("test", "dir") + tg.grepStderr("local import.*in non-local package", "did not diagnose local import") + + // Relative import plain ".." should not work. + tg.tempFile("src/dir/x/y/y.go", `package dir + import ".." + var _ = x.X + `) + tg.runFail("build", "dir/x/y") + tg.grepStderr("local import.*in non-local package", "did not diagnose local import") + + // ... even in a test. + tg.tempFile("src/dir/x/y/y.go", `package y + `) + tg.tempFile("src/dir/x/y/y_test.go", `package y + import ".." + import "testing" + var _ = x.X + func TestFoo(t *testing.T) {} + `) + tg.run("build", "dir/x/y") + tg.runFail("test", "dir/x/y") + tg.grepStderr("local import.*in non-local package", "did not diagnose local import") + + // ... even in an x test. + tg.tempFile("src/dir/x/y/y_test.go", `package y_test + import ".." + import "testing" + var _ = x.X + func TestFoo(t *testing.T) {} + `) + tg.run("build", "dir/x/y") + tg.runFail("test", "dir/x/y") + tg.grepStderr("local import.*in non-local package", "did not diagnose local import") + + // Relative import "." should not work. + tg.tempFile("src/dir/x/xx.go", `package x + import "." + var _ = x.X + `) + tg.runFail("build", "dir/x") + tg.grepStderr("local import.*in non-local package", "did not diagnose local import") + + // ... even in a test. + tg.tempFile("src/dir/x/xx.go", `package x + `) + tg.tempFile("src/dir/x/xx_test.go", `package x + import "." + import "testing" + var _ = x.X + func TestFoo(t *testing.T) {} + `) + tg.run("build", "dir/x") + tg.runFail("test", "dir/x") + tg.grepStderr("local import.*in non-local package", "did not diagnose local import") + + // ... even in an xtest. + tg.tempFile("src/dir/x/xx.go", `package x + `) + tg.tempFile("src/dir/x/xx_test.go", `package x_test + import "." + import "testing" + var _ = x.X + func TestFoo(t *testing.T) {} + `) + tg.run("build", "dir/x") + tg.runFail("test", "dir/x") + tg.grepStderr("local import.*in non-local package", "did not diagnose local import") +} + +func TestGoGetInsecure(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.failSSH() + + const repo = "insecure.go-get-issue-15410.appspot.com/pkg/p" + + // Try go get -d of HTTP-only repo (should fail). + tg.runFail("get", "-d", repo) + + // Try again with -insecure (should succeed). + tg.run("get", "-d", "-insecure", repo) + + // Try updating without -insecure (should fail). + tg.runFail("get", "-d", "-u", "-f", repo) +} + +func TestGoGetUpdateInsecure(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + + const repo = "github.com/golang/example" + + // Clone the repo via HTTP manually. + cmd := exec.Command("git", "clone", "-q", "http://"+repo, tg.path("src/"+repo)) + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("cloning %v repo: %v\n%s", repo, err, out) + } + + // Update without -insecure should fail. + // Update with -insecure should succeed. + // We need -f to ignore import comments. + const pkg = repo + "/hello" + tg.runFail("get", "-d", "-u", "-f", pkg) + tg.run("get", "-d", "-u", "-f", "-insecure", pkg) +} + +func TestGoGetInsecureCustomDomain(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + + const repo = "insecure.go-get-issue-15410.appspot.com/pkg/p" + tg.runFail("get", "-d", repo) + tg.run("get", "-d", "-insecure", repo) +} + +func TestGoRunDirs(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.cd("testdata/rundir") + tg.runFail("run", "x.go", "sub/sub.go") + tg.grepStderr("named files must all be in one directory; have ./ and sub/", "wrong output") + tg.runFail("run", "sub/sub.go", "x.go") + tg.grepStderr("named files must all be in one directory; have sub/ and ./", "wrong output") +} + +func TestGoInstallPkgdir(t *testing.T) { + tooSlow(t) + + tg := testgo(t) + tg.parallel() + defer tg.cleanup() + tg.makeTempdir() + pkg := tg.path(".") + tg.run("install", "-pkgdir", pkg, "sync") + tg.mustExist(filepath.Join(pkg, "sync.a")) + tg.mustNotExist(filepath.Join(pkg, "sync/atomic.a")) + tg.run("install", "-i", "-pkgdir", pkg, "sync") + tg.mustExist(filepath.Join(pkg, "sync.a")) + tg.mustExist(filepath.Join(pkg, "sync/atomic.a")) +} + +func TestGoTestRaceInstallCgo(t *testing.T) { + if !canRace { + t.Skip("skipping because race detector not supported") + } + + // golang.org/issue/10500. + // This used to install a race-enabled cgo. + tg := testgo(t) + defer tg.cleanup() + tg.run("tool", "-n", "cgo") + cgo := strings.TrimSpace(tg.stdout.String()) + old, err := os.Stat(cgo) + tg.must(err) + tg.run("test", "-race", "-i", "runtime/race") + new, err := os.Stat(cgo) + tg.must(err) + if !new.ModTime().Equal(old.ModTime()) { + t.Fatalf("go test -i runtime/race reinstalled cmd/cgo") + } +} + +func TestGoTestRaceFailures(t *testing.T) { + tooSlow(t) + + if !canRace { + t.Skip("skipping because race detector not supported") + } + + tg := testgo(t) + tg.parallel() + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + + tg.run("test", "testrace") + + tg.runFail("test", "-race", "testrace") + tg.grepStdout("FAIL: TestRace", "TestRace did not fail") + tg.grepBothNot("PASS", "something passed") + + tg.runFail("test", "-race", "testrace", "-run", "XXX", "-bench", ".") + tg.grepStdout("FAIL: BenchmarkRace", "BenchmarkRace did not fail") + tg.grepBothNot("PASS", "something passed") +} + +func TestGoTestImportErrorStack(t *testing.T) { + const out = `package testdep/p1 (test) + imports testdep/p2 + imports testdep/p3: build constraints exclude all Go files ` + + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("test", "testdep/p1") + if !strings.Contains(tg.stderr.String(), out) { + t.Fatalf("did not give full import stack:\n\n%s", tg.stderr.String()) + } +} + +func TestGoGetUpdate(t *testing.T) { + // golang.org/issue/9224. + // The recursive updating was trying to walk to + // former dependencies, not current ones. + + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + + rewind := func() { + tg.run("get", "github.com/rsc/go-get-issue-9224-cmd") + cmd := exec.Command("git", "reset", "--hard", "HEAD~") + cmd.Dir = tg.path("src/github.com/rsc/go-get-issue-9224-lib") + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("git: %v\n%s", err, out) + } + } + + rewind() + tg.run("get", "-u", "github.com/rsc/go-get-issue-9224-cmd") + + // Again with -d -u. + rewind() + tg.run("get", "-d", "-u", "github.com/rsc/go-get-issue-9224-cmd") +} + +// Issue #20512. +func TestGoGetRace(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + if !canRace { + t.Skip("skipping because race detector not supported") + } + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.run("get", "-race", "github.com/rsc/go-get-issue-9224-cmd") +} + +func TestGoGetDomainRoot(t *testing.T) { + // golang.org/issue/9357. + // go get foo.io (not foo.io/subdir) was not working consistently. + + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + + // go-get-issue-9357.appspot.com is running + // the code at github.com/rsc/go-get-issue-9357, + // a trivial Go on App Engine app that serves a + // <meta> tag for the domain root. + tg.run("get", "-d", "go-get-issue-9357.appspot.com") + tg.run("get", "go-get-issue-9357.appspot.com") + tg.run("get", "-u", "go-get-issue-9357.appspot.com") + + tg.must(os.RemoveAll(tg.path("src/go-get-issue-9357.appspot.com"))) + tg.run("get", "go-get-issue-9357.appspot.com") + + tg.must(os.RemoveAll(tg.path("src/go-get-issue-9357.appspot.com"))) + tg.run("get", "-u", "go-get-issue-9357.appspot.com") +} + +func TestGoInstallShadowedGOPATH(t *testing.T) { + // golang.org/issue/3652. + // go get foo.io (not foo.io/subdir) was not working consistently. + + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path("gopath1")+string(filepath.ListSeparator)+tg.path("gopath2")) + + tg.tempDir("gopath1/src/test") + tg.tempDir("gopath2/src/test") + tg.tempFile("gopath2/src/test/main.go", "package main\nfunc main(){}\n") + + tg.cd(tg.path("gopath2/src/test")) + tg.runFail("install") + tg.grepStderr("no install location for.*gopath2.src.test: hidden by .*gopath1.src.test", "missing error") +} + +func TestGoBuildGOPATHOrder(t *testing.T) { + // golang.org/issue/14176#issuecomment-179895769 + // golang.org/issue/14192 + // -I arguments to compiler could end up not in GOPATH order, + // leading to unexpected import resolution in the compiler. + // This is still not a complete fix (see golang.org/issue/14271 and next test) + // but it is clearly OK and enough to fix both of the two reported + // instances of the underlying problem. It will have to do for now. + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path("p1")+string(filepath.ListSeparator)+tg.path("p2")) + + tg.tempFile("p1/src/foo/foo.go", "package foo\n") + tg.tempFile("p2/src/baz/baz.go", "package baz\n") + tg.tempFile("p2/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/foo.a", "bad\n") + tg.tempFile("p1/src/bar/bar.go", ` + package bar + import _ "baz" + import _ "foo" + `) + + tg.run("install", "-x", "bar") +} + +func TestGoBuildGOPATHOrderBroken(t *testing.T) { + // This test is known not to work. + // See golang.org/issue/14271. + t.Skip("golang.org/issue/14271") + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + + tg.tempFile("p1/src/foo/foo.go", "package foo\n") + tg.tempFile("p2/src/baz/baz.go", "package baz\n") + tg.tempFile("p1/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/baz.a", "bad\n") + tg.tempFile("p2/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/foo.a", "bad\n") + tg.tempFile("p1/src/bar/bar.go", ` + package bar + import _ "baz" + import _ "foo" + `) + + colon := string(filepath.ListSeparator) + tg.setenv("GOPATH", tg.path("p1")+colon+tg.path("p2")) + tg.run("install", "-x", "bar") + + tg.setenv("GOPATH", tg.path("p2")+colon+tg.path("p1")) + tg.run("install", "-x", "bar") +} + +func TestIssue11709(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.tempFile("run.go", ` + package main + import "os" + func main() { + if os.Getenv("TERM") != "" { + os.Exit(1) + } + }`) + tg.unsetenv("TERM") + tg.run("run", tg.path("run.go")) +} + +func TestIssue12096(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.tempFile("test_test.go", ` + package main + import ("os"; "testing") + func TestEnv(t *testing.T) { + if os.Getenv("TERM") != "" { + t.Fatal("TERM is set") + } + }`) + tg.unsetenv("TERM") + tg.run("test", tg.path("test_test.go")) +} + +func TestGoBuildOutput(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + + tg.makeTempdir() + tg.cd(tg.path(".")) + + nonExeSuffix := ".exe" + if exeSuffix == ".exe" { + nonExeSuffix = "" + } + + tg.tempFile("x.go", "package main\nfunc main(){}\n") + tg.run("build", "x.go") + tg.wantExecutable("x"+exeSuffix, "go build x.go did not write x"+exeSuffix) + tg.must(os.Remove(tg.path("x" + exeSuffix))) + tg.mustNotExist("x" + nonExeSuffix) + + tg.run("build", "-o", "myprog", "x.go") + tg.mustNotExist("x") + tg.mustNotExist("x.exe") + tg.wantExecutable("myprog", "go build -o myprog x.go did not write myprog") + tg.mustNotExist("myprog.exe") + + tg.tempFile("p.go", "package p\n") + tg.run("build", "p.go") + tg.mustNotExist("p") + tg.mustNotExist("p.a") + tg.mustNotExist("p.o") + tg.mustNotExist("p.exe") + + tg.run("build", "-o", "p.a", "p.go") + tg.wantArchive("p.a") + + tg.run("build", "cmd/gofmt") + tg.wantExecutable("gofmt"+exeSuffix, "go build cmd/gofmt did not write gofmt"+exeSuffix) + tg.must(os.Remove(tg.path("gofmt" + exeSuffix))) + tg.mustNotExist("gofmt" + nonExeSuffix) + + tg.run("build", "-o", "mygofmt", "cmd/gofmt") + tg.wantExecutable("mygofmt", "go build -o mygofmt cmd/gofmt did not write mygofmt") + tg.mustNotExist("mygofmt.exe") + tg.mustNotExist("gofmt") + tg.mustNotExist("gofmt.exe") + + tg.run("build", "sync/atomic") + tg.mustNotExist("atomic") + tg.mustNotExist("atomic.exe") + + tg.run("build", "-o", "myatomic.a", "sync/atomic") + tg.wantArchive("myatomic.a") + tg.mustNotExist("atomic") + tg.mustNotExist("atomic.a") + tg.mustNotExist("atomic.exe") + + tg.runFail("build", "-o", "whatever", "cmd/gofmt", "sync/atomic") + tg.grepStderr("multiple packages", "did not reject -o with multiple packages") +} + +func TestGoBuildARM(t *testing.T) { + if testing.Short() { + t.Skip("skipping cross-compile in short mode") + } + + tg := testgo(t) + defer tg.cleanup() + + tg.makeTempdir() + tg.cd(tg.path(".")) + + tg.setenv("GOARCH", "arm") + tg.setenv("GOOS", "linux") + tg.setenv("GOARM", "5") + tg.tempFile("hello.go", `package main + func main() {}`) + tg.run("build", "hello.go") + tg.grepStderrNot("unable to find math.a", "did not build math.a correctly") +} + +// For issue 14337. +func TestParallelTest(t *testing.T) { + tooSlow(t) + tg := testgo(t) + tg.parallel() + defer tg.cleanup() + tg.makeTempdir() + const testSrc = `package package_test + import ( + "testing" + ) + func TestTest(t *testing.T) { + }` + tg.tempFile("src/p1/p1_test.go", strings.Replace(testSrc, "package_test", "p1_test", 1)) + tg.tempFile("src/p2/p2_test.go", strings.Replace(testSrc, "package_test", "p2_test", 1)) + tg.tempFile("src/p3/p3_test.go", strings.Replace(testSrc, "package_test", "p3_test", 1)) + tg.tempFile("src/p4/p4_test.go", strings.Replace(testSrc, "package_test", "p4_test", 1)) + tg.setenv("GOPATH", tg.path(".")) + tg.run("test", "-p=4", "p1", "p2", "p3", "p4") +} + +func TestCgoConsistentResults(t *testing.T) { + tooSlow(t) + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + switch runtime.GOOS { + case "freebsd": + testenv.SkipFlaky(t, 15405) + case "solaris": + testenv.SkipFlaky(t, 13247) + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + exe1 := tg.path("cgotest1" + exeSuffix) + exe2 := tg.path("cgotest2" + exeSuffix) + tg.run("build", "-o", exe1, "cgotest") + tg.run("build", "-x", "-o", exe2, "cgotest") + b1, err := ioutil.ReadFile(exe1) + tg.must(err) + b2, err := ioutil.ReadFile(exe2) + tg.must(err) + + if !tg.doGrepMatch(`-fdebug-prefix-map=\$WORK`, &tg.stderr) { + t.Skip("skipping because C compiler does not support -fdebug-prefix-map") + } + if !bytes.Equal(b1, b2) { + t.Error("building cgotest twice did not produce the same output") + } +} + +// Issue 14444: go get -u .../ duplicate loads errors +func TestGoGetUpdateAllDoesNotTryToLoadDuplicates(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.run("get", "-u", ".../") + tg.grepStderrNot("duplicate loads of", "did not remove old packages from cache") +} + +// Issue 17119 more duplicate load errors +func TestIssue17119(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("build", "dupload") + tg.grepBothNot("duplicate load|internal error", "internal error") +} + +func TestFatalInBenchmarkCauseNonZeroExitStatus(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.runFail("test", "-run", "^$", "-bench", ".", "./testdata/src/benchfatal") + tg.grepBothNot("^ok", "test passed unexpectedly") + tg.grepBoth("FAIL.*benchfatal", "test did not run everything") +} + +func TestBinaryOnlyPackages(t *testing.T) { + tooSlow(t) + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + + tg.tempFile("src/p1/p1.go", `//go:binary-only-package + + package p1 + `) + tg.wantStale("p1", "missing or invalid binary-only package", "p1 is binary-only but has no binary, should be stale") + tg.runFail("install", "p1") + tg.grepStderr("missing or invalid binary-only package", "did not report attempt to compile binary-only package") + + tg.tempFile("src/p1/p1.go", ` + package p1 + import "fmt" + func F(b bool) { fmt.Printf("hello from p1\n"); if b { F(false) } } + `) + tg.run("install", "p1") + os.Remove(tg.path("src/p1/p1.go")) + tg.mustNotExist(tg.path("src/p1/p1.go")) + + tg.tempFile("src/p2/p2.go", `//go:binary-only-packages-are-not-great + + package p2 + import "p1" + func F() { p1.F(true) } + `) + tg.runFail("install", "p2") + tg.grepStderr("no Go files", "did not complain about missing sources") + + tg.tempFile("src/p1/missing.go", `//go:binary-only-package + + package p1 + import _ "fmt" + func G() + `) + tg.wantNotStale("p1", "binary-only package", "should NOT want to rebuild p1 (first)") + tg.run("install", "-x", "p1") // no-op, up to date + tg.grepBothNot(`[\\/]compile`, "should not have run compiler") + tg.run("install", "p2") // does not rebuild p1 (or else p2 will fail) + tg.wantNotStale("p2", "", "should NOT want to rebuild p2") + + // changes to the non-source-code do not matter, + // and only one file needs the special comment. + tg.tempFile("src/p1/missing2.go", ` + package p1 + func H() + `) + tg.wantNotStale("p1", "binary-only package", "should NOT want to rebuild p1 (second)") + tg.wantNotStale("p2", "", "should NOT want to rebuild p2") + + tg.tempFile("src/p3/p3.go", ` + package main + import ( + "p1" + "p2" + ) + func main() { + p1.F(false) + p2.F() + } + `) + tg.run("install", "p3") + + tg.run("run", tg.path("src/p3/p3.go")) + tg.grepStdout("hello from p1", "did not see message from p1") + + tg.tempFile("src/p4/p4.go", `package main`) + // The odd string split below avoids vet complaining about + // a // +build line appearing too late in this source file. + tg.tempFile("src/p4/p4not.go", `//go:binary-only-package + + /`+`/ +build asdf + + package main + `) + tg.run("list", "-f", "{{.BinaryOnly}}", "p4") + tg.grepStdout("false", "did not see BinaryOnly=false for p4") +} + +// Issue 16050. +func TestAlwaysLinkSysoFiles(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempDir("src/syso") + tg.tempFile("src/syso/a.syso", ``) + tg.tempFile("src/syso/b.go", `package syso`) + tg.setenv("GOPATH", tg.path(".")) + + // We should see the .syso file regardless of the setting of + // CGO_ENABLED. + + tg.setenv("CGO_ENABLED", "1") + tg.run("list", "-f", "{{.SysoFiles}}", "syso") + tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=1") + + tg.setenv("CGO_ENABLED", "0") + tg.run("list", "-f", "{{.SysoFiles}}", "syso") + tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0") +} + +// Issue 16120. +func TestGenerateUsesBuildContext(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("this test won't run under Windows") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempDir("src/gen") + tg.tempFile("src/gen/gen.go", "package gen\n//go:generate echo $GOOS $GOARCH\n") + tg.setenv("GOPATH", tg.path(".")) + + tg.setenv("GOOS", "linux") + tg.setenv("GOARCH", "amd64") + tg.run("generate", "gen") + tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination") + + tg.setenv("GOOS", "darwin") + tg.setenv("GOARCH", "386") + tg.run("generate", "gen") + tg.grepStdout("darwin 386", "unexpected GOOS/GOARCH combination") +} + +// Issue 14450: go get -u .../ tried to import not downloaded package +func TestGoGetUpdateWithWildcard(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + const aPkgImportPath = "github.com/tmwh/go-get-issue-14450/a" + tg.run("get", aPkgImportPath) + tg.run("get", "-u", ".../") + tg.grepStderrNot("cannot find package", "did not update packages given wildcard path") + + var expectedPkgPaths = []string{ + "src/github.com/tmwh/go-get-issue-14450/b", + "src/github.com/tmwh/go-get-issue-14450-b-dependency/c", + "src/github.com/tmwh/go-get-issue-14450-b-dependency/d", + } + + for _, importPath := range expectedPkgPaths { + _, err := os.Stat(tg.path(importPath)) + tg.must(err) + } + const notExpectedPkgPath = "src/github.com/tmwh/go-get-issue-14450-c-dependency/e" + tg.mustNotExist(tg.path(notExpectedPkgPath)) +} + +func TestGoEnv(t *testing.T) { + tg := testgo(t) + tg.parallel() + defer tg.cleanup() + tg.setenv("GOOS", "freebsd") // to avoid invalid pair errors + tg.setenv("GOARCH", "arm") + tg.run("env", "GOARCH") + tg.grepStdout("^arm$", "GOARCH not honored") + + tg.run("env", "GCCGO") + tg.grepStdout(".", "GCCGO unexpectedly empty") + + tg.run("env", "CGO_CFLAGS") + tg.grepStdout(".", "default CGO_CFLAGS unexpectedly empty") + + tg.setenv("CGO_CFLAGS", "-foobar") + tg.run("env", "CGO_CFLAGS") + tg.grepStdout("^-foobar$", "CGO_CFLAGS not honored") + + tg.setenv("CC", "gcc -fmust -fgo -ffaster") + tg.run("env", "CC") + tg.grepStdout("gcc", "CC not found") + tg.run("env", "GOGCCFLAGS") + tg.grepStdout("-ffaster", "CC arguments not found") +} + +const ( + noMatchesPattern = `(?m)^ok.*\[no tests to run\]` + okPattern = `(?m)^ok` +) + +func TestMatchesNoTests(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.run("test", "-run", "ThisWillNotMatch", "testdata/standalone_test.go") + tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]") +} + +func TestMatchesNoTestsDoesNotOverrideBuildFailure(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("test", "-run", "ThisWillNotMatch", "syntaxerror") + tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]") + tg.grepBoth("FAIL", "go test did not say FAIL") +} + +func TestMatchesNoBenchmarksIsOK(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.run("test", "-run", "^$", "-bench", "ThisWillNotMatch", "testdata/standalone_benchmark_test.go") + tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]") + tg.grepBoth(okPattern, "go test did not say ok") +} + +func TestMatchesOnlyExampleIsOK(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.run("test", "-run", "Example", "testdata/example1_test.go") + tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]") + tg.grepBoth(okPattern, "go test did not say ok") +} + +func TestMatchesOnlyBenchmarkIsOK(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.run("test", "-run", "^$", "-bench", ".", "testdata/standalone_benchmark_test.go") + tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]") + tg.grepBoth(okPattern, "go test did not say ok") +} + +func TestBenchmarkLabels(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("test", "-run", "^$", "-bench", ".", "bench") + tg.grepStdout(`(?m)^goos: `+runtime.GOOS, "go test did not print goos") + tg.grepStdout(`(?m)^goarch: `+runtime.GOARCH, "go test did not print goarch") + tg.grepStdout(`(?m)^pkg: bench`, "go test did not say pkg: bench") + tg.grepBothNot(`(?s)pkg:.*pkg:`, "go test said pkg multiple times") +} + +func TestBenchmarkLabelsOutsideGOPATH(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.run("test", "-run", "^$", "-bench", ".", "testdata/standalone_benchmark_test.go") + tg.grepStdout(`(?m)^goos: `+runtime.GOOS, "go test did not print goos") + tg.grepStdout(`(?m)^goarch: `+runtime.GOARCH, "go test did not print goarch") + tg.grepBothNot(`(?m)^pkg:`, "go test did say pkg:") +} + +func TestMatchesOnlyTestIsOK(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + // TODO: tg.parallel() + tg.run("test", "-run", "Test", "testdata/standalone_test.go") + tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]") + tg.grepBoth(okPattern, "go test did not say ok") +} + +func TestMatchesNoTestsWithSubtests(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "-run", "ThisWillNotMatch", "testdata/standalone_sub_test.go") + tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]") +} + +func TestMatchesNoSubtestsMatch(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "-run", "Test/ThisWillNotMatch", "testdata/standalone_sub_test.go") + tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]") +} + +func TestMatchesNoSubtestsDoesNotOverrideFailure(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.runFail("test", "-run", "TestThatFails/ThisWillNotMatch", "testdata/standalone_fail_sub_test.go") + tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]") + tg.grepBoth("FAIL", "go test did not say FAIL") +} + +func TestMatchesOnlySubtestIsOK(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "-run", "Test/Sub", "testdata/standalone_sub_test.go") + tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]") + tg.grepBoth(okPattern, "go test did not say ok") +} + +func TestMatchesNoSubtestsParallel(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "-run", "Test/Sub/ThisWillNotMatch", "testdata/standalone_parallel_sub_test.go") + tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]") +} + +func TestMatchesOnlySubtestParallelIsOK(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "-run", "Test/Sub/Nested", "testdata/standalone_parallel_sub_test.go") + tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]") + tg.grepBoth(okPattern, "go test did not say ok") +} + +// Issue 18845 +func TestBenchTimeout(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "-bench", ".", "-timeout", "750ms", "testdata/timeoutbench_test.go") +} + +// Issue 19394 +func TestWriteProfilesOnTimeout(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.tempDir("profiling") + tg.tempFile("profiling/timeouttest_test.go", `package timeouttest_test +import "testing" +import "time" +func TestSleep(t *testing.T) { time.Sleep(time.Second) }`) + tg.cd(tg.path("profiling")) + tg.runFail( + "test", + "-cpuprofile", tg.path("profiling/cpu.pprof"), "-memprofile", tg.path("profiling/mem.pprof"), + "-timeout", "1ms") + tg.mustHaveContent(tg.path("profiling/cpu.pprof")) + tg.mustHaveContent(tg.path("profiling/mem.pprof")) +} + +func TestLinkXImportPathEscape(t *testing.T) { + // golang.org/issue/16710 + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + exe := "./linkx" + exeSuffix + tg.creatingTemp(exe) + tg.run("build", "-o", exe, "-ldflags", "-X=my.pkg.Text=linkXworked", "my.pkg/main") + out, err := exec.Command(exe).CombinedOutput() + if err != nil { + tg.t.Fatal(err) + } + if string(out) != "linkXworked\n" { + tg.t.Log(string(out)) + tg.t.Fatal(`incorrect output: expected "linkXworked\n"`) + } +} + +// Issue 18044. +func TestLdBindNow(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("LD_BIND_NOW", "1") + tg.run("help") +} + +// Issue 18225. +// This is really a cmd/asm issue but this is a convenient place to test it. +func TestConcurrentAsm(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + asm := `DATA ·constants<>+0x0(SB)/8,$0 +GLOBL ·constants<>(SB),8,$8 +` + tg.tempFile("go/src/p/a.s", asm) + tg.tempFile("go/src/p/b.s", asm) + tg.tempFile("go/src/p/p.go", `package p`) + tg.setenv("GOPATH", tg.path("go")) + tg.run("build", "p") +} + +// Issue 18778. +func TestDotDotDotOutsideGOPATH(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + + tg.tempFile("pkgs/a.go", `package x`) + tg.tempFile("pkgs/a_test.go", `package x_test +import "testing" +func TestX(t *testing.T) {}`) + + tg.tempFile("pkgs/a/a.go", `package a`) + tg.tempFile("pkgs/a/a_test.go", `package a_test +import "testing" +func TestA(t *testing.T) {}`) + + tg.cd(tg.path("pkgs")) + tg.run("build", "./...") + tg.run("test", "./...") + tg.run("list", "./...") + tg.grepStdout("pkgs$", "expected package not listed") + tg.grepStdout("pkgs/a", "expected package not listed") +} + +// Issue 18975. +func TestFFLAGS(t *testing.T) { + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + + tg.tempFile("p/src/p/main.go", `package main + // #cgo FFLAGS: -no-such-fortran-flag + import "C" + func main() {} + `) + tg.tempFile("p/src/p/a.f", `! comment`) + tg.setenv("GOPATH", tg.path("p")) + + // This should normally fail because we are passing an unknown flag, + // but issue #19080 points to Fortran compilers that succeed anyhow. + // To work either way we call doRun directly rather than run or runFail. + tg.doRun([]string{"build", "-x", "p"}) + + tg.grepStderr("no-such-fortran-flag", `missing expected "-no-such-fortran-flag"`) +} + +// Issue 19198. +// This is really a cmd/link issue but this is a convenient place to test it. +func TestDuplicateGlobalAsmSymbols(t *testing.T) { + tooSlow(t) + if runtime.GOARCH != "386" && runtime.GOARCH != "amd64" { + t.Skipf("skipping test on %s", runtime.GOARCH) + } + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + + asm := ` +#include "textflag.h" + +DATA sym<>+0x0(SB)/8,$0 +GLOBL sym<>(SB),(NOPTR+RODATA),$8 + +TEXT ·Data(SB),NOSPLIT,$0 + MOVB sym<>(SB), AX + MOVB AX, ret+0(FP) + RET +` + tg.tempFile("go/src/a/a.s", asm) + tg.tempFile("go/src/a/a.go", `package a; func Data() uint8`) + tg.tempFile("go/src/b/b.s", asm) + tg.tempFile("go/src/b/b.go", `package b; func Data() uint8`) + tg.tempFile("go/src/p/p.go", ` +package main +import "a" +import "b" +import "C" +func main() { + _ = a.Data() + b.Data() +} +`) + tg.setenv("GOPATH", tg.path("go")) + exe := tg.path("p.exe") + tg.creatingTemp(exe) + tg.run("build", "-o", exe, "p") +} + +func TestBuildTagsNoComma(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path("go")) + tg.run("build", "-tags", "tag1 tag2", "math") + tg.runFail("build", "-tags", "tag1,tag2", "math") + tg.grepBoth("space-separated list contains comma", "-tags with a comma-separated list didn't error") +} + +func copyFile(src, dst string, perm os.FileMode) error { + sf, err := os.Open(src) + if err != nil { + return err + } + defer sf.Close() + + df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) + if err != nil { + return err + } + + _, err = io.Copy(df, sf) + err2 := df.Close() + if err != nil { + return err + } + return err2 +} + +func TestExecutableGOROOT(t *testing.T) { + if runtime.GOOS == "openbsd" { + t.Skipf("test case does not work on %s, missing os.Executable", runtime.GOOS) + } + + // Env with no GOROOT. + var env []string + for _, e := range os.Environ() { + if !strings.HasPrefix(e, "GOROOT=") { + env = append(env, e) + } + } + + check := func(t *testing.T, exe, want string) { + cmd := exec.Command(exe, "env", "GOROOT") + cmd.Env = env + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("%s env GOROOT: %v, %s", exe, err, out) + } + goroot, err := filepath.EvalSymlinks(strings.TrimSpace(string(out))) + if err != nil { + t.Fatal(err) + } + want, err = filepath.EvalSymlinks(want) + if err != nil { + t.Fatal(err) + } + if !strings.EqualFold(goroot, want) { + t.Errorf("go env GOROOT:\nhave %s\nwant %s", goroot, want) + } else { + t.Logf("go env GOROOT: %s", goroot) + } + } + + // Note: Must not call tg methods inside subtests: tg is attached to outer t. + tg := testgo(t) + defer tg.cleanup() + + tg.makeTempdir() + tg.tempDir("new/bin") + newGoTool := tg.path("new/bin/go" + exeSuffix) + tg.must(copyFile(tg.goTool(), newGoTool, 0775)) + newRoot := tg.path("new") + + t.Run("RelocatedExe", func(t *testing.T) { + // Should fall back to default location in binary, + // which is the GOROOT we used when building testgo.exe. + check(t, newGoTool, testGOROOT) + }) + + // If the binary is sitting in a bin dir next to ../pkg/tool, that counts as a GOROOT, + // so it should find the new tree. + tg.tempDir("new/pkg/tool") + t.Run("RelocatedTree", func(t *testing.T) { + t.Skip("vgo detects fake GOROOT") + check(t, newGoTool, newRoot) + }) + + tg.tempDir("other/bin") + symGoTool := tg.path("other/bin/go" + exeSuffix) + + // Symlink into go tree should still find go tree. + t.Run("SymlinkedExe", func(t *testing.T) { + t.Skip("vgo detects fake GOROOT") + testenv.MustHaveSymlink(t) + if err := os.Symlink(newGoTool, symGoTool); err != nil { + t.Fatal(err) + } + check(t, symGoTool, newRoot) + }) + + tg.must(os.RemoveAll(tg.path("new/pkg"))) + + // Binaries built in the new tree should report the + // new tree when they call runtime.GOROOT. + t.Run("RuntimeGoroot", func(t *testing.T) { + // Build a working GOROOT the easy way, with symlinks. + testenv.MustHaveSymlink(t) + if err := os.Symlink(filepath.Join(testGOROOT, "src"), tg.path("new/src")); err != nil { + t.Fatal(err) + } + if err := os.Symlink(filepath.Join(testGOROOT, "pkg"), tg.path("new/pkg")); err != nil { + t.Fatal(err) + } + + cmd := exec.Command(newGoTool, "run", "testdata/print_goroot.go") + cmd.Env = env + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("%s run testdata/print_goroot.go: %v, %s", newGoTool, err, out) + } + goroot, err := filepath.EvalSymlinks(strings.TrimSpace(string(out))) + if err != nil { + t.Fatal(err) + } + want, err := filepath.EvalSymlinks(tg.path("new")) + if err != nil { + t.Fatal(err) + } + if !strings.EqualFold(goroot, want) { + t.Errorf("go run testdata/print_goroot.go:\nhave %s\nwant %s", goroot, want) + } else { + t.Logf("go run testdata/print_goroot.go: %s", goroot) + } + }) +} + +func TestNeedVersion(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("goversion.go", `package main; func main() {}`) + path := tg.path("goversion.go") + tg.setenv("TESTGO_VERSION", "go1.testgo") + tg.runFail("run", path) + tg.grepStderr("compile", "does not match go tool version") +} + +// Test that user can override default code generation flags. +func TestUserOverrideFlags(t *testing.T) { + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + if runtime.GOOS != "linux" { + // We are testing platform-independent code, so it's + // OK to skip cases that work differently. + t.Skipf("skipping on %s because test only works if c-archive implies -shared", runtime.GOOS) + } + + tg := testgo(t) + defer tg.cleanup() + // Don't call tg.parallel, as creating override.h and override.a may + // confuse other tests. + tg.tempFile("override.go", `package main + +import "C" + +//export GoFunc +func GoFunc() {} + +func main() {}`) + tg.creatingTemp("override.a") + tg.creatingTemp("override.h") + tg.run("build", "-x", "-buildmode=c-archive", "-gcflags=all=-shared=false", tg.path("override.go")) + tg.grepStderr("compile .*-shared .*-shared=false", "user can not override code generation flag") +} + +func TestCgoFlagContainsSpace(t *testing.T) { + tooSlow(t) + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + tg := testgo(t) + defer tg.cleanup() + + tg.makeTempdir() + tg.cd(tg.path(".")) + tg.tempFile("main.go", `package main + // #cgo CFLAGS: -I"c flags" + // #cgo LDFLAGS: -L"ld flags" + import "C" + func main() {} + `) + tg.run("run", "-x", "main.go") + tg.grepStderr(`"-I[^"]+c flags"`, "did not find quoted c flags") + tg.grepStderrNot(`"-I[^"]+c flags".*"-I[^"]+c flags"`, "found too many quoted c flags") + tg.grepStderr(`"-L[^"]+ld flags"`, "did not find quoted ld flags") + tg.grepStderrNot(`"-L[^"]+c flags".*"-L[^"]+c flags"`, "found too many quoted ld flags") +} + +// Issue #20435. +func TestGoTestRaceCoverModeFailures(t *testing.T) { + tooSlow(t) + if !canRace { + t.Skip("skipping because race detector not supported") + } + + tg := testgo(t) + tg.parallel() + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + + tg.run("test", "testrace") + + tg.runFail("test", "-race", "-covermode=set", "testrace") + tg.grepStderr(`-covermode must be "atomic", not "set", when -race is enabled`, "-race -covermode=set was allowed") + tg.grepBothNot("PASS", "something passed") +} + +// Issue 9737: verify that GOARM and GO386 affect the computed build ID. +func TestBuildIDContainsArchModeEnv(t *testing.T) { + t.Skip("broken in standard distribution") + + if testing.Short() { + t.Skip("skipping in short mode") + } + + var tg *testgoData + testWith := func(before, after func()) func(*testing.T) { + return func(t *testing.T) { + tg = testgo(t) + defer tg.cleanup() + tg.tempFile("src/mycmd/x.go", `package main +func main() {}`) + tg.setenv("GOPATH", tg.path(".")) + + tg.cd(tg.path("src/mycmd")) + tg.setenv("GOOS", "linux") + before() + tg.run("install", "mycmd") + after() + tg.wantStale("mycmd", "stale dependency: runtime/internal/sys", "should be stale after environment variable change") + } + } + + t.Run("386", testWith(func() { + tg.setenv("GOARCH", "386") + tg.setenv("GO386", "387") + }, func() { + tg.setenv("GO386", "sse2") + })) + + t.Run("arm", testWith(func() { + tg.setenv("GOARCH", "arm") + tg.setenv("GOARM", "5") + }, func() { + tg.setenv("GOARM", "7") + })) +} + +func TestTestRegexps(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("test", "-cpu=1", "-run=X/Y", "-bench=X/Y", "-count=2", "-v", "testregexp") + var lines []string + for _, line := range strings.SplitAfter(tg.getStdout(), "\n") { + if strings.Contains(line, "=== RUN") || strings.Contains(line, "--- BENCH") || strings.Contains(line, "LOG") { + lines = append(lines, line) + } + } + + // Important parts: + // TestX is run, twice + // TestX/Y is run, twice + // TestXX is run, twice + // TestZ is not run + // BenchmarkX is run but only with N=1, once + // BenchmarkXX is run but only with N=1, once + // BenchmarkX/Y is run in full, twice + want := `=== RUN TestX +=== RUN TestX/Y + x_test.go:6: LOG: X running + x_test.go:8: LOG: Y running +=== RUN TestXX + z_test.go:10: LOG: XX running +=== RUN TestX +=== RUN TestX/Y + x_test.go:6: LOG: X running + x_test.go:8: LOG: Y running +=== RUN TestXX + z_test.go:10: LOG: XX running +--- BENCH: BenchmarkX/Y + x_test.go:15: LOG: Y running N=1 + x_test.go:15: LOG: Y running N=100 + x_test.go:15: LOG: Y running N=10000 + x_test.go:15: LOG: Y running N=1000000 + x_test.go:15: LOG: Y running N=100000000 + x_test.go:15: LOG: Y running N=2000000000 +--- BENCH: BenchmarkX/Y + x_test.go:15: LOG: Y running N=1 + x_test.go:15: LOG: Y running N=100 + x_test.go:15: LOG: Y running N=10000 + x_test.go:15: LOG: Y running N=1000000 + x_test.go:15: LOG: Y running N=100000000 + x_test.go:15: LOG: Y running N=2000000000 +--- BENCH: BenchmarkX + x_test.go:13: LOG: X running N=1 +--- BENCH: BenchmarkXX + z_test.go:18: LOG: XX running N=1 +` + + have := strings.Join(lines, "") + if have != want { + t.Errorf("reduced output:<<<\n%s>>> want:<<<\n%s>>>", have, want) + } +} + +func TestListTests(t *testing.T) { + tooSlow(t) + var tg *testgoData + testWith := func(listName, expected string) func(*testing.T) { + return func(t *testing.T) { + tg = testgo(t) + defer tg.cleanup() + tg.run("test", "./testdata/src/testlist/...", fmt.Sprintf("-list=%s", listName)) + tg.grepStdout(expected, fmt.Sprintf("-test.list=%s returned %q, expected %s", listName, tg.getStdout(), expected)) + } + } + + t.Run("Test", testWith("Test", "TestSimple")) + t.Run("Bench", testWith("Benchmark", "BenchmarkSimple")) + t.Run("Example1", testWith("Example", "ExampleSimple")) + t.Run("Example2", testWith("Example", "ExampleWithEmptyOutput")) +} + +func TestBuildmodePIE(t *testing.T) { + if testing.Short() && testenv.Builder() == "" { + t.Skipf("skipping in -short mode on non-builder") + } + if runtime.Compiler == "gccgo" { + t.Skipf("skipping test because buildmode=pie is not supported on gccgo") + } + + platform := fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH) + switch platform { + case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x", + "android/amd64", "android/arm", "android/arm64", "android/386": + case "darwin/amd64": + default: + t.Skipf("skipping test because buildmode=pie is not supported on %s", platform) + } + + tg := testgo(t) + defer tg.cleanup() + + tg.tempFile("main.go", `package main; func main() { print("hello") }`) + src := tg.path("main.go") + obj := tg.path("main") + tg.run("build", "-buildmode=pie", "-o", obj, src) + + switch runtime.GOOS { + case "linux", "android": + f, err := elf.Open(obj) + if err != nil { + t.Fatal(err) + } + defer f.Close() + if f.Type != elf.ET_DYN { + t.Errorf("PIE type must be ET_DYN, but %s", f.Type) + } + case "darwin": + f, err := macho.Open(obj) + if err != nil { + t.Fatal(err) + } + defer f.Close() + if f.Flags&macho.FlagDyldLink == 0 { + t.Error("PIE must have DyldLink flag, but not") + } + if f.Flags&macho.FlagPIE == 0 { + t.Error("PIE must have PIE flag, but not") + } + default: + panic("unreachable") + } + + out, err := exec.Command(obj).CombinedOutput() + if err != nil { + t.Fatal(err) + } + + if string(out) != "hello" { + t.Errorf("got %q; want %q", out, "hello") + } +} + +func TestExecBuildX(t *testing.T) { + tooSlow(t) + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + + if runtime.GOOS == "plan9" || runtime.GOOS == "windows" { + t.Skipf("skipping because unix shell is not supported on %s", runtime.GOOS) + } + + tg := testgo(t) + defer tg.cleanup() + + tg.setenv("GOCACHE", "off") + + tg.tempFile("main.go", `package main; import "C"; func main() { print("hello") }`) + src := tg.path("main.go") + obj := tg.path("main") + tg.run("build", "-x", "-o", obj, src) + sh := tg.path("test.sh") + err := ioutil.WriteFile(sh, []byte("set -e\n"+tg.getStderr()), 0666) + if err != nil { + t.Fatal(err) + } + + out, err := exec.Command(obj).CombinedOutput() + if err != nil { + t.Fatal(err) + } + if string(out) != "hello" { + t.Fatalf("got %q; want %q", out, "hello") + } + + err = os.Remove(obj) + if err != nil { + t.Fatal(err) + } + + out, err = exec.Command("/usr/bin/env", "bash", "-x", sh).CombinedOutput() + if err != nil { + t.Fatalf("/bin/sh %s: %v\n%s", sh, err, out) + } + t.Logf("shell output:\n%s", out) + + out, err = exec.Command(obj).CombinedOutput() + if err != nil { + t.Fatal(err) + } + if string(out) != "hello" { + t.Fatalf("got %q; want %q", out, "hello") + } +} + +func TestParallelNumber(t *testing.T) { + tooSlow(t) + for _, n := range [...]string{"-1", "0"} { + t.Run(n, func(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.runFail("test", "-parallel", n, "testdata/standalone_parallel_sub_test.go") + tg.grepBoth("-parallel can only be given", "go test -parallel with N<1 did not error") + }) + } +} + +func TestWrongGOOSErrorBeforeLoadError(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.setenv("GOOS", "windwos") + tg.runFail("build", "exclude") + tg.grepStderr("unsupported GOOS/GOARCH pair", "GOOS=windwos go build exclude did not report 'unsupported GOOS/GOARCH pair'") +} + +func TestUpxCompression(t *testing.T) { + if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { + t.Skipf("skipping upx test on %s/%s", runtime.GOOS, runtime.GOARCH) + } + + out, err := exec.Command("upx", "--version").CombinedOutput() + if err != nil { + t.Skip("skipping because upx is not available") + } + + // upx --version prints `upx <version>` in the first line of output: + // upx 3.94 + // [...] + re := regexp.MustCompile(`([[:digit:]]+)\.([[:digit:]]+)`) + upxVersion := re.FindStringSubmatch(string(out)) + if len(upxVersion) != 3 { + t.Errorf("bad upx version string: %s", upxVersion) + } + + major, err1 := strconv.Atoi(upxVersion[1]) + minor, err2 := strconv.Atoi(upxVersion[2]) + if err1 != nil || err2 != nil { + t.Errorf("bad upx version string: %s", upxVersion[0]) + } + + // Anything below 3.94 is known not to work with go binaries + if (major < 3) || (major == 3 && minor < 94) { + t.Skipf("skipping because upx version %v.%v is too old", major, minor) + } + + tg := testgo(t) + defer tg.cleanup() + + tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`) + src := tg.path("main.go") + obj := tg.path("main") + tg.run("build", "-o", obj, src) + + out, err = exec.Command("upx", obj).CombinedOutput() + if err != nil { + t.Logf("executing upx\n%s\n", out) + t.Fatalf("upx failed with %v", err) + } + + out, err = exec.Command(obj).CombinedOutput() + if err != nil { + t.Logf("%s", out) + t.Fatalf("running compressed go binary failed with error %s", err) + } + if string(out) != "hello upx" { + t.Fatalf("bad output from compressed go binary:\ngot %q; want %q", out, "hello upx") + } +} + +func TestGOTMPDIR(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.makeTempdir() + tg.setenv("GOTMPDIR", tg.tempdir) + tg.setenv("GOCACHE", "off") + + // complex/x is a trivial non-main package. + tg.run("build", "-work", "-x", "complex/w") + tg.grepStderr("WORK="+regexp.QuoteMeta(tg.tempdir), "did not work in $GOTMPDIR") +} + +func TestBuildCache(t *testing.T) { + tooSlow(t) + if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + t.Skip("GODEBUG gocacheverify") + } + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.makeTempdir() + tg.setenv("GOCACHE", tg.tempdir) + + // complex/w is a trivial non-main package. + // It imports nothing, so there should be no Deps. + tg.run("list", "-f={{join .Deps \" \"}}", "complex/w") + tg.grepStdoutNot(".+", "complex/w depends on unexpected packages") + + tg.run("build", "-x", "complex/w") + tg.grepStderr(`[\\/]compile|gccgo`, "did not run compiler") + + tg.run("build", "-x", "complex/w") + tg.grepStderrNot(`[\\/]compile|gccgo`, "ran compiler incorrectly") + + tg.run("build", "-a", "-x", "complex/w") + tg.grepStderr(`[\\/]compile|gccgo`, "did not run compiler with -a") + + // complex is a non-trivial main package. + // the link step should not be cached. + tg.run("build", "-o", os.DevNull, "-x", "complex") + tg.grepStderr(`[\\/]link|gccgo`, "did not run linker") + + tg.run("build", "-o", os.DevNull, "-x", "complex") + tg.grepStderr(`[\\/]link|gccgo`, "did not run linker") +} + +func TestCacheOutput(t *testing.T) { + // Test that command output is cached and replayed too. + if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + t.Skip("GODEBUG gocacheverify") + } + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.makeTempdir() + tg.setenv("GOCACHE", tg.tempdir) + + tg.run("build", "-gcflags=-m", "errors") + stdout1 := tg.getStdout() + stderr1 := tg.getStderr() + + tg.run("build", "-gcflags=-m", "errors") + stdout2 := tg.getStdout() + stderr2 := tg.getStderr() + + if stdout2 != stdout1 || stderr2 != stderr1 { + t.Errorf("cache did not reproduce output:\n\nstdout1:\n%s\n\nstdout2:\n%s\n\nstderr1:\n%s\n\nstderr2:\n%s", + stdout1, stdout2, stderr1, stderr2) + } +} + +func TestCacheCoverage(t *testing.T) { + tooSlow(t) + + if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + t.Skip("GODEBUG gocacheverify") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.makeTempdir() + + tg.setenv("GOCACHE", tg.path("c1")) + tg.run("test", "-cover", "-short", "strings") + tg.run("test", "-cover", "-short", "math", "strings") +} + +func TestIssue22588(t *testing.T) { + // Don't get confused by stderr coming from tools. + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + + if _, err := os.Stat("/usr/bin/time"); err != nil { + t.Skip(err) + } + + tg.run("list", "-f={{.Stale}}", "runtime") + tg.run("list", "-toolexec=/usr/bin/time", "-f={{.Stale}}", "runtime") + tg.grepStdout("false", "incorrectly reported runtime as stale") +} + +func TestIssue22531(t *testing.T) { + tooSlow(t) + if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + t.Skip("GODEBUG gocacheverify") + } + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", tg.tempdir) + tg.setenv("GOCACHE", tg.path("cache")) + tg.tempFile("src/m/main.go", "package main /* c1 */; func main() {}\n") + tg.run("install", "-x", "m") + tg.run("list", "-f", "{{.Stale}}", "m") + tg.grepStdout("false", "reported m as stale after install") + tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix)) + + // The link action ID did not include the full main build ID, + // even though the full main build ID is written into the + // eventual binary. That caused the following install to + // be a no-op, thinking the gofmt binary was up-to-date, + // even though .Stale could see it was not. + tg.tempFile("src/m/main.go", "package main /* c2 */; func main() {}\n") + tg.run("install", "-x", "m") + tg.run("list", "-f", "{{.Stale}}", "m") + tg.grepStdout("false", "reported m as stale after reinstall") + tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix)) +} + +func TestIssue22596(t *testing.T) { + tooSlow(t) + if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + t.Skip("GODEBUG gocacheverify") + } + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOCACHE", tg.path("cache")) + tg.tempFile("gopath1/src/p/p.go", "package p; func F(){}\n") + tg.tempFile("gopath2/src/p/p.go", "package p; func F(){}\n") + + tg.setenv("GOPATH", tg.path("gopath1")) + tg.run("list", "-f={{.Target}}", "p") + target1 := strings.TrimSpace(tg.getStdout()) + tg.run("install", "p") + tg.wantNotStale("p", "", "p stale after install") + + tg.setenv("GOPATH", tg.path("gopath2")) + tg.run("list", "-f={{.Target}}", "p") + target2 := strings.TrimSpace(tg.getStdout()) + tg.must(os.MkdirAll(filepath.Dir(target2), 0777)) + tg.must(copyFile(target1, target2, 0666)) + tg.wantStale("p", "build ID mismatch", "p not stale after copy from gopath1") + tg.run("install", "p") + tg.wantNotStale("p", "", "p stale after install2") +} + +func TestTestCache(t *testing.T) { + tooSlow(t) + + if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + t.Skip("GODEBUG gocacheverify") + } + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", tg.tempdir) + tg.setenv("GOCACHE", tg.path("cache")) + + // timeout here should not affect result being cached + // or being retrieved later. + tg.run("test", "-x", "-timeout=10s", "errors") + tg.grepStderr(`[\\/]compile|gccgo`, "did not run compiler") + tg.grepStderr(`[\\/]link|gccgo`, "did not run linker") + tg.grepStderr(`errors\.test`, "did not run test") + + tg.run("test", "-x", "errors") + tg.grepStdout(`ok \terrors\t\(cached\)`, "did not report cached result") + tg.grepStderrNot(`[\\/]compile|gccgo`, "incorrectly ran compiler") + tg.grepStderrNot(`[\\/]link|gccgo`, "incorrectly ran linker") + tg.grepStderrNot(`errors\.test`, "incorrectly ran test") + tg.grepStderrNot("DO NOT USE", "poisoned action status leaked") + + // Even very low timeouts do not disqualify cached entries. + tg.run("test", "-timeout=1ns", "-x", "errors") + tg.grepStderrNot(`errors\.test`, "incorrectly ran test") + + tg.run("clean", "-testcache") + tg.run("test", "-x", "errors") + tg.grepStderr(`errors\.test`, "did not run test") + + // The -p=1 in the commands below just makes the -x output easier to read. + + t.Log("\n\nINITIAL\n\n") + + tg.tempFile("src/p1/p1.go", "package p1\nvar X = 1\n") + tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\nvar X = 1\n") + tg.tempFile("src/t/t1/t1_test.go", "package t\nimport \"testing\"\nfunc Test1(*testing.T) {}\n") + tg.tempFile("src/t/t2/t2_test.go", "package t\nimport _ \"p1\"\nimport \"testing\"\nfunc Test2(*testing.T) {}\n") + tg.tempFile("src/t/t3/t3_test.go", "package t\nimport \"p1\"\nimport \"testing\"\nfunc Test3(t *testing.T) {t.Log(p1.X)}\n") + tg.tempFile("src/t/t4/t4_test.go", "package t\nimport \"p2\"\nimport \"testing\"\nfunc Test4(t *testing.T) {t.Log(p2.X)}") + tg.run("test", "-x", "-v", "-short", "t/...") + + t.Log("\n\nREPEAT\n\n") + + tg.run("test", "-x", "-v", "-short", "t/...") + tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t1") + tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t2") + tg.grepStdout(`ok \tt/t3\t\(cached\)`, "did not cache t3") + tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t4") + tg.grepStderrNot(`[\\/]compile|gccgo`, "incorrectly ran compiler") + tg.grepStderrNot(`[\\/]link|gccgo`, "incorrectly ran linker") + tg.grepStderrNot(`p[0-9]\.test`, "incorrectly ran test") + + t.Log("\n\nCOMMENT\n\n") + + // Changing the program text without affecting the compiled package + // should result in the package being rebuilt but nothing more. + tg.tempFile("src/p1/p1.go", "package p1\nvar X = 01\n") + tg.run("test", "-p=1", "-x", "-v", "-short", "t/...") + tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t1") + tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t2") + tg.grepStdout(`ok \tt/t3\t\(cached\)`, "did not cache t3") + tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t4") + tg.grepStderrNot(`([\\/]compile|gccgo).*t[0-9]_test\.go`, "incorrectly ran compiler") + tg.grepStderrNot(`[\\/]link|gccgo`, "incorrectly ran linker") + tg.grepStderrNot(`t[0-9]\.test.*test\.short`, "incorrectly ran test") + + t.Log("\n\nCHANGE\n\n") + + // Changing the actual package should have limited effects. + tg.tempFile("src/p1/p1.go", "package p1\nvar X = 02\n") + tg.run("test", "-p=1", "-x", "-v", "-short", "t/...") + + // p2 should have been rebuilt. + tg.grepStderr(`([\\/]compile|gccgo).*p2.go`, "did not recompile p2") + + // t1 does not import anything, should not have been rebuilt. + tg.grepStderrNot(`([\\/]compile|gccgo).*t1_test.go`, "incorrectly recompiled t1") + tg.grepStderrNot(`([\\/]link|gccgo).*t1_test`, "incorrectly relinked t1_test") + tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t/t1") + + // t2 imports p1 and must be rebuilt and relinked, + // but the change should not have any effect on the test binary, + // so the test should not have been rerun. + tg.grepStderr(`([\\/]compile|gccgo).*t2_test.go`, "did not recompile t2") + tg.grepStderr(`([\\/]link|gccgo).*t2\.test`, "did not relink t2_test") + tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t/t2") + + // t3 imports p1, and changing X changes t3's test binary. + tg.grepStderr(`([\\/]compile|gccgo).*t3_test.go`, "did not recompile t3") + tg.grepStderr(`([\\/]link|gccgo).*t3\.test`, "did not relink t3_test") + tg.grepStderr(`t3\.test.*-test.short`, "did not rerun t3_test") + tg.grepStdoutNot(`ok \tt/t3\t\(cached\)`, "reported cached t3_test result") + + // t4 imports p2, but p2 did not change, so t4 should be relinked, not recompiled, + // and not rerun. + tg.grepStderrNot(`([\\/]compile|gccgo).*t4_test.go`, "incorrectly recompiled t4") + tg.grepStderr(`([\\/]link|gccgo).*t4\.test`, "did not relink t4_test") + tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t/t4") +} + +func TestTestCacheInputs(t *testing.T) { + tooSlow(t) + + if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + t.Skip("GODEBUG gocacheverify") + } + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.setenv("GOCACHE", tg.path("cache")) + + defer os.Remove(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt")) + defer os.Remove(filepath.Join(tg.pwd(), "testdata/src/testcache/script.sh")) + tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), []byte("x"), 0644)) + old := time.Now().Add(-1 * time.Minute) + tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), old, old)) + info, err := os.Stat(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt")) + if err != nil { + t.Fatal(err) + } + t.Logf("file.txt: old=%v, info.ModTime=%v", old, info.ModTime()) // help debug when Chtimes lies about succeeding + tg.setenv("TESTKEY", "x") + + tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/script.sh"), []byte("#!/bin/sh\nexit 0\n"), 0755)) + tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/script.sh"), old, old)) + + tg.run("test", "testcache") + tg.run("test", "testcache") + tg.grepStdout(`\(cached\)`, "did not cache") + + tg.setenv("TESTKEY", "y") + tg.run("test", "testcache") + tg.grepStdoutNot(`\(cached\)`, "did not notice env var change") + tg.run("test", "testcache") + tg.grepStdout(`\(cached\)`, "did not cache") + + tg.run("test", "testcache", "-run=FileSize") + tg.run("test", "testcache", "-run=FileSize") + tg.grepStdout(`\(cached\)`, "did not cache") + tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), []byte("xxx"), 0644)) + tg.run("test", "testcache", "-run=FileSize") + tg.grepStdoutNot(`\(cached\)`, "did not notice file size change") + tg.run("test", "testcache", "-run=FileSize") + tg.grepStdout(`\(cached\)`, "did not cache") + + tg.run("test", "testcache", "-run=Chdir") + tg.run("test", "testcache", "-run=Chdir") + tg.grepStdout(`\(cached\)`, "did not cache") + tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), []byte("xxxxx"), 0644)) + tg.run("test", "testcache", "-run=Chdir") + tg.grepStdoutNot(`\(cached\)`, "did not notice file size change") + tg.run("test", "testcache", "-run=Chdir") + tg.grepStdout(`\(cached\)`, "did not cache") + + tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), old, old)) + tg.run("test", "testcache", "-run=FileContent") + tg.run("test", "testcache", "-run=FileContent") + tg.grepStdout(`\(cached\)`, "did not cache") + tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), []byte("yyy"), 0644)) + old2 := old.Add(10 * time.Second) + tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), old2, old2)) + tg.run("test", "testcache", "-run=FileContent") + tg.grepStdoutNot(`\(cached\)`, "did not notice file content change") + tg.run("test", "testcache", "-run=FileContent") + tg.grepStdout(`\(cached\)`, "did not cache") + + tg.run("test", "testcache", "-run=DirList") + tg.run("test", "testcache", "-run=DirList") + tg.grepStdout(`\(cached\)`, "did not cache") + tg.must(os.Remove(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"))) + tg.run("test", "testcache", "-run=DirList") + tg.grepStdoutNot(`\(cached\)`, "did not notice directory change") + tg.run("test", "testcache", "-run=DirList") + tg.grepStdout(`\(cached\)`, "did not cache") + + tg.tempFile("file.txt", "") + tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/testcachetmp_test.go"), []byte(`package testcache + + import ( + "os" + "testing" + ) + + func TestExternalFile(t *testing.T) { + os.Open(`+fmt.Sprintf("%q", tg.path("file.txt"))+`) + _, err := os.Stat(`+fmt.Sprintf("%q", tg.path("file.txt"))+`) + if err != nil { + t.Fatal(err) + } + } + `), 0666)) + defer os.Remove(filepath.Join(tg.pwd(), "testdata/src/testcache/testcachetmp_test.go")) + tg.run("test", "testcache", "-run=ExternalFile") + tg.run("test", "testcache", "-run=ExternalFile") + tg.grepStdout(`\(cached\)`, "did not cache") + tg.must(os.Remove(filepath.Join(tg.tempdir, "file.txt"))) + tg.run("test", "testcache", "-run=ExternalFile") + tg.grepStdout(`\(cached\)`, "did not cache") + + switch runtime.GOOS { + case "nacl", "plan9", "windows": + // no shell scripts + default: + tg.run("test", "testcache", "-run=Exec") + tg.run("test", "testcache", "-run=Exec") + tg.grepStdout(`\(cached\)`, "did not cache") + tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/script.sh"), old2, old2)) + tg.run("test", "testcache", "-run=Exec") + tg.grepStdoutNot(`\(cached\)`, "did not notice script change") + tg.run("test", "testcache", "-run=Exec") + tg.grepStdout(`\(cached\)`, "did not cache") + } +} + +func TestNoCache(t *testing.T) { + switch runtime.GOOS { + case "windows": + t.Skipf("no unwritable directories on %s", runtime.GOOS) + } + if os.Getuid() == 0 { + t.Skip("skipping test because running as root") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("triv.go", `package main; func main() {}`) + tg.must(os.MkdirAll(tg.path("unwritable"), 0555)) + home := "HOME" + if runtime.GOOS == "plan9" { + home = "home" + } + tg.setenv(home, tg.path(filepath.Join("unwritable", "home"))) + tg.unsetenv("GOCACHE") + tg.run("build", "-o", tg.path("triv"), tg.path("triv.go")) + tg.grepStderr("disabling cache", "did not disable cache") +} + +func TestTestVet(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + + tg.tempFile("p1_test.go", ` + package p + import "testing" + func Test(t *testing.T) { + t.Logf("%d") // oops + } + `) + + tg.runFail("test", tg.path("p1_test.go")) + tg.grepStderr(`Logf format %d`, "did not diagnose bad Logf") + tg.run("test", "-vet=off", tg.path("p1_test.go")) + tg.grepStdout(`^ok`, "did not print test summary") + + tg.tempFile("p1.go", ` + package p + import "fmt" + func F() { + fmt.Printf("%d") // oops + } + `) + tg.runFail("test", tg.path("p1.go")) + tg.grepStderr(`Printf format %d`, "did not diagnose bad Printf") + tg.run("test", "-x", "-vet=shift", tg.path("p1.go")) + tg.grepStderr(`[\\/]vet.*-shift`, "did not run vet with -shift") + tg.grepStdout(`\[no test files\]`, "did not print test summary") + tg.run("test", "-vet=off", tg.path("p1.go")) + tg.grepStdout(`\[no test files\]`, "did not print test summary") + + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("test", "vetcycle") // must not fail; #22890 + + tg.runFail("test", "vetfail/...") + tg.grepStderr(`Printf format %d`, "did not diagnose bad Printf") + tg.grepStdout(`ok\s+vetfail/p2`, "did not run vetfail/p2") +} + +func TestTestRebuild(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + + // golang.org/issue/23701. + // b_test imports b with augmented method from export_test.go. + // b_test also imports a, which imports b. + // Must not accidentally see un-augmented b propagate through a to b_test. + tg.tempFile("src/a/a.go", `package a + import "b" + type Type struct{} + func (*Type) M() b.T {return 0} + `) + tg.tempFile("src/b/b.go", `package b + type T int + type I interface {M() T} + `) + tg.tempFile("src/b/export_test.go", `package b + func (*T) Method() *T { return nil } + `) + tg.tempFile("src/b/b_test.go", `package b_test + import ( + "testing" + "a" + . "b" + ) + func TestBroken(t *testing.T) { + x := new(T) + x.Method() + _ = new(a.Type) + } + `) + + tg.setenv("GOPATH", tg.path(".")) + tg.run("test", "b") +} + +func TestInstallDeps(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", tg.tempdir) + + tg.tempFile("src/p1/p1.go", "package p1\nvar X = 1\n") + tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\n") + tg.tempFile("src/main1/main.go", "package main\nimport _ \"p2\"\nfunc main() {}\n") + + tg.run("list", "-f={{.Target}}", "p1") + p1 := strings.TrimSpace(tg.getStdout()) + tg.run("list", "-f={{.Target}}", "p2") + p2 := strings.TrimSpace(tg.getStdout()) + tg.run("list", "-f={{.Target}}", "main1") + main1 := strings.TrimSpace(tg.getStdout()) + + tg.run("install", "main1") + + tg.mustExist(main1) + tg.mustNotExist(p2) + tg.mustNotExist(p1) + + tg.run("install", "p2") + tg.mustExist(p2) + tg.mustNotExist(p1) + + // don't let install -i overwrite runtime + tg.wantNotStale("runtime", "", "must be non-stale before install -i") + + tg.run("install", "-i", "main1") + tg.mustExist(p1) + tg.must(os.Remove(p1)) + + tg.run("install", "-i", "p2") + tg.mustExist(p1) +} + +func TestFmtLoadErrors(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.runFail("fmt", "does-not-exist") + tg.run("fmt", "-n", "exclude") +} + +func TestRelativePkgdir(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOCACHE", "off") + tg.cd(tg.tempdir) + + tg.run("build", "-i", "-pkgdir=.", "runtime") +} + +func TestGcflagsPatterns(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", "") + tg.setenv("GOCACHE", "off") + + tg.run("build", "-n", "-v", "-gcflags= \t\r\n -e", "fmt") + tg.grepStderr("^# fmt", "did not rebuild fmt") + tg.grepStderrNot("^# reflect", "incorrectly rebuilt reflect") + + tg.run("build", "-n", "-v", "-gcflags=-e", "fmt", "reflect") + tg.grepStderr("^# fmt", "did not rebuild fmt") + tg.grepStderr("^# reflect", "did not rebuild reflect") + tg.grepStderrNot("^# runtime", "incorrectly rebuilt runtime") + + tg.run("build", "-n", "-x", "-v", "-gcflags= \t\r\n reflect \t\r\n = \t\r\n -N", "fmt") + tg.grepStderr("^# fmt", "did not rebuild fmt") + tg.grepStderr("^# reflect", "did not rebuild reflect") + tg.grepStderr("compile.* -N .*-p reflect", "did not build reflect with -N flag") + tg.grepStderrNot("compile.* -N .*-p fmt", "incorrectly built fmt with -N flag") + + tg.run("test", "-c", "-n", "-gcflags=-N", "-ldflags=-X=x.y=z", "strings") + tg.grepStderr("compile.* -N .*compare_test.go", "did not compile strings_test package with -N flag") + tg.grepStderr("link.* -X=x.y=z", "did not link strings.test binary with -X flag") + + tg.run("test", "-c", "-n", "-gcflags=strings=-N", "-ldflags=strings=-X=x.y=z", "strings") + tg.grepStderr("compile.* -N .*compare_test.go", "did not compile strings_test package with -N flag") + tg.grepStderr("link.* -X=x.y=z", "did not link strings.test binary with -X flag") +} + +func TestGoTestMinusN(t *testing.T) { + // Intent here is to verify that 'go test -n' works without crashing. + // This reuses flag_test.go, but really any test would do. + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "testdata/flag_test.go", "-n", "-args", "-v=7") +} + +func TestGoTestJSON(t *testing.T) { + tooSlow(t) + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOCACHE", tg.tempdir) + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + + // It would be nice to test that the output is interlaced + // but it seems to be impossible to do that in a short test + // that isn't also flaky. Just check that we get JSON output. + tg.run("test", "-json", "-short", "-v", "errors", "empty/pkg", "skipper") + tg.grepStdout(`"Package":"errors"`, "did not see JSON output") + tg.grepStdout(`"Action":"run"`, "did not see JSON output") + + tg.grepStdout(`"Action":"output","Package":"empty/pkg","Output":".*no test files`, "did not see no test files print") + tg.grepStdout(`"Action":"skip","Package":"empty/pkg"`, "did not see skip") + + tg.grepStdout(`"Action":"output","Package":"skipper","Test":"Test","Output":"--- SKIP:`, "did not see SKIP output") + tg.grepStdout(`"Action":"skip","Package":"skipper","Test":"Test"`, "did not see skip result for Test") + + tg.run("test", "-json", "-short", "-v", "errors") + tg.grepStdout(`"Action":"output","Package":"errors","Output":".*\(cached\)`, "did not see no cached output") + + tg.run("test", "-json", "-bench=NONE", "-short", "-v", "errors") + tg.grepStdout(`"Package":"errors"`, "did not see JSON output") + tg.grepStdout(`"Action":"run"`, "did not see JSON output") + + tg.run("test", "-o", tg.path("errors.test.exe"), "-c", "errors") + tg.run("tool", "test2json", "-p", "errors", tg.path("errors.test.exe"), "-test.v", "-test.short") + tg.grepStdout(`"Package":"errors"`, "did not see JSON output") + tg.grepStdout(`"Action":"run"`, "did not see JSON output") + tg.grepStdout(`\{"Action":"pass","Package":"errors"\}`, "did not see final pass") +} + +func TestFailFast(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + + tests := []struct { + run string + failfast bool + nfail int + }{ + {"TestFailingA", true, 1}, + {"TestFailing[AB]", true, 1}, + {"TestFailing[AB]", false, 2}, + // mix with non-failing tests: + {"TestA|TestFailing[AB]", true, 1}, + {"TestA|TestFailing[AB]", false, 2}, + // mix with parallel tests: + {"TestFailingB|TestParallelFailingA", true, 2}, + {"TestFailingB|TestParallelFailingA", false, 2}, + {"TestFailingB|TestParallelFailing[AB]", true, 3}, + {"TestFailingB|TestParallelFailing[AB]", false, 3}, + // mix with parallel sub-tests + {"TestFailingB|TestParallelFailing[AB]|TestParallelFailingSubtestsA", true, 3}, + {"TestFailingB|TestParallelFailing[AB]|TestParallelFailingSubtestsA", false, 5}, + {"TestParallelFailingSubtestsA", true, 1}, + // only parallels: + {"TestParallelFailing[AB]", false, 2}, + // non-parallel subtests: + {"TestFailingSubtestsA", true, 1}, + {"TestFailingSubtestsA", false, 2}, + } + + for _, tt := range tests { + t.Run(tt.run, func(t *testing.T) { + tg.runFail("test", "./testdata/src/failfast_test.go", "-run="+tt.run, "-failfast="+strconv.FormatBool(tt.failfast)) + + nfail := strings.Count(tg.getStdout(), "FAIL - ") + + if nfail != tt.nfail { + t.Errorf("go test -run=%s -failfast=%t printed %d FAILs, want %d", tt.run, tt.failfast, nfail, tt.nfail) + } + }) + } +} + +// Issue 22986. +func TestImportPath(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + + tg.tempFile("src/a/a.go", ` +package main + +import ( + "log" + p "a/p-1.0" +) + +func main() { + if !p.V { + log.Fatal("false") + } +}`) + + tg.tempFile("src/a/a_test.go", ` +package main_test + +import ( + p "a/p-1.0" + "testing" +) + +func TestV(t *testing.T) { + if !p.V { + t.Fatal("false") + } +}`) + + tg.tempFile("src/a/p-1.0/p.go", ` +package p + +var V = true + +func init() {} +`) + + tg.setenv("GOPATH", tg.path(".")) + tg.run("build", "-o", tg.path("a.exe"), "a") + tg.run("test", "a") +} + +// Issue 23150. +func TestCpuprofileTwice(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("prof/src/x/x_test.go", ` + package x_test + import ( + "testing" + "time" + ) + func TestSleep(t *testing.T) { time.Sleep(10 * time.Millisecond) }`) + tg.setenv("GOPATH", tg.path("prof")) + bin := tg.path("x.test") + out := tg.path("cpu.out") + tg.run("test", "-o="+bin, "-cpuprofile="+out, "x") + tg.must(os.Remove(out)) + tg.run("test", "-o="+bin, "-cpuprofile="+out, "x") + tg.mustExist(out) +} + +// Issue 23694. +func TestAtomicCoverpkgAll(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + + tg.tempFile("src/x/x.go", `package x; import _ "sync/atomic"; func F() {}`) + tg.tempFile("src/x/x_test.go", `package x; import "testing"; func TestF(t *testing.T) { F() }`) + tg.setenv("GOPATH", tg.path(".")) + tg.run("test", "-coverpkg=all", "-covermode=atomic", "x") + if canRace { + tg.run("test", "-coverpkg=all", "-race", "x") + } +} + +func TestBadCommandLines(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + + tg.tempFile("src/x/x.go", "package x\n") + tg.setenv("GOPATH", tg.path(".")) + + tg.run("build", "x") + + tg.tempFile("src/x/@y.go", "package x\n") + tg.runFail("build", "x") + tg.grepStderr("invalid input file name \"@y.go\"", "did not reject @y.go") + tg.must(os.Remove(tg.path("src/x/@y.go"))) + + tg.tempFile("src/x/-y.go", "package x\n") + tg.runFail("build", "x") + tg.grepStderr("invalid input file name \"-y.go\"", "did not reject -y.go") + tg.must(os.Remove(tg.path("src/x/-y.go"))) + + tg.runFail("build", "-gcflags=all=@x", "x") + tg.grepStderr("invalid command-line argument @x in command", "did not reject @x during exec") + + 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\"", "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\"", "did not reject @x/y import path") + + 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\"", "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\"", "did not reject -x/y import path") +} + +func TestBadCgoDirectives(t *testing.T) { + if !canCgo { + t.Skip("no cgo") + } + tg := testgo(t) + defer tg.cleanup() + + tg.tempFile("src/x/x.go", "package x\n") + tg.setenv("GOPATH", tg.path(".")) + + tg.tempFile("src/x/x.go", `package x + + //go:cgo_ldflag "-fplugin=foo.so" + + import "C" + `) + tg.runFail("build", "x") + tg.grepStderr("//go:cgo_ldflag .* only allowed in cgo-generated code", "did not reject //go:cgo_ldflag directive") + + tg.must(os.Remove(tg.path("src/x/x.go"))) + tg.runFail("build", "x") + tg.grepStderr("no Go files", "did not report missing source code") + tg.tempFile("src/x/_cgo_yy.go", `package x + + //go:cgo_ldflag "-fplugin=foo.so" + + import "C" + `) + tg.runFail("build", "x") + tg.grepStderr("no Go files", "did not report missing source code") // _* files are ignored... + + tg.runFail("build", tg.path("src/x/_cgo_yy.go")) // ... but if forced, the comment is rejected + // Actually, today there is a separate issue that _ files named + // on the command-line are ignored. Once that is fixed, + // we want to see the cgo_ldflag error. + tg.grepStderr("//go:cgo_ldflag only allowed in cgo-generated code|no Go files", "did not reject //go:cgo_ldflag directive") + tg.must(os.Remove(tg.path("src/x/_cgo_yy.go"))) + + tg.tempFile("src/x/x.go", "package x\n") + tg.tempFile("src/x/y.go", `package x + // #cgo CFLAGS: -fplugin=foo.so + import "C" + `) + tg.runFail("build", "x") + tg.grepStderr("invalid flag in #cgo CFLAGS: -fplugin=foo.so", "did not reject -fplugin") + + tg.tempFile("src/x/y.go", `package x + // #cgo CFLAGS: -Ibar -fplugin=foo.so + import "C" + `) + tg.runFail("build", "x") + tg.grepStderr("invalid flag in #cgo CFLAGS: -fplugin=foo.so", "did not reject -fplugin") + + tg.tempFile("src/x/y.go", `package x + // #cgo pkg-config: -foo + import "C" + `) + tg.runFail("build", "x") + tg.grepStderr("invalid pkg-config package name: -foo", "did not reject pkg-config: -foo") + + tg.tempFile("src/x/y.go", `package x + // #cgo pkg-config: @foo + import "C" + `) + tg.runFail("build", "x") + tg.grepStderr("invalid pkg-config package name: @foo", "did not reject pkg-config: -foo") + + tg.tempFile("src/x/y.go", `package x + // #cgo CFLAGS: @foo + import "C" + `) + tg.runFail("build", "x") + tg.grepStderr("invalid flag in #cgo CFLAGS: @foo", "did not reject @foo flag") + + tg.tempFile("src/x/y.go", `package x + // #cgo CFLAGS: -D + import "C" + `) + tg.runFail("build", "x") + tg.grepStderr("invalid flag in #cgo CFLAGS: -D without argument", "did not reject trailing -I flag") + + // Note that -I @foo is allowed because we rewrite it into -I /path/to/src/@foo + // before the check is applied. There's no such rewrite for -D. + + tg.tempFile("src/x/y.go", `package x + // #cgo CFLAGS: -D @foo + import "C" + `) + tg.runFail("build", "x") + tg.grepStderr("invalid flag in #cgo CFLAGS: -D @foo", "did not reject -D @foo flag") + + tg.tempFile("src/x/y.go", `package x + // #cgo CFLAGS: -D@foo + import "C" + `) + tg.runFail("build", "x") + tg.grepStderr("invalid flag in #cgo CFLAGS: -D@foo", "did not reject -D@foo flag") + + tg.setenv("CGO_CFLAGS", "-D@foo") + tg.tempFile("src/x/y.go", `package x + import "C" + `) + tg.run("build", "-n", "x") + tg.grepStderr("-D@foo", "did not find -D@foo in commands") +}
diff --git a/vendor/cmd/go/go_unix_test.go b/vendor/cmd/go/go_unix_test.go new file mode 100644 index 0000000..6ff89f4 --- /dev/null +++ b/vendor/cmd/go/go_unix_test.go
@@ -0,0 +1,35 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin dragonfly freebsd linux netbsd openbsd solaris + +package Main_test + +import ( + "os" + "syscall" + "testing" +) + +func TestGoBuildUmask(t *testing.T) { + // Do not use tg.parallel; avoid other tests seeing umask manipulation. + mask := syscall.Umask(0077) // prohibit low bits + defer syscall.Umask(mask) + tg := testgo(t) + defer tg.cleanup() + tg.tempFile("x.go", `package main; func main() {}`) + // Make sure artifact will be output to /tmp/... in case the user + // has POSIX acl's on their go source tree. + // See issue 17909. + exe := tg.path("x") + tg.creatingTemp(exe) + tg.run("build", "-o", exe, tg.path("x.go")) + fi, err := os.Stat(exe) + if err != nil { + t.Fatal(err) + } + if mode := fi.Mode(); mode&0077 != 0 { + t.Fatalf("wrote x with mode=%v, wanted no 0077 bits", mode) + } +}
diff --git a/vendor/cmd/go/go_windows_test.go b/vendor/cmd/go/go_windows_test.go new file mode 100644 index 0000000..c67954d --- /dev/null +++ b/vendor/cmd/go/go_windows_test.go
@@ -0,0 +1,123 @@ +// Copyright 2014 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 Main + +import ( + "fmt" + "internal/testenv" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" +) + +func TestAbsolutePath(t *testing.T) { + tmp, err := ioutil.TempDir("", "TestAbsolutePath") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmp) + + file := filepath.Join(tmp, "a.go") + err = ioutil.WriteFile(file, []byte{}, 0644) + if err != nil { + t.Fatal(err) + } + dir := filepath.Join(tmp, "dir") + err = os.Mkdir(dir, 0777) + if err != nil { + t.Fatal(err) + } + + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + defer os.Chdir(wd) + + // Chdir so current directory and a.go reside on the same drive. + err = os.Chdir(dir) + if err != nil { + t.Fatal(err) + } + + noVolume := file[len(filepath.VolumeName(file)):] + wrongPath := filepath.Join(dir, noVolume) + output, err := exec.Command(testenv.GoToolPath(t), "build", noVolume).CombinedOutput() + if err == nil { + t.Fatal("build should fail") + } + if strings.Contains(string(output), wrongPath) { + t.Fatalf("wrong output found: %v %v", err, string(output)) + } +} + +func runIcacls(t *testing.T, args ...string) string { + t.Helper() + out, err := exec.Command("icacls", args...).CombinedOutput() + if err != nil { + t.Fatalf("icacls failed: %v\n%v", err, string(out)) + } + return string(out) +} + +func runGetACL(t *testing.T, path string) string { + t.Helper() + cmd := fmt.Sprintf(`Get-Acl "%s" | Select -expand AccessToString`, path) + out, err := exec.Command("powershell", "-Command", cmd).CombinedOutput() + if err != nil { + t.Fatalf("Get-Acl failed: %v\n%v", err, string(out)) + } + return string(out) +} + +// For issue 22343: verify that executable file created by "go build" command +// has discretionary access control list (DACL) set as if the file +// was created in the destination directory. +func TestACL(t *testing.T) { + tmpdir, err := ioutil.TempDir("", "TestACL") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + + newtmpdir := filepath.Join(tmpdir, "tmp") + err = os.Mkdir(newtmpdir, 0777) + if err != nil { + t.Fatal(err) + } + + // When TestACL/tmp directory is created, it will have + // the same security attributes as TestACL. + // Add Guest account full access to TestACL/tmp - this + // will make all files created in TestACL/tmp have different + // security attributes to the files created in TestACL. + runIcacls(t, newtmpdir, + "/grant", "guest:(oi)(ci)f", // add Guest user to have full access + ) + + src := filepath.Join(tmpdir, "main.go") + err = ioutil.WriteFile(src, []byte("package main; func main() { }\n"), 0644) + if err != nil { + t.Fatal(err) + } + exe := filepath.Join(tmpdir, "main.exe") + cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, src) + cmd.Env = append(os.Environ(), + "TMP="+newtmpdir, + "TEMP="+newtmpdir, + ) + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("go command failed: %v\n%v", err, string(out)) + } + + // exe file is expected to have the same security attributes as the src. + if got, expected := runGetACL(t, exe), runGetACL(t, src); got != expected { + t.Fatalf("expected Get-Acl output of \n%v\n, got \n%v\n", expected, got) + } +}
diff --git a/vendor/cmd/go/internal/base/base.go b/vendor/cmd/go/internal/base/base.go new file mode 100644 index 0000000..286efbc --- /dev/null +++ b/vendor/cmd/go/internal/base/base.go
@@ -0,0 +1,173 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package base defines shared basic pieces of the go command, +// in particular logging and the Command structure. +package base + +import ( + "bytes" + "errors" + "flag" + "fmt" + "go/scanner" + "log" + "os" + "os/exec" + "strings" + "sync" + + "cmd/go/internal/cfg" + "cmd/go/internal/str" +) + +// A Command is an implementation of a go command +// like go build or go fix. +type Command struct { + // Run runs the command. + // The args are the arguments after the command name. + Run func(cmd *Command, args []string) + + // UsageLine is the one-line usage message. + // The first word in the line is taken to be the command name. + UsageLine string + + // Short is the short description shown in the 'go help' output. + Short string + + // Long is the long message shown in the 'go help <this-command>' output. + Long string + + // Flag is a set of flags specific to this command. + Flag flag.FlagSet + + // CustomFlags indicates that the command will do its own + // flag parsing. + CustomFlags bool +} + +// Commands lists the available commands and help topics. +// The order here is the order in which they are printed by 'go help'. +var Commands []*Command + +// Name returns the command's name: the first word in the usage line. +func (c *Command) Name() string { + name := c.UsageLine + i := strings.Index(name, " ") + if i >= 0 { + name = name[:i] + } + return name +} + +func (c *Command) Usage() { + fmt.Fprintf(os.Stderr, "usage: %s\n", c.UsageLine) + fmt.Fprintf(os.Stderr, "Run 'go help %s' for details.\n", c.Name()) + os.Exit(2) +} + +// Runnable reports whether the command can be run; otherwise +// it is a documentation pseudo-command such as importpath. +func (c *Command) Runnable() bool { + return c.Run != nil +} + +var atExitFuncs []func() + +func AtExit(f func()) { + atExitFuncs = append(atExitFuncs, f) +} + +func Exit() { + for _, f := range atExitFuncs { + f() + } + os.Exit(exitStatus) +} + +func Fatalf(format string, args ...interface{}) { + Errorf(format, args...) + Exit() +} + +func Errorf(format string, args ...interface{}) { + log.Printf(format, args...) + SetExitStatus(1) +} + +func ExitIfErrors() { + if exitStatus != 0 { + Exit() + } +} + +var exitStatus = 0 +var exitMu sync.Mutex + +func SetExitStatus(n int) { + exitMu.Lock() + if exitStatus < n { + exitStatus = n + } + exitMu.Unlock() +} + +// Run runs the command, with stdout and stderr +// connected to the go command's own stdout and stderr. +// If the command fails, Run reports the error using Errorf. +func Run(cmdargs ...interface{}) { + cmdline := str.StringList(cmdargs...) + if cfg.BuildN || cfg.BuildX { + fmt.Printf("%s\n", strings.Join(cmdline, " ")) + if cfg.BuildN { + return + } + } + + cmd := exec.Command(cmdline[0], cmdline[1:]...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + Errorf("%v", err) + } +} + +// RunStdin is like run but connects Stdin. +func RunStdin(cmdline []string) { + cmd := exec.Command(cmdline[0], cmdline[1:]...) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Env = cfg.OrigEnv + StartSigHandlers() + if err := cmd.Run(); err != nil { + Errorf("%v", err) + } +} + +// Usage is the usage-reporting function, filled in by package main +// but here for reference by other packages. +var Usage func() + +// ExpandScanner expands a scanner.List error into all the errors in the list. +// The default Error method only shows the first error +// and does not shorten paths. +func ExpandScanner(err error) error { + // Look for parser errors. + if err, ok := err.(scanner.ErrorList); ok { + // Prepare error with \n before each message. + // When printed in something like context: %v + // this will put the leading file positions each on + // its own line. It will also show all the errors + // instead of just the first, as err.Error does. + var buf bytes.Buffer + for _, e := range err { + e.Pos.Filename = ShortPath(e.Pos.Filename) + buf.WriteString("\n") + buf.WriteString(e.Error()) + } + return errors.New(buf.String()) + } + return err +}
diff --git a/vendor/cmd/go/internal/base/env.go b/vendor/cmd/go/internal/base/env.go new file mode 100644 index 0000000..fcade9d --- /dev/null +++ b/vendor/cmd/go/internal/base/env.go
@@ -0,0 +1,37 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package base + +import "strings" + +// EnvForDir returns a copy of the environment +// suitable for running in the given directory. +// The environment is the current process's environment +// but with an updated $PWD, so that an os.Getwd in the +// child will be faster. +func EnvForDir(dir string, base []string) []string { + // Internally we only use rooted paths, so dir is rooted. + // Even if dir is not rooted, no harm done. + return MergeEnvLists([]string{"PWD=" + dir}, base) +} + +// MergeEnvLists merges the two environment lists such that +// variables with the same name in "in" replace those in "out". +// This always returns a newly allocated slice. +func MergeEnvLists(in, out []string) []string { + out = append([]string(nil), out...) +NextVar: + for _, inkv := range in { + k := strings.SplitAfterN(inkv, "=", 2)[0] + for i, outkv := range out { + if strings.HasPrefix(outkv, k) { + out[i] = inkv + continue NextVar + } + } + out = append(out, inkv) + } + return out +}
diff --git a/vendor/cmd/go/internal/base/flag.go b/vendor/cmd/go/internal/base/flag.go new file mode 100644 index 0000000..5e03e64 --- /dev/null +++ b/vendor/cmd/go/internal/base/flag.go
@@ -0,0 +1,35 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package base + +import ( + "flag" + + "cmd/go/internal/cfg" + "cmd/go/internal/str" +) + +// A StringsFlag is a command-line flag that interprets its argument +// as a space-separated list of possibly-quoted strings. +type StringsFlag []string + +func (v *StringsFlag) Set(s string) error { + var err error + *v, err = str.SplitQuotedFields(s) + if *v == nil { + *v = []string{} + } + return err +} + +func (v *StringsFlag) String() string { + return "<StringsFlag>" +} + +// AddBuildFlagsNX adds the -n and -x build flags to the flag set. +func AddBuildFlagsNX(flags *flag.FlagSet) { + flags.BoolVar(&cfg.BuildN, "n", false, "") + flags.BoolVar(&cfg.BuildX, "x", false, "") +}
diff --git a/vendor/cmd/go/internal/base/path.go b/vendor/cmd/go/internal/base/path.go new file mode 100644 index 0000000..7a51181 --- /dev/null +++ b/vendor/cmd/go/internal/base/path.go
@@ -0,0 +1,52 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package base + +import ( + "os" + "path/filepath" + "strings" +) + +func getwd() string { + wd, err := os.Getwd() + if err != nil { + Fatalf("cannot determine current directory: %v", err) + } + return wd +} + +var Cwd = getwd() + +// ShortPath returns an absolute or relative name for path, whatever is shorter. +func ShortPath(path string) string { + if rel, err := filepath.Rel(Cwd, path); err == nil && len(rel) < len(path) { + return rel + } + return path +} + +// RelPaths returns a copy of paths with absolute paths +// made relative to the current directory if they would be shorter. +func RelPaths(paths []string) []string { + var out []string + // TODO(rsc): Can this use Cwd from above? + pwd, _ := os.Getwd() + for _, p := range paths { + rel, err := filepath.Rel(pwd, p) + if err == nil && len(rel) < len(p) { + p = rel + } + out = append(out, p) + } + return out +} + +// IsTestFile reports whether the source file is a set of tests and should therefore +// be excluded from coverage analysis. +func IsTestFile(file string) bool { + // We don't cover tests, only the code they test. + return strings.HasSuffix(file, "_test.go") +}
diff --git a/vendor/cmd/go/internal/base/signal.go b/vendor/cmd/go/internal/base/signal.go new file mode 100644 index 0000000..54d1187 --- /dev/null +++ b/vendor/cmd/go/internal/base/signal.go
@@ -0,0 +1,31 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package base + +import ( + "os" + "os/signal" + "sync" +) + +// Interrupted is closed when the go command receives an interrupt signal. +var Interrupted = make(chan struct{}) + +// processSignals setups signal handler. +func processSignals() { + sig := make(chan os.Signal) + signal.Notify(sig, signalsToIgnore...) + go func() { + <-sig + close(Interrupted) + }() +} + +var onceProcessSignals sync.Once + +// StartSigHandlers starts the signal handlers. +func StartSigHandlers() { + onceProcessSignals.Do(processSignals) +}
diff --git a/vendor/cmd/go/internal/base/signal_notunix.go b/vendor/cmd/go/internal/base/signal_notunix.go new file mode 100644 index 0000000..9e869b0 --- /dev/null +++ b/vendor/cmd/go/internal/base/signal_notunix.go
@@ -0,0 +1,17 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build plan9 windows + +package base + +import ( + "os" +) + +var signalsToIgnore = []os.Signal{os.Interrupt} + +// SignalTrace is the signal to send to make a Go program +// crash with a stack trace (no such signal in this case). +var SignalTrace os.Signal = nil
diff --git a/vendor/cmd/go/internal/base/signal_unix.go b/vendor/cmd/go/internal/base/signal_unix.go new file mode 100644 index 0000000..4ca3da9 --- /dev/null +++ b/vendor/cmd/go/internal/base/signal_unix.go
@@ -0,0 +1,18 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris + +package base + +import ( + "os" + "syscall" +) + +var signalsToIgnore = []os.Signal{os.Interrupt, syscall.SIGQUIT} + +// SignalTrace is the signal to send to make a Go program +// crash with a stack trace. +var SignalTrace os.Signal = syscall.SIGQUIT
diff --git a/vendor/cmd/go/internal/base/tool.go b/vendor/cmd/go/internal/base/tool.go new file mode 100644 index 0000000..d0da65e --- /dev/null +++ b/vendor/cmd/go/internal/base/tool.go
@@ -0,0 +1,44 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package base + +import ( + "fmt" + "go/build" + "os" + "path/filepath" + "runtime" + + "cmd/go/internal/cfg" +) + +// Configuration for finding tool binaries. +var ( + ToolGOOS = runtime.GOOS + ToolGOARCH = runtime.GOARCH + ToolIsWindows = ToolGOOS == "windows" + ToolDir = build.ToolDir +) + +const ToolWindowsExtension = ".exe" + +// Tool returns the path to the named tool (for example, "vet"). +// If the tool cannot be found, Tool exits the process. +func Tool(toolName string) string { + toolPath := filepath.Join(ToolDir, toolName) + if ToolIsWindows { + toolPath += ToolWindowsExtension + } + if len(cfg.BuildToolexec) > 0 { + return toolPath + } + // Give a nice message if there is no tool with that name. + if _, err := os.Stat(toolPath); err != nil { + fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName) + SetExitStatus(2) + Exit() + } + return toolPath +}
diff --git a/vendor/cmd/go/internal/bug/bug.go b/vendor/cmd/go/internal/bug/bug.go new file mode 100644 index 0000000..963da94 --- /dev/null +++ b/vendor/cmd/go/internal/bug/bug.go
@@ -0,0 +1,218 @@ +// Copyright 2016 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 bug implements the ``go bug'' command. +package bug + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "regexp" + "runtime" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/envcmd" + "cmd/go/internal/web" +) + +var CmdBug = &base.Command{ + Run: runBug, + UsageLine: "bug", + Short: "start a bug report", + Long: ` +Bug opens the default browser and starts a new bug report. +The report includes useful system information. + `, +} + +func init() { + CmdBug.Flag.BoolVar(&cfg.BuildV, "v", false, "") +} + +func runBug(cmd *base.Command, args []string) { + var buf bytes.Buffer + buf.WriteString(bugHeader) + inspectGoVersion(&buf) + fmt.Fprint(&buf, "#### System details\n\n") + fmt.Fprintln(&buf, "```") + fmt.Fprintf(&buf, "go version %s %s/%s\n", runtime.Version(), runtime.GOOS, runtime.GOARCH) + env := cfg.CmdEnv + env = append(env, envcmd.ExtraEnvVars()...) + for _, e := range env { + // Hide the TERM environment variable from "go bug". + // See issue #18128 + if e.Name != "TERM" { + fmt.Fprintf(&buf, "%s=\"%s\"\n", e.Name, e.Value) + } + } + printGoDetails(&buf) + printOSDetails(&buf) + printCDetails(&buf) + fmt.Fprintln(&buf, "```") + + body := buf.String() + url := "https://github.com/golang/go/issues/new?body=" + web.QueryEscape(body) + if !web.OpenBrowser(url) { + fmt.Print("Please file a new issue at golang.org/issue/new using this template:\n\n") + fmt.Print(body) + } +} + +const bugHeader = `Please answer these questions before submitting your issue. Thanks! + +#### What did you do? +If possible, provide a recipe for reproducing the error. +A complete runnable program is good. +A link on play.golang.org is best. + + +#### What did you expect to see? + + +#### What did you see instead? + + +` + +func printGoDetails(w io.Writer) { + printCmdOut(w, "GOROOT/bin/go version: ", filepath.Join(runtime.GOROOT(), "bin/go"), "version") + printCmdOut(w, "GOROOT/bin/go tool compile -V: ", filepath.Join(runtime.GOROOT(), "bin/go"), "tool", "compile", "-V") +} + +func printOSDetails(w io.Writer) { + switch runtime.GOOS { + case "darwin": + printCmdOut(w, "uname -v: ", "uname", "-v") + printCmdOut(w, "", "sw_vers") + case "linux": + printCmdOut(w, "uname -sr: ", "uname", "-sr") + printCmdOut(w, "", "lsb_release", "-a") + printGlibcVersion(w) + case "openbsd", "netbsd", "freebsd", "dragonfly": + printCmdOut(w, "uname -v: ", "uname", "-v") + case "solaris": + out, err := ioutil.ReadFile("/etc/release") + if err == nil { + fmt.Fprintf(w, "/etc/release: %s\n", out) + } else { + if cfg.BuildV { + fmt.Printf("failed to read /etc/release: %v\n", err) + } + } + } +} + +func printCDetails(w io.Writer) { + printCmdOut(w, "lldb --version: ", "lldb", "--version") + cmd := exec.Command("gdb", "--version") + out, err := cmd.Output() + if err == nil { + // There's apparently no combination of command line flags + // to get gdb to spit out its version without the license and warranty. + // Print up to the first newline. + fmt.Fprintf(w, "gdb --version: %s\n", firstLine(out)) + } else { + if cfg.BuildV { + fmt.Printf("failed to run gdb --version: %v\n", err) + } + } +} + +func inspectGoVersion(w io.Writer) { + data, err := web.Get("https://golang.org/VERSION?m=text") + if err != nil { + if cfg.BuildV { + fmt.Printf("failed to read from golang.org/VERSION: %v\n", err) + } + return + } + + // golang.org/VERSION currently returns a whitespace-free string, + // but just in case, protect against that changing. + // Similarly so for runtime.Version. + release := string(bytes.TrimSpace(data)) + vers := strings.TrimSpace(runtime.Version()) + + if vers == release { + // Up to date + return + } + + // Devel version or outdated release. Either way, this request is apropos. + fmt.Fprintf(w, "#### Does this issue reproduce with the latest release (%s)?\n\n\n", release) +} + +// printCmdOut prints the output of running the given command. +// It ignores failures; 'go bug' is best effort. +func printCmdOut(w io.Writer, prefix, path string, args ...string) { + cmd := exec.Command(path, args...) + out, err := cmd.Output() + if err != nil { + if cfg.BuildV { + fmt.Printf("%s %s: %v\n", path, strings.Join(args, " "), err) + } + return + } + fmt.Fprintf(w, "%s%s\n", prefix, bytes.TrimSpace(out)) +} + +// firstLine returns the first line of a given byte slice. +func firstLine(buf []byte) []byte { + idx := bytes.IndexByte(buf, '\n') + if idx > 0 { + buf = buf[:idx] + } + return bytes.TrimSpace(buf) +} + +// printGlibcVersion prints information about the glibc version. +// It ignores failures. +func printGlibcVersion(w io.Writer) { + tempdir := os.TempDir() + if tempdir == "" { + return + } + src := []byte(`int main() {}`) + srcfile := filepath.Join(tempdir, "go-bug.c") + outfile := filepath.Join(tempdir, "go-bug") + err := ioutil.WriteFile(srcfile, src, 0644) + if err != nil { + return + } + defer os.Remove(srcfile) + cmd := exec.Command("gcc", "-o", outfile, srcfile) + if _, err = cmd.CombinedOutput(); err != nil { + return + } + defer os.Remove(outfile) + + cmd = exec.Command("ldd", outfile) + out, err := cmd.CombinedOutput() + if err != nil { + return + } + re := regexp.MustCompile(`libc\.so[^ ]* => ([^ ]+)`) + m := re.FindStringSubmatch(string(out)) + if m == nil { + return + } + cmd = exec.Command(m[1]) + out, err = cmd.Output() + if err != nil { + return + } + fmt.Fprintf(w, "%s: %s\n", m[1], firstLine(out)) + + // print another line (the one containing version string) in case of musl libc + if idx := bytes.IndexByte(out, '\n'); bytes.Index(out, []byte("musl")) != -1 && idx > -1 { + fmt.Fprintf(w, "%s\n", firstLine(out[idx+1:])) + } +}
diff --git a/vendor/cmd/go/internal/cache/cache.go b/vendor/cmd/go/internal/cache/cache.go new file mode 100644 index 0000000..edb5882 --- /dev/null +++ b/vendor/cmd/go/internal/cache/cache.go
@@ -0,0 +1,459 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cache implements a build artifact cache. +package cache + +import ( + "bytes" + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" + "time" +) + +// An ActionID is a cache action key, the hash of a complete description of a +// repeatable computation (command line, environment variables, +// input file contents, executable contents). +type ActionID [HashSize]byte + +// An OutputID is a cache output key, the hash of an output of a computation. +type OutputID [HashSize]byte + +// A Cache is a package cache, backed by a file system directory tree. +type Cache struct { + dir string + log *os.File + now func() time.Time +} + +// Open opens and returns the cache in the given directory. +// +// It is safe for multiple processes on a single machine to use the +// same cache directory in a local file system simultaneously. +// They will coordinate using operating system file locks and may +// duplicate effort but will not corrupt the cache. +// +// However, it is NOT safe for multiple processes on different machines +// to share a cache directory (for example, if the directory were stored +// in a network file system). File locking is notoriously unreliable in +// network file systems and may not suffice to protect the cache. +// +func Open(dir string) (*Cache, error) { + info, err := os.Stat(dir) + if err != nil { + return nil, err + } + if !info.IsDir() { + return nil, &os.PathError{Op: "open", Path: dir, Err: fmt.Errorf("not a directory")} + } + for i := 0; i < 256; i++ { + name := filepath.Join(dir, fmt.Sprintf("%02x", i)) + if err := os.MkdirAll(name, 0777); err != nil { + return nil, err + } + } + f, err := os.OpenFile(filepath.Join(dir, "log.txt"), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666) + if err != nil { + return nil, err + } + c := &Cache{ + dir: dir, + log: f, + now: time.Now, + } + return c, nil +} + +// fileName returns the name of the file corresponding to the given id. +func (c *Cache) fileName(id [HashSize]byte, key string) string { + return filepath.Join(c.dir, fmt.Sprintf("%02x", id[0]), fmt.Sprintf("%x", id)+"-"+key) +} + +var errMissing = errors.New("cache entry not found") + +const ( + // action entry file is "v1 <hex id> <hex out> <decimal size space-padded to 20 bytes> <unixnano space-padded to 20 bytes>\n" + hexSize = HashSize * 2 + entrySize = 2 + 1 + hexSize + 1 + hexSize + 1 + 20 + 1 + 20 + 1 +) + +// verify controls whether to run the cache in verify mode. +// In verify mode, the cache always returns errMissing from Get +// but then double-checks in Put that the data being written +// exactly matches any existing entry. This provides an easy +// way to detect program behavior that would have been different +// had the cache entry been returned from Get. +// +// verify is enabled by setting the environment variable +// GODEBUG=gocacheverify=1. +var verify = false + +// DebugTest is set when GODEBUG=gocachetest=1 is in the environment. +var DebugTest = false + +func init() { initEnv() } + +func initEnv() { + verify = false + debugHash = false + debug := strings.Split(os.Getenv("GODEBUG"), ",") + for _, f := range debug { + if f == "gocacheverify=1" { + verify = true + } + if f == "gocachehash=1" { + debugHash = true + } + if f == "gocachetest=1" { + DebugTest = true + } + } +} + +// Get looks up the action ID in the cache, +// returning the corresponding output ID and file size, if any. +// Note that finding an output ID does not guarantee that the +// saved file for that output ID is still available. +func (c *Cache) Get(id ActionID) (Entry, error) { + if verify { + return Entry{}, errMissing + } + return c.get(id) +} + +type Entry struct { + OutputID OutputID + Size int64 + Time time.Time +} + +// get is Get but does not respect verify mode, so that Put can use it. +func (c *Cache) get(id ActionID) (Entry, error) { + missing := func() (Entry, error) { + fmt.Fprintf(c.log, "%d miss %x\n", c.now().Unix(), id) + return Entry{}, errMissing + } + f, err := os.Open(c.fileName(id, "a")) + if err != nil { + return missing() + } + defer f.Close() + entry := make([]byte, entrySize+1) // +1 to detect whether f is too long + if n, err := io.ReadFull(f, entry); n != entrySize || err != io.ErrUnexpectedEOF { + return missing() + } + if entry[0] != 'v' || entry[1] != '1' || entry[2] != ' ' || entry[3+hexSize] != ' ' || entry[3+hexSize+1+hexSize] != ' ' || entry[3+hexSize+1+hexSize+1+20] != ' ' || entry[entrySize-1] != '\n' { + return missing() + } + eid, entry := entry[3:3+hexSize], entry[3+hexSize:] + eout, entry := entry[1:1+hexSize], entry[1+hexSize:] + esize, entry := entry[1:1+20], entry[1+20:] + etime, entry := entry[1:1+20], entry[1+20:] + var buf [HashSize]byte + if _, err := hex.Decode(buf[:], eid); err != nil || buf != id { + return missing() + } + if _, err := hex.Decode(buf[:], eout); err != nil { + return missing() + } + i := 0 + for i < len(esize) && esize[i] == ' ' { + i++ + } + size, err := strconv.ParseInt(string(esize[i:]), 10, 64) + if err != nil || size < 0 { + return missing() + } + i = 0 + for i < len(etime) && etime[i] == ' ' { + i++ + } + tm, err := strconv.ParseInt(string(etime[i:]), 10, 64) + if err != nil || size < 0 { + return missing() + } + + fmt.Fprintf(c.log, "%d get %x\n", c.now().Unix(), id) + + c.used(c.fileName(id, "a")) + + return Entry{buf, size, time.Unix(0, tm)}, nil +} + +// GetBytes looks up the action ID in the cache and returns +// the corresponding output bytes. +// GetBytes should only be used for data that can be expected to fit in memory. +func (c *Cache) GetBytes(id ActionID) ([]byte, Entry, error) { + entry, err := c.Get(id) + if err != nil { + return nil, entry, err + } + data, _ := ioutil.ReadFile(c.OutputFile(entry.OutputID)) + if sha256.Sum256(data) != entry.OutputID { + return nil, entry, errMissing + } + return data, entry, nil +} + +// OutputFile returns the name of the cache file storing output with the given OutputID. +func (c *Cache) OutputFile(out OutputID) string { + file := c.fileName(out, "d") + c.used(file) + return file +} + +// Time constants for cache expiration. +// +// We set the mtime on a cache file on each use, but at most one per mtimeInterval (1 hour), +// to avoid causing many unnecessary inode updates. The mtimes therefore +// roughly reflect "time of last use" but may in fact be older by at most an hour. +// +// We scan the cache for entries to delete at most once per trimInterval (1 day). +// +// When we do scan the cache, we delete entries that have not been used for +// at least trimLimit (5 days). Statistics gathered from a month of usage by +// Go developers found that essentially all reuse of cached entries happened +// within 5 days of the previous reuse. See golang.org/issue/22990. +const ( + mtimeInterval = 1 * time.Hour + trimInterval = 24 * time.Hour + trimLimit = 5 * 24 * time.Hour +) + +// used makes a best-effort attempt to update mtime on file, +// so that mtime reflects cache access time. +// +// Because the reflection only needs to be approximate, +// and to reduce the amount of disk activity caused by using +// cache entries, used only updates the mtime if the current +// mtime is more than an hour old. This heuristic eliminates +// nearly all of the mtime updates that would otherwise happen, +// while still keeping the mtimes useful for cache trimming. +func (c *Cache) used(file string) { + info, err := os.Stat(file) + if err == nil && c.now().Sub(info.ModTime()) < mtimeInterval { + return + } + os.Chtimes(file, c.now(), c.now()) +} + +// Trim removes old cache entries that are likely not to be reused. +func (c *Cache) Trim() { + now := c.now() + + // We maintain in dir/trim.txt the time of the last completed cache trim. + // If the cache has been trimmed recently enough, do nothing. + // This is the common case. + data, _ := ioutil.ReadFile(filepath.Join(c.dir, "trim.txt")) + t, err := strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64) + if err == nil && now.Sub(time.Unix(t, 0)) < trimInterval { + return + } + + // Trim each of the 256 subdirectories. + // We subtract an additional mtimeInterval + // to account for the imprecision of our "last used" mtimes. + cutoff := now.Add(-trimLimit - mtimeInterval) + for i := 0; i < 256; i++ { + subdir := filepath.Join(c.dir, fmt.Sprintf("%02x", i)) + c.trimSubdir(subdir, cutoff) + } + + ioutil.WriteFile(filepath.Join(c.dir, "trim.txt"), []byte(fmt.Sprintf("%d", now.Unix())), 0666) +} + +// trimSubdir trims a single cache subdirectory. +func (c *Cache) trimSubdir(subdir string, cutoff time.Time) { + // Read all directory entries from subdir before removing + // any files, in case removing files invalidates the file offset + // in the directory scan. Also, ignore error from f.Readdirnames, + // because we don't care about reporting the error and we still + // want to process any entries found before the error. + f, err := os.Open(subdir) + if err != nil { + return + } + names, _ := f.Readdirnames(-1) + f.Close() + + for _, name := range names { + // Remove only cache entries (xxxx-a and xxxx-d). + if !strings.HasSuffix(name, "-a") && !strings.HasSuffix(name, "-d") { + continue + } + entry := filepath.Join(subdir, name) + info, err := os.Stat(entry) + if err == nil && info.ModTime().Before(cutoff) { + os.Remove(entry) + } + } +} + +// putIndexEntry adds an entry to the cache recording that executing the action +// with the given id produces an output with the given output id (hash) and size. +func (c *Cache) putIndexEntry(id ActionID, out OutputID, size int64, allowVerify bool) error { + // Note: We expect that for one reason or another it may happen + // that repeating an action produces a different output hash + // (for example, if the output contains a time stamp or temp dir name). + // While not ideal, this is also not a correctness problem, so we + // don't make a big deal about it. In particular, we leave the action + // cache entries writable specifically so that they can be overwritten. + // + // Setting GODEBUG=gocacheverify=1 does make a big deal: + // in verify mode we are double-checking that the cache entries + // are entirely reproducible. As just noted, this may be unrealistic + // in some cases but the check is also useful for shaking out real bugs. + entry := []byte(fmt.Sprintf("v1 %x %x %20d %20d\n", id, out, size, time.Now().UnixNano())) + if verify && allowVerify { + old, err := c.get(id) + if err == nil && (old.OutputID != out || old.Size != size) { + // panic to show stack trace, so we can see what code is generating this cache entry. + msg := fmt.Sprintf("go: internal cache error: cache verify failed: id=%x changed:<<<\n%s\n>>>\nold: %x %d\nnew: %x %d", id, reverseHash(id), out, size, old.OutputID, old.Size) + panic(msg) + } + } + file := c.fileName(id, "a") + if err := ioutil.WriteFile(file, entry, 0666); err != nil { + os.Remove(file) + return err + } + os.Chtimes(file, c.now(), c.now()) // mainly for tests + + fmt.Fprintf(c.log, "%d put %x %x %d\n", c.now().Unix(), id, out, size) + return nil +} + +// Put stores the given output in the cache as the output for the action ID. +// It may read file twice. The content of file must not change between the two passes. +func (c *Cache) Put(id ActionID, file io.ReadSeeker) (OutputID, int64, error) { + return c.put(id, file, true) +} + +// PutNoVerify is like Put but disables the verify check +// when GODEBUG=goverifycache=1 is set. +// It is meant for data that is OK to cache but that we expect to vary slightly from run to run, +// like test output containing times and the like. +func (c *Cache) PutNoVerify(id ActionID, file io.ReadSeeker) (OutputID, int64, error) { + return c.put(id, file, false) +} + +func (c *Cache) put(id ActionID, file io.ReadSeeker, allowVerify bool) (OutputID, int64, error) { + // Compute output ID. + h := sha256.New() + if _, err := file.Seek(0, 0); err != nil { + return OutputID{}, 0, err + } + size, err := io.Copy(h, file) + if err != nil { + return OutputID{}, 0, err + } + var out OutputID + h.Sum(out[:0]) + + // Copy to cached output file (if not already present). + if err := c.copyFile(file, out, size); err != nil { + return out, size, err + } + + // Add to cache index. + return out, size, c.putIndexEntry(id, out, size, allowVerify) +} + +// PutBytes stores the given bytes in the cache as the output for the action ID. +func (c *Cache) PutBytes(id ActionID, data []byte) error { + _, _, err := c.Put(id, bytes.NewReader(data)) + return err +} + +// copyFile copies file into the cache, expecting it to have the given +// output ID and size, if that file is not present already. +func (c *Cache) copyFile(file io.ReadSeeker, out OutputID, size int64) error { + name := c.fileName(out, "d") + info, err := os.Stat(name) + if err == nil && info.Size() == size { + // Check hash. + if f, err := os.Open(name); err == nil { + h := sha256.New() + io.Copy(h, f) + f.Close() + var out2 OutputID + h.Sum(out2[:0]) + if out == out2 { + return nil + } + } + // Hash did not match. Fall through and rewrite file. + } + + // Copy file to cache directory. + mode := os.O_RDWR | os.O_CREATE + if err == nil && info.Size() > size { // shouldn't happen but fix in case + mode |= os.O_TRUNC + } + f, err := os.OpenFile(name, mode, 0666) + if err != nil { + return err + } + defer f.Close() + if size == 0 { + // File now exists with correct size. + // Only one possible zero-length file, so contents are OK too. + // Early return here makes sure there's a "last byte" for code below. + return nil + } + + // From here on, if any of the I/O writing the file fails, + // we make a best-effort attempt to truncate the file f + // before returning, to avoid leaving bad bytes in the file. + + // Copy file to f, but also into h to double-check hash. + if _, err := file.Seek(0, 0); err != nil { + f.Truncate(0) + return err + } + h := sha256.New() + w := io.MultiWriter(f, h) + if _, err := io.CopyN(w, file, size-1); err != nil { + f.Truncate(0) + return err + } + // Check last byte before writing it; writing it will make the size match + // what other processes expect to find and might cause them to start + // using the file. + buf := make([]byte, 1) + if _, err := file.Read(buf); err != nil { + f.Truncate(0) + return err + } + h.Write(buf) + sum := h.Sum(nil) + if !bytes.Equal(sum, out[:]) { + f.Truncate(0) + return fmt.Errorf("file content changed underfoot") + } + + // Commit cache file entry. + if _, err := f.Write(buf); err != nil { + f.Truncate(0) + return err + } + if err := f.Close(); err != nil { + // Data might not have been written, + // but file may look like it is the right size. + // To be extra careful, remove cached file. + os.Remove(name) + return err + } + os.Chtimes(name, c.now(), c.now()) // mainly for tests + + return nil +}
diff --git a/vendor/cmd/go/internal/cache/cache_test.go b/vendor/cmd/go/internal/cache/cache_test.go new file mode 100644 index 0000000..d3dafcc --- /dev/null +++ b/vendor/cmd/go/internal/cache/cache_test.go
@@ -0,0 +1,319 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cache + +import ( + "bytes" + "encoding/binary" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "testing" + "time" +) + +func init() { + verify = false // even if GODEBUG is set +} + +func TestBasic(t *testing.T) { + dir, err := ioutil.TempDir("", "cachetest-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + _, err = Open(filepath.Join(dir, "notexist")) + if err == nil { + t.Fatal(`Open("tmp/notexist") succeeded, want failure`) + } + + cdir := filepath.Join(dir, "c1") + if err := os.Mkdir(cdir, 0777); err != nil { + t.Fatal(err) + } + + c1, err := Open(cdir) + if err != nil { + t.Fatalf("Open(c1) (create): %v", err) + } + if err := c1.putIndexEntry(dummyID(1), dummyID(12), 13, true); err != nil { + t.Fatalf("addIndexEntry: %v", err) + } + if err := c1.putIndexEntry(dummyID(1), dummyID(2), 3, true); err != nil { // overwrite entry + t.Fatalf("addIndexEntry: %v", err) + } + if entry, err := c1.Get(dummyID(1)); err != nil || entry.OutputID != dummyID(2) || entry.Size != 3 { + t.Fatalf("c1.Get(1) = %x, %v, %v, want %x, %v, nil", entry.OutputID, entry.Size, err, dummyID(2), 3) + } + + c2, err := Open(cdir) + if err != nil { + t.Fatalf("Open(c2) (reuse): %v", err) + } + if entry, err := c2.Get(dummyID(1)); err != nil || entry.OutputID != dummyID(2) || entry.Size != 3 { + t.Fatalf("c2.Get(1) = %x, %v, %v, want %x, %v, nil", entry.OutputID, entry.Size, err, dummyID(2), 3) + } + if err := c2.putIndexEntry(dummyID(2), dummyID(3), 4, true); err != nil { + t.Fatalf("addIndexEntry: %v", err) + } + if entry, err := c1.Get(dummyID(2)); err != nil || entry.OutputID != dummyID(3) || entry.Size != 4 { + t.Fatalf("c1.Get(2) = %x, %v, %v, want %x, %v, nil", entry.OutputID, entry.Size, err, dummyID(3), 4) + } +} + +func TestGrowth(t *testing.T) { + dir, err := ioutil.TempDir("", "cachetest-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + c, err := Open(dir) + if err != nil { + t.Fatalf("Open: %v", err) + } + + n := 10000 + if testing.Short() { + n = 1000 + } + + for i := 0; i < n; i++ { + if err := c.putIndexEntry(dummyID(i), dummyID(i*99), int64(i)*101, true); err != nil { + t.Fatalf("addIndexEntry: %v", err) + } + id := ActionID(dummyID(i)) + entry, err := c.Get(id) + if err != nil { + t.Fatalf("Get(%x): %v", id, err) + } + if entry.OutputID != dummyID(i*99) || entry.Size != int64(i)*101 { + t.Errorf("Get(%x) = %x, %d, want %x, %d", id, entry.OutputID, entry.Size, dummyID(i*99), int64(i)*101) + } + } + for i := 0; i < n; i++ { + id := ActionID(dummyID(i)) + entry, err := c.Get(id) + if err != nil { + t.Fatalf("Get2(%x): %v", id, err) + } + if entry.OutputID != dummyID(i*99) || entry.Size != int64(i)*101 { + t.Errorf("Get2(%x) = %x, %d, want %x, %d", id, entry.OutputID, entry.Size, dummyID(i*99), int64(i)*101) + } + } +} + +func TestVerifyPanic(t *testing.T) { + os.Setenv("GODEBUG", "gocacheverify=1") + initEnv() + defer func() { + os.Unsetenv("GODEBUG") + verify = false + }() + + if !verify { + t.Fatal("initEnv did not set verify") + } + + dir, err := ioutil.TempDir("", "cachetest-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + c, err := Open(dir) + if err != nil { + t.Fatalf("Open: %v", err) + } + + id := ActionID(dummyID(1)) + if err := c.PutBytes(id, []byte("abc")); err != nil { + t.Fatal(err) + } + + defer func() { + if err := recover(); err != nil { + t.Log(err) + return + } + }() + c.PutBytes(id, []byte("def")) + t.Fatal("mismatched Put did not panic in verify mode") +} + +func TestCacheLog(t *testing.T) { + dir, err := ioutil.TempDir("", "cachetest-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + c, err := Open(dir) + if err != nil { + t.Fatalf("Open: %v", err) + } + c.now = func() time.Time { return time.Unix(1e9, 0) } + + id := ActionID(dummyID(1)) + c.Get(id) + c.PutBytes(id, []byte("abc")) + c.Get(id) + + c, err = Open(dir) + if err != nil { + t.Fatalf("Open #2: %v", err) + } + c.now = func() time.Time { return time.Unix(1e9+1, 0) } + c.Get(id) + + id2 := ActionID(dummyID(2)) + c.Get(id2) + c.PutBytes(id2, []byte("abc")) + c.Get(id2) + c.Get(id) + + data, err := ioutil.ReadFile(filepath.Join(dir, "log.txt")) + if err != nil { + t.Fatal(err) + } + want := `1000000000 miss 0100000000000000000000000000000000000000000000000000000000000000 +1000000000 put 0100000000000000000000000000000000000000000000000000000000000000 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad 3 +1000000000 get 0100000000000000000000000000000000000000000000000000000000000000 +1000000001 get 0100000000000000000000000000000000000000000000000000000000000000 +1000000001 miss 0200000000000000000000000000000000000000000000000000000000000000 +1000000001 put 0200000000000000000000000000000000000000000000000000000000000000 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad 3 +1000000001 get 0200000000000000000000000000000000000000000000000000000000000000 +1000000001 get 0100000000000000000000000000000000000000000000000000000000000000 +` + if string(data) != want { + t.Fatalf("log:\n%s\nwant:\n%s", string(data), want) + } +} + +func dummyID(x int) [HashSize]byte { + var out [HashSize]byte + binary.LittleEndian.PutUint64(out[:], uint64(x)) + return out +} + +func TestCacheTrim(t *testing.T) { + dir, err := ioutil.TempDir("", "cachetest-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + c, err := Open(dir) + if err != nil { + t.Fatalf("Open: %v", err) + } + const start = 1000000000 + now := int64(start) + c.now = func() time.Time { return time.Unix(now, 0) } + + checkTime := func(name string, mtime int64) { + t.Helper() + file := filepath.Join(c.dir, name[:2], name) + info, err := os.Stat(file) + if err != nil { + t.Fatal(err) + } + if info.ModTime().Unix() != mtime { + t.Fatalf("%s mtime = %d, want %d", name, info.ModTime().Unix(), mtime) + } + } + + id := ActionID(dummyID(1)) + c.PutBytes(id, []byte("abc")) + entry, _ := c.Get(id) + c.PutBytes(ActionID(dummyID(2)), []byte("def")) + mtime := now + checkTime(fmt.Sprintf("%x-a", id), mtime) + checkTime(fmt.Sprintf("%x-d", entry.OutputID), mtime) + + // Get should not change recent mtimes. + now = start + 10 + c.Get(id) + checkTime(fmt.Sprintf("%x-a", id), mtime) + checkTime(fmt.Sprintf("%x-d", entry.OutputID), mtime) + + // Get should change distant mtimes. + now = start + 5000 + mtime2 := now + if _, err := c.Get(id); err != nil { + t.Fatal(err) + } + c.OutputFile(entry.OutputID) + checkTime(fmt.Sprintf("%x-a", id), mtime2) + checkTime(fmt.Sprintf("%x-d", entry.OutputID), mtime2) + + // Trim should leave everything alone: it's all too new. + c.Trim() + if _, err := c.Get(id); err != nil { + t.Fatal(err) + } + c.OutputFile(entry.OutputID) + data, err := ioutil.ReadFile(filepath.Join(dir, "trim.txt")) + if err != nil { + t.Fatal(err) + } + checkTime(fmt.Sprintf("%x-a", dummyID(2)), start) + + // Trim less than a day later should not do any work at all. + now = start + 80000 + c.Trim() + if _, err := c.Get(id); err != nil { + t.Fatal(err) + } + c.OutputFile(entry.OutputID) + data2, err := ioutil.ReadFile(filepath.Join(dir, "trim.txt")) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(data, data2) { + t.Fatalf("second trim did work: %q -> %q", data, data2) + } + + // Fast forward and do another trim just before the 5 day cutoff. + // Note that because of usedQuantum the cutoff is actually 5 days + 1 hour. + // We used c.Get(id) just now, so 5 days later it should still be kept. + // On the other hand almost a full day has gone by since we wrote dummyID(2) + // and we haven't looked at it since, so 5 days later it should be gone. + now += 5 * 86400 + checkTime(fmt.Sprintf("%x-a", dummyID(2)), start) + c.Trim() + if _, err := c.Get(id); err != nil { + t.Fatal(err) + } + c.OutputFile(entry.OutputID) + mtime3 := now + if _, err := c.Get(dummyID(2)); err == nil { // haven't done a Get for this since original write above + t.Fatalf("Trim did not remove dummyID(2)") + } + + // The c.Get(id) refreshed id's mtime again. + // Check that another 5 days later it is still not gone, + // but check by using checkTime, which doesn't bring mtime forward. + now += 5 * 86400 + c.Trim() + checkTime(fmt.Sprintf("%x-a", id), mtime3) + checkTime(fmt.Sprintf("%x-d", entry.OutputID), mtime3) + + // Half a day later Trim should still be a no-op, because there was a Trim recently. + // Even though the entry for id is now old enough to be trimmed, + // it gets a reprieve until the time comes for a new Trim scan. + now += 86400 / 2 + c.Trim() + checkTime(fmt.Sprintf("%x-a", id), mtime3) + checkTime(fmt.Sprintf("%x-d", entry.OutputID), mtime3) + + // Another half a day later, Trim should actually run, and it should remove id. + now += 86400/2 + 1 + c.Trim() + if _, err := c.Get(dummyID(1)); err == nil { + t.Fatal("Trim did not remove dummyID(1)") + } +}
diff --git a/vendor/cmd/go/internal/cache/default.go b/vendor/cmd/go/internal/cache/default.go new file mode 100644 index 0000000..9728376 --- /dev/null +++ b/vendor/cmd/go/internal/cache/default.go
@@ -0,0 +1,110 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cache + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "runtime" + "sync" +) + +// Default returns the default cache to use, or nil if no cache should be used. +func Default() *Cache { + defaultOnce.Do(initDefaultCache) + return defaultCache +} + +var ( + defaultOnce sync.Once + defaultCache *Cache +) + +// cacheREADME is a message stored in a README in the cache directory. +// Because the cache lives outside the normal Go trees, we leave the +// README as a courtesy to explain where it came from. +const cacheREADME = `This directory holds cached build artifacts from the Go build system. +Run "go clean -cache" if the directory is getting too large. +See golang.org to learn more about Go. +` + +// initDefaultCache does the work of finding the default cache +// the first time Default is called. +func initDefaultCache() { + dir := DefaultDir() + if dir == "off" { + return + } + if err := os.MkdirAll(dir, 0777); err != nil { + fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err) + return + } + if _, err := os.Stat(filepath.Join(dir, "README")); err != nil { + // Best effort. + ioutil.WriteFile(filepath.Join(dir, "README"), []byte(cacheREADME), 0666) + } + + c, err := Open(dir) + if err != nil { + fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err) + return + } + defaultCache = c +} + +// DefaultDir returns the effective GOCACHE setting. +// It returns "off" if the cache is disabled. +func DefaultDir() string { + dir := os.Getenv("GOCACHE") + if dir != "" { + return dir + } + + // Compute default location. + // TODO(rsc): This code belongs somewhere else, + // like maybe ioutil.CacheDir or os.CacheDir. + switch runtime.GOOS { + case "windows": + dir = os.Getenv("LocalAppData") + if dir == "" { + // Fall back to %AppData%, the old name of + // %LocalAppData% on Windows XP. + dir = os.Getenv("AppData") + } + if dir == "" { + return "off" + } + + case "darwin": + dir = os.Getenv("HOME") + if dir == "" { + return "off" + } + dir += "/Library/Caches" + + case "plan9": + dir = os.Getenv("home") + if dir == "" { + return "off" + } + // Plan 9 has no established per-user cache directory, + // but $home/lib/xyz is the usual equivalent of $HOME/.xyz on Unix. + dir += "/lib/cache" + + default: // Unix + // https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + dir = os.Getenv("XDG_CACHE_HOME") + if dir == "" { + dir = os.Getenv("HOME") + if dir == "" { + return "off" + } + dir += "/.cache" + } + } + return filepath.Join(dir, "go-build") +}
diff --git a/vendor/cmd/go/internal/cache/hash.go b/vendor/cmd/go/internal/cache/hash.go new file mode 100644 index 0000000..0e45e7d --- /dev/null +++ b/vendor/cmd/go/internal/cache/hash.go
@@ -0,0 +1,174 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cache + +import ( + "bytes" + "crypto/sha256" + "fmt" + "hash" + "io" + "os" + "runtime" + "sync" +) + +var debugHash = false // set when GODEBUG=gocachehash=1 + +// HashSize is the number of bytes in a hash. +const HashSize = 32 + +// A Hash provides access to the canonical hash function used to index the cache. +// The current implementation uses salted SHA256, but clients must not assume this. +type Hash struct { + h hash.Hash + name string // for debugging + buf *bytes.Buffer // for verify +} + +// hashSalt is a salt string added to the beginning of every hash +// created by NewHash. Using the Go version makes sure that different +// versions of the go command (or even different Git commits during +// work on the development branch) do not address the same cache +// entries, so that a bug in one version does not affect the execution +// of other versions. This salt will result in additional ActionID files +// in the cache, but not additional copies of the large output files, +// which are still addressed by unsalted SHA256. +var hashSalt = []byte(runtime.Version()) + +// Subkey returns an action ID corresponding to mixing a parent +// action ID with a string description of the subkey. +func Subkey(parent ActionID, desc string) ActionID { + h := sha256.New() + h.Write([]byte("subkey:")) + h.Write(parent[:]) + h.Write([]byte(desc)) + var out ActionID + h.Sum(out[:0]) + if debugHash { + fmt.Fprintf(os.Stderr, "HASH subkey %x %q = %x\n", parent, desc, out) + } + if verify { + hashDebug.Lock() + hashDebug.m[out] = fmt.Sprintf("subkey %x %q", parent, desc) + hashDebug.Unlock() + } + return out +} + +// NewHash returns a new Hash. +// The caller is expected to Write data to it and then call Sum. +func NewHash(name string) *Hash { + h := &Hash{h: sha256.New(), name: name} + if debugHash { + fmt.Fprintf(os.Stderr, "HASH[%s]\n", h.name) + } + h.Write(hashSalt) + if verify { + h.buf = new(bytes.Buffer) + } + return h +} + +// Write writes data to the running hash. +func (h *Hash) Write(b []byte) (int, error) { + if debugHash { + fmt.Fprintf(os.Stderr, "HASH[%s]: %q\n", h.name, b) + } + if h.buf != nil { + h.buf.Write(b) + } + return h.h.Write(b) +} + +// Sum returns the hash of the data written previously. +func (h *Hash) Sum() [HashSize]byte { + var out [HashSize]byte + h.h.Sum(out[:0]) + if debugHash { + fmt.Fprintf(os.Stderr, "HASH[%s]: %x\n", h.name, out) + } + if h.buf != nil { + hashDebug.Lock() + if hashDebug.m == nil { + hashDebug.m = make(map[[HashSize]byte]string) + } + hashDebug.m[out] = h.buf.String() + hashDebug.Unlock() + } + return out +} + +// In GODEBUG=gocacheverify=1 mode, +// hashDebug holds the input to every computed hash ID, +// so that we can work backward from the ID involved in a +// cache entry mismatch to a description of what should be there. +var hashDebug struct { + sync.Mutex + m map[[HashSize]byte]string +} + +// reverseHash returns the input used to compute the hash id. +func reverseHash(id [HashSize]byte) string { + hashDebug.Lock() + s := hashDebug.m[id] + hashDebug.Unlock() + return s +} + +var hashFileCache struct { + sync.Mutex + m map[string][HashSize]byte +} + +// HashFile returns the hash of the named file. +// It caches repeated lookups for a given file, +// and the cache entry for a file can be initialized +// using SetFileHash. +// The hash used by FileHash is not the same as +// the hash used by NewHash. +func FileHash(file string) ([HashSize]byte, error) { + hashFileCache.Lock() + out, ok := hashFileCache.m[file] + hashFileCache.Unlock() + + if ok { + return out, nil + } + + h := sha256.New() + f, err := os.Open(file) + if err != nil { + if debugHash { + fmt.Fprintf(os.Stderr, "HASH %s: %v\n", file, err) + } + return [HashSize]byte{}, err + } + _, err = io.Copy(h, f) + f.Close() + if err != nil { + if debugHash { + fmt.Fprintf(os.Stderr, "HASH %s: %v\n", file, err) + } + return [HashSize]byte{}, err + } + h.Sum(out[:0]) + if debugHash { + fmt.Fprintf(os.Stderr, "HASH %s: %x\n", file, out) + } + + SetFileHash(file, out) + return out, nil +} + +// SetFileHash sets the hash returned by FileHash for file. +func SetFileHash(file string, sum [HashSize]byte) { + hashFileCache.Lock() + if hashFileCache.m == nil { + hashFileCache.m = make(map[string][HashSize]byte) + } + hashFileCache.m[file] = sum + hashFileCache.Unlock() +}
diff --git a/vendor/cmd/go/internal/cache/hash_test.go b/vendor/cmd/go/internal/cache/hash_test.go new file mode 100644 index 0000000..3bf7143 --- /dev/null +++ b/vendor/cmd/go/internal/cache/hash_test.go
@@ -0,0 +1,52 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cache + +import ( + "fmt" + "io/ioutil" + "os" + "testing" +) + +func TestHash(t *testing.T) { + oldSalt := hashSalt + hashSalt = nil + defer func() { + hashSalt = oldSalt + }() + + h := NewHash("alice") + h.Write([]byte("hello world")) + sum := fmt.Sprintf("%x", h.Sum()) + want := "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9" + if sum != want { + t.Errorf("hash(hello world) = %v, want %v", sum, want) + } +} + +func TestHashFile(t *testing.T) { + f, err := ioutil.TempFile("", "cmd-go-test-") + if err != nil { + t.Fatal(err) + } + name := f.Name() + fmt.Fprintf(f, "hello world") + defer os.Remove(name) + if err := f.Close(); err != nil { + t.Fatal(err) + } + + var h ActionID // make sure hash result is assignable to ActionID + h, err = FileHash(name) + if err != nil { + t.Fatal(err) + } + sum := fmt.Sprintf("%x", h) + want := "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9" + if sum != want { + t.Errorf("hash(hello world) = %v, want %v", sum, want) + } +}
diff --git a/vendor/cmd/go/internal/cfg/cfg.go b/vendor/cmd/go/internal/cfg/cfg.go new file mode 100644 index 0000000..c9039b6 --- /dev/null +++ b/vendor/cmd/go/internal/cfg/cfg.go
@@ -0,0 +1,183 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cfg holds configuration shared by multiple parts +// of the go command. +package cfg + +import ( + "bytes" + "fmt" + "go/build" + "io/ioutil" + "os" + "path/filepath" + "runtime" +) + +// These are general "build flags" used by build and other commands. +var ( + BuildA bool // -a flag + BuildBuildmode string // -buildmode flag + BuildContext = build.Default + BuildI bool // -i flag + BuildLinkshared bool // -linkshared flag + BuildMSan bool // -msan flag + BuildN bool // -n flag + BuildO string // -o flag + BuildP = runtime.NumCPU() // -p flag + BuildPkgdir string // -pkgdir flag + BuildRace bool // -race flag + BuildToolexec []string // -toolexec flag + BuildToolchainName string + BuildToolchainCompiler func() string + BuildToolchainLinker func() string + BuildV bool // -v flag + BuildWork bool // -work flag + BuildX bool // -x flag + + CmdName string // "build", "install", "list", etc. + + DebugActiongraph string // -debug-actiongraph flag (undocumented, unstable) +) + +func init() { + BuildToolchainCompiler = func() string { return "missing-compiler" } + BuildToolchainLinker = func() string { return "missing-linker" } +} + +// An EnvVar is an environment variable Name=Value. +type EnvVar struct { + Name string + Value string +} + +// OrigEnv is the original environment of the program at startup. +var OrigEnv []string + +// CmdEnv is the new environment for running go tool commands. +// User binaries (during go test or go run) are run with OrigEnv, +// not CmdEnv. +var CmdEnv []EnvVar + +// Global build parameters (used during package load) +var ( + Goarch = BuildContext.GOARCH + Goos = BuildContext.GOOS + ExeSuffix string + Gopath = filepath.SplitList(BuildContext.GOPATH) +) + +func init() { + if Goos == "windows" { + ExeSuffix = ".exe" + } +} + +var ( + GOROOT = findGOROOT() + GOBIN = os.Getenv("GOBIN") + GOROOTbin = filepath.Join(GOROOT, "bin") + GOROOTpkg = filepath.Join(GOROOT, "pkg") + GOROOTsrc = filepath.Join(GOROOT, "src") + GOROOT_FINAL = findGOROOT_FINAL() + + // Used in envcmd.MkEnv and build ID computations. + GOARM, GO386, GOMIPS = objabi() +) + +// Update build context to use our computed GOROOT. +func init() { + BuildContext.GOROOT = GOROOT + // Note that we must use runtime.GOOS and runtime.GOARCH here, + // as the tool directory does not move based on environment variables. + // This matches the initialization of ToolDir in go/build, + // except for using GOROOT rather than runtime.GOROOT(). + build.ToolDir = filepath.Join(GOROOT, "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH) +} + +func objabi() (GOARM, GO386, GOMIPS string) { + data, err := ioutil.ReadFile(filepath.Join(GOROOT, "src/cmd/internal/objabi/zbootstrap.go")) + if err != nil { + fmt.Fprintf(os.Stderr, "vgo objabi: %v\n", err) + } + + find := func(key string) string { + if env := os.Getenv(key); env != "" { + return env + } + i := bytes.Index(data, []byte("default"+key+" = `")) + if i < 0 { + fmt.Fprintf(os.Stderr, "vgo objabi: cannot find %s\n", key) + os.Exit(2) + } + line := data[i:] + line = line[bytes.IndexByte(line, '`')+1:] + return string(line[:bytes.IndexByte(line, '`')]) + } + + return find("GOARM"), find("GO386"), find("GOMIPS") +} + +func findGOROOT() string { + if env := os.Getenv("GOROOT"); env != "" { + return filepath.Clean(env) + } + def := filepath.Clean(runtime.GOROOT()) + exe, err := os.Executable() + if err == nil { + exe, err = filepath.Abs(exe) + if err == nil { + if dir := filepath.Join(exe, "../.."); isGOROOT(dir) { + // If def (runtime.GOROOT()) and dir are the same + // directory, prefer the spelling used in def. + if isSameDir(def, dir) { + return def + } + return dir + } + exe, err = filepath.EvalSymlinks(exe) + if err == nil { + if dir := filepath.Join(exe, "../.."); isGOROOT(dir) { + if isSameDir(def, dir) { + return def + } + return dir + } + } + } + } + return def +} + +func findGOROOT_FINAL() string { + def := GOROOT + if env := os.Getenv("GOROOT_FINAL"); env != "" { + def = filepath.Clean(env) + } + return def +} + +// isSameDir reports whether dir1 and dir2 are the same directory. +func isSameDir(dir1, dir2 string) bool { + if dir1 == dir2 { + return true + } + info1, err1 := os.Stat(dir1) + info2, err2 := os.Stat(dir2) + return err1 == nil && err2 == nil && os.SameFile(info1, info2) +} + +// isGOROOT reports whether path looks like a GOROOT. +// +// It does this by looking for the path/pkg/tool directory, +// which is necessary for useful operation of the cmd/go tool, +// and is not typically present in a GOPATH. +func isGOROOT(path string) bool { + stat, err := os.Stat(filepath.Join(path, "pkg", "tool")) + if err != nil { + return false + } + return stat.IsDir() +}
diff --git a/vendor/cmd/go/internal/cfg/zdefaultcc.go b/vendor/cmd/go/internal/cfg/zdefaultcc.go new file mode 100644 index 0000000..28761b7 --- /dev/null +++ b/vendor/cmd/go/internal/cfg/zdefaultcc.go
@@ -0,0 +1,15 @@ +// Code generated by go tool dist; DO NOT EDIT. + +package cfg + +const DefaultPkgConfig = `pkg-config` +func DefaultCC(goos, goarch string) string { + switch goos+`/`+goarch { + } + return "clang" +} +func DefaultCXX(goos, goarch string) string { + switch goos+`/`+goarch { + } + return "clang++" +}
diff --git a/vendor/cmd/go/internal/cfg/zosarch.go b/vendor/cmd/go/internal/cfg/zosarch.go new file mode 100644 index 0000000..b7cfc7b --- /dev/null +++ b/vendor/cmd/go/internal/cfg/zosarch.go
@@ -0,0 +1,44 @@ +// Code generated by go tool dist; DO NOT EDIT. + +package cfg + +var OSArchSupportsCgo = map[string]bool{ + "android/386": true, + "android/amd64": true, + "android/arm": true, + "android/arm64": true, + "darwin/386": true, + "darwin/amd64": true, + "darwin/arm": true, + "darwin/arm64": true, + "dragonfly/amd64": true, + "freebsd/386": true, + "freebsd/amd64": true, + "freebsd/arm": false, + "linux/386": true, + "linux/amd64": true, + "linux/arm": true, + "linux/arm64": true, + "linux/mips": true, + "linux/mips64": true, + "linux/mips64le": true, + "linux/mipsle": true, + "linux/ppc64": false, + "linux/ppc64le": true, + "linux/s390x": true, + "nacl/386": false, + "nacl/amd64p32": false, + "nacl/arm": false, + "netbsd/386": true, + "netbsd/amd64": true, + "netbsd/arm": true, + "openbsd/386": true, + "openbsd/amd64": true, + "openbsd/arm": false, + "plan9/386": false, + "plan9/amd64": false, + "plan9/arm": false, + "solaris/amd64": true, + "windows/386": true, + "windows/amd64": true, +}
diff --git a/vendor/cmd/go/internal/clean/clean.go b/vendor/cmd/go/internal/clean/clean.go new file mode 100644 index 0000000..fa5af94 --- /dev/null +++ b/vendor/cmd/go/internal/clean/clean.go
@@ -0,0 +1,308 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package clean implements the ``go clean'' command. +package clean + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" + + "cmd/go/internal/base" + "cmd/go/internal/cache" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/go/internal/work" +) + +var CmdClean = &base.Command{ + UsageLine: "clean [-i] [-r] [-n] [-x] [-cache] [-testcache] [build flags] [packages]", + Short: "remove object files and cached files", + Long: ` +Clean removes object files from package source directories. +The go command builds most objects in a temporary directory, +so go clean is mainly concerned with object files left by other +tools or by manual invocations of go build. + +Specifically, clean removes the following files from each of the +source directories corresponding to the import paths: + + _obj/ old object directory, left from Makefiles + _test/ old test directory, left from Makefiles + _testmain.go old gotest file, left from Makefiles + test.out old test log, left from Makefiles + build.out old test log, left from Makefiles + *.[568ao] object files, left from Makefiles + + DIR(.exe) from go build + DIR.test(.exe) from go test -c + MAINFILE(.exe) from go build MAINFILE.go + *.so from SWIG + +In the list, DIR represents the final path element of the +directory, and MAINFILE is the base name of any Go source +file in the directory that is not included when building +the package. + +The -i flag causes clean to remove the corresponding installed +archive or binary (what 'go install' would create). + +The -n flag causes clean to print the remove commands it would execute, +but not run them. + +The -r flag causes clean to be applied recursively to all the +dependencies of the packages named by the import paths. + +The -x flag causes clean to print remove commands as it executes them. + +The -cache flag causes clean to remove the entire go build cache. + +The -testcache flag causes clean to expire all test results in the +go build cache. + +For more about build flags, see 'go help build'. + +For more about specifying packages, see 'go help packages'. + `, +} + +var ( + cleanI bool // clean -i flag + cleanR bool // clean -r flag + cleanCache bool // clean -cache flag + cleanTestcache bool // clean -testcache flag +) + +func init() { + // break init cycle + CmdClean.Run = runClean + + CmdClean.Flag.BoolVar(&cleanI, "i", false, "") + CmdClean.Flag.BoolVar(&cleanR, "r", false, "") + CmdClean.Flag.BoolVar(&cleanCache, "cache", false, "") + CmdClean.Flag.BoolVar(&cleanTestcache, "testcache", false, "") + + // -n and -x are important enough to be + // mentioned explicitly in the docs but they + // are part of the build flags. + + work.AddBuildFlags(CmdClean) +} + +func runClean(cmd *base.Command, args []string) { + for _, pkg := range load.PackagesAndErrors(args) { + clean(pkg) + } + + if cleanCache { + var b work.Builder + b.Print = fmt.Print + dir := cache.DefaultDir() + if dir != "off" { + // Remove the cache subdirectories but not the top cache directory. + // The top cache directory may have been created with special permissions + // and not something that we want to remove. Also, we'd like to preserve + // the access log for future analysis, even if the cache is cleared. + subdirs, _ := filepath.Glob(filepath.Join(dir, "[0-9a-f][0-9a-f]")) + if len(subdirs) > 0 { + if cfg.BuildN || cfg.BuildX { + b.Showcmd("", "rm -r %s", strings.Join(subdirs, " ")) + } + printedErrors := false + for _, d := range subdirs { + // Only print the first error - there may be many. + // This also mimics what os.RemoveAll(dir) would do. + if err := os.RemoveAll(d); err != nil && !printedErrors { + printedErrors = true + base.Errorf("go clean -cache: %v", err) + } + } + } + } + } + + if cleanTestcache && !cleanCache { + // Instead of walking through the entire cache looking for test results, + // we write a file to the cache indicating that all test results from before + // right now are to be ignored. + dir := cache.DefaultDir() + if dir != "off" { + err := ioutil.WriteFile(filepath.Join(dir, "testexpire.txt"), []byte(fmt.Sprintf("%d\n", time.Now().UnixNano())), 0666) + if err != nil { + base.Errorf("go clean -testcache: %v", err) + } + } + } +} + +var cleaned = map[*load.Package]bool{} + +// TODO: These are dregs left by Makefile-based builds. +// Eventually, can stop deleting these. +var cleanDir = map[string]bool{ + "_test": true, + "_obj": true, +} + +var cleanFile = map[string]bool{ + "_testmain.go": true, + "test.out": true, + "build.out": true, + "a.out": true, +} + +var cleanExt = map[string]bool{ + ".5": true, + ".6": true, + ".8": true, + ".a": true, + ".o": true, + ".so": true, +} + +func clean(p *load.Package) { + if cleaned[p] { + return + } + cleaned[p] = true + + if p.Dir == "" { + base.Errorf("can't load package: %v", p.Error) + return + } + dirs, err := ioutil.ReadDir(p.Dir) + if err != nil { + base.Errorf("go clean %s: %v", p.Dir, err) + return + } + + var b work.Builder + b.Print = fmt.Print + + packageFile := map[string]bool{} + if p.Name != "main" { + // Record which files are not in package main. + // The others are. + keep := func(list []string) { + for _, f := range list { + packageFile[f] = true + } + } + keep(p.GoFiles) + keep(p.CgoFiles) + keep(p.TestGoFiles) + keep(p.XTestGoFiles) + } + + _, elem := filepath.Split(p.Dir) + var allRemove []string + + // Remove dir-named executable only if this is package main. + if p.Name == "main" { + allRemove = append(allRemove, + elem, + elem+".exe", + ) + } + + // Remove package test executables. + allRemove = append(allRemove, + elem+".test", + elem+".test.exe", + ) + + // Remove a potential executable for each .go file in the directory that + // is not part of the directory's package. + for _, dir := range dirs { + name := dir.Name() + if packageFile[name] { + continue + } + if !dir.IsDir() && strings.HasSuffix(name, ".go") { + // TODO(adg,rsc): check that this .go file is actually + // in "package main", and therefore capable of building + // to an executable file. + base := name[:len(name)-len(".go")] + allRemove = append(allRemove, base, base+".exe") + } + } + + if cfg.BuildN || cfg.BuildX { + b.Showcmd(p.Dir, "rm -f %s", strings.Join(allRemove, " ")) + } + + toRemove := map[string]bool{} + for _, name := range allRemove { + toRemove[name] = true + } + for _, dir := range dirs { + name := dir.Name() + if dir.IsDir() { + // TODO: Remove once Makefiles are forgotten. + if cleanDir[name] { + if cfg.BuildN || cfg.BuildX { + b.Showcmd(p.Dir, "rm -r %s", name) + if cfg.BuildN { + continue + } + } + if err := os.RemoveAll(filepath.Join(p.Dir, name)); err != nil { + base.Errorf("go clean: %v", err) + } + } + continue + } + + if cfg.BuildN { + continue + } + + if cleanFile[name] || cleanExt[filepath.Ext(name)] || toRemove[name] { + removeFile(filepath.Join(p.Dir, name)) + } + } + + if cleanI && p.Target != "" { + if cfg.BuildN || cfg.BuildX { + b.Showcmd("", "rm -f %s", p.Target) + } + if !cfg.BuildN { + removeFile(p.Target) + } + } + + if cleanR { + for _, p1 := range p.Internal.Imports { + clean(p1) + } + } +} + +// removeFile tries to remove file f, if error other than file doesn't exist +// occurs, it will report the error. +func removeFile(f string) { + err := os.Remove(f) + if err == nil || os.IsNotExist(err) { + return + } + // Windows does not allow deletion of a binary file while it is executing. + if base.ToolIsWindows { + // Remove lingering ~ file from last attempt. + if _, err2 := os.Stat(f + "~"); err2 == nil { + os.Remove(f + "~") + } + // Try to move it out of the way. If the move fails, + // which is likely, we'll try again the + // next time we do an install of this binary. + if err2 := os.Rename(f, f+"~"); err2 == nil { + os.Remove(f + "~") + return + } + } + base.Errorf("go clean: %v", err) +}
diff --git a/vendor/cmd/go/internal/cmdflag/flag.go b/vendor/cmd/go/internal/cmdflag/flag.go new file mode 100644 index 0000000..7ab3022 --- /dev/null +++ b/vendor/cmd/go/internal/cmdflag/flag.go
@@ -0,0 +1,123 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cmdflag handles flag processing common to several go tools. +package cmdflag + +import ( + "flag" + "fmt" + "os" + "strconv" + "strings" + + "cmd/go/internal/base" +) + +// The flag handling part of go commands such as test is large and distracting. +// We can't use the standard flag package because some of the flags from +// our command line are for us, and some are for the binary we're running, +// and some are for both. + +// Defn defines a flag we know about. +type Defn struct { + Name string // Name on command line. + BoolVar *bool // If it's a boolean flag, this points to it. + Value flag.Value // The flag.Value represented. + PassToTest bool // Pass to the test binary? Used only by go test. + Present bool // Flag has been seen. +} + +// IsBool reports whether v is a bool flag. +func IsBool(v flag.Value) bool { + vv, ok := v.(interface { + IsBoolFlag() bool + }) + if ok { + return vv.IsBoolFlag() + } + return false +} + +// SetBool sets the addressed boolean to the value. +func SetBool(cmd string, flag *bool, value string) { + x, err := strconv.ParseBool(value) + if err != nil { + SyntaxError(cmd, "illegal bool flag value "+value) + } + *flag = x +} + +// SetInt sets the addressed integer to the value. +func SetInt(cmd string, flag *int, value string) { + x, err := strconv.Atoi(value) + if err != nil { + SyntaxError(cmd, "illegal int flag value "+value) + } + *flag = x +} + +// SyntaxError reports an argument syntax error and exits the program. +func SyntaxError(cmd, msg string) { + fmt.Fprintf(os.Stderr, "go %s: %s\n", cmd, msg) + if cmd == "test" { + fmt.Fprintf(os.Stderr, `run "go help %s" or "go help testflag" for more information`+"\n", cmd) + } else { + fmt.Fprintf(os.Stderr, `run "go help %s" for more information`+"\n", cmd) + } + os.Exit(2) +} + +// Parse sees if argument i is present in the definitions and if so, +// returns its definition, value, and whether it consumed an extra word. +// If the flag begins (cmd+".") it is ignored for the purpose of this function. +func Parse(cmd string, defns []*Defn, args []string, i int) (f *Defn, value string, extra bool) { + arg := args[i] + if strings.HasPrefix(arg, "--") { // reduce two minuses to one + arg = arg[1:] + } + switch arg { + case "-?", "-h", "-help": + base.Usage() + } + if arg == "" || arg[0] != '-' { + return + } + name := arg[1:] + // If there's already a prefix such as "test.", drop it for now. + name = strings.TrimPrefix(name, cmd+".") + equals := strings.Index(name, "=") + if equals >= 0 { + value = name[equals+1:] + name = name[:equals] + } + for _, f = range defns { + if name == f.Name { + // Booleans are special because they have modes -x, -x=true, -x=false. + if f.BoolVar != nil || IsBool(f.Value) { + if equals < 0 { // Otherwise, it's been set and will be verified in SetBool. + value = "true" + } else { + // verify it parses + SetBool(cmd, new(bool), value) + } + } else { // Non-booleans must have a value. + extra = equals < 0 + if extra { + if i+1 >= len(args) { + SyntaxError(cmd, "missing argument for flag "+f.Name) + } + value = args[i+1] + } + } + if f.Present { + SyntaxError(cmd, f.Name+" flag may be set only once") + } + f.Present = true + return + } + } + f = nil + return +}
diff --git a/vendor/cmd/go/internal/doc/doc.go b/vendor/cmd/go/internal/doc/doc.go new file mode 100644 index 0000000..d73dd9a --- /dev/null +++ b/vendor/cmd/go/internal/doc/doc.go
@@ -0,0 +1,123 @@ +// Copyright 2015 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 doc implements the ``go doc'' command. +package doc + +import ( + "cmd/go/internal/base" + "cmd/go/internal/cfg" +) + +var CmdDoc = &base.Command{ + Run: runDoc, + UsageLine: "doc [-u] [-c] [package|[package.]symbol[.methodOrField]]", + CustomFlags: true, + Short: "show documentation for package or symbol", + Long: ` +Doc prints the documentation comments associated with the item identified by its +arguments (a package, const, func, type, var, method, or struct field) +followed by a one-line summary of each of the first-level items "under" +that item (package-level declarations for a package, methods for a type, +etc.). + +Doc accepts zero, one, or two arguments. + +Given no arguments, that is, when run as + + go doc + +it prints the package documentation for the package in the current directory. +If the package is a command (package main), the exported symbols of the package +are elided from the presentation unless the -cmd flag is provided. + +When run with one argument, the argument is treated as a Go-syntax-like +representation of the item to be documented. What the argument selects depends +on what is installed in GOROOT and GOPATH, as well as the form of the argument, +which is schematically one of these: + + go doc <pkg> + go doc <sym>[.<methodOrField>] + go doc [<pkg>.]<sym>[.<methodOrField>] + go doc [<pkg>.][<sym>.]<methodOrField> + +The first item in this list matched by the argument is the one whose documentation +is printed. (See the examples below.) However, if the argument starts with a capital +letter it is assumed to identify a symbol or method in the current directory. + +For packages, the order of scanning is determined lexically in breadth-first order. +That is, the package presented is the one that matches the search and is nearest +the root and lexically first at its level of the hierarchy. The GOROOT tree is +always scanned in its entirety before GOPATH. + +If there is no package specified or matched, the package in the current +directory is selected, so "go doc Foo" shows the documentation for symbol Foo in +the current package. + +The package path must be either a qualified path or a proper suffix of a +path. The go tool's usual package mechanism does not apply: package path +elements like . and ... are not implemented by go doc. + +When run with two arguments, the first must be a full package path (not just a +suffix), and the second is a symbol, or symbol with method or struct field. +This is similar to the syntax accepted by godoc: + + go doc <pkg> <sym>[.<methodOrField>] + +In all forms, when matching symbols, lower-case letters in the argument match +either case but upper-case letters match exactly. This means that there may be +multiple matches of a lower-case argument in a package if different symbols have +different cases. If this occurs, documentation for all matches is printed. + +Examples: + go doc + Show documentation for current package. + go doc Foo + Show documentation for Foo in the current package. + (Foo starts with a capital letter so it cannot match + a package path.) + go doc encoding/json + Show documentation for the encoding/json package. + go doc json + Shorthand for encoding/json. + go doc json.Number (or go doc json.number) + Show documentation and method summary for json.Number. + go doc json.Number.Int64 (or go doc json.number.int64) + Show documentation for json.Number's Int64 method. + go doc cmd/doc + Show package docs for the doc command. + go doc -cmd cmd/doc + Show package docs and exported symbols within the doc command. + go doc template.new + Show documentation for html/template's New function. + (html/template is lexically before text/template) + go doc text/template.new # One argument + Show documentation for text/template's New function. + go doc text/template new # Two arguments + Show documentation for text/template's New function. + + At least in the current tree, these invocations all print the + documentation for json.Decoder's Decode method: + + go doc json.Decoder.Decode + go doc json.decoder.decode + go doc json.decode + cd go/src/encoding/json; go doc decode + +Flags: + -c + Respect case when matching symbols. + -cmd + Treat a command (package main) like a regular package. + Otherwise package main's exported symbols are hidden + when showing the package's top-level documentation. + -u + Show documentation for unexported as well as exported + symbols, methods, and fields. +`, +} + +func runDoc(cmd *base.Command, args []string) { + base.Run(cfg.BuildToolexec, base.Tool("doc"), args) +}
diff --git a/vendor/cmd/go/internal/envcmd/env.go b/vendor/cmd/go/internal/envcmd/env.go new file mode 100644 index 0000000..603f7b5 --- /dev/null +++ b/vendor/cmd/go/internal/envcmd/env.go
@@ -0,0 +1,221 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package envcmd implements the ``go env'' command. +package envcmd + +import ( + "encoding/json" + "fmt" + "os" + "runtime" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/cache" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/go/internal/work" +) + +var CmdEnv = &base.Command{ + UsageLine: "env [-json] [var ...]", + Short: "print Go environment information", + Long: ` +Env prints Go environment information. + +By default env prints information as a shell script +(on Windows, a batch file). If one or more variable +names is given as arguments, env prints the value of +each named variable on its own line. + +The -json flag prints the environment in JSON format +instead of as a shell script. + +For more about environment variables, see 'go help environment'. + `, +} + +func init() { + CmdEnv.Run = runEnv // break init cycle +} + +var envJson = CmdEnv.Flag.Bool("json", false, "") + +func MkEnv() []cfg.EnvVar { + var b work.Builder + b.Init() + + env := []cfg.EnvVar{ + {Name: "GOARCH", Value: cfg.Goarch}, + {Name: "GOBIN", Value: cfg.GOBIN}, + {Name: "GOCACHE", Value: cache.DefaultDir()}, + {Name: "GOEXE", Value: cfg.ExeSuffix}, + {Name: "GOHOSTARCH", Value: runtime.GOARCH}, + {Name: "GOHOSTOS", Value: runtime.GOOS}, + {Name: "GOOS", Value: cfg.Goos}, + {Name: "GOPATH", Value: cfg.BuildContext.GOPATH}, + {Name: "GORACE", Value: os.Getenv("GORACE")}, + {Name: "GOROOT", Value: cfg.GOROOT}, + {Name: "GOTMPDIR", Value: os.Getenv("GOTMPDIR")}, + {Name: "GOTOOLDIR", Value: base.ToolDir}, + + // disable escape codes in clang errors + {Name: "TERM", Value: "dumb"}, + } + + if work.GccgoBin != "" { + env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoBin}) + } else { + env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoName}) + } + + switch cfg.Goarch { + case "arm": + env = append(env, cfg.EnvVar{Name: "GOARM", Value: cfg.GOARM}) + case "386": + env = append(env, cfg.EnvVar{Name: "GO386", Value: cfg.GO386}) + case "mips", "mipsle": + env = append(env, cfg.EnvVar{Name: "GOMIPS", Value: cfg.GOMIPS}) + } + + cc := cfg.DefaultCC(cfg.Goos, cfg.Goarch) + if env := strings.Fields(os.Getenv("CC")); len(env) > 0 { + cc = env[0] + } + cxx := cfg.DefaultCXX(cfg.Goos, cfg.Goarch) + if env := strings.Fields(os.Getenv("CXX")); len(env) > 0 { + cxx = env[0] + } + env = append(env, cfg.EnvVar{Name: "CC", Value: cc}) + env = append(env, cfg.EnvVar{Name: "CXX", Value: cxx}) + + if cfg.BuildContext.CgoEnabled { + env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "1"}) + } else { + env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "0"}) + } + + return env +} + +func findEnv(env []cfg.EnvVar, name string) string { + for _, e := range env { + if e.Name == name { + return e.Value + } + } + return "" +} + +// ExtraEnvVars returns environment variables that should not leak into child processes. +func ExtraEnvVars() []cfg.EnvVar { + var b work.Builder + b.Init() + cppflags, cflags, cxxflags, fflags, ldflags, err := b.CFlags(&load.Package{}) + if err != nil { + // Should not happen - b.CFlags was given an empty package. + fmt.Fprintf(os.Stderr, "go: invalid cflags: %v\n", err) + return nil + } + cmd := b.GccCmd(".", "") + return []cfg.EnvVar{ + // Note: Update the switch in runEnv below when adding to this list. + {Name: "CGO_CFLAGS", Value: strings.Join(cflags, " ")}, + {Name: "CGO_CPPFLAGS", Value: strings.Join(cppflags, " ")}, + {Name: "CGO_CXXFLAGS", Value: strings.Join(cxxflags, " ")}, + {Name: "CGO_FFLAGS", Value: strings.Join(fflags, " ")}, + {Name: "CGO_LDFLAGS", Value: strings.Join(ldflags, " ")}, + {Name: "PKG_CONFIG", Value: b.PkgconfigCmd()}, + {Name: "GOGCCFLAGS", Value: strings.Join(cmd[3:], " ")}, + } +} + +func runEnv(cmd *base.Command, args []string) { + env := cfg.CmdEnv + + // Do we need to call ExtraEnvVars, which is a bit expensive? + // Only if we're listing all environment variables ("go env") + // or the variables being requested are in the extra list. + needExtra := true + if len(args) > 0 { + needExtra = false + for _, arg := range args { + switch arg { + case "CGO_CFLAGS", + "CGO_CPPFLAGS", + "CGO_CXXFLAGS", + "CGO_FFLAGS", + "CGO_LDFLAGS", + "PKG_CONFIG", + "GOGCCFLAGS": + needExtra = true + } + } + } + if needExtra { + env = append(env, ExtraEnvVars()...) + } + + if len(args) > 0 { + if *envJson { + var es []cfg.EnvVar + for _, name := range args { + e := cfg.EnvVar{Name: name, Value: findEnv(env, name)} + es = append(es, e) + } + printEnvAsJSON(es) + } else { + for _, name := range args { + fmt.Printf("%s\n", findEnv(env, name)) + } + } + return + } + + if *envJson { + printEnvAsJSON(env) + return + } + + for _, e := range env { + if e.Name != "TERM" { + switch runtime.GOOS { + default: + fmt.Printf("%s=\"%s\"\n", e.Name, e.Value) + case "plan9": + if strings.IndexByte(e.Value, '\x00') < 0 { + fmt.Printf("%s='%s'\n", e.Name, strings.Replace(e.Value, "'", "''", -1)) + } else { + v := strings.Split(e.Value, "\x00") + fmt.Printf("%s=(", e.Name) + for x, s := range v { + if x > 0 { + fmt.Printf(" ") + } + fmt.Printf("%s", s) + } + fmt.Printf(")\n") + } + case "windows": + fmt.Printf("set %s=%s\n", e.Name, e.Value) + } + } + } +} + +func printEnvAsJSON(env []cfg.EnvVar) { + m := make(map[string]string) + for _, e := range env { + if e.Name == "TERM" { + continue + } + m[e.Name] = e.Value + } + enc := json.NewEncoder(os.Stdout) + enc.SetIndent("", "\t") + if err := enc.Encode(m); err != nil { + base.Fatalf("%s", err) + } +}
diff --git a/vendor/cmd/go/internal/fix/fix.go b/vendor/cmd/go/internal/fix/fix.go new file mode 100644 index 0000000..99c7ca5 --- /dev/null +++ b/vendor/cmd/go/internal/fix/fix.go
@@ -0,0 +1,39 @@ +// Copyright 2011 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 fix implements the ``go fix'' command. +package fix + +import ( + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/go/internal/str" +) + +var CmdFix = &base.Command{ + Run: runFix, + UsageLine: "fix [packages]", + Short: "update packages to use new APIs", + Long: ` +Fix runs the Go fix command on the packages named by the import paths. + +For more about fix, see 'go doc cmd/fix'. +For more about specifying packages, see 'go help packages'. + +To run fix with specific options, run 'go tool fix'. + +See also: go fmt, go vet. + `, +} + +func runFix(cmd *base.Command, args []string) { + for _, pkg := range load.Packages(args) { + // Use pkg.gofiles instead of pkg.Dir so that + // the command only applies to this package, + // not to packages in subdirectories. + files := base.RelPaths(pkg.InternalAllGoFiles()) + base.Run(str.StringList(cfg.BuildToolexec, base.Tool("fix"), files)) + } +}
diff --git a/vendor/cmd/go/internal/fmtcmd/fmt.go b/vendor/cmd/go/internal/fmtcmd/fmt.go new file mode 100644 index 0000000..eb96823 --- /dev/null +++ b/vendor/cmd/go/internal/fmtcmd/fmt.go
@@ -0,0 +1,99 @@ +// Copyright 2011 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 fmtcmd implements the ``go fmt'' command. +package fmtcmd + +import ( + "os" + "path/filepath" + "runtime" + "strings" + "sync" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/go/internal/str" +) + +func init() { + base.AddBuildFlagsNX(&CmdFmt.Flag) +} + +var CmdFmt = &base.Command{ + Run: runFmt, + UsageLine: "fmt [-n] [-x] [packages]", + Short: "gofmt (reformat) package sources", + Long: ` +Fmt runs the command 'gofmt -l -w' on the packages named +by the import paths. It prints the names of the files that are modified. + +For more about gofmt, see 'go doc cmd/gofmt'. +For more about specifying packages, see 'go help packages'. + +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + +To run gofmt with specific options, run gofmt itself. + +See also: go fix, go vet. + `, +} + +func runFmt(cmd *base.Command, args []string) { + gofmt := gofmtPath() + procs := runtime.GOMAXPROCS(0) + var wg sync.WaitGroup + wg.Add(procs) + fileC := make(chan string, 2*procs) + for i := 0; i < procs; i++ { + go func() { + defer wg.Done() + for file := range fileC { + base.Run(str.StringList(gofmt, "-l", "-w", file)) + } + }() + } + for _, pkg := range load.PackagesAndErrors(args) { + if pkg.Error != nil { + if strings.HasPrefix(pkg.Error.Err, "build constraints exclude all Go files") { + // Skip this error, as we will format + // all files regardless. + } else { + base.Errorf("can't load package: %s", pkg.Error) + continue + } + } + // Use pkg.gofiles instead of pkg.Dir so that + // the command only applies to this package, + // not to packages in subdirectories. + files := base.RelPaths(pkg.InternalAllGoFiles()) + for _, file := range files { + fileC <- file + } + } + close(fileC) + wg.Wait() +} + +func gofmtPath() string { + gofmt := "gofmt" + if base.ToolIsWindows { + gofmt += base.ToolWindowsExtension + } + + gofmtPath := filepath.Join(cfg.GOBIN, gofmt) + if _, err := os.Stat(gofmtPath); err == nil { + return gofmtPath + } + + gofmtPath = filepath.Join(cfg.GOROOT, "bin", gofmt) + if _, err := os.Stat(gofmtPath); err == nil { + return gofmtPath + } + + // fallback to looking for gofmt in $PATH + return "gofmt" +}
diff --git a/vendor/cmd/go/internal/generate/generate.go b/vendor/cmd/go/internal/generate/generate.go new file mode 100644 index 0000000..75c0d3b --- /dev/null +++ b/vendor/cmd/go/internal/generate/generate.go
@@ -0,0 +1,407 @@ +// Copyright 2011 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 generate implements the ``go generate'' command. +package generate + +import ( + "bufio" + "bytes" + "fmt" + "io" + "log" + "os" + "os/exec" + "path/filepath" + "regexp" + "strconv" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/go/internal/work" +) + +var CmdGenerate = &base.Command{ + Run: runGenerate, + UsageLine: "generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]", + Short: "generate Go files by processing source", + Long: ` +Generate runs commands described by directives within existing +files. Those commands can run any process but the intent is to +create or update Go source files. + +Go generate is never run automatically by go build, go get, go test, +and so on. It must be run explicitly. + +Go generate scans the file for directives, which are lines of +the form, + + //go:generate command argument... + +(note: no leading spaces and no space in "//go") where command +is the generator to be run, corresponding to an executable file +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. + +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. + +The arguments to the directive are space-separated tokens or +double-quoted strings passed to the generator as individual +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. + +Go generate sets several variables when it runs the generator: + + $GOARCH + The execution architecture (arm, amd64, etc.) + $GOOS + The execution operating system (linux, windows, etc.) + $GOFILE + The base name of the file. + $GOLINE + The line number of the directive in the source file. + $GOPACKAGE + The name of the package of the file containing the directive. + $DOLLAR + A dollar sign. + +Other than variable substitution and quoted-string evaluation, no +special processing such as "globbing" is performed on the command +line. + +As a last step before running the command, any invocations of any +environment variables with alphanumeric names, such as $GOFILE or +$HOME, are expanded throughout the command line. The syntax for +variable expansion is $NAME on all operating systems. Due to the +order of evaluation, variables are expanded even inside quoted +strings. If the variable NAME is not set, $NAME expands to the +empty string. + +A directive of the form, + + //go:generate -command xxx args... + +specifies, for the remainder of this source file only, that the +string xxx represents the command identified by the arguments. This +can be used to create aliases or to handle multiword generators. +For example, + + //go:generate -command foo go tool foo + +specifies that the command "foo" represents the generator +"go tool foo". + +Generate processes packages in the order given on the command line, +one at a time. If the command line lists .go files, they are treated +as a single package. Within a package, generate processes the +source files in a package in file name order, one at a time. Within +a source file, generate runs generators in the order they appear +in the file, one at a time. + +If any generator returns an error exit status, "go generate" skips +all further processing for that package. + +The generator is run in the package's source directory. + +Go generate accepts one specific flag: + + -run="" + if non-empty, specifies a regular expression to select + directives whose full original source text (excluding + any trailing spaces and final newline) matches the + expression. + +It also accepts the standard build flags including -v, -n, and -x. +The -v flag prints the names of packages and files as they are +processed. +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + +For more about build flags, see 'go help build'. + +For more about specifying packages, see 'go help packages'. + `, +} + +var ( + generateRunFlag string // generate -run flag + generateRunRE *regexp.Regexp // compiled expression for -run +) + +func init() { + work.AddBuildFlags(CmdGenerate) + CmdGenerate.Flag.StringVar(&generateRunFlag, "run", "", "") +} + +func runGenerate(cmd *base.Command, args []string) { + load.IgnoreImports = true + + if generateRunFlag != "" { + var err error + generateRunRE, err = regexp.Compile(generateRunFlag) + if err != nil { + log.Fatalf("generate: %s", err) + } + } + // Even if the arguments are .go files, this loop suffices. + for _, pkg := range load.Packages(args) { + for _, file := range pkg.InternalGoFiles() { + if !generate(pkg.Name, file) { + break + } + } + } +} + +// generate runs the generation directives for a single file. +func generate(pkg, absFile string) bool { + fd, err := os.Open(absFile) + if err != nil { + log.Fatalf("generate: %s", err) + } + defer fd.Close() + g := &Generator{ + r: fd, + path: absFile, + pkg: pkg, + commands: make(map[string][]string), + } + return g.run() +} + +// A Generator represents the state of a single Go source file +// being scanned for generator commands. +type Generator struct { + r io.Reader + path string // full rooted path name. + dir string // full rooted directory of file. + file string // base name of file. + pkg string + commands map[string][]string + lineNum int // current line number. + env []string +} + +// run runs the generators in the current file. +func (g *Generator) run() (ok bool) { + // Processing below here calls g.errorf on failure, which does panic(stop). + // If we encounter an error, we abort the package. + defer func() { + e := recover() + if e != nil { + ok = false + if e != stop { + panic(e) + } + base.SetExitStatus(1) + } + }() + g.dir, g.file = filepath.Split(g.path) + g.dir = filepath.Clean(g.dir) // No final separator please. + if cfg.BuildV { + fmt.Fprintf(os.Stderr, "%s\n", base.ShortPath(g.path)) + } + + // Scan for lines that start "//go:generate". + // Can't use bufio.Scanner because it can't handle long lines, + // which are likely to appear when using generate. + input := bufio.NewReader(g.r) + var err error + // One line per loop. + for { + g.lineNum++ // 1-indexed. + var buf []byte + buf, err = input.ReadSlice('\n') + if err == bufio.ErrBufferFull { + // Line too long - consume and ignore. + if isGoGenerate(buf) { + g.errorf("directive too long") + } + for err == bufio.ErrBufferFull { + _, err = input.ReadSlice('\n') + } + if err != nil { + break + } + continue + } + + if err != nil { + // Check for marker at EOF without final \n. + if err == io.EOF && isGoGenerate(buf) { + err = io.ErrUnexpectedEOF + } + break + } + + if !isGoGenerate(buf) { + continue + } + if generateRunFlag != "" { + if !generateRunRE.Match(bytes.TrimSpace(buf)) { + continue + } + } + + g.setEnv() + words := g.split(string(buf)) + if len(words) == 0 { + g.errorf("no arguments to directive") + } + if words[0] == "-command" { + g.setShorthand(words) + continue + } + // Run the command line. + if cfg.BuildN || cfg.BuildX { + fmt.Fprintf(os.Stderr, "%s\n", strings.Join(words, " ")) + } + if cfg.BuildN { + continue + } + g.exec(words) + } + if err != nil && err != io.EOF { + g.errorf("error reading %s: %s", base.ShortPath(g.path), err) + } + return true +} + +func isGoGenerate(buf []byte) bool { + return bytes.HasPrefix(buf, []byte("//go:generate ")) || bytes.HasPrefix(buf, []byte("//go:generate\t")) +} + +// setEnv sets the extra environment variables used when executing a +// single go:generate command. +func (g *Generator) setEnv() { + g.env = []string{ + "GOARCH=" + cfg.BuildContext.GOARCH, + "GOOS=" + cfg.BuildContext.GOOS, + "GOFILE=" + g.file, + "GOLINE=" + strconv.Itoa(g.lineNum), + "GOPACKAGE=" + g.pkg, + "DOLLAR=" + "$", + } +} + +// split breaks the line into words, evaluating quoted +// strings and evaluating environment variables. +// The initial //go:generate element is present in line. +func (g *Generator) split(line string) []string { + // Parse line, obeying quoted strings. + var words []string + line = line[len("//go:generate ") : len(line)-1] // Drop preamble and final newline. + // There may still be a carriage return. + if len(line) > 0 && line[len(line)-1] == '\r' { + line = line[:len(line)-1] + } + // One (possibly quoted) word per iteration. +Words: + for { + line = strings.TrimLeft(line, " \t") + if len(line) == 0 { + break + } + if line[0] == '"' { + for i := 1; i < len(line); i++ { + c := line[i] // Only looking for ASCII so this is OK. + switch c { + case '\\': + if i+1 == len(line) { + g.errorf("bad backslash") + } + i++ // Absorb next byte (If it's a multibyte we'll get an error in Unquote). + case '"': + word, err := strconv.Unquote(line[0 : i+1]) + if err != nil { + g.errorf("bad quoted string") + } + words = append(words, word) + line = line[i+1:] + // Check the next character is space or end of line. + if len(line) > 0 && line[0] != ' ' && line[0] != '\t' { + g.errorf("expect space after quoted argument") + } + continue Words + } + } + g.errorf("mismatched quoted string") + } + i := strings.IndexAny(line, " \t") + if i < 0 { + i = len(line) + } + words = append(words, line[0:i]) + line = line[i:] + } + // Substitute command if required. + if len(words) > 0 && g.commands[words[0]] != nil { + // Replace 0th word by command substitution. + words = append(g.commands[words[0]], words[1:]...) + } + // Substitute environment variables. + for i, word := range words { + words[i] = os.Expand(word, g.expandVar) + } + return words +} + +var stop = fmt.Errorf("error in generation") + +// errorf logs an error message prefixed with the file and line number. +// It then exits the program (with exit status 1) because generation stops +// at the first error. +func (g *Generator) errorf(format string, args ...interface{}) { + fmt.Fprintf(os.Stderr, "%s:%d: %s\n", base.ShortPath(g.path), g.lineNum, + fmt.Sprintf(format, args...)) + panic(stop) +} + +// expandVar expands the $XXX invocation in word. It is called +// by os.Expand. +func (g *Generator) expandVar(word string) string { + w := word + "=" + for _, e := range g.env { + if strings.HasPrefix(e, w) { + return e[len(w):] + } + } + return os.Getenv(word) +} + +// setShorthand installs a new shorthand as defined by a -command directive. +func (g *Generator) setShorthand(words []string) { + // Create command shorthand. + if len(words) == 1 { + g.errorf("no command specified for -command") + } + command := words[1] + if g.commands[command] != nil { + g.errorf("command %q multiply defined", command) + } + g.commands[command] = words[2:len(words):len(words)] // force later append to make copy +} + +// exec runs the command specified by the argument. The first word is +// the command name itself. +func (g *Generator) exec(words []string) { + cmd := exec.Command(words[0], words[1:]...) + // Standard in and out of generator should be the usual. + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + // Run the command in the package directory. + cmd.Dir = g.dir + cmd.Env = base.MergeEnvLists(g.env, cfg.OrigEnv) + err := cmd.Run() + if err != nil { + g.errorf("running %q: %s", words[0], err) + } +}
diff --git a/vendor/cmd/go/internal/generate/generate_test.go b/vendor/cmd/go/internal/generate/generate_test.go new file mode 100644 index 0000000..defc153 --- /dev/null +++ b/vendor/cmd/go/internal/generate/generate_test.go
@@ -0,0 +1,56 @@ +// Copyright 2011 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 generate + +import ( + "reflect" + "runtime" + "testing" +) + +type splitTest struct { + in string + out []string +} + +var splitTests = []splitTest{ + {"", nil}, + {"x", []string{"x"}}, + {" a b\tc ", []string{"a", "b", "c"}}, + {` " a " `, []string{" a "}}, + {"$GOARCH", []string{runtime.GOARCH}}, + {"$GOOS", []string{runtime.GOOS}}, + {"$GOFILE", []string{"proc.go"}}, + {"$GOPACKAGE", []string{"sys"}}, + {"a $XXNOTDEFINEDXX b", []string{"a", "", "b"}}, + {"/$XXNOTDEFINED/", []string{"//"}}, + {"/$DOLLAR/", []string{"/$/"}}, + {"yacc -o $GOARCH/yacc_$GOFILE", []string{"go", "tool", "yacc", "-o", runtime.GOARCH + "/yacc_proc.go"}}, +} + +func TestGenerateCommandParse(t *testing.T) { + g := &Generator{ + r: nil, // Unused here. + path: "/usr/ken/sys/proc.go", + dir: "/usr/ken/sys", + file: "proc.go", + pkg: "sys", + commands: make(map[string][]string), + } + g.setEnv() + g.setShorthand([]string{"-command", "yacc", "go", "tool", "yacc"}) + for _, test := range splitTests { + // First with newlines. + got := g.split("//go:generate " + test.in + "\n") + if !reflect.DeepEqual(got, test.out) { + t.Errorf("split(%q): got %q expected %q", test.in, got, test.out) + } + // Then with CRLFs, thank you Windows. + got = g.split("//go:generate " + test.in + "\r\n") + if !reflect.DeepEqual(got, test.out) { + t.Errorf("split(%q): got %q expected %q", test.in, got, test.out) + } + } +}
diff --git a/vendor/cmd/go/internal/get/discovery.go b/vendor/cmd/go/internal/get/discovery.go new file mode 100644 index 0000000..b2918db --- /dev/null +++ b/vendor/cmd/go/internal/get/discovery.go
@@ -0,0 +1,76 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package get + +import ( + "encoding/xml" + "fmt" + "io" + "strings" +) + +// charsetReader returns a reader for the given charset. Currently +// it only supports UTF-8 and ASCII. Otherwise, it returns a meaningful +// error which is printed by go get, so the user can find why the package +// wasn't downloaded if the encoding is not supported. Note that, in +// order to reduce potential errors, ASCII is treated as UTF-8 (i.e. characters +// greater than 0x7f are not rejected). +func charsetReader(charset string, input io.Reader) (io.Reader, error) { + switch strings.ToLower(charset) { + case "ascii": + return input, nil + default: + return nil, fmt.Errorf("can't decode XML document using charset %q", charset) + } +} + +// parseMetaGoImports returns meta imports from the HTML in r. +// Parsing ends at the end of the <head> section or the beginning of the <body>. +func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) { + d := xml.NewDecoder(r) + d.CharsetReader = charsetReader + d.Strict = false + var t xml.Token + for { + t, err = d.RawToken() + if err != nil { + if err == io.EOF || len(imports) > 0 { + err = nil + } + return + } + if e, ok := t.(xml.StartElement); ok && strings.EqualFold(e.Name.Local, "body") { + return + } + if e, ok := t.(xml.EndElement); ok && strings.EqualFold(e.Name.Local, "head") { + return + } + e, ok := t.(xml.StartElement) + if !ok || !strings.EqualFold(e.Name.Local, "meta") { + continue + } + if attrValue(e.Attr, "name") != "go-import" { + continue + } + if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 { + imports = append(imports, metaImport{ + Prefix: f[0], + VCS: f[1], + RepoRoot: f[2], + }) + } + } +} + +// attrValue returns the attribute value for the case-insensitive key +// `name', or the empty string if nothing is found. +func attrValue(attrs []xml.Attr, name string) string { + for _, a := range attrs { + if strings.EqualFold(a.Name.Local, name) { + return a.Value + } + } + return "" +}
diff --git a/vendor/cmd/go/internal/get/get.go b/vendor/cmd/go/internal/get/get.go new file mode 100644 index 0000000..733116e --- /dev/null +++ b/vendor/cmd/go/internal/get/get.go
@@ -0,0 +1,528 @@ +// Copyright 2011 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 get implements the ``go get'' command. +package get + +import ( + "fmt" + "go/build" + "os" + "path/filepath" + "runtime" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/go/internal/str" + "cmd/go/internal/web" + "cmd/go/internal/work" +) + +var CmdGet = &base.Command{ + UsageLine: "get [-d] [-f] [-fix] [-insecure] [-t] [-u] [-v] [build flags] [packages]", + Short: "download and install packages and dependencies", + Long: ` +Get downloads the packages named by the import paths, along with their +dependencies. It then installs the named packages, like 'go install'. + +The -d flag instructs get to stop after downloading the packages; that is, +it instructs get not to install the packages. + +The -f flag, valid only when -u is set, forces get -u not to verify that +each package has been checked out from the source control repository +implied by its import path. This can be useful if the source is a local fork +of the original. + +The -fix flag instructs get to run the fix tool on the downloaded packages +before resolving dependencies or building the code. + +The -insecure flag permits fetching from repositories and resolving +custom domains using insecure schemes such as HTTP. Use with caution. + +The -t flag instructs get to also download the packages required to build +the tests for the specified packages. + +The -u flag instructs get to use the network to update the named packages +and their dependencies. By default, get uses the network to check out +missing packages but does not use it to look for updates to existing packages. + +The -v flag enables verbose progress and debug output. + +Get also accepts build flags to control the installation. See 'go help build'. + +When checking out a new package, get creates the target directory +GOPATH/src/<import-path>. If the GOPATH contains multiple entries, +get uses the first one. For more details see: 'go help gopath'. + +When checking out or updating a package, get looks for a branch or tag +that matches the locally installed version of Go. The most important +rule is that if the local installation is running version "go1", get +searches for a branch or tag named "go1". If no such version exists +it retrieves the default branch of the package. + +When go get checks out or updates a Git repository, +it also updates any git submodules referenced by the repository. + +Get never checks out or updates code stored in vendor directories. + +For more about specifying packages, see 'go help packages'. + +For more about how 'go get' finds source code to +download, see 'go help importpath'. + +See also: go build, go install, go clean. + `, +} + +var getD = CmdGet.Flag.Bool("d", false, "") +var getF = CmdGet.Flag.Bool("f", false, "") +var getT = CmdGet.Flag.Bool("t", false, "") +var getU = CmdGet.Flag.Bool("u", false, "") +var getFix = CmdGet.Flag.Bool("fix", false, "") +var getInsecure = CmdGet.Flag.Bool("insecure", false, "") + +func init() { + work.AddBuildFlags(CmdGet) + CmdGet.Run = runGet // break init loop +} + +func runGet(cmd *base.Command, args []string) { + work.BuildInit() + + if *getF && !*getU { + base.Fatalf("go get: cannot use -f flag without -u") + } + + // Disable any prompting for passwords by Git. + // Only has an effect for 2.3.0 or later, but avoiding + // the prompt in earlier versions is just too hard. + // If user has explicitly set GIT_TERMINAL_PROMPT=1, keep + // prompting. + // See golang.org/issue/9341 and golang.org/issue/12706. + if os.Getenv("GIT_TERMINAL_PROMPT") == "" { + os.Setenv("GIT_TERMINAL_PROMPT", "0") + } + + // Disable any ssh connection pooling by Git. + // If a Git subprocess forks a child into the background to cache a new connection, + // that child keeps stdout/stderr open. After the Git subprocess exits, + // os /exec expects to be able to read from the stdout/stderr pipe + // until EOF to get all the data that the Git subprocess wrote before exiting. + // The EOF doesn't come until the child exits too, because the child + // is holding the write end of the pipe. + // This is unfortunate, but it has come up at least twice + // (see golang.org/issue/13453 and golang.org/issue/16104) + // and confuses users when it does. + // If the user has explicitly set GIT_SSH or GIT_SSH_COMMAND, + // assume they know what they are doing and don't step on it. + // But default to turning off ControlMaster. + if os.Getenv("GIT_SSH") == "" && os.Getenv("GIT_SSH_COMMAND") == "" { + os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no") + } + + // Phase 1. Download/update. + var stk load.ImportStack + mode := 0 + if *getT { + mode |= load.GetTestDeps + } + args = downloadPaths(args) + for _, arg := range args { + download(arg, nil, &stk, mode) + } + base.ExitIfErrors() + + // Phase 2. Rescan packages and re-evaluate args list. + + // Code we downloaded and all code that depends on it + // needs to be evicted from the package cache so that + // the information will be recomputed. Instead of keeping + // track of the reverse dependency information, evict + // everything. + load.ClearPackageCache() + + // In order to rebuild packages information completely, + // we need to clear commands cache. Command packages are + // referring to evicted packages from the package cache. + // This leads to duplicated loads of the standard packages. + load.ClearCmdCache() + + args = load.ImportPaths(args) + load.PackagesForBuild(args) + + // Phase 3. Install. + if *getD { + // Download only. + // Check delayed until now so that importPaths + // and packagesForBuild have a chance to print errors. + return + } + + work.InstallPackages(args, true) +} + +// downloadPaths prepares the list of paths to pass to download. +// It expands ... patterns that can be expanded. If there is no match +// for a particular pattern, downloadPaths leaves it in the result list, +// in the hope that we can figure out the repository from the +// initial ...-free prefix. +func downloadPaths(args []string) []string { + args = load.ImportPathsNoDotExpansion(args) + var out []string + for _, a := range args { + if strings.Contains(a, "...") { + var expand []string + // Use matchPackagesInFS to avoid printing + // warnings. They will be printed by the + // eventual call to importPaths instead. + if build.IsLocalImport(a) { + expand = load.MatchPackagesInFS(a) + } else { + expand = load.MatchPackages(a) + } + if len(expand) > 0 { + out = append(out, expand...) + continue + } + } + out = append(out, a) + } + return out +} + +// downloadCache records the import paths we have already +// considered during the download, to avoid duplicate work when +// there is more than one dependency sequence leading to +// a particular package. +var downloadCache = map[string]bool{} + +// downloadRootCache records the version control repository +// root directories we have already considered during the download. +// For example, all the packages in the github.com/google/codesearch repo +// share the same root (the directory for that path), and we only need +// to run the hg commands to consider each repository once. +var downloadRootCache = map[string]bool{} + +// download runs the download half of the get command +// for the package named by the argument. +func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) { + if mode&load.UseVendor != 0 { + // Caller is responsible for expanding vendor paths. + panic("internal error: download mode has useVendor set") + } + load1 := func(path string, mode int) *load.Package { + if parent == nil { + return load.LoadPackage(path, stk) + } + return load.LoadImport(path, parent.Dir, parent, stk, nil, mode) + } + + p := load1(arg, mode) + if p.Error != nil && p.Error.Hard { + base.Errorf("%s", p.Error) + return + } + + // loadPackage inferred the canonical ImportPath from arg. + // Use that in the following to prevent hysteresis effects + // in e.g. downloadCache and packageCache. + // This allows invocations such as: + // mkdir -p $GOPATH/src/github.com/user + // cd $GOPATH/src/github.com/user + // go get ./foo + // see: golang.org/issue/9767 + arg = p.ImportPath + + // There's nothing to do if this is a package in the standard library. + if p.Standard { + return + } + + // Only process each package once. + // (Unless we're fetching test dependencies for this package, + // in which case we want to process it again.) + if downloadCache[arg] && mode&load.GetTestDeps == 0 { + return + } + downloadCache[arg] = true + + pkgs := []*load.Package{p} + wildcardOkay := len(*stk) == 0 + isWildcard := false + + // Download if the package is missing, or update if we're using -u. + if p.Dir == "" || *getU { + // The actual download. + stk.Push(arg) + err := downloadPackage(p) + if err != nil { + base.Errorf("%s", &load.PackageError{ImportStack: stk.Copy(), Err: err.Error()}) + stk.Pop() + return + } + stk.Pop() + + args := []string{arg} + // If the argument has a wildcard in it, re-evaluate the wildcard. + // We delay this until after reloadPackage so that the old entry + // for p has been replaced in the package cache. + if wildcardOkay && strings.Contains(arg, "...") { + if build.IsLocalImport(arg) { + args = load.MatchPackagesInFS(arg) + } else { + args = load.MatchPackages(arg) + } + isWildcard = true + } + + // Clear all relevant package cache entries before + // doing any new loads. + load.ClearPackageCachePartial(args) + + pkgs = pkgs[:0] + for _, arg := range args { + // Note: load calls loadPackage or loadImport, + // which push arg onto stk already. + // Do not push here too, or else stk will say arg imports arg. + p := load1(arg, mode) + if p.Error != nil { + base.Errorf("%s", p.Error) + continue + } + pkgs = append(pkgs, p) + } + } + + // Process package, which might now be multiple packages + // due to wildcard expansion. + for _, p := range pkgs { + if *getFix { + files := base.RelPaths(p.InternalAllGoFiles()) + base.Run(cfg.BuildToolexec, str.StringList(base.Tool("fix"), files)) + + // The imports might have changed, so reload again. + p = load.ReloadPackage(arg, stk) + if p.Error != nil { + base.Errorf("%s", p.Error) + return + } + } + + if isWildcard { + // Report both the real package and the + // wildcard in any error message. + stk.Push(p.ImportPath) + } + + // Process dependencies, now that we know what they are. + imports := p.Imports + if mode&load.GetTestDeps != 0 { + // Process test dependencies when -t is specified. + // (But don't get test dependencies for test dependencies: + // we always pass mode 0 to the recursive calls below.) + imports = str.StringList(imports, p.TestImports, p.XTestImports) + } + for i, path := range imports { + if path == "C" { + continue + } + // Fail fast on import naming full vendor path. + // Otherwise expand path as needed for test imports. + // Note that p.Imports can have additional entries beyond p.Internal.Build.Imports. + orig := path + if i < len(p.Internal.Build.Imports) { + orig = p.Internal.Build.Imports[i] + } + if j, ok := load.FindVendor(orig); ok { + stk.Push(path) + err := &load.PackageError{ + ImportStack: stk.Copy(), + Err: "must be imported as " + path[j+len("vendor/"):], + } + stk.Pop() + base.Errorf("%s", err) + continue + } + // If this is a test import, apply vendor lookup now. + // We cannot pass useVendor to download, because + // download does caching based on the value of path, + // so it must be the fully qualified path already. + if i >= len(p.Imports) { + path = load.VendoredImportPath(p, path) + } + download(path, p, stk, 0) + } + + if isWildcard { + stk.Pop() + } + } +} + +// downloadPackage runs the create or download command +// to make the first copy of or update a copy of the given package. +func downloadPackage(p *load.Package) error { + var ( + vcs *vcsCmd + repo, rootPath string + err error + ) + + security := web.Secure + if *getInsecure { + security = web.Insecure + } + + if p.Internal.Build.SrcRoot != "" { + // Directory exists. Look for checkout along path to src. + vcs, rootPath, err = vcsFromDir(p.Dir, p.Internal.Build.SrcRoot) + if err != nil { + return err + } + repo = "<local>" // should be unused; make distinctive + + // Double-check where it came from. + if *getU && vcs.remoteRepo != nil { + dir := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath)) + remote, err := vcs.remoteRepo(vcs, dir) + if err != nil { + return err + } + repo = remote + if !*getF { + if rr, err := repoRootForImportPath(p.ImportPath, security); err == nil { + repo := rr.repo + if rr.vcs.resolveRepo != nil { + resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo) + if err == nil { + repo = resolved + } + } + if remote != repo && rr.isCustom { + return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.root, repo, dir, remote) + } + } + } + } + } else { + // Analyze the import path to determine the version control system, + // repository, and the import path for the root of the repository. + rr, err := repoRootForImportPath(p.ImportPath, security) + if err != nil { + return err + } + vcs, repo, rootPath = rr.vcs, rr.repo, rr.root + } + if !vcs.isSecure(repo) && !*getInsecure { + return fmt.Errorf("cannot download, %v uses insecure protocol", repo) + } + + if p.Internal.Build.SrcRoot == "" { + // Package not found. Put in first directory of $GOPATH. + list := filepath.SplitList(cfg.BuildContext.GOPATH) + if len(list) == 0 { + return fmt.Errorf("cannot download, $GOPATH not set. For more details see: 'go help gopath'") + } + // Guard against people setting GOPATH=$GOROOT. + if filepath.Clean(list[0]) == filepath.Clean(cfg.GOROOT) { + return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: 'go help gopath'") + } + if _, err := os.Stat(filepath.Join(list[0], "src/cmd/go/alldocs.go")); err == nil { + return fmt.Errorf("cannot download, %s is a GOROOT, not a GOPATH. For more details see: 'go help gopath'", list[0]) + } + p.Internal.Build.Root = list[0] + p.Internal.Build.SrcRoot = filepath.Join(list[0], "src") + p.Internal.Build.PkgRoot = filepath.Join(list[0], "pkg") + } + root := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath)) + + if err := checkNestedVCS(vcs, root, p.Internal.Build.SrcRoot); err != nil { + return err + } + + // If we've considered this repository already, don't do it again. + if downloadRootCache[root] { + return nil + } + downloadRootCache[root] = true + + if cfg.BuildV { + fmt.Fprintf(os.Stderr, "%s (download)\n", rootPath) + } + + // Check that this is an appropriate place for the repo to be checked out. + // The target directory must either not exist or have a repo checked out already. + meta := filepath.Join(root, "."+vcs.cmd) + if _, err := os.Stat(meta); err != nil { + // Metadata file or directory does not exist. Prepare to checkout new copy. + // Some version control tools require the target directory not to exist. + // We require that too, just to avoid stepping on existing work. + if _, err := os.Stat(root); err == nil { + return fmt.Errorf("%s exists but %s does not - stale checkout?", root, meta) + } + + _, err := os.Stat(p.Internal.Build.Root) + gopathExisted := err == nil + + // Some version control tools require the parent of the target to exist. + parent, _ := filepath.Split(root) + if err = os.MkdirAll(parent, 0777); err != nil { + return err + } + if cfg.BuildV && !gopathExisted && p.Internal.Build.Root == cfg.BuildContext.GOPATH { + fmt.Fprintf(os.Stderr, "created GOPATH=%s; see 'go help gopath'\n", p.Internal.Build.Root) + } + + if err = vcs.create(root, repo); err != nil { + return err + } + } else { + // Metadata directory does exist; download incremental updates. + if err = vcs.download(root); err != nil { + return err + } + } + + if cfg.BuildN { + // Do not show tag sync in -n; it's noise more than anything, + // and since we're not running commands, no tag will be found. + // But avoid printing nothing. + fmt.Fprintf(os.Stderr, "# cd %s; %s sync/update\n", root, vcs.cmd) + return nil + } + + // Select and sync to appropriate version of the repository. + tags, err := vcs.tags(root) + if err != nil { + return err + } + vers := runtime.Version() + if i := strings.Index(vers, " "); i >= 0 { + vers = vers[:i] + } + if err := vcs.tagSync(root, selectTag(vers, tags)); err != nil { + return err + } + + return nil +} + +// selectTag returns the closest matching tag for a given version. +// Closest means the latest one that is not after the current release. +// Version "goX" (or "goX.Y" or "goX.Y.Z") matches tags of the same form. +// Version "release.rN" matches tags of the form "go.rN" (N being a floating-point number). +// Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD". +// +// NOTE(rsc): Eventually we will need to decide on some logic here. +// For now, there is only "go1". This matches the docs in go help get. +func selectTag(goVersion string, tags []string) (match string) { + for _, t := range tags { + if t == "go1" { + return "go1" + } + } + return "" +}
diff --git a/vendor/cmd/go/internal/get/pkg_test.go b/vendor/cmd/go/internal/get/pkg_test.go new file mode 100644 index 0000000..b8937a5 --- /dev/null +++ b/vendor/cmd/go/internal/get/pkg_test.go
@@ -0,0 +1,83 @@ +// Copyright 2014 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 get + +import ( + "cmd/go/internal/str" + "reflect" + "strings" + "testing" +) + +var foldDupTests = []struct { + list []string + f1, f2 string +}{ + {str.StringList("math/rand", "math/big"), "", ""}, + {str.StringList("math", "strings"), "", ""}, + {str.StringList("strings"), "", ""}, + {str.StringList("strings", "strings"), "strings", "strings"}, + {str.StringList("Rand", "rand", "math", "math/rand", "math/Rand"), "Rand", "rand"}, +} + +func TestFoldDup(t *testing.T) { + for _, tt := range foldDupTests { + f1, f2 := str.FoldDup(tt.list) + if f1 != tt.f1 || f2 != tt.f2 { + t.Errorf("foldDup(%q) = %q, %q, want %q, %q", tt.list, f1, f2, tt.f1, tt.f2) + } + } +} + +var parseMetaGoImportsTests = []struct { + in string + out []metaImport +}{ + { + `<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">`, + []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}}, + }, + { + `<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar"> + <meta name="go-import" content="baz/quux git http://github.com/rsc/baz/quux">`, + []metaImport{ + {"foo/bar", "git", "https://github.com/rsc/foo/bar"}, + {"baz/quux", "git", "http://github.com/rsc/baz/quux"}, + }, + }, + { + `<head> + <meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar"> + </head>`, + []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}}, + }, + { + `<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar"> + <body>`, + []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}}, + }, + { + `<!doctype html><meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">`, + []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}}, + }, + { + // XML doesn't like <div style=position:relative>. + `<!doctype html><title>Page Not Found</title><meta name=go-import content="chitin.io/chitin git https://github.com/chitin-io/chitin"><div style=position:relative>DRAFT</div>`, + []metaImport{{"chitin.io/chitin", "git", "https://github.com/chitin-io/chitin"}}, + }, +} + +func TestParseMetaGoImports(t *testing.T) { + for i, tt := range parseMetaGoImportsTests { + out, err := parseMetaGoImports(strings.NewReader(tt.in)) + if err != nil { + t.Errorf("test#%d: %v", i, err) + continue + } + if !reflect.DeepEqual(out, tt.out) { + t.Errorf("test#%d:\n\thave %q\n\twant %q", i, out, tt.out) + } + } +}
diff --git a/vendor/cmd/go/internal/get/tag_test.go b/vendor/cmd/go/internal/get/tag_test.go new file mode 100644 index 0000000..9a25dfa --- /dev/null +++ b/vendor/cmd/go/internal/get/tag_test.go
@@ -0,0 +1,100 @@ +// Copyright 2011 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 get + +import "testing" + +var selectTagTestTags = []string{ + "go.r58", + "go.r58.1", + "go.r59", + "go.r59.1", + "go.r61", + "go.r61.1", + "go.weekly.2010-01-02", + "go.weekly.2011-10-12", + "go.weekly.2011-10-12.1", + "go.weekly.2011-10-14", + "go.weekly.2011-11-01", + "go1", + "go1.0.1", + "go1.999", + "go1.9.2", + "go5", + + // these should be ignored: + "release.r59", + "release.r59.1", + "release", + "weekly.2011-10-12", + "weekly.2011-10-12.1", + "weekly", + "foo", + "bar", + "go.f00", + "go!r60", + "go.1999-01-01", + "go.2x", + "go.20000000000000", + "go.2.", + "go.2.0", + "go2x", + "go20000000000000", + "go2.", + "go2.0", +} + +var selectTagTests = []struct { + version string + selected string +}{ + /* + {"release.r57", ""}, + {"release.r58.2", "go.r58.1"}, + {"release.r59", "go.r59"}, + {"release.r59.1", "go.r59.1"}, + {"release.r60", "go.r59.1"}, + {"release.r60.1", "go.r59.1"}, + {"release.r61", "go.r61"}, + {"release.r66", "go.r61.1"}, + {"weekly.2010-01-01", ""}, + {"weekly.2010-01-02", "go.weekly.2010-01-02"}, + {"weekly.2010-01-02.1", "go.weekly.2010-01-02"}, + {"weekly.2010-01-03", "go.weekly.2010-01-02"}, + {"weekly.2011-10-12", "go.weekly.2011-10-12"}, + {"weekly.2011-10-12.1", "go.weekly.2011-10-12.1"}, + {"weekly.2011-10-13", "go.weekly.2011-10-12.1"}, + {"weekly.2011-10-14", "go.weekly.2011-10-14"}, + {"weekly.2011-10-14.1", "go.weekly.2011-10-14"}, + {"weekly.2011-11-01", "go.weekly.2011-11-01"}, + {"weekly.2014-01-01", "go.weekly.2011-11-01"}, + {"weekly.3000-01-01", "go.weekly.2011-11-01"}, + {"go1", "go1"}, + {"go1.1", "go1.0.1"}, + {"go1.998", "go1.9.2"}, + {"go1.1000", "go1.999"}, + {"go6", "go5"}, + + // faulty versions: + {"release.f00", ""}, + {"weekly.1999-01-01", ""}, + {"junk", ""}, + {"", ""}, + {"go2x", ""}, + {"go200000000000", ""}, + {"go2.", ""}, + {"go2.0", ""}, + */ + {"anything", "go1"}, +} + +func TestSelectTag(t *testing.T) { + for _, c := range selectTagTests { + selected := selectTag(c.version, selectTagTestTags) + if selected != c.selected { + t.Errorf("selectTag(%q) = %q, want %q", c.version, selected, c.selected) + } + } +}
diff --git a/vendor/cmd/go/internal/get/vcs.go b/vendor/cmd/go/internal/get/vcs.go new file mode 100644 index 0000000..ee6b16a --- /dev/null +++ b/vendor/cmd/go/internal/get/vcs.go
@@ -0,0 +1,1111 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package get + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "internal/singleflight" + "log" + "net/url" + "os" + "os/exec" + "path/filepath" + "regexp" + "strings" + "sync" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/web" +) + +// A vcsCmd describes how to use a version control system +// like Mercurial, Git, or Subversion. +type vcsCmd struct { + name string + cmd string // name of binary to invoke command + + createCmd []string // commands to download a fresh copy of a repository + downloadCmd []string // commands to download updates into an existing repository + + tagCmd []tagCmd // commands to list tags + tagLookupCmd []tagCmd // commands to lookup tags before running tagSyncCmd + tagSyncCmd []string // commands to sync to specific tag + tagSyncDefault []string // commands to sync to default tag + + scheme []string + pingCmd string + + remoteRepo func(v *vcsCmd, rootDir string) (remoteRepo string, err error) + resolveRepo func(v *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error) +} + +var defaultSecureScheme = map[string]bool{ + "https": true, + "git+ssh": true, + "bzr+ssh": true, + "svn+ssh": true, + "ssh": true, +} + +func (v *vcsCmd) isSecure(repo string) bool { + u, err := url.Parse(repo) + if err != nil { + // If repo is not a URL, it's not secure. + return false + } + return v.isSecureScheme(u.Scheme) +} + +func (v *vcsCmd) isSecureScheme(scheme string) bool { + switch v.cmd { + case "git": + // GIT_ALLOW_PROTOCOL is an environment variable defined by Git. It is a + // colon-separated list of schemes that are allowed to be used with git + // fetch/clone. Any scheme not mentioned will be considered insecure. + if allow := os.Getenv("GIT_ALLOW_PROTOCOL"); allow != "" { + for _, s := range strings.Split(allow, ":") { + if s == scheme { + return true + } + } + return false + } + } + return defaultSecureScheme[scheme] +} + +// A tagCmd describes a command to list available tags +// that can be passed to tagSyncCmd. +type tagCmd struct { + cmd string // command to list tags + pattern string // regexp to extract tags from list +} + +// vcsList lists the known version control systems +var vcsList = []*vcsCmd{ + vcsHg, + vcsGit, + vcsSvn, + vcsBzr, + vcsFossil, +} + +// vcsByCmd returns the version control system for the given +// command name (hg, git, svn, bzr). +func vcsByCmd(cmd string) *vcsCmd { + for _, vcs := range vcsList { + if vcs.cmd == cmd { + return vcs + } + } + return nil +} + +// vcsHg describes how to use Mercurial. +var vcsHg = &vcsCmd{ + name: "Mercurial", + cmd: "hg", + + createCmd: []string{"clone -U {repo} {dir}"}, + downloadCmd: []string{"pull"}, + + // We allow both tag and branch names as 'tags' + // for selecting a version. This lets people have + // a go.release.r60 branch and a go1 branch + // and make changes in both, without constantly + // editing .hgtags. + tagCmd: []tagCmd{ + {"tags", `^(\S+)`}, + {"branches", `^(\S+)`}, + }, + tagSyncCmd: []string{"update -r {tag}"}, + tagSyncDefault: []string{"update default"}, + + scheme: []string{"https", "http", "ssh"}, + pingCmd: "identify {scheme}://{repo}", + remoteRepo: hgRemoteRepo, +} + +func hgRemoteRepo(vcsHg *vcsCmd, rootDir string) (remoteRepo string, err error) { + out, err := vcsHg.runOutput(rootDir, "paths default") + if err != nil { + return "", err + } + return strings.TrimSpace(string(out)), nil +} + +// vcsGit describes how to use Git. +var vcsGit = &vcsCmd{ + name: "Git", + cmd: "git", + + createCmd: []string{"clone {repo} {dir}", "-go-internal-cd {dir} submodule update --init --recursive"}, + downloadCmd: []string{"pull --ff-only", "submodule update --init --recursive"}, + + tagCmd: []tagCmd{ + // tags/xxx matches a git tag named xxx + // origin/xxx matches a git branch named xxx on the default remote repository + {"show-ref", `(?:tags|origin)/(\S+)$`}, + }, + tagLookupCmd: []tagCmd{ + {"show-ref tags/{tag} origin/{tag}", `((?:tags|origin)/\S+)$`}, + }, + tagSyncCmd: []string{"checkout {tag}", "submodule update --init --recursive"}, + // both createCmd and downloadCmd update the working dir. + // No need to do more here. We used to 'checkout master' + // but that doesn't work if the default branch is not named master. + // DO NOT add 'checkout master' here. + // See golang.org/issue/9032. + tagSyncDefault: []string{"submodule update --init --recursive"}, + + scheme: []string{"git", "https", "http", "git+ssh", "ssh"}, + pingCmd: "ls-remote {scheme}://{repo}", + remoteRepo: gitRemoteRepo, +} + +// scpSyntaxRe matches the SCP-like addresses used by Git to access +// repositories by SSH. +var scpSyntaxRe = regexp.MustCompile(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`) + +func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error) { + cmd := "config remote.origin.url" + errParse := errors.New("unable to parse output of git " + cmd) + errRemoteOriginNotFound := errors.New("remote origin not found") + outb, err := vcsGit.run1(rootDir, cmd, nil, false) + if err != nil { + // if it doesn't output any message, it means the config argument is correct, + // but the config value itself doesn't exist + if outb != nil && len(outb) == 0 { + return "", errRemoteOriginNotFound + } + return "", err + } + out := strings.TrimSpace(string(outb)) + + var repoURL *url.URL + if m := scpSyntaxRe.FindStringSubmatch(out); m != nil { + // Match SCP-like syntax and convert it to a URL. + // Eg, "git@github.com:user/repo" becomes + // "ssh://git@github.com/user/repo". + repoURL = &url.URL{ + Scheme: "ssh", + User: url.User(m[1]), + Host: m[2], + Path: m[3], + } + } else { + repoURL, err = url.Parse(out) + if err != nil { + return "", err + } + } + + // Iterate over insecure schemes too, because this function simply + // reports the state of the repo. If we can't see insecure schemes then + // we can't report the actual repo URL. + for _, s := range vcsGit.scheme { + if repoURL.Scheme == s { + return repoURL.String(), nil + } + } + return "", errParse +} + +// vcsBzr describes how to use Bazaar. +var vcsBzr = &vcsCmd{ + name: "Bazaar", + cmd: "bzr", + + createCmd: []string{"branch {repo} {dir}"}, + + // Without --overwrite bzr will not pull tags that changed. + // Replace by --overwrite-tags after http://pad.lv/681792 goes in. + downloadCmd: []string{"pull --overwrite"}, + + tagCmd: []tagCmd{{"tags", `^(\S+)`}}, + tagSyncCmd: []string{"update -r {tag}"}, + tagSyncDefault: []string{"update -r revno:-1"}, + + scheme: []string{"https", "http", "bzr", "bzr+ssh"}, + pingCmd: "info {scheme}://{repo}", + remoteRepo: bzrRemoteRepo, + resolveRepo: bzrResolveRepo, +} + +func bzrRemoteRepo(vcsBzr *vcsCmd, rootDir string) (remoteRepo string, err error) { + outb, err := vcsBzr.runOutput(rootDir, "config parent_location") + if err != nil { + return "", err + } + return strings.TrimSpace(string(outb)), nil +} + +func bzrResolveRepo(vcsBzr *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error) { + outb, err := vcsBzr.runOutput(rootDir, "info "+remoteRepo) + if err != nil { + return "", err + } + out := string(outb) + + // Expect: + // ... + // (branch root|repository branch): <URL> + // ... + + found := false + for _, prefix := range []string{"\n branch root: ", "\n repository branch: "} { + i := strings.Index(out, prefix) + if i >= 0 { + out = out[i+len(prefix):] + found = true + break + } + } + if !found { + return "", fmt.Errorf("unable to parse output of bzr info") + } + + i := strings.Index(out, "\n") + if i < 0 { + return "", fmt.Errorf("unable to parse output of bzr info") + } + out = out[:i] + return strings.TrimSpace(out), nil +} + +// vcsSvn describes how to use Subversion. +var vcsSvn = &vcsCmd{ + name: "Subversion", + cmd: "svn", + + createCmd: []string{"checkout {repo} {dir}"}, + downloadCmd: []string{"update"}, + + // There is no tag command in subversion. + // The branch information is all in the path names. + + scheme: []string{"https", "http", "svn", "svn+ssh"}, + pingCmd: "info {scheme}://{repo}", + remoteRepo: svnRemoteRepo, +} + +func svnRemoteRepo(vcsSvn *vcsCmd, rootDir string) (remoteRepo string, err error) { + outb, err := vcsSvn.runOutput(rootDir, "info") + if err != nil { + return "", err + } + out := string(outb) + + // Expect: + // + // ... + // URL: <URL> + // ... + // + // Note that we're not using the Repository Root line, + // because svn allows checking out subtrees. + // The URL will be the URL of the subtree (what we used with 'svn co') + // while the Repository Root may be a much higher parent. + i := strings.Index(out, "\nURL: ") + if i < 0 { + return "", fmt.Errorf("unable to parse output of svn info") + } + out = out[i+len("\nURL: "):] + i = strings.Index(out, "\n") + if i < 0 { + return "", fmt.Errorf("unable to parse output of svn info") + } + out = out[:i] + return strings.TrimSpace(out), nil +} + +// fossilRepoName is the name go get associates with a fossil repository. In the +// real world the file can be named anything. +const fossilRepoName = ".fossil" + +// vcsFossil describes how to use Fossil (fossil-scm.org) +var vcsFossil = &vcsCmd{ + name: "Fossil", + cmd: "fossil", + + createCmd: []string{"-go-internal-mkdir {dir} clone {repo} " + filepath.Join("{dir}", fossilRepoName), "-go-internal-cd {dir} open .fossil"}, + downloadCmd: []string{"up"}, + + tagCmd: []tagCmd{{"tag ls", `(.*)`}}, + tagSyncCmd: []string{"up tag:{tag}"}, + tagSyncDefault: []string{"up trunk"}, + + scheme: []string{"https", "http"}, + remoteRepo: fossilRemoteRepo, +} + +func fossilRemoteRepo(vcsFossil *vcsCmd, rootDir string) (remoteRepo string, err error) { + out, err := vcsFossil.runOutput(rootDir, "remote-url") + if err != nil { + return "", err + } + return strings.TrimSpace(string(out)), nil +} + +func (v *vcsCmd) String() string { + return v.name +} + +// run runs the command line cmd in the given directory. +// keyval is a list of key, value pairs. run expands +// instances of {key} in cmd into value, but only after +// splitting cmd into individual arguments. +// If an error occurs, run prints the command line and the +// command's combined stdout+stderr to standard error. +// Otherwise run discards the command's output. +func (v *vcsCmd) run(dir string, cmd string, keyval ...string) error { + _, err := v.run1(dir, cmd, keyval, true) + return err +} + +// runVerboseOnly is like run but only generates error output to standard error in verbose mode. +func (v *vcsCmd) runVerboseOnly(dir string, cmd string, keyval ...string) error { + _, err := v.run1(dir, cmd, keyval, false) + return err +} + +// runOutput is like run but returns the output of the command. +func (v *vcsCmd) runOutput(dir string, cmd string, keyval ...string) ([]byte, error) { + return v.run1(dir, cmd, keyval, true) +} + +// run1 is the generalized implementation of run and runOutput. +func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([]byte, error) { + m := make(map[string]string) + for i := 0; i < len(keyval); i += 2 { + m[keyval[i]] = keyval[i+1] + } + args := strings.Fields(cmdline) + for i, arg := range args { + args[i] = expand(m, arg) + } + + if len(args) >= 2 && args[0] == "-go-internal-mkdir" { + var err error + if filepath.IsAbs(args[1]) { + err = os.Mkdir(args[1], os.ModePerm) + } else { + err = os.Mkdir(filepath.Join(dir, args[1]), os.ModePerm) + } + if err != nil { + return nil, err + } + args = args[2:] + } + + if len(args) >= 2 && args[0] == "-go-internal-cd" { + if filepath.IsAbs(args[1]) { + dir = args[1] + } else { + dir = filepath.Join(dir, args[1]) + } + args = args[2:] + } + + _, err := exec.LookPath(v.cmd) + if err != nil { + fmt.Fprintf(os.Stderr, + "go: missing %s command. See https://golang.org/s/gogetcmd\n", + v.name) + return nil, err + } + + cmd := exec.Command(v.cmd, args...) + cmd.Dir = dir + cmd.Env = base.EnvForDir(cmd.Dir, os.Environ()) + if cfg.BuildX { + fmt.Printf("cd %s\n", dir) + fmt.Printf("%s %s\n", v.cmd, strings.Join(args, " ")) + } + var buf bytes.Buffer + cmd.Stdout = &buf + cmd.Stderr = &buf + err = cmd.Run() + out := buf.Bytes() + if err != nil { + if verbose || cfg.BuildV { + fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " ")) + os.Stderr.Write(out) + } + return out, err + } + return out, nil +} + +// ping pings to determine scheme to use. +func (v *vcsCmd) ping(scheme, repo string) error { + return v.runVerboseOnly(".", v.pingCmd, "scheme", scheme, "repo", repo) +} + +// create creates a new copy of repo in dir. +// The parent of dir must exist; dir must not. +func (v *vcsCmd) create(dir, repo string) error { + for _, cmd := range v.createCmd { + if err := v.run(".", cmd, "dir", dir, "repo", repo); err != nil { + return err + } + } + return nil +} + +// download downloads any new changes for the repo in dir. +func (v *vcsCmd) download(dir string) error { + for _, cmd := range v.downloadCmd { + if err := v.run(dir, cmd); err != nil { + return err + } + } + return nil +} + +// tags returns the list of available tags for the repo in dir. +func (v *vcsCmd) tags(dir string) ([]string, error) { + var tags []string + for _, tc := range v.tagCmd { + out, err := v.runOutput(dir, tc.cmd) + if err != nil { + return nil, err + } + re := regexp.MustCompile(`(?m-s)` + tc.pattern) + for _, m := range re.FindAllStringSubmatch(string(out), -1) { + tags = append(tags, m[1]) + } + } + return tags, nil +} + +// tagSync syncs the repo in dir to the named tag, +// which either is a tag returned by tags or is v.tagDefault. +func (v *vcsCmd) tagSync(dir, tag string) error { + if v.tagSyncCmd == nil { + return nil + } + if tag != "" { + for _, tc := range v.tagLookupCmd { + out, err := v.runOutput(dir, tc.cmd, "tag", tag) + if err != nil { + return err + } + re := regexp.MustCompile(`(?m-s)` + tc.pattern) + m := re.FindStringSubmatch(string(out)) + if len(m) > 1 { + tag = m[1] + break + } + } + } + + if tag == "" && v.tagSyncDefault != nil { + for _, cmd := range v.tagSyncDefault { + if err := v.run(dir, cmd); err != nil { + return err + } + } + return nil + } + + for _, cmd := range v.tagSyncCmd { + if err := v.run(dir, cmd, "tag", tag); err != nil { + return err + } + } + return nil +} + +// A vcsPath describes how to convert an import path into a +// version control system and repository name. +type vcsPath struct { + prefix string // prefix this description applies to + re string // pattern for import path + repo string // repository to use (expand with match of re) + vcs string // version control system to use (expand with match of re) + check func(match map[string]string) error // additional checks + ping bool // ping for scheme to use to download repo + + regexp *regexp.Regexp // cached compiled form of re +} + +// vcsFromDir inspects dir and its parents to determine the +// version control system and code repository to use. +// On return, root is the import path +// corresponding to the root of the repository. +func vcsFromDir(dir, srcRoot string) (vcs *vcsCmd, root string, err error) { + // Clean and double-check that dir is in (a subdirectory of) srcRoot. + dir = filepath.Clean(dir) + srcRoot = filepath.Clean(srcRoot) + if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator { + return nil, "", fmt.Errorf("directory %q is outside source root %q", dir, srcRoot) + } + + var vcsRet *vcsCmd + var rootRet string + + origDir := dir + for len(dir) > len(srcRoot) { + for _, vcs := range vcsList { + if _, err := os.Stat(filepath.Join(dir, "."+vcs.cmd)); err == nil { + root := filepath.ToSlash(dir[len(srcRoot)+1:]) + // Record first VCS we find, but keep looking, + // to detect mistakes like one kind of VCS inside another. + if vcsRet == nil { + vcsRet = vcs + rootRet = root + continue + } + // Allow .git inside .git, which can arise due to submodules. + if vcsRet == vcs && vcs.cmd == "git" { + continue + } + // Otherwise, we have one VCS inside a different VCS. + return nil, "", fmt.Errorf("directory %q uses %s, but parent %q uses %s", + filepath.Join(srcRoot, rootRet), vcsRet.cmd, filepath.Join(srcRoot, root), vcs.cmd) + } + } + + // Move to parent. + ndir := filepath.Dir(dir) + if len(ndir) >= len(dir) { + // Shouldn't happen, but just in case, stop. + break + } + dir = ndir + } + + if vcsRet != nil { + return vcsRet, rootRet, nil + } + + return nil, "", fmt.Errorf("directory %q is not using a known version control system", origDir) +} + +// checkNestedVCS checks for an incorrectly-nested VCS-inside-VCS +// situation for dir, checking parents up until srcRoot. +func checkNestedVCS(vcs *vcsCmd, dir, srcRoot string) error { + if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator { + return fmt.Errorf("directory %q is outside source root %q", dir, srcRoot) + } + + otherDir := dir + for len(otherDir) > len(srcRoot) { + for _, otherVCS := range vcsList { + if _, err := os.Stat(filepath.Join(otherDir, "."+otherVCS.cmd)); err == nil { + // Allow expected vcs in original dir. + if otherDir == dir && otherVCS == vcs { + continue + } + // Allow .git inside .git, which can arise due to submodules. + if otherVCS == vcs && vcs.cmd == "git" { + continue + } + // Otherwise, we have one VCS inside a different VCS. + return fmt.Errorf("directory %q uses %s, but parent %q uses %s", dir, vcs.cmd, otherDir, otherVCS.cmd) + } + } + // Move to parent. + newDir := filepath.Dir(otherDir) + if len(newDir) >= len(otherDir) { + // Shouldn't happen, but just in case, stop. + break + } + otherDir = newDir + } + + return nil +} + +// repoRoot represents a version control system, a repo, and a root of +// where to put it on disk. +type repoRoot struct { + vcs *vcsCmd + + // repo is the repository URL, including scheme + repo string + + // root is the import path corresponding to the root of the + // repository + root string + + // isCustom is true for custom import paths (those defined by HTML meta tags) + isCustom bool +} + +var httpPrefixRE = regexp.MustCompile(`^https?:`) + +// repoRootForImportPath analyzes importPath to determine the +// version control system, and code repository to use. +func repoRootForImportPath(importPath string, security web.SecurityMode) (*repoRoot, error) { + rr, err := repoRootFromVCSPaths(importPath, "", security, vcsPaths) + if err == errUnknownSite { + // If there are wildcards, look up the thing before the wildcard, + // hoping it applies to the wildcarded parts too. + // This makes 'go get rsc.io/pdf/...' work in a fresh GOPATH. + lookup := strings.TrimSuffix(importPath, "/...") + if i := strings.Index(lookup, "/.../"); i >= 0 { + lookup = lookup[:i] + } + rr, err = repoRootForImportDynamic(lookup, security) + if err != nil { + err = fmt.Errorf("unrecognized import path %q (%v)", importPath, err) + } + } + if err != nil { + rr1, err1 := repoRootFromVCSPaths(importPath, "", security, vcsPathsAfterDynamic) + if err1 == nil { + rr = rr1 + err = nil + } + } + + if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.root, "...") { + // Do not allow wildcards in the repo root. + rr = nil + err = fmt.Errorf("cannot expand ... in %q", importPath) + } + return rr, err +} + +var errUnknownSite = errors.New("dynamic lookup required to find mapping") + +// repoRootFromVCSPaths attempts to map importPath to a repoRoot +// using the mappings defined in vcsPaths. +// If scheme is non-empty, that scheme is forced. +func repoRootFromVCSPaths(importPath, scheme string, security web.SecurityMode, vcsPaths []*vcsPath) (*repoRoot, error) { + // A common error is to use https://packagepath because that's what + // hg and git require. Diagnose this helpfully. + if loc := httpPrefixRE.FindStringIndex(importPath); loc != nil { + // The importPath has been cleaned, so has only one slash. The pattern + // ignores the slashes; the error message puts them back on the RHS at least. + return nil, fmt.Errorf("%q not allowed in import path", importPath[loc[0]:loc[1]]+"//") + } + for _, srv := range vcsPaths { + if !strings.HasPrefix(importPath, srv.prefix) { + continue + } + m := srv.regexp.FindStringSubmatch(importPath) + if m == nil { + if srv.prefix != "" { + return nil, fmt.Errorf("invalid %s import path %q", srv.prefix, importPath) + } + continue + } + + // Build map of named subexpression matches for expand. + match := map[string]string{ + "prefix": srv.prefix, + "import": importPath, + } + for i, name := range srv.regexp.SubexpNames() { + if name != "" && match[name] == "" { + match[name] = m[i] + } + } + if srv.vcs != "" { + match["vcs"] = expand(match, srv.vcs) + } + if srv.repo != "" { + match["repo"] = expand(match, srv.repo) + } + if srv.check != nil { + if err := srv.check(match); err != nil { + return nil, err + } + } + vcs := vcsByCmd(match["vcs"]) + if vcs == nil { + return nil, fmt.Errorf("unknown version control system %q", match["vcs"]) + } + if srv.ping { + if scheme != "" { + match["repo"] = scheme + "://" + match["repo"] + } else { + for _, scheme := range vcs.scheme { + if security == web.Secure && !vcs.isSecureScheme(scheme) { + continue + } + if vcs.ping(scheme, match["repo"]) == nil { + match["repo"] = scheme + "://" + match["repo"] + break + } + } + } + } + rr := &repoRoot{ + vcs: vcs, + repo: match["repo"], + root: match["root"], + } + return rr, nil + } + return nil, errUnknownSite +} + +// repoRootForImportDynamic finds a *repoRoot for a custom domain that's not +// statically known by repoRootForImportPathStatic. +// +// This handles custom import paths like "name.tld/pkg/foo" or just "name.tld". +func repoRootForImportDynamic(importPath string, security web.SecurityMode) (*repoRoot, error) { + slash := strings.Index(importPath, "/") + if slash < 0 { + slash = len(importPath) + } + host := importPath[:slash] + if !strings.Contains(host, ".") { + return nil, errors.New("import path does not begin with hostname") + } + urlStr, body, err := web.GetMaybeInsecure(importPath, security) + if err != nil { + msg := "https fetch: %v" + if security == web.Insecure { + msg = "http/" + msg + } + return nil, fmt.Errorf(msg, err) + } + defer body.Close() + imports, err := parseMetaGoImports(body) + if err != nil { + return nil, fmt.Errorf("parsing %s: %v", importPath, err) + } + // Find the matched meta import. + mmi, err := matchGoImport(imports, importPath) + if err != nil { + if _, ok := err.(ImportMismatchError); !ok { + return nil, fmt.Errorf("parse %s: %v", urlStr, err) + } + return nil, fmt.Errorf("parse %s: no go-import meta tags (%s)", urlStr, err) + } + if cfg.BuildV { + log.Printf("get %q: found meta tag %#v at %s", importPath, mmi, urlStr) + } + // If the import was "uni.edu/bob/project", which said the + // prefix was "uni.edu" and the RepoRoot was "evilroot.com", + // make sure we don't trust Bob and check out evilroot.com to + // "uni.edu" yet (possibly overwriting/preempting another + // non-evil student). Instead, first verify the root and see + // if it matches Bob's claim. + if mmi.Prefix != importPath { + if cfg.BuildV { + log.Printf("get %q: verifying non-authoritative meta tag", importPath) + } + urlStr0 := urlStr + var imports []metaImport + urlStr, imports, err = metaImportsForPrefix(mmi.Prefix, security) + if err != nil { + return nil, err + } + metaImport2, err := matchGoImport(imports, importPath) + if err != nil || mmi != metaImport2 { + return nil, fmt.Errorf("%s and %s disagree about go-import for %s", urlStr0, urlStr, mmi.Prefix) + } + } + + if !strings.Contains(mmi.RepoRoot, "://") { + return nil, fmt.Errorf("%s: invalid repo root %q; no scheme", urlStr, mmi.RepoRoot) + } + rr := &repoRoot{ + vcs: vcsByCmd(mmi.VCS), + repo: mmi.RepoRoot, + root: mmi.Prefix, + isCustom: true, + } + if rr.vcs == nil { + return nil, fmt.Errorf("%s: unknown vcs %q", urlStr, mmi.VCS) + } + return rr, nil +} + +var fetchGroup singleflight.Group +var ( + fetchCacheMu sync.Mutex + fetchCache = map[string]fetchResult{} // key is metaImportsForPrefix's importPrefix +) + +// metaImportsForPrefix takes a package's root import path as declared in a <meta> tag +// and returns its HTML discovery URL and the parsed metaImport lines +// found on the page. +// +// The importPath is of the form "golang.org/x/tools". +// It is an error if no imports are found. +// urlStr will still be valid if err != nil. +// The returned urlStr will be of the form "https://golang.org/x/tools?go-get=1" +func metaImportsForPrefix(importPrefix string, security web.SecurityMode) (urlStr string, imports []metaImport, err error) { + setCache := func(res fetchResult) (fetchResult, error) { + fetchCacheMu.Lock() + defer fetchCacheMu.Unlock() + fetchCache[importPrefix] = res + return res, nil + } + + resi, _, _ := fetchGroup.Do(importPrefix, func() (resi interface{}, err error) { + fetchCacheMu.Lock() + if res, ok := fetchCache[importPrefix]; ok { + fetchCacheMu.Unlock() + return res, nil + } + fetchCacheMu.Unlock() + + urlStr, body, err := web.GetMaybeInsecure(importPrefix, security) + if err != nil { + return setCache(fetchResult{urlStr: urlStr, err: fmt.Errorf("fetch %s: %v", urlStr, err)}) + } + imports, err := parseMetaGoImports(body) + if err != nil { + return setCache(fetchResult{urlStr: urlStr, err: fmt.Errorf("parsing %s: %v", urlStr, err)}) + } + if len(imports) == 0 { + err = fmt.Errorf("fetch %s: no go-import meta tag", urlStr) + } + return setCache(fetchResult{urlStr: urlStr, imports: imports, err: err}) + }) + res := resi.(fetchResult) + return res.urlStr, res.imports, res.err +} + +type fetchResult struct { + urlStr string // e.g. "https://foo.com/x/bar?go-get=1" + imports []metaImport + err error +} + +// metaImport represents the parsed <meta name="go-import" +// content="prefix vcs reporoot" /> tags from HTML files. +type metaImport struct { + Prefix, VCS, RepoRoot string +} + +func splitPathHasPrefix(path, prefix []string) bool { + if len(path) < len(prefix) { + return false + } + for i, p := range prefix { + if path[i] != p { + return false + } + } + return true +} + +// A ImportMismatchError is returned where metaImport/s are present +// but none match our import path. +type ImportMismatchError struct { + importPath string + mismatches []string // the meta imports that were discarded for not matching our importPath +} + +func (m ImportMismatchError) Error() string { + formattedStrings := make([]string, len(m.mismatches)) + for i, pre := range m.mismatches { + formattedStrings[i] = fmt.Sprintf("meta tag %s did not match import path %s", pre, m.importPath) + } + return strings.Join(formattedStrings, ", ") +} + +// matchGoImport returns the metaImport from imports matching importPath. +// An error is returned if there are multiple matches. +// errNoMatch is returned if none match. +func matchGoImport(imports []metaImport, importPath string) (metaImport, error) { + match := -1 + imp := strings.Split(importPath, "/") + + errImportMismatch := ImportMismatchError{importPath: importPath} + for i, im := range imports { + pre := strings.Split(im.Prefix, "/") + + if !splitPathHasPrefix(imp, pre) { + errImportMismatch.mismatches = append(errImportMismatch.mismatches, im.Prefix) + continue + } + + if match != -1 { + return metaImport{}, fmt.Errorf("multiple meta tags match import path %q", importPath) + } + match = i + } + + if match == -1 { + return metaImport{}, errImportMismatch + } + return imports[match], nil +} + +// expand rewrites s to replace {k} with match[k] for each key k in match. +func expand(match map[string]string, s string) string { + for k, v := range match { + s = strings.Replace(s, "{"+k+"}", v, -1) + } + return s +} + +// vcsPaths defines the meaning of import paths referring to +// commonly-used VCS hosting sites (github.com/user/dir) +// and import paths referring to a fully-qualified importPath +// containing a VCS type (foo.com/repo.git/dir) +var vcsPaths = []*vcsPath{ + // Github + { + prefix: "github.com/", + re: `^(?P<root>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[\p{L}0-9_.\-]+)*$`, + vcs: "git", + repo: "https://{root}", + check: noVCSSuffix, + }, + + // Bitbucket + { + prefix: "bitbucket.org/", + re: `^(?P<root>bitbucket\.org/(?P<bitname>[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`, + repo: "https://{root}", + check: bitbucketVCS, + }, + + // IBM DevOps Services (JazzHub) + { + prefix: "hub.jazz.net/git/", + re: `^(?P<root>hub\.jazz\.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`, + vcs: "git", + repo: "https://{root}", + check: noVCSSuffix, + }, + + // Git at Apache + { + prefix: "git.apache.org/", + re: `^(?P<root>git\.apache\.org/[a-z0-9_.\-]+\.git)(/[A-Za-z0-9_.\-]+)*$`, + vcs: "git", + repo: "https://{root}", + }, + + // Git at OpenStack + { + prefix: "git.openstack.org/", + re: `^(?P<root>git\.openstack\.org/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(\.git)?(/[A-Za-z0-9_.\-]+)*$`, + vcs: "git", + repo: "https://{root}", + }, + + // chiselapp.com for fossil + { + prefix: "chiselapp.com/", + re: `^(?P<root>chiselapp\.com/user/[A-Za-z0-9]+/repository/[A-Za-z0-9_.\-]+)$`, + vcs: "fossil", + repo: "https://{root}", + }, + + // General syntax for any server. + // Must be last. + { + re: `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?(/~?[A-Za-z0-9_.\-]+)+?)\.(?P<vcs>bzr|fossil|git|hg|svn))(/~?[A-Za-z0-9_.\-]+)*$`, + ping: true, + }, +} + +// vcsPathsAfterDynamic gives additional vcsPaths entries +// to try after the dynamic HTML check. +// This gives those sites a chance to introduce <meta> tags +// as part of a graceful transition away from the hard-coded logic. +var vcsPathsAfterDynamic = []*vcsPath{ + // Launchpad. See golang.org/issue/11436. + { + prefix: "launchpad.net/", + re: `^(?P<root>launchpad\.net/((?P<project>[A-Za-z0-9_.\-]+)(?P<series>/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`, + vcs: "bzr", + repo: "https://{root}", + check: launchpadVCS, + }, +} + +func init() { + // fill in cached regexps. + // Doing this eagerly discovers invalid regexp syntax + // without having to run a command that needs that regexp. + for _, srv := range vcsPaths { + srv.regexp = regexp.MustCompile(srv.re) + } + for _, srv := range vcsPathsAfterDynamic { + srv.regexp = regexp.MustCompile(srv.re) + } +} + +// noVCSSuffix checks that the repository name does not +// end in .foo for any version control system foo. +// The usual culprit is ".git". +func noVCSSuffix(match map[string]string) error { + repo := match["repo"] + for _, vcs := range vcsList { + if strings.HasSuffix(repo, "."+vcs.cmd) { + return fmt.Errorf("invalid version control suffix in %s path", match["prefix"]) + } + } + return nil +} + +// bitbucketVCS determines the version control system for a +// Bitbucket repository, by using the Bitbucket API. +func bitbucketVCS(match map[string]string) error { + if err := noVCSSuffix(match); err != nil { + return err + } + + var resp struct { + SCM string `json:"scm"` + } + url := expand(match, "https://api.bitbucket.org/2.0/repositories/{bitname}?fields=scm") + data, err := web.Get(url) + if err != nil { + if httpErr, ok := err.(*web.HTTPError); ok && httpErr.StatusCode == 403 { + // this may be a private repository. If so, attempt to determine which + // VCS it uses. See issue 5375. + root := match["root"] + for _, vcs := range []string{"git", "hg"} { + if vcsByCmd(vcs).ping("https", root) == nil { + resp.SCM = vcs + break + } + } + } + + if resp.SCM == "" { + return err + } + } else { + if err := json.Unmarshal(data, &resp); err != nil { + return fmt.Errorf("decoding %s: %v", url, err) + } + } + + if vcsByCmd(resp.SCM) != nil { + match["vcs"] = resp.SCM + if resp.SCM == "git" { + match["repo"] += ".git" + } + return nil + } + + return fmt.Errorf("unable to detect version control system for bitbucket.org/ path") +} + +// launchpadVCS solves the ambiguity for "lp.net/project/foo". In this case, +// "foo" could be a series name registered in Launchpad with its own branch, +// and it could also be the name of a directory within the main project +// branch one level up. +func launchpadVCS(match map[string]string) error { + if match["project"] == "" || match["series"] == "" { + return nil + } + _, err := web.Get(expand(match, "https://code.launchpad.net/{project}{series}/.bzr/branch-format")) + if err != nil { + match["root"] = expand(match, "launchpad.net/{project}") + match["repo"] = expand(match, "https://{root}") + } + return nil +}
diff --git a/vendor/cmd/go/internal/get/vcs_test.go b/vendor/cmd/go/internal/get/vcs_test.go new file mode 100644 index 0000000..2cb611f --- /dev/null +++ b/vendor/cmd/go/internal/get/vcs_test.go
@@ -0,0 +1,418 @@ +// Copyright 2014 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 get + +import ( + "errors" + "internal/testenv" + "io/ioutil" + "os" + "path" + "path/filepath" + "testing" + + "cmd/go/internal/web" +) + +// Test that RepoRootForImportPath creates the correct RepoRoot for a given importPath. +// TODO(cmang): Add tests for SVN and BZR. +func TestRepoRootForImportPath(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tests := []struct { + path string + want *repoRoot + }{ + { + "github.com/golang/groupcache", + &repoRoot{ + vcs: vcsGit, + repo: "https://github.com/golang/groupcache", + }, + }, + // Unicode letters in directories (issue 18660). + { + "github.com/user/unicode/испытание", + &repoRoot{ + vcs: vcsGit, + repo: "https://github.com/user/unicode", + }, + }, + // IBM DevOps Services tests + { + "hub.jazz.net/git/user1/pkgname", + &repoRoot{ + vcs: vcsGit, + repo: "https://hub.jazz.net/git/user1/pkgname", + }, + }, + { + "hub.jazz.net/git/user1/pkgname/submodule/submodule/submodule", + &repoRoot{ + vcs: vcsGit, + repo: "https://hub.jazz.net/git/user1/pkgname", + }, + }, + { + "hub.jazz.net", + nil, + }, + { + "hubajazz.net", + nil, + }, + { + "hub2.jazz.net", + nil, + }, + { + "hub.jazz.net/someotherprefix", + nil, + }, + { + "hub.jazz.net/someotherprefix/user1/pkgname", + nil, + }, + // Spaces are not valid in user names or package names + { + "hub.jazz.net/git/User 1/pkgname", + nil, + }, + { + "hub.jazz.net/git/user1/pkg name", + nil, + }, + // Dots are not valid in user names + { + "hub.jazz.net/git/user.1/pkgname", + nil, + }, + { + "hub.jazz.net/git/user/pkg.name", + &repoRoot{ + vcs: vcsGit, + repo: "https://hub.jazz.net/git/user/pkg.name", + }, + }, + // User names cannot have uppercase letters + { + "hub.jazz.net/git/USER/pkgname", + nil, + }, + // OpenStack tests + { + "git.openstack.org/openstack/swift", + &repoRoot{ + vcs: vcsGit, + repo: "https://git.openstack.org/openstack/swift", + }, + }, + // Trailing .git is less preferred but included for + // compatibility purposes while the same source needs to + // be compilable on both old and new go + { + "git.openstack.org/openstack/swift.git", + &repoRoot{ + vcs: vcsGit, + repo: "https://git.openstack.org/openstack/swift.git", + }, + }, + { + "git.openstack.org/openstack/swift/go/hummingbird", + &repoRoot{ + vcs: vcsGit, + repo: "https://git.openstack.org/openstack/swift", + }, + }, + { + "git.openstack.org", + nil, + }, + { + "git.openstack.org/openstack", + nil, + }, + // Spaces are not valid in package name + { + "git.apache.org/package name/path/to/lib", + nil, + }, + // Should have ".git" suffix + { + "git.apache.org/package-name/path/to/lib", + nil, + }, + { + "gitbapache.org", + nil, + }, + { + "git.apache.org/package-name.git", + &repoRoot{ + vcs: vcsGit, + repo: "https://git.apache.org/package-name.git", + }, + }, + { + "git.apache.org/package-name_2.x.git/path/to/lib", + &repoRoot{ + vcs: vcsGit, + repo: "https://git.apache.org/package-name_2.x.git", + }, + }, + { + "chiselapp.com/user/kyle/repository/fossilgg", + &repoRoot{ + vcs: vcsFossil, + repo: "https://chiselapp.com/user/kyle/repository/fossilgg", + }, + }, + { + // must have a user/$name/repository/$repo path + "chiselapp.com/kyle/repository/fossilgg", + nil, + }, + { + "chiselapp.com/user/kyle/fossilgg", + nil, + }, + } + + for _, test := range tests { + got, err := repoRootForImportPath(test.path, web.Secure) + want := test.want + + if want == nil { + if err == nil { + t.Errorf("repoRootForImportPath(%q): Error expected but not received", test.path) + } + continue + } + if err != nil { + t.Errorf("repoRootForImportPath(%q): %v", test.path, err) + continue + } + if got.vcs.name != want.vcs.name || got.repo != want.repo { + t.Errorf("repoRootForImportPath(%q) = VCS(%s) Repo(%s), want VCS(%s) Repo(%s)", test.path, got.vcs, got.repo, want.vcs, want.repo) + } + } +} + +// Test that vcsFromDir correctly inspects a given directory and returns the right VCS and root. +func TestFromDir(t *testing.T) { + tempDir, err := ioutil.TempDir("", "vcstest") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tempDir) + + for j, vcs := range vcsList { + dir := filepath.Join(tempDir, "example.com", vcs.name, "."+vcs.cmd) + if j&1 == 0 { + err := os.MkdirAll(dir, 0755) + if err != nil { + t.Fatal(err) + } + } else { + err := os.MkdirAll(filepath.Dir(dir), 0755) + if err != nil { + t.Fatal(err) + } + f, err := os.Create(dir) + if err != nil { + t.Fatal(err) + } + f.Close() + } + + want := repoRoot{ + vcs: vcs, + root: path.Join("example.com", vcs.name), + } + var got repoRoot + got.vcs, got.root, err = vcsFromDir(dir, tempDir) + if err != nil { + t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err) + continue + } + if got.vcs.name != want.vcs.name || got.root != want.root { + t.Errorf("FromDir(%q, %q) = VCS(%s) Root(%s), want VCS(%s) Root(%s)", dir, tempDir, got.vcs, got.root, want.vcs, want.root) + } + } +} + +func TestIsSecure(t *testing.T) { + tests := []struct { + vcs *vcsCmd + url string + secure bool + }{ + {vcsGit, "http://example.com/foo.git", false}, + {vcsGit, "https://example.com/foo.git", true}, + {vcsBzr, "http://example.com/foo.bzr", false}, + {vcsBzr, "https://example.com/foo.bzr", true}, + {vcsSvn, "http://example.com/svn", false}, + {vcsSvn, "https://example.com/svn", true}, + {vcsHg, "http://example.com/foo.hg", false}, + {vcsHg, "https://example.com/foo.hg", true}, + {vcsGit, "ssh://user@example.com/foo.git", true}, + {vcsGit, "user@server:path/to/repo.git", false}, + {vcsGit, "user@server:", false}, + {vcsGit, "server:repo.git", false}, + {vcsGit, "server:path/to/repo.git", false}, + {vcsGit, "example.com:path/to/repo.git", false}, + {vcsGit, "path/that/contains/a:colon/repo.git", false}, + {vcsHg, "ssh://user@example.com/path/to/repo.hg", true}, + {vcsFossil, "http://example.com/foo", false}, + {vcsFossil, "https://example.com/foo", true}, + } + + for _, test := range tests { + secure := test.vcs.isSecure(test.url) + if secure != test.secure { + t.Errorf("%s isSecure(%q) = %t; want %t", test.vcs, test.url, secure, test.secure) + } + } +} + +func TestIsSecureGitAllowProtocol(t *testing.T) { + tests := []struct { + vcs *vcsCmd + url string + secure bool + }{ + // Same as TestIsSecure to verify same behavior. + {vcsGit, "http://example.com/foo.git", false}, + {vcsGit, "https://example.com/foo.git", true}, + {vcsBzr, "http://example.com/foo.bzr", false}, + {vcsBzr, "https://example.com/foo.bzr", true}, + {vcsSvn, "http://example.com/svn", false}, + {vcsSvn, "https://example.com/svn", true}, + {vcsHg, "http://example.com/foo.hg", false}, + {vcsHg, "https://example.com/foo.hg", true}, + {vcsGit, "user@server:path/to/repo.git", false}, + {vcsGit, "user@server:", false}, + {vcsGit, "server:repo.git", false}, + {vcsGit, "server:path/to/repo.git", false}, + {vcsGit, "example.com:path/to/repo.git", false}, + {vcsGit, "path/that/contains/a:colon/repo.git", false}, + {vcsHg, "ssh://user@example.com/path/to/repo.hg", true}, + // New behavior. + {vcsGit, "ssh://user@example.com/foo.git", false}, + {vcsGit, "foo://example.com/bar.git", true}, + {vcsHg, "foo://example.com/bar.hg", false}, + {vcsSvn, "foo://example.com/svn", false}, + {vcsBzr, "foo://example.com/bar.bzr", false}, + } + + defer os.Unsetenv("GIT_ALLOW_PROTOCOL") + os.Setenv("GIT_ALLOW_PROTOCOL", "https:foo") + for _, test := range tests { + secure := test.vcs.isSecure(test.url) + if secure != test.secure { + t.Errorf("%s isSecure(%q) = %t; want %t", test.vcs, test.url, secure, test.secure) + } + } +} + +func TestMatchGoImport(t *testing.T) { + tests := []struct { + imports []metaImport + path string + mi metaImport + err error + }{ + { + imports: []metaImport{ + {Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + }, + path: "example.com/user/foo", + mi: metaImport{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + }, + { + imports: []metaImport{ + {Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + }, + path: "example.com/user/foo/", + mi: metaImport{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + }, + { + imports: []metaImport{ + {Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + {Prefix: "example.com/user/fooa", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + }, + path: "example.com/user/foo", + mi: metaImport{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + }, + { + imports: []metaImport{ + {Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + {Prefix: "example.com/user/fooa", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + }, + path: "example.com/user/fooa", + mi: metaImport{Prefix: "example.com/user/fooa", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + }, + { + imports: []metaImport{ + {Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + {Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + }, + path: "example.com/user/foo/bar", + err: errors.New("should not be allowed to create nested repo"), + }, + { + imports: []metaImport{ + {Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + {Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + }, + path: "example.com/user/foo/bar/baz", + err: errors.New("should not be allowed to create nested repo"), + }, + { + imports: []metaImport{ + {Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + {Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + }, + path: "example.com/user/foo/bar/baz/qux", + err: errors.New("should not be allowed to create nested repo"), + }, + { + imports: []metaImport{ + {Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + {Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + }, + path: "example.com/user/foo/bar/baz/", + err: errors.New("should not be allowed to create nested repo"), + }, + { + imports: []metaImport{ + {Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + {Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + }, + path: "example.com", + err: errors.New("pathologically short path"), + }, + { + imports: []metaImport{ + {Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"}, + }, + path: "different.example.com/user/foo", + err: errors.New("meta tags do not match import path"), + }, + } + + for _, test := range tests { + mi, err := matchGoImport(test.imports, test.path) + if mi != test.mi { + t.Errorf("unexpected metaImport; got %v, want %v", mi, test.mi) + } + + got := err + want := test.err + if (got == nil) != (want == nil) { + t.Errorf("unexpected error; got %v, want %v", got, want) + } + } +}
diff --git a/vendor/cmd/go/internal/help/help.go b/vendor/cmd/go/internal/help/help.go new file mode 100644 index 0000000..b4c5217 --- /dev/null +++ b/vendor/cmd/go/internal/help/help.go
@@ -0,0 +1,178 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package help implements the ``go help'' command. +package help + +import ( + "bufio" + "bytes" + "fmt" + "io" + "os" + "strings" + "text/template" + "unicode" + "unicode/utf8" + + "cmd/go/internal/base" +) + +// Help implements the 'help' command. +func Help(args []string) { + if len(args) == 0 { + PrintUsage(os.Stdout) + // not exit 2: succeeded at 'go help'. + return + } + if len(args) != 1 { + fmt.Fprintf(os.Stderr, "usage: go help command\n\nToo many arguments given.\n") + os.Exit(2) // failed at 'go help' + } + + arg := args[0] + + // 'go help documentation' generates doc.go. + if arg == "documentation" { + fmt.Println("// Copyright 2011 The Go Authors. All rights reserved.") + fmt.Println("// Use of this source code is governed by a BSD-style") + fmt.Println("// license that can be found in the LICENSE file.") + fmt.Println() + fmt.Println("// DO NOT EDIT THIS FILE. GENERATED BY mkalldocs.sh.") + fmt.Println("// Edit the documentation in other files and rerun mkalldocs.sh to generate this one.") + fmt.Println() + buf := new(bytes.Buffer) + PrintUsage(buf) + usage := &base.Command{Long: buf.String()} + tmpl(&commentWriter{W: os.Stdout}, documentationTemplate, append([]*base.Command{usage}, base.Commands...)) + fmt.Println("package main") + return + } + + for _, cmd := range base.Commands { + if cmd.Name() == arg { + tmpl(os.Stdout, helpTemplate, cmd) + // not exit 2: succeeded at 'go help cmd'. + return + } + } + + fmt.Fprintf(os.Stderr, "Unknown help topic %#q. Run 'go help'.\n", arg) + os.Exit(2) // failed at 'go help cmd' +} + +var usageTemplate = `Go is a tool for managing Go source code. + +Usage: + + go command [arguments] + +The commands are: +{{range .}}{{if .Runnable}} + {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}} + +Use "go help [command]" for more information about a command. + +Additional help topics: +{{range .}}{{if not .Runnable}} + {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}} + +Use "go help [topic]" for more information about that topic. + +` + +var helpTemplate = `{{if .Runnable}}usage: go {{.UsageLine}} + +{{end}}{{.Long | trim}} +` + +var documentationTemplate = `{{range .}}{{if .Short}}{{.Short | capitalize}} + +{{end}}{{if .Runnable}}Usage: + + go {{.UsageLine}} + +{{end}}{{.Long | trim}} + + +{{end}}` + +// commentWriter writes a Go comment to the underlying io.Writer, +// using line comment form (//). +type commentWriter struct { + W io.Writer + wroteSlashes bool // Wrote "//" at the beginning of the current line. +} + +func (c *commentWriter) Write(p []byte) (int, error) { + var n int + for i, b := range p { + if !c.wroteSlashes { + s := "//" + if b != '\n' { + s = "// " + } + if _, err := io.WriteString(c.W, s); err != nil { + return n, err + } + c.wroteSlashes = true + } + n0, err := c.W.Write(p[i : i+1]) + n += n0 + if err != nil { + return n, err + } + if b == '\n' { + c.wroteSlashes = false + } + } + return len(p), nil +} + +// An errWriter wraps a writer, recording whether a write error occurred. +type errWriter struct { + w io.Writer + err error +} + +func (w *errWriter) Write(b []byte) (int, error) { + n, err := w.w.Write(b) + if err != nil { + w.err = err + } + return n, err +} + +// tmpl executes the given template text on data, writing the result to w. +func tmpl(w io.Writer, text string, data interface{}) { + t := template.New("top") + t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize}) + template.Must(t.Parse(text)) + ew := &errWriter{w: w} + err := t.Execute(ew, data) + if ew.err != nil { + // I/O error writing. Ignore write on closed pipe. + if strings.Contains(ew.err.Error(), "pipe") { + os.Exit(1) + } + base.Fatalf("writing output: %v", ew.err) + } + if err != nil { + panic(err) + } +} + +func capitalize(s string) string { + if s == "" { + return s + } + r, n := utf8.DecodeRuneInString(s) + return string(unicode.ToTitle(r)) + s[n:] +} + +func PrintUsage(w io.Writer) { + bw := bufio.NewWriter(w) + tmpl(bw, usageTemplate, base.Commands) + bw.Flush() +}
diff --git a/vendor/cmd/go/internal/help/helpdoc.go b/vendor/cmd/go/internal/help/helpdoc.go new file mode 100644 index 0000000..c39af79 --- /dev/null +++ b/vendor/cmd/go/internal/help/helpdoc.go
@@ -0,0 +1,682 @@ +// Copyright 2011 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 help + +import "cmd/go/internal/base" + +var HelpC = &base.Command{ + UsageLine: "c", + Short: "calling between Go and C", + Long: ` +There are two different ways to call between Go and C/C++ code. + +The first is the cgo tool, which is part of the Go distribution. For +information on how to use it see the cgo documentation (go doc cmd/cgo). + +The second is the SWIG program, which is a general tool for +interfacing between languages. For information on SWIG see +http://swig.org/. When running go build, any file with a .swig +extension will be passed to SWIG. Any file with a .swigcxx extension +will be passed to SWIG with the -c++ option. + +When either cgo or SWIG is used, go build will pass any .c, .m, .s, +or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++ +compiler. The CC or CXX environment variables may be set to determine +the C or C++ compiler, respectively, to use. + `, +} + +var HelpPackages = &base.Command{ + UsageLine: "packages", + Short: "package lists", + Long: ` +Many commands apply to a set of packages: + + go action [packages] + +Usually, [packages] is a list of import paths. + +An import path that is a rooted path or that begins with +a . or .. element is interpreted as a file system path and +denotes the package in that directory. + +Otherwise, the import path P denotes the package found in +the directory DIR/src/P for some DIR listed in the GOPATH +environment variable (For more details see: 'go help gopath'). + +If no import paths are given, the action applies to the +package in the current directory. + +There are four reserved names for paths that should not be used +for packages to be built with the go tool: + +- "main" denotes the top-level package in a stand-alone executable. + +- "all" expands to all package directories found in all the GOPATH +trees. For example, 'go list all' lists all the packages on the local +system. + +- "std" is like all but expands to just the packages in the standard +Go library. + +- "cmd" expands to the Go repository's commands and their +internal libraries. + +Import paths beginning with "cmd/" only match source code in +the Go repository. + +An import path is a pattern if it includes one or more "..." wildcards, +each of which can match any string, including the empty string and +strings containing slashes. Such a pattern expands to all package +directories found in the GOPATH trees with names matching the +patterns. + +To make common patterns more convenient, there are two special cases. +First, /... at the end of the pattern can match an empty string, +so that net/... matches both net and packages in its subdirectories, like net/http. +Second, any slash-separated pattern element containing a wildcard never +participates in a match of the "vendor" element in the path of a vendored +package, so that ./... does not match packages in subdirectories of +./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do. +Note, however, that a directory named vendor that itself contains code +is not a vendored package: cmd/vendor would be a command named vendor, +and the pattern cmd/... matches it. +See golang.org/s/go15vendor for more about vendoring. + +An import path can also name a package to be downloaded from +a remote repository. Run 'go help importpath' for details. + +Every package in a program must have a unique import path. +By convention, this is arranged by starting each path with a +unique prefix that belongs to you. For example, paths used +internally at Google all begin with 'google', and paths +denoting remote repositories begin with the path to the code, +such as 'github.com/user/repo'. + +Packages in a program need not have unique package names, +but there are two reserved package names with special meaning. +The name main indicates a command, not a library. +Commands are built into binaries and cannot be imported. +The name documentation indicates documentation for +a non-Go program in the directory. Files in package documentation +are ignored by the go command. + +As a special case, if the package list is a list of .go files from a +single directory, the command is applied to a single synthesized +package made up of exactly those files, ignoring any build constraints +in those files and ignoring any other files in the directory. + +Directory and file names that begin with "." or "_" are ignored +by the go tool, as are directories named "testdata". + `, +} + +var HelpImportPath = &base.Command{ + UsageLine: "importpath", + Short: "import path syntax", + Long: ` + +An import path (see 'go help packages') denotes a package stored in the local +file system. In general, an import path denotes either a standard package (such +as "unicode/utf8") or a package found in one of the work spaces (For more +details see: 'go help gopath'). + +Relative import paths + +An import path beginning with ./ or ../ is called a relative path. +The toolchain supports relative import paths as a shortcut in two ways. + +First, a relative path can be used as a shorthand on the command line. +If you are working in the directory containing the code imported as +"unicode" and want to run the tests for "unicode/utf8", you can type +"go test ./utf8" instead of needing to specify the full path. +Similarly, in the reverse situation, "go test .." will test "unicode" from +the "unicode/utf8" directory. Relative patterns are also allowed, like +"go test ./..." to test all subdirectories. See 'go help packages' for details +on the pattern syntax. + +Second, if you are compiling a Go program not in a work space, +you can use a relative path in an import statement in that program +to refer to nearby code also not in a work space. +This makes it easy to experiment with small multipackage programs +outside of the usual work spaces, but such programs cannot be +installed with "go install" (there is no work space in which to install them), +so they are rebuilt from scratch each time they are built. +To avoid ambiguity, Go programs cannot use relative import paths +within a work space. + +Remote import paths + +Certain import paths also +describe how to obtain the source code for the package using +a revision control system. + +A few common code hosting sites have special syntax: + + Bitbucket (Git, Mercurial) + + import "bitbucket.org/user/project" + import "bitbucket.org/user/project/sub/directory" + + GitHub (Git) + + import "github.com/user/project" + import "github.com/user/project/sub/directory" + + Launchpad (Bazaar) + + import "launchpad.net/project" + import "launchpad.net/project/series" + import "launchpad.net/project/series/sub/directory" + + import "launchpad.net/~user/project/branch" + import "launchpad.net/~user/project/branch/sub/directory" + + IBM DevOps Services (Git) + + import "hub.jazz.net/git/user/project" + import "hub.jazz.net/git/user/project/sub/directory" + +For code hosted on other servers, import paths may either be qualified +with the version control type, or the go tool can dynamically fetch +the import path over https/http and discover where the code resides +from a <meta> tag in the HTML. + +To declare the code location, an import path of the form + + repository.vcs/path + +specifies the given repository, with or without the .vcs suffix, +using the named version control system, and then the path inside +that repository. The supported version control systems are: + + Bazaar .bzr + Git .git + Mercurial .hg + Subversion .svn + +For example, + + import "example.org/user/foo.hg" + +denotes the root directory of the Mercurial repository at +example.org/user/foo or foo.hg, and + + import "example.org/repo.git/foo/bar" + +denotes the foo/bar directory of the Git repository at +example.org/repo or repo.git. + +When a version control system supports multiple protocols, +each is tried in turn when downloading. For example, a Git +download tries https://, then git+ssh://. + +By default, downloads are restricted to known secure protocols +(e.g. https, ssh). To override this setting for Git downloads, the +GIT_ALLOW_PROTOCOL environment variable can be set (For more details see: +'go help environment'). + +If the import path is not a known code hosting site and also lacks a +version control qualifier, the go tool attempts to fetch the import +over https/http and looks for a <meta> tag in the document's HTML +<head>. + +The meta tag has the form: + + <meta name="go-import" content="import-prefix vcs repo-root"> + +The import-prefix is the import path corresponding to the repository +root. It must be a prefix or an exact match of the package being +fetched with "go get". If it's not an exact match, another http +request is made at the prefix to verify the <meta> tags match. + +The meta tag should appear as early in the file as possible. +In particular, it should appear before any raw JavaScript or CSS, +to avoid confusing the go command's restricted parser. + +The vcs is one of "git", "hg", "svn", etc, + +The repo-root is the root of the version control system +containing a scheme and not containing a .vcs qualifier. + +For example, + + import "example.org/pkg/foo" + +will result in the following requests: + + https://example.org/pkg/foo?go-get=1 (preferred) + http://example.org/pkg/foo?go-get=1 (fallback, only with -insecure) + +If that page contains the meta tag + + <meta name="go-import" content="example.org git https://code.org/r/p/exproj"> + +the go tool will verify that https://example.org/?go-get=1 contains the +same meta tag and then git clone https://code.org/r/p/exproj into +GOPATH/src/example.org. + +New downloaded packages are written to the first directory listed in the GOPATH +environment variable (For more details see: 'go help gopath'). + +The go command attempts to download the version of the +package appropriate for the Go release being used. +Run 'go help get' for more. + +Import path checking + +When the custom import path feature described above redirects to a +known code hosting site, each of the resulting packages has two possible +import paths, using the custom domain or the known hosting site. + +A package statement is said to have an "import comment" if it is immediately +followed (before the next newline) by a comment of one of these two forms: + + package math // import "path" + package math /* import "path" */ + +The go command will refuse to install a package with an import comment +unless it is being referred to by that import path. In this way, import comments +let package authors make sure the custom import path is used and not a +direct path to the underlying code hosting site. + +Import path checking is disabled for code found within vendor trees. +This makes it possible to copy code into alternate locations in vendor trees +without needing to update import comments. + +See https://golang.org/s/go14customimport for details. + `, +} + +var HelpGopath = &base.Command{ + UsageLine: "gopath", + Short: "GOPATH environment variable", + Long: ` +The Go path is used to resolve import statements. +It is implemented by and documented in the go/build package. + +The GOPATH environment variable lists places to look for Go code. +On Unix, the value is a colon-separated string. +On Windows, the value is a semicolon-separated string. +On Plan 9, the value is a list. + +If the environment variable is unset, GOPATH defaults +to a subdirectory named "go" in the user's home directory +($HOME/go on Unix, %USERPROFILE%\go on Windows), +unless that directory holds a Go distribution. +Run "go env GOPATH" to see the current GOPATH. + +See https://golang.org/wiki/SettingGOPATH to set a custom GOPATH. + +Each directory listed in GOPATH must have a prescribed structure: + +The src directory holds source code. The path below src +determines the import path or executable name. + +The pkg directory holds installed package objects. +As in the Go tree, each target operating system and +architecture pair has its own subdirectory of pkg +(pkg/GOOS_GOARCH). + +If DIR is a directory listed in the GOPATH, a package with +source in DIR/src/foo/bar can be imported as "foo/bar" and +has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a". + +The bin directory holds compiled commands. +Each command is named for its source directory, but only +the final element, not the entire path. That is, the +command with source in DIR/src/foo/quux is installed into +DIR/bin/quux, not DIR/bin/foo/quux. The "foo/" prefix is stripped +so that you can add DIR/bin to your PATH to get at the +installed commands. If the GOBIN environment variable is +set, commands are installed to the directory it names instead +of DIR/bin. GOBIN must be an absolute path. + +Here's an example directory layout: + + GOPATH=/home/user/go + + /home/user/go/ + src/ + foo/ + bar/ (go code in package bar) + x.go + quux/ (go code in package main) + y.go + bin/ + quux (installed command) + pkg/ + linux_amd64/ + foo/ + bar.a (installed package object) + +Go searches each directory listed in GOPATH to find source code, +but new packages are always downloaded into the first directory +in the list. + +See https://golang.org/doc/code.html for an example. + +Internal Directories + +Code in or below a directory named "internal" is importable only +by code in the directory tree rooted at the parent of "internal". +Here's an extended version of the directory layout above: + + /home/user/go/ + src/ + crash/ + bang/ (go code in package bang) + b.go + foo/ (go code in package foo) + f.go + bar/ (go code in package bar) + x.go + internal/ + baz/ (go code in package baz) + z.go + quux/ (go code in package main) + y.go + + +The code in z.go is imported as "foo/internal/baz", but that +import statement can only appear in source files in the subtree +rooted at foo. The source files foo/f.go, foo/bar/x.go, and +foo/quux/y.go can all import "foo/internal/baz", but the source file +crash/bang/b.go cannot. + +See https://golang.org/s/go14internal for details. + +Vendor Directories + +Go 1.6 includes support for using local copies of external dependencies +to satisfy imports of those dependencies, often referred to as vendoring. + +Code below a directory named "vendor" is importable only +by code in the directory tree rooted at the parent of "vendor", +and only using an import path that omits the prefix up to and +including the vendor element. + +Here's the example from the previous section, +but with the "internal" directory renamed to "vendor" +and a new foo/vendor/crash/bang directory added: + + /home/user/go/ + src/ + crash/ + bang/ (go code in package bang) + b.go + foo/ (go code in package foo) + f.go + bar/ (go code in package bar) + x.go + vendor/ + crash/ + bang/ (go code in package bang) + b.go + baz/ (go code in package baz) + z.go + quux/ (go code in package main) + y.go + +The same visibility rules apply as for internal, but the code +in z.go is imported as "baz", not as "foo/vendor/baz". + +Code in vendor directories deeper in the source tree shadows +code in higher directories. Within the subtree rooted at foo, an import +of "crash/bang" resolves to "foo/vendor/crash/bang", not the +top-level "crash/bang". + +Code in vendor directories is not subject to import path +checking (see 'go help importpath'). + +When 'go get' checks out or updates a git repository, it now also +updates submodules. + +Vendor directories do not affect the placement of new repositories +being checked out for the first time by 'go get': those are always +placed in the main GOPATH, never in a vendor subtree. + +See https://golang.org/s/go15vendor for details. + `, +} + +var HelpEnvironment = &base.Command{ + UsageLine: "environment", + Short: "environment variables", + Long: ` + +The go command, and the tools it invokes, examine a few different +environment variables. For many of these, you can see the default +value of on your system by running 'go env NAME', where NAME is the +name of the variable. + +General-purpose environment variables: + + GCCGO + The gccgo command to run for 'go build -compiler=gccgo'. + GOARCH + The architecture, or processor, for which to compile code. + Examples are amd64, 386, arm, ppc64. + GOBIN + The directory where 'go install' will install a command. + GOOS + The operating system for which to compile code. + Examples are linux, darwin, windows, netbsd. + GOPATH + For more details see: 'go help gopath'. + GORACE + Options for the race detector. + See https://golang.org/doc/articles/race_detector.html. + GOROOT + The root of the go tree. + GOTMPDIR + The directory where the go command will write + temporary source files, packages, and binaries. + GOCACHE + The directory where the go command will store + cached information for reuse in future builds. + +Environment variables for use with cgo: + + CC + The command to use to compile C code. + CGO_ENABLED + Whether the cgo command is supported. Either 0 or 1. + CGO_CFLAGS + Flags that cgo will pass to the compiler when compiling + C code. + CGO_CFLAGS_ALLOW + A regular expression specifying additional flags to allow + to appear in #cgo CFLAGS source code directives. + Does not apply to the CGO_CFLAGS environment variable. + CGO_CFLAGS_DISALLOW + A regular expression specifying flags that must be disallowed + from appearing in #cgo CFLAGS source code directives. + Does not apply to the CGO_CFLAGS environment variable. + CGO_CPPFLAGS, CGO_CPPFLAGS_ALLOW, CGO_CPPFLAGS_DISALLOW + Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, + but for the C preprocessor. + CGO_CXXFLAGS, CGO_CXXFLAGS_ALLOW, CGO_CXXFLAGS_DISALLOW + Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, + but for the C++ compiler. + CGO_FFLAGS, CGO_FFLAGS_ALLOW, CGO_FFLAGS_DISALLOW + Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, + but for the Fortran compiler. + CGO_LDFLAGS, CGO_LDFLAGS_ALLOW, CGO_LDFLAGS_DISALLOW + Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, + but for the linker. + CXX + The command to use to compile C++ code. + PKG_CONFIG + Path to pkg-config tool. + +Architecture-specific environment variables: + + GOARM + For GOARCH=arm, the ARM architecture for which to compile. + Valid values are 5, 6, 7. + GO386 + For GOARCH=386, the floating point instruction set. + Valid values are 387, sse2. + GOMIPS + For GOARCH=mips{,le}, whether to use floating point instructions. + Valid values are hardfloat (default), softfloat. + +Special-purpose environment variables: + + GOROOT_FINAL + The root of the installed Go tree, when it is + installed in a location other than where it is built. + File names in stack traces are rewritten from GOROOT to + GOROOT_FINAL. + GO_EXTLINK_ENABLED + Whether the linker should use external linking mode + when using -linkmode=auto with code that uses cgo. + Set to 0 to disable external linking mode, 1 to enable it. + GIT_ALLOW_PROTOCOL + Defined by Git. A colon-separated list of schemes that are allowed to be used + with git fetch/clone. If set, any scheme not explicitly mentioned will be + considered insecure by 'go get'. + `, +} + +var HelpFileType = &base.Command{ + UsageLine: "filetype", + Short: "file types", + Long: ` +The go command examines the contents of a restricted set of files +in each directory. It identifies which files to examine based on +the extension of the file name. These extensions are: + + .go + Go source files. + .c, .h + C source files. + If the package uses cgo or SWIG, these will be compiled with the + OS-native compiler (typically gcc); otherwise they will + trigger an error. + .cc, .cpp, .cxx, .hh, .hpp, .hxx + C++ source files. Only useful with cgo or SWIG, and always + compiled with the OS-native compiler. + .m + Objective-C source files. Only useful with cgo, and always + compiled with the OS-native compiler. + .s, .S + Assembler source files. + If the package uses cgo or SWIG, these will be assembled with the + OS-native assembler (typically gcc (sic)); otherwise they + will be assembled with the Go assembler. + .swig, .swigcxx + SWIG definition files. + .syso + System object files. + +Files of each of these types except .syso may contain build +constraints, but the go command stops scanning for build constraints +at the first item in the file that is not a blank line or //-style +line comment. See the go/build package documentation for +more details. + +Non-test Go source files can also include a //go:binary-only-package +comment, indicating that the package sources are included +for documentation only and must not be used to build the +package binary. This enables distribution of Go packages in +their compiled form alone. Even binary-only packages require +accurate import blocks listing required dependencies, so that +those dependencies can be supplied when linking the resulting +command. + `, +} + +var HelpBuildmode = &base.Command{ + UsageLine: "buildmode", + Short: "build modes", + Long: ` +The 'go build' and 'go install' commands take a -buildmode argument which +indicates which kind of object file is to be built. Currently supported values +are: + + -buildmode=archive + Build the listed non-main packages into .a files. Packages named + main are ignored. + + -buildmode=c-archive + Build the listed main package, plus all packages it imports, + into a C archive file. The only callable symbols will be those + functions exported using a cgo //export comment. Requires + exactly one main package to be listed. + + -buildmode=c-shared + Build the listed main package, plus all packages it imports, + into a C shared library. The only callable symbols will + be those functions exported using a cgo //export comment. + Requires exactly one main package to be listed. + + -buildmode=default + Listed main packages are built into executables and listed + non-main packages are built into .a files (the default + behavior). + + -buildmode=shared + Combine all the listed non-main packages into a single shared + library that will be used when building with the -linkshared + option. Packages named main are ignored. + + -buildmode=exe + Build the listed main packages and everything they import into + executables. Packages not named main are ignored. + + -buildmode=pie + Build the listed main packages and everything they import into + position independent executables (PIE). Packages not named + main are ignored. + + -buildmode=plugin + Build the listed main packages, plus all packages that they + import, into a Go plugin. Packages not named main are ignored. +`, +} + +var HelpCache = &base.Command{ + UsageLine: "cache", + Short: "build and test caching", + Long: ` +The go command caches build outputs for reuse in future builds. +The default location for cache data is a subdirectory named go-build +in the standard user cache directory for the current operating system. +Setting the GOCACHE environment variable overrides this default, +and running 'go env GOCACHE' prints the current cache directory. + +The go command periodically deletes cached data that has not been +used recently. Running 'go clean -cache' deletes all cached data. + +The build cache correctly accounts for changes to Go source files, +compilers, compiler options, and so on: cleaning the cache explicitly +should not be necessary in typical use. However, the build cache +does not detect changes to C libraries imported with cgo. +If you have made changes to the C libraries on your system, you +will need to clean the cache explicitly or else use the -a build flag +(see 'go help build') to force rebuilding of packages that +depend on the updated C libraries. + +The go command also caches successful package test results. +See 'go help test' for details. Running 'go clean -testcache' removes +all cached test results (but not cached build results). + +The GODEBUG environment variable can enable printing of debugging +information about the state of the cache: + +GODEBUG=gocacheverify=1 causes the go command to bypass the +use of any cache entries and instead rebuild everything and check +that the results match existing cache entries. + +GODEBUG=gocachehash=1 causes the go command to print the inputs +for all of the content hashes it uses to construct cache lookup keys. +The output is voluminous but can be useful for debugging the cache. + +GODEBUG=gocachetest=1 causes the go command to print details of its +decisions about whether to reuse a cached test result. +`, +}
diff --git a/vendor/cmd/go/internal/list/context.go b/vendor/cmd/go/internal/list/context.go new file mode 100644 index 0000000..68d691e --- /dev/null +++ b/vendor/cmd/go/internal/list/context.go
@@ -0,0 +1,37 @@ +// Copyright 2014 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 list + +import ( + "go/build" +) + +type Context struct { + GOARCH string `json:",omitempty"` // target architecture + GOOS string `json:",omitempty"` // target operating system + GOROOT string `json:",omitempty"` // Go root + GOPATH string `json:",omitempty"` // Go path + CgoEnabled bool `json:",omitempty"` // whether cgo can be used + UseAllFiles bool `json:",omitempty"` // use files regardless of +build lines, file names + Compiler string `json:",omitempty"` // compiler to assume when computing target paths + BuildTags []string `json:",omitempty"` // build constraints to match in +build lines + ReleaseTags []string `json:",omitempty"` // releases the current release is compatible with + InstallSuffix string `json:",omitempty"` // suffix to use in the name of the install dir +} + +func newContext(c *build.Context) *Context { + return &Context{ + GOARCH: c.GOARCH, + GOOS: c.GOOS, + GOROOT: c.GOROOT, + GOPATH: c.GOPATH, + CgoEnabled: c.CgoEnabled, + UseAllFiles: c.UseAllFiles, + Compiler: c.Compiler, + BuildTags: c.BuildTags, + ReleaseTags: c.ReleaseTags, + InstallSuffix: c.InstallSuffix, + } +}
diff --git a/vendor/cmd/go/internal/list/list.go b/vendor/cmd/go/internal/list/list.go new file mode 100644 index 0000000..7435273 --- /dev/null +++ b/vendor/cmd/go/internal/list/list.go
@@ -0,0 +1,257 @@ +// Copyright 2011 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 list implements the ``go list'' command. +package list + +import ( + "bufio" + "encoding/json" + "io" + "os" + "strings" + "text/template" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/go/internal/work" +) + +var CmdList = &base.Command{ + UsageLine: "list [-e] [-f format] [-json] [build flags] [packages]", + Short: "list packages", + Long: ` +List lists the packages named by the import paths, one per line. + +The default output shows the package import path: + + bytes + encoding/json + github.com/gorilla/mux + golang.org/x/net/html + +The -f flag specifies an alternate format for the list, using the +syntax of package template. The default output is equivalent to -f +'{{.ImportPath}}'. The struct being passed to the template is: + + type Package struct { + Dir string // directory containing package sources + ImportPath string // import path of package in dir + ImportComment string // path in import comment on package statement + Name string // package name + Doc string // package documentation string + Target string // install path + Shlib string // the shared library that contains this package (only set when -linkshared) + Goroot bool // is this package in the Go root? + Standard bool // is this package part of the standard Go library? + Stale bool // would 'go install' do anything for this package? + StaleReason string // explanation for Stale==true + Root string // Go root or Go path dir containing this package + ConflictDir string // this directory shadows Dir in $GOPATH + BinaryOnly bool // binary-only package: cannot be recompiled from sources + + // Source files + GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) + CgoFiles []string // .go sources files that import "C" + IgnoredGoFiles []string // .go sources ignored due to build constraints + CFiles []string // .c source files + CXXFiles []string // .cc, .cxx and .cpp source files + MFiles []string // .m source files + HFiles []string // .h, .hh, .hpp and .hxx source files + FFiles []string // .f, .F, .for and .f90 Fortran source files + SFiles []string // .s source files + SwigFiles []string // .swig files + SwigCXXFiles []string // .swigcxx files + SysoFiles []string // .syso object files to add to archive + TestGoFiles []string // _test.go files in package + XTestGoFiles []string // _test.go files outside package + + // Cgo directives + CgoCFLAGS []string // cgo: flags for C compiler + CgoCPPFLAGS []string // cgo: flags for C preprocessor + CgoCXXFLAGS []string // cgo: flags for C++ compiler + CgoFFLAGS []string // cgo: flags for Fortran compiler + CgoLDFLAGS []string // cgo: flags for linker + CgoPkgConfig []string // cgo: pkg-config names + + // Dependency information + Imports []string // import paths used by this package + Deps []string // all (recursively) imported dependencies + TestImports []string // imports from TestGoFiles + XTestImports []string // imports from XTestGoFiles + + // Error information + Incomplete bool // this package or a dependency has an error + Error *PackageError // error loading package + DepsErrors []*PackageError // errors loading dependencies + } + +Packages stored in vendor directories report an ImportPath that includes the +path to the vendor directory (for example, "d/vendor/p" instead of "p"), +so that the ImportPath uniquely identifies a given copy of a package. +The Imports, Deps, TestImports, and XTestImports lists also contain these +expanded imports paths. See golang.org/s/go15vendor for more about vendoring. + +The error information, if any, is + + type PackageError struct { + ImportStack []string // shortest path from package named on command line to this one + Pos string // position of error (if present, file:line:col) + Err string // the error itself + } + +The template function "join" calls strings.Join. + +The template function "context" returns the build context, defined as: + + type Context struct { + GOARCH string // target architecture + GOOS string // target operating system + GOROOT string // Go root + GOPATH string // Go path + CgoEnabled bool // whether cgo can be used + UseAllFiles bool // use files regardless of +build lines, file names + Compiler string // compiler to assume when computing target paths + BuildTags []string // build constraints to match in +build lines + ReleaseTags []string // releases the current release is compatible with + InstallSuffix string // suffix to use in the name of the install dir + } + +For more information about the meaning of these fields see the documentation +for the go/build package's Context type. + +The -json flag causes the package data to be printed in JSON format +instead of using the template format. + +The -e flag changes the handling of erroneous packages, those that +cannot be found or are malformed. By default, the list command +prints an error to standard error for each erroneous package and +omits the packages from consideration during the usual printing. +With the -e flag, the list command never prints errors to standard +error and instead processes the erroneous packages with the usual +printing. Erroneous packages will have a non-empty ImportPath and +a non-nil Error field; other information may or may not be missing +(zeroed). + +For more about build flags, see 'go help build'. + +For more about specifying packages, see 'go help packages'. + `, +} + +func init() { + CmdList.Run = runList // break init cycle + work.AddBuildFlags(CmdList) +} + +var listE = CmdList.Flag.Bool("e", false, "") +var listFmt = CmdList.Flag.String("f", "{{.ImportPath}}", "") +var listJson = CmdList.Flag.Bool("json", false, "") +var nl = []byte{'\n'} + +func runList(cmd *base.Command, args []string) { + work.BuildInit() + out := newTrackingWriter(os.Stdout) + defer out.w.Flush() + + var do func(*load.PackagePublic) + if *listJson { + do = func(p *load.PackagePublic) { + b, err := json.MarshalIndent(p, "", "\t") + if err != nil { + out.Flush() + base.Fatalf("%s", err) + } + out.Write(b) + out.Write(nl) + } + } else { + var cachedCtxt *Context + context := func() *Context { + if cachedCtxt == nil { + cachedCtxt = newContext(&cfg.BuildContext) + } + return cachedCtxt + } + fm := template.FuncMap{ + "join": strings.Join, + "context": context, + } + tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt) + if err != nil { + base.Fatalf("%s", err) + } + do = func(p *load.PackagePublic) { + if err := tmpl.Execute(out, p); err != nil { + out.Flush() + base.Fatalf("%s", err) + } + if out.NeedNL() { + out.Write(nl) + } + } + } + + var pkgs []*load.Package + if *listE { + pkgs = load.PackagesAndErrors(args) + } else { + pkgs = load.Packages(args) + } + + // Estimate whether staleness information is needed, + // since it's a little bit of work to compute. + needStale := *listJson || strings.Contains(*listFmt, ".Stale") + if needStale { + var b work.Builder + b.Init() + b.ComputeStaleOnly = true + a := &work.Action{} + // TODO: Use pkgsFilter? + for _, p := range pkgs { + a.Deps = append(a.Deps, b.AutoAction(work.ModeInstall, work.ModeInstall, p)) + } + b.Do(a) + } + + for _, pkg := range pkgs { + // Show vendor-expanded paths in listing + pkg.TestImports = pkg.Vendored(pkg.TestImports) + pkg.XTestImports = pkg.Vendored(pkg.XTestImports) + + do(&pkg.PackagePublic) + } +} + +// TrackingWriter tracks the last byte written on every write so +// we can avoid printing a newline if one was already written or +// if there is no output at all. +type TrackingWriter struct { + w *bufio.Writer + last byte +} + +func newTrackingWriter(w io.Writer) *TrackingWriter { + return &TrackingWriter{ + w: bufio.NewWriter(w), + last: '\n', + } +} + +func (t *TrackingWriter) Write(p []byte) (n int, err error) { + n, err = t.w.Write(p) + if n > 0 { + t.last = p[n-1] + } + return +} + +func (t *TrackingWriter) Flush() { + t.w.Flush() +} + +func (t *TrackingWriter) NeedNL() bool { + return t.last != '\n' +}
diff --git a/vendor/cmd/go/internal/load/flag.go b/vendor/cmd/go/internal/load/flag.go new file mode 100644 index 0000000..7ad4208 --- /dev/null +++ b/vendor/cmd/go/internal/load/flag.go
@@ -0,0 +1,121 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package load + +import ( + "cmd/go/internal/base" + "cmd/go/internal/str" + "fmt" + "strings" +) + +var ( + BuildAsmflags PerPackageFlag // -asmflags + BuildGcflags PerPackageFlag // -gcflags + BuildLdflags PerPackageFlag // -ldflags + BuildGccgoflags PerPackageFlag // -gccgoflags +) + +// A PerPackageFlag is a command-line flag implementation (a flag.Value) +// that allows specifying different effective flags for different packages. +// See 'go help build' for more details about per-package flags. +type PerPackageFlag struct { + present bool + values []ppfValue +} + +// A ppfValue is a single <pattern>=<flags> per-package flag value. +type ppfValue struct { + match func(*Package) bool // compiled pattern + flags []string +} + +// Set is called each time the flag is encountered on the command line. +func (f *PerPackageFlag) Set(v string) error { + return f.set(v, base.Cwd) +} + +// set is the implementation of Set, taking a cwd (current working directory) for easier testing. +func (f *PerPackageFlag) set(v, cwd string) error { + f.present = true + match := func(p *Package) bool { return p.Internal.CmdlinePkg || p.Internal.CmdlineFiles } // default predicate with no pattern + // For backwards compatibility with earlier flag splitting, ignore spaces around flags. + v = strings.TrimSpace(v) + if v == "" { + // Special case: -gcflags="" means no flags for command-line arguments + // (overrides previous -gcflags="-whatever"). + f.values = append(f.values, ppfValue{match, []string{}}) + return nil + } + if !strings.HasPrefix(v, "-") { + i := strings.Index(v, "=") + if i < 0 { + return fmt.Errorf("missing =<value> in <pattern>=<value>") + } + if i == 0 { + return fmt.Errorf("missing <pattern> in <pattern>=<value>") + } + pattern := strings.TrimSpace(v[:i]) + match = MatchPackage(pattern, cwd) + v = v[i+1:] + } + flags, err := str.SplitQuotedFields(v) + if err != nil { + return err + } + if flags == nil { + flags = []string{} + } + f.values = append(f.values, ppfValue{match, flags}) + return nil +} + +// String is required to implement flag.Value. +// It is not used, because cmd/go never calls flag.PrintDefaults. +func (f *PerPackageFlag) String() string { return "<PerPackageFlag>" } + +// Present reports whether the flag appeared on the command line. +func (f *PerPackageFlag) Present() bool { + return f.present +} + +// For returns the flags to use for the given package. +func (f *PerPackageFlag) For(p *Package) []string { + flags := []string{} + for _, v := range f.values { + if v.match(p) { + flags = v.flags + } + } + return flags +} + +var cmdlineMatchers []func(*Package) bool + +// SetCmdlinePatterns records the set of patterns given on the command line, +// for use by the PerPackageFlags. +func SetCmdlinePatterns(args []string) { + setCmdlinePatterns(args, base.Cwd) +} + +func setCmdlinePatterns(args []string, cwd string) { + if len(args) == 0 { + args = []string{"."} + } + cmdlineMatchers = nil // allow reset for testing + for _, arg := range args { + cmdlineMatchers = append(cmdlineMatchers, MatchPackage(arg, cwd)) + } +} + +// isCmdlinePkg reports whether p is a package listed on the command line. +func isCmdlinePkg(p *Package) bool { + for _, m := range cmdlineMatchers { + if m(p) { + return true + } + } + return false +}
diff --git a/vendor/cmd/go/internal/load/flag_test.go b/vendor/cmd/go/internal/load/flag_test.go new file mode 100644 index 0000000..d3223e1 --- /dev/null +++ b/vendor/cmd/go/internal/load/flag_test.go
@@ -0,0 +1,135 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package load + +import ( + "fmt" + "path/filepath" + "reflect" + "testing" +) + +type ppfTestPackage struct { + path string + dir string + cmdline bool + flags []string +} + +type ppfTest struct { + args []string + pkgs []ppfTestPackage +} + +var ppfTests = []ppfTest{ + // -gcflags=-S applies only to packages on command line. + { + args: []string{"-S"}, + pkgs: []ppfTestPackage{ + {cmdline: true, flags: []string{"-S"}}, + {cmdline: false, flags: []string{}}, + }, + }, + + // -gcflags=-S -gcflags= overrides the earlier -S. + { + args: []string{"-S", ""}, + pkgs: []ppfTestPackage{ + {cmdline: true, flags: []string{}}, + }, + }, + + // -gcflags=net=-S applies only to package net + { + args: []string{"net=-S"}, + pkgs: []ppfTestPackage{ + {path: "math", cmdline: true, flags: []string{}}, + {path: "net", flags: []string{"-S"}}, + }, + }, + + // -gcflags=net=-S -gcflags=net= also overrides the earlier -S + { + args: []string{"net=-S", "net="}, + pkgs: []ppfTestPackage{ + {path: "net", flags: []string{}}, + }, + }, + + // -gcflags=net/...=-S net math + // applies -S to net and net/http but not math + { + args: []string{"net/...=-S"}, + pkgs: []ppfTestPackage{ + {path: "net", flags: []string{"-S"}}, + {path: "net/http", flags: []string{"-S"}}, + {path: "math", flags: []string{}}, + }, + }, + + // -gcflags=net/...=-S -gcflags=-m net math + // applies -m to net and math and -S to other packages matching net/... + // (net matches too, but it was grabbed by the later -gcflags). + { + args: []string{"net/...=-S", "-m"}, + pkgs: []ppfTestPackage{ + {path: "net", cmdline: true, flags: []string{"-m"}}, + {path: "math", cmdline: true, flags: []string{"-m"}}, + {path: "net", cmdline: false, flags: []string{"-S"}}, + {path: "net/http", flags: []string{"-S"}}, + {path: "math", flags: []string{}}, + }, + }, + + // relative path patterns + // ppfDirTest(pattern, n, dirs...) says the first n dirs should match and the others should not. + ppfDirTest(".", 1, "/my/test/dir", "/my/test", "/my/test/other", "/my/test/dir/sub"), + ppfDirTest("..", 1, "/my/test", "/my/test/dir", "/my/test/other", "/my/test/dir/sub"), + ppfDirTest("./sub", 1, "/my/test/dir/sub", "/my/test", "/my/test/dir", "/my/test/other", "/my/test/dir/sub/sub"), + ppfDirTest("../other", 1, "/my/test/other", "/my/test", "/my/test/dir", "/my/test/other/sub", "/my/test/dir/other", "/my/test/dir/sub"), + ppfDirTest("./...", 3, "/my/test/dir", "/my/test/dir/sub", "/my/test/dir/sub/sub", "/my/test/other", "/my/test/other/sub"), + ppfDirTest("../...", 4, "/my/test/dir", "/my/test/other", "/my/test/dir/sub", "/my/test/other/sub", "/my/other/test"), + ppfDirTest("../...sub...", 3, "/my/test/dir/sub", "/my/test/othersub", "/my/test/yellowsubmarine", "/my/other/test"), +} + +func ppfDirTest(pattern string, nmatch int, dirs ...string) ppfTest { + var pkgs []ppfTestPackage + for i, d := range dirs { + flags := []string{} + if i < nmatch { + flags = []string{"-S"} + } + pkgs = append(pkgs, ppfTestPackage{path: "p", dir: d, flags: flags}) + } + return ppfTest{args: []string{pattern + "=-S"}, pkgs: pkgs} +} + +func TestPerPackageFlag(t *testing.T) { + nativeDir := func(d string) string { + if filepath.Separator == '\\' { + return `C:` + filepath.FromSlash(d) + } + return d + } + + for i, tt := range ppfTests { + t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) { + ppFlags := new(PerPackageFlag) + for _, arg := range tt.args { + t.Logf("set(%s)", arg) + if err := ppFlags.set(arg, nativeDir("/my/test/dir")); err != nil { + t.Fatal(err) + } + } + for _, p := range tt.pkgs { + dir := nativeDir(p.dir) + flags := ppFlags.For(&Package{PackagePublic: PackagePublic{ImportPath: p.path, Dir: dir}, Internal: PackageInternal{CmdlinePkg: p.cmdline}}) + if !reflect.DeepEqual(flags, p.flags) { + t.Errorf("For(%v, %v, %v) = %v, want %v", p.path, dir, p.cmdline, flags, p.flags) + } + } + }) + } +}
diff --git a/vendor/cmd/go/internal/load/icfg.go b/vendor/cmd/go/internal/load/icfg.go new file mode 100644 index 0000000..d8dd664 --- /dev/null +++ b/vendor/cmd/go/internal/load/icfg.go
@@ -0,0 +1,78 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package load + +import ( + "bytes" + "encoding/json" + "errors" + "io/ioutil" +) + +// DebugDeprecatedImportcfg is installed as the undocumented -debug-deprecated-importcfg build flag. +// It is useful for debugging subtle problems in the go command logic but not something +// we want users to depend on. The hope is that the "deprecated" will make that clear. +// We intend to remove this flag in Go 1.11. +var DebugDeprecatedImportcfg debugDeprecatedImportcfgFlag + +type debugDeprecatedImportcfgFlag struct { + enabled bool + Import map[string]string + Pkg map[string]*debugDeprecatedImportcfgPkg +} + +type debugDeprecatedImportcfgPkg struct { + Dir string + Import map[string]string +} + +var ( + debugDeprecatedImportcfgMagic = []byte("# debug-deprecated-importcfg\n") + errImportcfgSyntax = errors.New("malformed syntax") +) + +func (f *debugDeprecatedImportcfgFlag) String() string { return "" } + +func (f *debugDeprecatedImportcfgFlag) Set(x string) error { + if x == "" { + *f = debugDeprecatedImportcfgFlag{} + return nil + } + data, err := ioutil.ReadFile(x) + if err != nil { + return err + } + + if !bytes.HasPrefix(data, debugDeprecatedImportcfgMagic) { + return errImportcfgSyntax + } + data = data[len(debugDeprecatedImportcfgMagic):] + + f.Import = nil + f.Pkg = nil + if err := json.Unmarshal(data, &f); err != nil { + return errImportcfgSyntax + } + f.enabled = true + return nil +} + +func (f *debugDeprecatedImportcfgFlag) lookup(parent *Package, path string) (dir, newPath string) { + newPath = path + if p := f.Import[path]; p != "" { + newPath = p + } + if parent != nil { + if p1 := f.Pkg[parent.ImportPath]; p1 != nil { + if p := p1.Import[path]; p != "" { + newPath = p + } + } + } + if p2 := f.Pkg[newPath]; p2 != nil { + return p2.Dir, newPath + } + return "", "" +}
diff --git a/vendor/cmd/go/internal/load/match_test.go b/vendor/cmd/go/internal/load/match_test.go new file mode 100644 index 0000000..b8d67da --- /dev/null +++ b/vendor/cmd/go/internal/load/match_test.go
@@ -0,0 +1,165 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package load + +import ( + "strings" + "testing" +) + +var matchPatternTests = ` + pattern ... + match foo + + pattern net + match net + not net/http + + pattern net/http + match net/http + not net + + pattern net... + match net net/http netchan + not not/http not/net/http + + # Special cases. Quoting docs: + + # First, /... at the end of the pattern can match an empty string, + # so that net/... matches both net and packages in its subdirectories, like net/http. + pattern net/... + match net net/http + not not/http not/net/http netchan + + # Second, any slash-separted pattern element containing a wildcard never + # participates in a match of the "vendor" element in the path of a vendored + # package, so that ./... does not match packages in subdirectories of + # ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do. + # Note, however, that a directory named vendor that itself contains code + # is not a vendored package: cmd/vendor would be a command named vendor, + # and the pattern cmd/... matches it. + pattern ./... + match ./vendor ./mycode/vendor + not ./vendor/foo ./mycode/vendor/foo + + pattern ./vendor/... + match ./vendor/foo ./vendor/foo/vendor + not ./vendor/foo/vendor/bar + + pattern mycode/vendor/... + match mycode/vendor mycode/vendor/foo mycode/vendor/foo/vendor + not mycode/vendor/foo/vendor/bar + + pattern x/vendor/y + match x/vendor/y + not x/vendor + + pattern x/vendor/y/... + match x/vendor/y x/vendor/y/z x/vendor/y/vendor x/vendor/y/z/vendor + not x/vendor/y/vendor/z + + pattern .../vendor/... + match x/vendor/y x/vendor/y/z x/vendor/y/vendor x/vendor/y/z/vendor +` + +func TestMatchPattern(t *testing.T) { + testPatterns(t, "matchPattern", matchPatternTests, func(pattern, name string) bool { + return matchPattern(pattern)(name) + }) +} + +var treeCanMatchPatternTests = ` + pattern ... + match foo + + pattern net + match net + not net/http + + pattern net/http + match net net/http + + pattern net... + match net netchan net/http + not not/http not/net/http + + pattern net/... + match net net/http + not not/http netchan + + pattern abc.../def + match abcxyz + not xyzabc + + pattern x/y/z/... + match x x/y x/y/z x/y/z/w + + pattern x/y/z + match x x/y x/y/z + not x/y/z/w + + pattern x/.../y/z + match x/a/b/c + not y/x/a/b/c +` + +func TestTreeCanMatchPattern(t *testing.T) { + testPatterns(t, "treeCanMatchPattern", treeCanMatchPatternTests, func(pattern, name string) bool { + return treeCanMatchPattern(pattern)(name) + }) +} + +var hasPathPrefixTests = []stringPairTest{ + {"abc", "a", false}, + {"a/bc", "a", true}, + {"a", "a", true}, + {"a/bc", "a/", true}, +} + +func TestHasPathPrefix(t *testing.T) { + testStringPairs(t, "hasPathPrefix", hasPathPrefixTests, hasPathPrefix) +} + +type stringPairTest struct { + in1 string + in2 string + out bool +} + +func testStringPairs(t *testing.T, name string, tests []stringPairTest, f func(string, string) bool) { + for _, tt := range tests { + if out := f(tt.in1, tt.in2); out != tt.out { + t.Errorf("%s(%q, %q) = %v, want %v", name, tt.in1, tt.in2, out, tt.out) + } + } +} + +func testPatterns(t *testing.T, name, tests string, fn func(string, string) bool) { + var patterns []string + for _, line := range strings.Split(tests, "\n") { + if i := strings.Index(line, "#"); i >= 0 { + line = line[:i] + } + f := strings.Fields(line) + if len(f) == 0 { + continue + } + switch f[0] { + default: + t.Fatalf("unknown directive %q", f[0]) + case "pattern": + patterns = f[1:] + case "match", "not": + want := f[0] == "match" + for _, pattern := range patterns { + for _, in := range f[1:] { + if fn(pattern, in) != want { + t.Errorf("%s(%q, %q) = %v, want %v", name, pattern, in, !want, want) + } + } + } + } + } +}
diff --git a/vendor/cmd/go/internal/load/path.go b/vendor/cmd/go/internal/load/path.go new file mode 100644 index 0000000..45a9e7b --- /dev/null +++ b/vendor/cmd/go/internal/load/path.go
@@ -0,0 +1,58 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package load + +import ( + "path/filepath" + "strings" +) + +// hasSubdir reports whether dir is a subdirectory of +// (possibly multiple levels below) root. +// If so, it sets rel to the path fragment that must be +// appended to root to reach dir. +func hasSubdir(root, dir string) (rel string, ok bool) { + if p, err := filepath.EvalSymlinks(root); err == nil { + root = p + } + if p, err := filepath.EvalSymlinks(dir); err == nil { + dir = p + } + const sep = string(filepath.Separator) + root = filepath.Clean(root) + if !strings.HasSuffix(root, sep) { + root += sep + } + dir = filepath.Clean(dir) + if !strings.HasPrefix(dir, root) { + return "", false + } + return filepath.ToSlash(dir[len(root):]), true +} + +// hasPathPrefix reports whether the path s begins with the +// elements in prefix. +func hasPathPrefix(s, prefix string) bool { + switch { + default: + return false + case len(s) == len(prefix): + return s == prefix + case len(s) > len(prefix): + if prefix != "" && prefix[len(prefix)-1] == '/' { + return strings.HasPrefix(s, prefix) + } + return s[len(prefix)] == '/' && s[:len(prefix)] == prefix + } +} + +// expandPath returns the symlink-expanded form of path. +func expandPath(p string) string { + x, err := filepath.EvalSymlinks(p) + if err == nil { + return x + } + return p +}
diff --git a/vendor/cmd/go/internal/load/pkg.go b/vendor/cmd/go/internal/load/pkg.go new file mode 100644 index 0000000..b006d41 --- /dev/null +++ b/vendor/cmd/go/internal/load/pkg.go
@@ -0,0 +1,1727 @@ +// Copyright 2011 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 load loads packages. +package load + +import ( + "fmt" + "go/build" + "go/token" + "io/ioutil" + "os" + pathpkg "path" + "path/filepath" + "sort" + "strings" + "unicode" + "unicode/utf8" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/str" +) + +var IgnoreImports bool // control whether we ignore imports in packages + +// A Package describes a single package found in a directory. +type Package struct { + PackagePublic // visible in 'go list' + Internal PackageInternal // for use inside go command only +} + +type PackagePublic struct { + // Note: These fields are part of the go command's public API. + // See list.go. It is okay to add fields, but not to change or + // remove existing ones. Keep in sync with list.go + Dir string `json:",omitempty"` // directory containing package sources + ImportPath string `json:",omitempty"` // import path of package in dir + ImportComment string `json:",omitempty"` // path in import comment on package statement + Name string `json:",omitempty"` // package name + Doc string `json:",omitempty"` // package documentation string + Target string `json:",omitempty"` // installed target for this package (may be executable) + Shlib string `json:",omitempty"` // the shared library that contains this package (only set when -linkshared) + Goroot bool `json:",omitempty"` // is this package found in the Go root? + Standard bool `json:",omitempty"` // is this package part of the standard Go library? + Root string `json:",omitempty"` // Go root or Go path dir containing this package + ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory + BinaryOnly bool `json:",omitempty"` // package cannot be recompiled + + // Stale and StaleReason remain here *only* for the list command. + // They are only initialized in preparation for list execution. + // The regular build determines staleness on the fly during action execution. + Stale bool `json:",omitempty"` // would 'go install' do anything for this package? + StaleReason string `json:",omitempty"` // why is Stale true? + + // Source files + // If you add to this list you MUST add to p.AllFiles (below) too. + // Otherwise file name security lists will not apply to any new additions. + GoFiles []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) + CgoFiles []string `json:",omitempty"` // .go sources files that import "C" + IgnoredGoFiles []string `json:",omitempty"` // .go sources ignored due to build constraints + CFiles []string `json:",omitempty"` // .c source files + CXXFiles []string `json:",omitempty"` // .cc, .cpp and .cxx source files + MFiles []string `json:",omitempty"` // .m source files + HFiles []string `json:",omitempty"` // .h, .hh, .hpp and .hxx source files + FFiles []string `json:",omitempty"` // .f, .F, .for and .f90 Fortran source files + SFiles []string `json:",omitempty"` // .s source files + SwigFiles []string `json:",omitempty"` // .swig files + SwigCXXFiles []string `json:",omitempty"` // .swigcxx files + SysoFiles []string `json:",omitempty"` // .syso system object files added to package + + // Cgo directives + CgoCFLAGS []string `json:",omitempty"` // cgo: flags for C compiler + CgoCPPFLAGS []string `json:",omitempty"` // cgo: flags for C preprocessor + CgoCXXFLAGS []string `json:",omitempty"` // cgo: flags for C++ compiler + CgoFFLAGS []string `json:",omitempty"` // cgo: flags for Fortran compiler + CgoLDFLAGS []string `json:",omitempty"` // cgo: flags for linker + CgoPkgConfig []string `json:",omitempty"` // cgo: pkg-config names + + // Dependency information + Imports []string `json:",omitempty"` // import paths used by this package + Deps []string `json:",omitempty"` // all (recursively) imported dependencies + + // Error information + Incomplete bool `json:",omitempty"` // was there an error loading this package or dependencies? + Error *PackageError `json:",omitempty"` // error loading this package (not dependencies) + DepsErrors []*PackageError `json:",omitempty"` // errors loading dependencies + + // Test information + // If you add to this list you MUST add to p.AllFiles (below) too. + // Otherwise file name security lists will not apply to any new additions. + TestGoFiles []string `json:",omitempty"` // _test.go files in package + TestImports []string `json:",omitempty"` // imports from TestGoFiles + XTestGoFiles []string `json:",omitempty"` // _test.go files outside package + XTestImports []string `json:",omitempty"` // imports from XTestGoFiles +} + +// AllFiles returns the names of all the files considered for the package. +// This is used for sanity and security checks, so we include all files, +// even IgnoredGoFiles, because some subcommands consider them. +// The go/build package filtered others out (like foo_wrongGOARCH.s) +// and that's OK. +func (p *Package) AllFiles() []string { + return str.StringList( + p.GoFiles, + p.CgoFiles, + p.IgnoredGoFiles, + p.CFiles, + p.CXXFiles, + p.MFiles, + p.HFiles, + p.FFiles, + p.SFiles, + p.SwigFiles, + p.SwigCXXFiles, + p.SysoFiles, + p.TestGoFiles, + p.XTestGoFiles, + ) +} + +type PackageInternal struct { + // Unexported fields are not part of the public API. + Build *build.Package + Imports []*Package // this package's direct imports + RawImports []string // this package's original imports as they appear in the text of the program + ForceLibrary bool // this package is a library (even if named "main") + CmdlineFiles bool // package built from files listed on command line + CmdlinePkg bool // package listed on command line + Local bool // imported via local path (./ or ../) + LocalPrefix string // interpret ./ and ../ imports relative to this prefix + ExeName string // desired name for temporary executable + CoverMode string // preprocess Go source files with the coverage tool in this mode + CoverVars map[string]*CoverVar // variables created by coverage analysis + OmitDebug bool // tell linker not to write debug information + GobinSubdir bool // install target would be subdir of GOBIN + + Asmflags []string // -asmflags for this package + Gcflags []string // -gcflags for this package + Ldflags []string // -ldflags for this package + Gccgoflags []string // -gccgoflags for this package +} + +type NoGoError struct { + Package *Package +} + +func (e *NoGoError) Error() string { + // Count files beginning with _ and ., which we will pretend don't exist at all. + dummy := 0 + for _, name := range e.Package.IgnoredGoFiles { + if strings.HasPrefix(name, "_") || strings.HasPrefix(name, ".") { + dummy++ + } + } + + if len(e.Package.IgnoredGoFiles) > dummy { + // Go files exist, but they were ignored due to build constraints. + return "build constraints exclude all Go files in " + e.Package.Dir + } + if len(e.Package.TestGoFiles)+len(e.Package.XTestGoFiles) > 0 { + // Test Go files exist, but we're not interested in them. + // The double-negative is unfortunate but we want e.Package.Dir + // to appear at the end of error message. + return "no non-test Go files in " + e.Package.Dir + } + return "no Go files in " + e.Package.Dir +} + +// Vendored returns the vendor-resolved version of imports, +// which should be p.TestImports or p.XTestImports, NOT p.Imports. +// The imports in p.TestImports and p.XTestImports are not recursively +// loaded during the initial load of p, so they list the imports found in +// the source file, but most processing should be over the vendor-resolved +// import paths. We do this resolution lazily both to avoid file system work +// and because the eventual real load of the test imports (during 'go test') +// can produce better error messages if it starts with the original paths. +// The initial load of p loads all the non-test imports and rewrites +// the vendored paths, so nothing should ever call p.vendored(p.Imports). +func (p *Package) Vendored(imports []string) []string { + if len(imports) > 0 && len(p.Imports) > 0 && &imports[0] == &p.Imports[0] { + panic("internal error: p.vendored(p.Imports) called") + } + seen := make(map[string]bool) + var all []string + for _, path := range imports { + path = VendoredImportPath(p, path) + if !seen[path] { + seen[path] = true + all = append(all, path) + } + } + sort.Strings(all) + return all +} + +// CoverVar holds the name of the generated coverage variables targeting the named file. +type CoverVar struct { + File string // local file name + Var string // name of count struct +} + +func (p *Package) copyBuild(pp *build.Package) { + p.Internal.Build = pp + + if pp.PkgTargetRoot != "" && cfg.BuildPkgdir != "" { + old := pp.PkgTargetRoot + pp.PkgRoot = cfg.BuildPkgdir + pp.PkgTargetRoot = cfg.BuildPkgdir + pp.PkgObj = filepath.Join(cfg.BuildPkgdir, strings.TrimPrefix(pp.PkgObj, old)) + } + + p.Dir = pp.Dir + p.ImportPath = pp.ImportPath + p.ImportComment = pp.ImportComment + p.Name = pp.Name + p.Doc = pp.Doc + p.Root = pp.Root + p.ConflictDir = pp.ConflictDir + p.BinaryOnly = pp.BinaryOnly + + // TODO? Target + p.Goroot = pp.Goroot + p.Standard = p.Goroot && p.ImportPath != "" && isStandardImportPath(p.ImportPath) + p.GoFiles = pp.GoFiles + p.CgoFiles = pp.CgoFiles + p.IgnoredGoFiles = pp.IgnoredGoFiles + p.CFiles = pp.CFiles + p.CXXFiles = pp.CXXFiles + p.MFiles = pp.MFiles + p.HFiles = pp.HFiles + p.FFiles = pp.FFiles + p.SFiles = pp.SFiles + p.SwigFiles = pp.SwigFiles + p.SwigCXXFiles = pp.SwigCXXFiles + p.SysoFiles = pp.SysoFiles + p.CgoCFLAGS = pp.CgoCFLAGS + p.CgoCPPFLAGS = pp.CgoCPPFLAGS + p.CgoCXXFLAGS = pp.CgoCXXFLAGS + p.CgoFFLAGS = pp.CgoFFLAGS + p.CgoLDFLAGS = pp.CgoLDFLAGS + p.CgoPkgConfig = pp.CgoPkgConfig + // We modify p.Imports in place, so make copy now. + p.Imports = make([]string, len(pp.Imports)) + copy(p.Imports, pp.Imports) + p.Internal.RawImports = pp.Imports + p.TestGoFiles = pp.TestGoFiles + p.TestImports = pp.TestImports + p.XTestGoFiles = pp.XTestGoFiles + p.XTestImports = pp.XTestImports + if IgnoreImports { + p.Imports = nil + p.TestImports = nil + p.XTestImports = nil + } +} + +// 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. +type PackageError struct { + ImportStack []string // shortest path from package named on command line to this one + Pos string // position of error + Err string // the error itself + IsImportCycle bool `json:"-"` // the error is an import cycle + Hard bool `json:"-"` // whether the error is soft or hard; soft errors are ignored in some places +} + +func (p *PackageError) Error() string { + // Import cycles deserve special treatment. + if p.IsImportCycle { + return fmt.Sprintf("%s\npackage %s\n", p.Err, strings.Join(p.ImportStack, "\n\timports ")) + } + if p.Pos != "" { + // Omit import stack. The full path to the file where the error + // is the most important thing. + return p.Pos + ": " + p.Err + } + if len(p.ImportStack) == 0 { + return p.Err + } + return "package " + strings.Join(p.ImportStack, "\n\timports ") + ": " + p.Err +} + +// An ImportStack is a stack of import paths. +type ImportStack []string + +func (s *ImportStack) Push(p string) { + *s = append(*s, p) +} + +func (s *ImportStack) Pop() { + *s = (*s)[0 : len(*s)-1] +} + +func (s *ImportStack) Copy() []string { + return append([]string{}, *s...) +} + +// shorterThan reports whether sp is shorter than t. +// We use this to record the shortest import sequence +// that leads to a particular package. +func (sp *ImportStack) shorterThan(t []string) bool { + s := *sp + if len(s) != len(t) { + return len(s) < len(t) + } + // If they are the same length, settle ties using string ordering. + for i := range s { + if s[i] != t[i] { + return s[i] < t[i] + } + } + return false // they are equal +} + +// packageCache is a lookup cache for loadPackage, +// so that if we look up a package multiple times +// we return the same pointer each time. +var packageCache = map[string]*Package{} + +func ClearPackageCache() { + for name := range packageCache { + delete(packageCache, name) + } +} + +func ClearPackageCachePartial(args []string) { + for _, arg := range args { + p := packageCache[arg] + if p != nil { + delete(packageCache, p.Dir) + delete(packageCache, p.ImportPath) + } + } +} + +// reloadPackage is like loadPackage but makes sure +// not to use the package cache. +func ReloadPackage(arg string, stk *ImportStack) *Package { + p := packageCache[arg] + if p != nil { + delete(packageCache, p.Dir) + delete(packageCache, p.ImportPath) + } + return LoadPackage(arg, stk) +} + +// dirToImportPath returns the pseudo-import path we use for a package +// outside the Go path. It begins with _/ and then contains the full path +// to the directory. If the package lives in c:\home\gopher\my\pkg then +// the pseudo-import path is _/c_/home/gopher/my/pkg. +// Using a pseudo-import path like this makes the ./ imports no longer +// a special case, so that all the code to deal with ordinary imports works +// automatically. +func dirToImportPath(dir string) string { + return pathpkg.Join("_", strings.Map(makeImportValid, filepath.ToSlash(dir))) +} + +func makeImportValid(r rune) rune { + // Should match Go spec, compilers, and ../../go/parser/parser.go:/isValidImport. + const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD" + if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) { + return '_' + } + return r +} + +// Mode flags for loadImport and download (in get.go). +const ( + // UseVendor means that loadImport should do vendor expansion + // (provided the vendoring experiment is enabled). + // That is, useVendor means that the import path came from + // a source file and has not been vendor-expanded yet. + // Every import path should be loaded initially with useVendor, + // and then the expanded version (with the /vendor/ in it) gets + // recorded as the canonical import path. At that point, future loads + // of that package must not pass useVendor, because + // disallowVendor will reject direct use of paths containing /vendor/. + UseVendor = 1 << iota + + // GetTestDeps is for download (part of "go get") and indicates + // that test dependencies should be fetched too. + GetTestDeps +) + +// LoadImport scans the directory named by path, which must be an import path, +// but possibly a local import path (an absolute file system path or one beginning +// with ./ or ../). A local relative path is interpreted relative to srcDir. +// It returns a *Package describing the package found in that directory. +func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package { + stk.Push(path) + defer stk.Pop() + + // Determine canonical identifier for this package. + // For a local import the identifier is the pseudo-import path + // we create from the full directory to the package. + // Otherwise it is the usual import path. + // For vendored imports, it is the expanded form. + importPath := path + origPath := path + isLocal := build.IsLocalImport(path) + var debugDeprecatedImportcfgDir string + if isLocal { + importPath = dirToImportPath(filepath.Join(srcDir, path)) + } else if DebugDeprecatedImportcfg.enabled { + if d, i := DebugDeprecatedImportcfg.lookup(parent, path); d != "" { + debugDeprecatedImportcfgDir = d + importPath = i + } + } else if mode&UseVendor != 0 { + // We do our own vendor resolution, because we want to + // find out the key to use in packageCache without the + // overhead of repeated calls to buildContext.Import. + // The code is also needed in a few other places anyway. + path = VendoredImportPath(parent, path) + importPath = path + } + + p := packageCache[importPath] + if p != nil { + p = reusePackage(p, stk) + } else { + p = new(Package) + p.Internal.Local = isLocal + p.ImportPath = importPath + packageCache[importPath] = p + + // Load package. + // Import always returns bp != nil, even if an error occurs, + // in order to return partial information. + var bp *build.Package + var err error + if debugDeprecatedImportcfgDir != "" { + bp, err = cfg.BuildContext.ImportDir(debugDeprecatedImportcfgDir, 0) + } else if DebugDeprecatedImportcfg.enabled { + bp = new(build.Package) + err = fmt.Errorf("unknown import path %q: not in import cfg", importPath) + } else { + buildMode := build.ImportComment + if mode&UseVendor == 0 || path != origPath { + // Not vendoring, or we already found the vendored path. + buildMode |= build.IgnoreVendor + } + bp, err = cfg.BuildContext.Import(path, srcDir, buildMode) + } + bp.ImportPath = importPath + if cfg.GOBIN != "" { + bp.BinDir = cfg.GOBIN + } + if debugDeprecatedImportcfgDir == "" && err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path && + !strings.Contains(path, "/vendor/") && !strings.HasPrefix(path, "vendor/") { + err = fmt.Errorf("code in directory %s expects import %q", bp.Dir, bp.ImportComment) + } + p.load(stk, bp, err) + if p.Error != nil && p.Error.Pos == "" { + p = setErrorPos(p, importPos) + } + + if debugDeprecatedImportcfgDir == "" && origPath != cleanImport(origPath) { + p.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: fmt.Sprintf("non-canonical import path: %q should be %q", origPath, pathpkg.Clean(origPath)), + } + p.Incomplete = true + } + } + + // Checked on every import because the rules depend on the code doing the importing. + if perr := disallowInternal(srcDir, p, stk); perr != p { + return setErrorPos(perr, importPos) + } + if mode&UseVendor != 0 { + if perr := disallowVendor(srcDir, origPath, p, stk); perr != p { + return setErrorPos(perr, importPos) + } + } + + if p.Name == "main" && parent != nil && parent.Dir != p.Dir { + perr := *p + perr.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: fmt.Sprintf("import %q is a program, not an importable package", path), + } + return setErrorPos(&perr, importPos) + } + + if p.Internal.Local && parent != nil && !parent.Internal.Local { + perr := *p + perr.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: fmt.Sprintf("local import %q in non-local package", path), + } + return setErrorPos(&perr, importPos) + } + + 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 +} + +func cleanImport(path string) string { + orig := path + path = pathpkg.Clean(path) + if strings.HasPrefix(orig, "./") && path != ".." && !strings.HasPrefix(path, "../") { + path = "./" + path + } + return path +} + +var isDirCache = map[string]bool{} + +func isDir(path string) bool { + result, ok := isDirCache[path] + if ok { + return result + } + + fi, err := os.Stat(path) + result = err == nil && fi.IsDir() + isDirCache[path] = result + return result +} + +// VendoredImportPath returns the expansion of path when it appears in parent. +// If parent is x/y/z, then path might expand to x/y/z/vendor/path, x/y/vendor/path, +// x/vendor/path, vendor/path, or else stay path if none of those exist. +// VendoredImportPath returns the expanded path or, if no expansion is found, the original. +func VendoredImportPath(parent *Package, path string) (found string) { + if DebugDeprecatedImportcfg.enabled { + if d, i := DebugDeprecatedImportcfg.lookup(parent, path); d != "" { + return i + } + return path + } + + if parent == nil || parent.Root == "" { + return path + } + + dir := filepath.Clean(parent.Dir) + root := filepath.Join(parent.Root, "src") + if !str.HasFilePathPrefix(dir, root) || parent.ImportPath != "command-line-arguments" && filepath.Join(root, parent.ImportPath) != dir { + // Look for symlinks before reporting error. + dir = expandPath(dir) + root = expandPath(root) + } + + if !str.HasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || parent.ImportPath != "command-line-arguments" && !parent.Internal.Local && filepath.Join(root, parent.ImportPath) != dir { + base.Fatalf("unexpected directory layout:\n"+ + " import path: %s\n"+ + " root: %s\n"+ + " dir: %s\n"+ + " expand root: %s\n"+ + " expand dir: %s\n"+ + " separator: %s", + parent.ImportPath, + filepath.Join(parent.Root, "src"), + filepath.Clean(parent.Dir), + root, + dir, + string(filepath.Separator)) + } + + vpath := "vendor/" + path + for i := len(dir); i >= len(root); i-- { + if i < len(dir) && dir[i] != filepath.Separator { + continue + } + // Note: checking for the vendor directory before checking + // for the vendor/path directory helps us hit the + // isDir cache more often. It also helps us prepare a more useful + // list of places we looked, to report when an import is not found. + if !isDir(filepath.Join(dir[:i], "vendor")) { + continue + } + targ := filepath.Join(dir[:i], vpath) + if isDir(targ) && hasGoFiles(targ) { + importPath := parent.ImportPath + if importPath == "command-line-arguments" { + // If parent.ImportPath is 'command-line-arguments'. + // set to relative directory to root (also chopped root directory) + importPath = dir[len(root)+1:] + } + // We started with parent's dir c:\gopath\src\foo\bar\baz\quux\xyzzy. + // We know the import path for parent's dir. + // We chopped off some number of path elements and + // added vendor\path to produce c:\gopath\src\foo\bar\baz\vendor\path. + // Now we want to know the import path for that directory. + // Construct it by chopping the same number of path elements + // (actually the same number of bytes) from parent's import path + // and then append /vendor/path. + chopped := len(dir) - i + if chopped == len(importPath)+1 { + // We walked up from c:\gopath\src\foo\bar + // and found c:\gopath\src\vendor\path. + // We chopped \foo\bar (length 8) but the import path is "foo/bar" (length 7). + // Use "vendor/path" without any prefix. + return vpath + } + return importPath[:len(importPath)-chopped] + "/" + vpath + } + } + return path +} + +// hasGoFiles reports whether dir contains any files with names ending in .go. +// For a vendor check we must exclude directories that contain no .go files. +// Otherwise it is not possible to vendor just a/b/c and still import the +// non-vendored a/b. See golang.org/issue/13832. +func hasGoFiles(dir string) bool { + fis, _ := ioutil.ReadDir(dir) + for _, fi := range fis { + if !fi.IsDir() && strings.HasSuffix(fi.Name(), ".go") { + return true + } + } + return false +} + +// reusePackage reuses package p to satisfy the import at the top +// of the import stack stk. If this use causes an import loop, +// reusePackage updates p's error information to record the loop. +func reusePackage(p *Package, stk *ImportStack) *Package { + // We use p.Internal.Imports==nil to detect a package that + // is in the midst of its own loadPackage call + // (all the recursion below happens before p.Internal.Imports gets set). + if p.Internal.Imports == nil { + if p.Error == nil { + p.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: "import cycle not allowed", + IsImportCycle: true, + } + } + p.Incomplete = true + } + // Don't rewrite the import stack in the error if we have an import cycle. + // If we do, we'll lose the path that describes the cycle. + if p.Error != nil && !p.Error.IsImportCycle && stk.shorterThan(p.Error.ImportStack) { + p.Error.ImportStack = stk.Copy() + } + return p +} + +// disallowInternal checks that srcDir is allowed to import p. +// If the import is allowed, disallowInternal returns the original package p. +// If not, it returns a new package containing just an appropriate error. +func disallowInternal(srcDir string, p *Package, stk *ImportStack) *Package { + // golang.org/s/go14internal: + // An import of a path containing the element “internal” + // is disallowed if the importing code is outside the tree + // rooted at the parent of the “internal” directory. + + // There was an error loading the package; stop here. + if p.Error != nil { + return p + } + + // The generated 'testmain' package is allowed to access testing/internal/..., + // as if it were generated into the testing directory tree + // (it's actually in a temporary directory outside any Go tree). + // This cleans up a former kludge in passing functionality to the testing package. + if strings.HasPrefix(p.ImportPath, "testing/internal") && len(*stk) >= 2 && (*stk)[len(*stk)-2] == "testmain" { + return p + } + + // We can't check standard packages with gccgo. + if cfg.BuildContext.Compiler == "gccgo" && p.Standard { + return p + } + + // The stack includes p.ImportPath. + // If that's the only thing on the stack, we started + // with a name given on the command line, not an + // import. Anything listed on the command line is fine. + if len(*stk) == 1 { + return p + } + + // Check for "internal" element: three cases depending on begin of string and/or end of string. + i, ok := findInternal(p.ImportPath) + if !ok { + return p + } + + // Internal is present. + // Map import path back to directory corresponding to parent of internal. + if i > 0 { + i-- // rewind over slash in ".../internal" + } + parent := p.Dir[:i+len(p.Dir)-len(p.ImportPath)] + if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) { + return p + } + + // Look for symlinks before reporting error. + srcDir = expandPath(srcDir) + parent = expandPath(parent) + if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) { + return p + } + + // Internal is present, and srcDir is outside parent's tree. Not allowed. + perr := *p + perr.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: "use of internal package not allowed", + } + perr.Incomplete = true + return &perr +} + +// findInternal looks for the final "internal" path element in the given import path. +// If there isn't one, findInternal returns ok=false. +// Otherwise, findInternal returns ok=true and the index of the "internal". +func findInternal(path string) (index int, ok bool) { + // Three cases, depending on internal at start/end of string or not. + // The order matters: we must return the index of the final element, + // because the final one produces the most restrictive requirement + // on the importer. + switch { + case strings.HasSuffix(path, "/internal"): + return len(path) - len("internal"), true + case strings.Contains(path, "/internal/"): + return strings.LastIndex(path, "/internal/") + 1, true + case path == "internal", strings.HasPrefix(path, "internal/"): + return 0, true + } + return 0, false +} + +// disallowVendor checks that srcDir is allowed to import p as path. +// If the import is allowed, disallowVendor returns the original package p. +// If not, it returns a new package containing just an appropriate error. +func disallowVendor(srcDir, path string, p *Package, stk *ImportStack) *Package { + // The stack includes p.ImportPath. + // If that's the only thing on the stack, we started + // with a name given on the command line, not an + // import. Anything listed on the command line is fine. + if len(*stk) == 1 { + return p + } + + if perr := disallowVendorVisibility(srcDir, p, stk); perr != p { + return perr + } + + // Paths like x/vendor/y must be imported as y, never as x/vendor/y. + if i, ok := FindVendor(path); ok { + perr := *p + perr.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: "must be imported as " + path[i+len("vendor/"):], + } + perr.Incomplete = true + return &perr + } + + return p +} + +// disallowVendorVisibility checks that srcDir is allowed to import p. +// The rules are the same as for /internal/ except that a path ending in /vendor +// is not subject to the rules, only subdirectories of vendor. +// This allows people to have packages and commands named vendor, +// for maximal compatibility with existing source trees. +func disallowVendorVisibility(srcDir string, p *Package, stk *ImportStack) *Package { + // The stack includes p.ImportPath. + // If that's the only thing on the stack, we started + // with a name given on the command line, not an + // import. Anything listed on the command line is fine. + if len(*stk) == 1 { + return p + } + + // Check for "vendor" element. + i, ok := FindVendor(p.ImportPath) + if !ok { + return p + } + + // Vendor is present. + // Map import path back to directory corresponding to parent of vendor. + if i > 0 { + i-- // rewind over slash in ".../vendor" + } + truncateTo := i + len(p.Dir) - len(p.ImportPath) + if truncateTo < 0 || len(p.Dir) < truncateTo { + return p + } + parent := p.Dir[:truncateTo] + if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) { + return p + } + + // Look for symlinks before reporting error. + srcDir = expandPath(srcDir) + parent = expandPath(parent) + if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) { + return p + } + + // Vendor is present, and srcDir is outside parent's tree. Not allowed. + perr := *p + perr.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: "use of vendored package not allowed", + } + perr.Incomplete = true + return &perr +} + +// FindVendor looks for the last non-terminating "vendor" path element in the given import path. +// If there isn't one, FindVendor returns ok=false. +// Otherwise, FindVendor returns ok=true and the index of the "vendor". +// +// Note that terminating "vendor" elements don't count: "x/vendor" is its own package, +// not the vendored copy of an import "" (the empty import path). +// This will allow people to have packages or commands named vendor. +// This may help reduce breakage, or it may just be confusing. We'll see. +func FindVendor(path string) (index int, ok bool) { + // Two cases, depending on internal at start of string or not. + // The order matters: we must return the index of the final element, + // because the final one is where the effective import path starts. + switch { + case strings.Contains(path, "/vendor/"): + return strings.LastIndex(path, "/vendor/") + 1, true + case strings.HasPrefix(path, "vendor/"): + return 0, true + } + return 0, false +} + +type TargetDir int + +const ( + ToTool TargetDir = iota // to GOROOT/pkg/tool (default for cmd/*) + ToBin // to bin dir inside package root (default for non-cmd/*) + StalePath // an old import path; fail to build +) + +// InstallTargetDir reports the target directory for installing the command p. +func InstallTargetDir(p *Package) TargetDir { + if strings.HasPrefix(p.ImportPath, "code.google.com/p/go.tools/cmd/") { + return StalePath + } + if p.Goroot && strings.HasPrefix(p.ImportPath, "cmd/") && p.Name == "main" { + switch p.ImportPath { + case "cmd/go", "cmd/gofmt": + return ToBin + } + return ToTool + } + return ToBin +} + +var cgoExclude = map[string]bool{ + "runtime/cgo": true, +} + +var cgoSyscallExclude = map[string]bool{ + "runtime/cgo": true, + "runtime/race": true, + "runtime/msan": true, +} + +var foldPath = make(map[string]string) + +// load populates p using information from bp, err, which should +// be the result of calling build.Context.Import. +func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { + p.copyBuild(bp) + + // Decide whether p was listed on the command line. + // Given that load is called while processing the command line, + // you might think we could simply pass a flag down into load + // saying whether we are loading something named on the command + // line or something to satisfy an import. But the first load of a + // package named on the command line may be as a dependency + // of an earlier package named on the command line, not when we + // get to that package during command line processing. + // For example "go test fmt reflect" will load reflect as a dependency + // of fmt before it attempts to load as a command-line argument. + // Because loads are cached, the later load will be a no-op, + // so it is important that the first load can fill in CmdlinePkg correctly. + // Hence the call to an explicit matching check here. + p.Internal.CmdlinePkg = isCmdlinePkg(p) + + p.Internal.Asmflags = BuildAsmflags.For(p) + p.Internal.Gcflags = BuildGcflags.For(p) + p.Internal.Ldflags = BuildLdflags.For(p) + p.Internal.Gccgoflags = BuildGccgoflags.For(p) + + // The localPrefix is the path we interpret ./ imports relative to. + // Synthesized main packages sometimes override this. + if p.Internal.Local { + p.Internal.LocalPrefix = dirToImportPath(p.Dir) + } + + if err != nil { + if _, ok := err.(*build.NoGoError); ok { + err = &NoGoError{Package: p} + } + p.Incomplete = true + err = base.ExpandScanner(err) + p.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: err.Error(), + } + return + } + + useBindir := p.Name == "main" + if !p.Standard { + switch cfg.BuildBuildmode { + case "c-archive", "c-shared", "plugin": + useBindir = false + } + } + + if useBindir { + // Report an error when the old code.google.com/p/go.tools paths are used. + if InstallTargetDir(p) == StalePath { + newPath := strings.Replace(p.ImportPath, "code.google.com/p/go.", "golang.org/x/", 1) + e := fmt.Sprintf("the %v command has moved; use %v instead.", p.ImportPath, newPath) + p.Error = &PackageError{Err: e} + return + } + _, elem := filepath.Split(p.Dir) + full := cfg.BuildContext.GOOS + "_" + cfg.BuildContext.GOARCH + "/" + elem + if cfg.BuildContext.GOOS != base.ToolGOOS || cfg.BuildContext.GOARCH != base.ToolGOARCH { + // Install cross-compiled binaries to subdirectories of bin. + elem = full + } + if p.Internal.Build.BinDir != "" { + // Install to GOBIN or bin of GOPATH entry. + p.Target = filepath.Join(p.Internal.Build.BinDir, elem) + if !p.Goroot && strings.Contains(elem, "/") && cfg.GOBIN != "" { + // Do not create $GOBIN/goos_goarch/elem. + p.Target = "" + p.Internal.GobinSubdir = true + } + } + if InstallTargetDir(p) == ToTool { + // This is for 'go tool'. + // Override all the usual logic and force it into the tool directory. + p.Target = filepath.Join(cfg.GOROOTpkg, "tool", full) + } + if p.Target != "" && cfg.BuildContext.GOOS == "windows" { + p.Target += ".exe" + } + } else if p.Internal.Local { + // Local import turned into absolute path. + // No permanent install target. + p.Target = "" + } else { + p.Target = p.Internal.Build.PkgObj + if cfg.BuildLinkshared { + shlibnamefile := p.Target[:len(p.Target)-2] + ".shlibname" + shlib, err := ioutil.ReadFile(shlibnamefile) + if err != nil && !os.IsNotExist(err) { + base.Fatalf("reading shlibname: %v", err) + } + if err == nil { + libname := strings.TrimSpace(string(shlib)) + if cfg.BuildContext.Compiler == "gccgo" { + p.Shlib = filepath.Join(p.Internal.Build.PkgTargetRoot, "shlibs", libname) + } else { + p.Shlib = filepath.Join(p.Internal.Build.PkgTargetRoot, libname) + } + } + } + } + + // Build augmented import list to add implicit dependencies. + // Be careful not to add imports twice, just to avoid confusion. + importPaths := p.Imports + addImport := func(path string) { + for _, p := range importPaths { + if path == p { + return + } + } + importPaths = append(importPaths, path) + } + + // Cgo translation adds imports of "runtime/cgo" and "syscall", + // except for certain packages, to avoid circular dependencies. + if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) { + addImport("runtime/cgo") + } + if p.UsesCgo() && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) { + addImport("syscall") + } + + // SWIG adds imports of some standard packages. + if p.UsesSwig() { + addImport("runtime/cgo") + addImport("syscall") + addImport("sync") + + // TODO: The .swig and .swigcxx files can use + // %go_import directives to import other packages. + } + + // The linker loads implicit dependencies. + if p.Name == "main" && !p.Internal.ForceLibrary { + for _, dep := range LinkerDeps(p) { + addImport(dep) + } + } + + // 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 + // comparison. + inputs := p.AllFiles() + f1, f2 := str.FoldDup(inputs) + if f1 != "" { + p.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: fmt.Sprintf("case-insensitive file name collision: %q and %q", f1, f2), + } + return + } + + // If first letter of input file is ASCII, it must be alphanumeric. + // This avoids files turning into flags when invoking commands, + // and other problems we haven't thought of yet. + // Also, _cgo_ files must be generated by us, not supplied. + // They are allowed to have //go:cgo_ldflag directives. + // The directory scan ignores files beginning with _, + // so we shouldn't see any _cgo_ files anyway, but just be safe. + for _, file := range inputs { + if !SafeArg(file) || strings.HasPrefix(file, "_cgo_") { + p.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: fmt.Sprintf("invalid input file name %q", file), + } + return + } + } + if name := pathpkg.Base(p.ImportPath); !SafeArg(name) { + p.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: fmt.Sprintf("invalid input directory name %q", name), + } + return + } + if !SafeArg(p.ImportPath) { + p.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: fmt.Sprintf("invalid import path %q", p.ImportPath), + } + return + } + + // Build list of imported packages and full dependency list. + imports := make([]*Package, 0, len(p.Imports)) + for i, path := range importPaths { + if path == "C" { + continue + } + p1 := LoadImport(path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], UseVendor) + if p.Standard && p.Error == nil && !p1.Standard && p1.Error == nil { + p.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: fmt.Sprintf("non-standard import %q in standard package %q", path, p.ImportPath), + } + pos := p.Internal.Build.ImportPos[path] + if len(pos) > 0 { + p.Error.Pos = pos[0].String() + } + } + + path = p1.ImportPath + importPaths[i] = path + if i < len(p.Imports) { + p.Imports[i] = path + } + + imports = append(imports, p1) + if p1.Incomplete { + p.Incomplete = true + } + } + p.Internal.Imports = imports + + deps := make(map[string]*Package) + var q []*Package + q = append(q, imports...) + for i := 0; i < len(q); i++ { + p1 := q[i] + path := p1.ImportPath + // The same import path could produce an error or not, + // depending on what tries to import it. + // Prefer to record entries with errors, so we can report them. + p0 := deps[path] + if p0 == nil || p1.Error != nil && (p0.Error == nil || len(p0.Error.ImportStack) > len(p1.Error.ImportStack)) { + deps[path] = p1 + for _, p2 := range p1.Internal.Imports { + if deps[p2.ImportPath] != p2 { + q = append(q, p2) + } + } + } + } + + p.Deps = make([]string, 0, len(deps)) + for dep := range deps { + p.Deps = append(p.Deps, dep) + } + sort.Strings(p.Deps) + for _, dep := range p.Deps { + p1 := deps[dep] + if p1 == nil { + panic("impossible: missing entry in package cache for " + dep + " imported by " + p.ImportPath) + } + if p1.Error != nil { + p.DepsErrors = append(p.DepsErrors, p1.Error) + } + } + + // unsafe is a fake package. + if p.Standard && (p.ImportPath == "unsafe" || cfg.BuildContext.Compiler == "gccgo") { + p.Target = "" + } + + // If cgo is not enabled, ignore cgo supporting sources + // just as we ignore go files containing import "C". + if !cfg.BuildContext.CgoEnabled { + p.CFiles = nil + p.CXXFiles = nil + p.MFiles = nil + p.SwigFiles = nil + p.SwigCXXFiles = nil + // Note that SFiles are okay (they go to the Go assembler) + // and HFiles are okay (they might be used by the SFiles). + // Also Sysofiles are okay (they might not contain object + // code; see issue #16050). + } + + setError := func(msg string) { + p.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: msg, + } + } + + // The gc toolchain only permits C source files with cgo or SWIG. + if len(p.CFiles) > 0 && !p.UsesCgo() && !p.UsesSwig() && cfg.BuildContext.Compiler == "gc" { + setError(fmt.Sprintf("C source files not allowed when not using cgo or SWIG: %s", strings.Join(p.CFiles, " "))) + return + } + + // C++, Objective-C, and Fortran source files are permitted only with cgo or SWIG, + // regardless of toolchain. + if len(p.CXXFiles) > 0 && !p.UsesCgo() && !p.UsesSwig() { + setError(fmt.Sprintf("C++ source files not allowed when not using cgo or SWIG: %s", strings.Join(p.CXXFiles, " "))) + return + } + if len(p.MFiles) > 0 && !p.UsesCgo() && !p.UsesSwig() { + setError(fmt.Sprintf("Objective-C source files not allowed when not using cgo or SWIG: %s", strings.Join(p.MFiles, " "))) + return + } + if len(p.FFiles) > 0 && !p.UsesCgo() && !p.UsesSwig() { + setError(fmt.Sprintf("Fortran source files not allowed when not using cgo or SWIG: %s", strings.Join(p.FFiles, " "))) + return + } + + // Check for case-insensitive collisions of import paths. + fold := str.ToFold(p.ImportPath) + if other := foldPath[fold]; other == "" { + foldPath[fold] = p.ImportPath + } else if other != p.ImportPath { + setError(fmt.Sprintf("case-insensitive import collision: %q and %q", p.ImportPath, other)) + return + } +} + +// SafeArg reports whether arg is a "safe" command-line argument, +// meaning that when it appears in a command-line, it probably +// doesn't have some special meaning other than its own name. +// Obviously args beginning with - are not safe (they look like flags). +// Less obviously, args beginning with @ are not safe (they look like +// GNU binutils flagfile specifiers, sometimes called "response files"). +// To be conservative, we reject almost any arg beginning with non-alphanumeric ASCII. +// We accept leading . _ and / as likely in file system paths. +// There is a copy of this function in cmd/compile/internal/gc/noder.go. +func SafeArg(name string) bool { + if name == "" { + return false + } + c := name[0] + return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf +} + +// LinkerDeps returns the list of linker-induced dependencies for main package p. +func LinkerDeps(p *Package) []string { + // Everything links runtime. + deps := []string{"runtime"} + + // External linking mode forces an import of runtime/cgo. + if externalLinkingForced(p) { + deps = append(deps, "runtime/cgo") + } + // On ARM with GOARM=5, it forces an import of math, for soft floating point. + if cfg.Goarch == "arm" { + deps = append(deps, "math") + } + // Using the race detector forces an import of runtime/race. + if cfg.BuildRace { + deps = append(deps, "runtime/race") + } + // Using memory sanitizer forces an import of runtime/msan. + if cfg.BuildMSan { + deps = append(deps, "runtime/msan") + } + + return deps +} + +// externalLinkingForced reports whether external linking is being +// forced even for programs that do not use cgo. +func externalLinkingForced(p *Package) bool { + // Some targets must use external linking even inside GOROOT. + switch cfg.BuildContext.GOOS { + case "android": + return true + case "darwin": + switch cfg.BuildContext.GOARCH { + case "arm", "arm64": + return true + } + } + + if !cfg.BuildContext.CgoEnabled { + return false + } + // Currently build modes c-shared, pie (on systems that do not + // support PIE with internal linking mode (currently all + // systems: issue #18968)), plugin, and -linkshared force + // external linking mode, as of course does + // -ldflags=-linkmode=external. External linking mode forces + // an import of runtime/cgo. + pieCgo := cfg.BuildBuildmode == "pie" + linkmodeExternal := false + if p != nil { + ldflags := BuildLdflags.For(p) + for i, a := range ldflags { + if a == "-linkmode=external" { + linkmodeExternal = true + } + if a == "-linkmode" && i+1 < len(ldflags) && ldflags[i+1] == "external" { + linkmodeExternal = true + } + } + } + + return cfg.BuildBuildmode == "c-shared" || cfg.BuildBuildmode == "plugin" || pieCgo || cfg.BuildLinkshared || linkmodeExternal +} + +// mkAbs rewrites list, which must be paths relative to p.Dir, +// into a sorted list of absolute paths. It edits list in place but for +// convenience also returns list back to its caller. +func (p *Package) mkAbs(list []string) []string { + for i, f := range list { + list[i] = filepath.Join(p.Dir, f) + } + sort.Strings(list) + return list +} + +// InternalGoFiles returns the list of Go files being built for the package, +// using absolute paths. +func (p *Package) InternalGoFiles() []string { + return p.mkAbs(str.StringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles)) +} + +// InternalGoFiles returns the list of all Go files possibly relevant for the package, +// using absolute paths. "Possibly relevant" means that files are not excluded +// due to build tags, but files with names beginning with . or _ are still excluded. +func (p *Package) InternalAllGoFiles() []string { + var extra []string + for _, f := range p.IgnoredGoFiles { + if f != "" && f[0] != '.' || f[0] != '_' { + extra = append(extra, f) + } + } + return p.mkAbs(str.StringList(extra, p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles)) +} + +// usesSwig reports whether the package needs to run SWIG. +func (p *Package) UsesSwig() bool { + return len(p.SwigFiles) > 0 || len(p.SwigCXXFiles) > 0 +} + +// usesCgo reports whether the package needs to run cgo +func (p *Package) UsesCgo() bool { + return len(p.CgoFiles) > 0 +} + +// packageList returns the list of packages in the dag rooted at roots +// as visited in a depth-first post-order traversal. +func PackageList(roots []*Package) []*Package { + seen := map[*Package]bool{} + all := []*Package{} + var walk func(*Package) + walk = func(p *Package) { + if seen[p] { + return + } + seen[p] = true + for _, p1 := range p.Internal.Imports { + walk(p1) + } + all = append(all, p) + } + for _, root := range roots { + walk(root) + } + return all +} + +var cmdCache = map[string]*Package{} + +func ClearCmdCache() { + for name := range cmdCache { + delete(cmdCache, name) + } +} + +// loadPackage is like loadImport but is used for command-line arguments, +// not for paths found in import statements. In addition to ordinary import paths, +// loadPackage accepts pseudo-paths beginning with cmd/ to denote commands +// in the Go command directory, as well as paths to those directories. +func LoadPackage(arg string, stk *ImportStack) *Package { + if build.IsLocalImport(arg) { + dir := arg + if !filepath.IsAbs(dir) { + if abs, err := filepath.Abs(dir); err == nil { + // interpret relative to current directory + dir = abs + } + } + if sub, ok := hasSubdir(cfg.GOROOTsrc, dir); ok && strings.HasPrefix(sub, "cmd/") && !strings.Contains(sub[4:], "/") { + arg = sub + } + } + if strings.HasPrefix(arg, "cmd/") && !strings.Contains(arg[4:], "/") { + if p := cmdCache[arg]; p != nil { + return p + } + stk.Push(arg) + defer stk.Pop() + + bp, err := cfg.BuildContext.ImportDir(filepath.Join(cfg.GOROOTsrc, arg), 0) + bp.ImportPath = arg + bp.Goroot = true + bp.BinDir = cfg.GOROOTbin + if cfg.GOROOTbin != "" { + bp.BinDir = cfg.GOROOTbin + } + bp.Root = cfg.GOROOT + bp.SrcRoot = cfg.GOROOTsrc + p := new(Package) + cmdCache[arg] = p + p.load(stk, bp, err) + if p.Error == nil && p.Name != "main" { + p.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: fmt.Sprintf("expected package main but found package %s in %s", p.Name, p.Dir), + } + } + return p + } + + // Wasn't a command; must be a package. + // If it is a local import path but names a standard package, + // we treat it as if the user specified the standard package. + // This lets you run go test ./ioutil in package io and be + // referring to io/ioutil rather than a hypothetical import of + // "./ioutil". + if build.IsLocalImport(arg) { + bp, _ := cfg.BuildContext.ImportDir(filepath.Join(base.Cwd, arg), build.FindOnly) + if bp.ImportPath != "" && bp.ImportPath != "." { + arg = bp.ImportPath + } + } + + return LoadImport(arg, base.Cwd, nil, stk, nil, 0) +} + +// packages returns the packages named by the +// command line arguments 'args'. If a named package +// cannot be loaded at all (for example, if the directory does not exist), +// then packages prints an error and does not include that +// package in the results. However, if errors occur trying +// to load dependencies of a named package, the named +// package is still returned, with p.Incomplete = true +// and details in p.DepsErrors. +func Packages(args []string) []*Package { + var pkgs []*Package + for _, pkg := range PackagesAndErrors(args) { + if pkg.Error != nil { + base.Errorf("can't load package: %s", pkg.Error) + continue + } + pkgs = append(pkgs, pkg) + } + return pkgs +} + +// packagesAndErrors is like 'packages' but returns a +// *Package for every argument, even the ones that +// cannot be loaded at all. +// The packages that fail to load will have p.Error != nil. +func PackagesAndErrors(args []string) []*Package { + if len(args) > 0 && strings.HasSuffix(args[0], ".go") { + return []*Package{GoFilesPackage(args)} + } + + args = ImportPaths(args) + var ( + pkgs []*Package + stk ImportStack + seenArg = make(map[string]bool) + seenPkg = make(map[*Package]bool) + ) + + for _, arg := range args { + if seenArg[arg] { + continue + } + seenArg[arg] = true + pkg := LoadPackage(arg, &stk) + if seenPkg[pkg] { + continue + } + seenPkg[pkg] = true + pkgs = append(pkgs, pkg) + } + + return pkgs +} + +// packagesForBuild is like 'packages' but fails if any of +// the packages or their dependencies have errors +// (cannot be built). +func PackagesForBuild(args []string) []*Package { + pkgs := PackagesAndErrors(args) + printed := map[*PackageError]bool{} + for _, pkg := range pkgs { + if pkg.Error != nil { + base.Errorf("can't load package: %s", pkg.Error) + } + for _, err := range pkg.DepsErrors { + // 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. + if !printed[err] { + printed[err] = true + base.Errorf("%s", err) + } + } + } + base.ExitIfErrors() + + // Check for duplicate loads of the same package. + // That should be impossible, but if it does happen then + // we end up trying to build the same package twice, + // usually in parallel overwriting the same files, + // which doesn't work very well. + seen := map[string]bool{} + reported := map[string]bool{} + for _, pkg := range PackageList(pkgs) { + if seen[pkg.ImportPath] && !reported[pkg.ImportPath] { + reported[pkg.ImportPath] = true + base.Errorf("internal error: duplicate loads of %s", pkg.ImportPath) + } + seen[pkg.ImportPath] = true + } + base.ExitIfErrors() + + return pkgs +} + +// GoFilesPackage creates a package for building a collection of Go files +// (typically named on the command line). The target is named p.a for +// package p or named after the first Go file for package main. +func GoFilesPackage(gofiles []string) *Package { + // TODO: Remove this restriction. + for _, f := range gofiles { + if !strings.HasSuffix(f, ".go") { + base.Fatalf("named files must be .go files") + } + } + + var stk ImportStack + ctxt := cfg.BuildContext + ctxt.UseAllFiles = true + + // Synthesize fake "directory" that only shows the named files, + // to make it look like this is a standard package or + // command directory. So that local imports resolve + // consistently, the files must all be in the same directory. + var dirent []os.FileInfo + var dir string + for _, file := range gofiles { + fi, err := os.Stat(file) + if err != nil { + base.Fatalf("%s", err) + } + if fi.IsDir() { + base.Fatalf("%s is a directory, should be a Go file", file) + } + dir1, _ := filepath.Split(file) + if dir1 == "" { + dir1 = "./" + } + if dir == "" { + dir = dir1 + } else if dir != dir1 { + base.Fatalf("named files must all be in one directory; have %s and %s", dir, dir1) + } + dirent = append(dirent, fi) + } + ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil } + + var err error + if dir == "" { + dir = base.Cwd + } + dir, err = filepath.Abs(dir) + if err != nil { + base.Fatalf("%s", err) + } + + bp, err := ctxt.ImportDir(dir, 0) + pkg := new(Package) + pkg.Internal.Local = true + pkg.Internal.CmdlineFiles = true + stk.Push("main") + pkg.load(&stk, bp, err) + stk.Pop() + pkg.Internal.LocalPrefix = dirToImportPath(dir) + pkg.ImportPath = "command-line-arguments" + pkg.Target = "" + + if pkg.Name == "main" { + _, elem := filepath.Split(gofiles[0]) + exe := elem[:len(elem)-len(".go")] + cfg.ExeSuffix + if cfg.BuildO == "" { + cfg.BuildO = exe + } + if cfg.GOBIN != "" { + pkg.Target = filepath.Join(cfg.GOBIN, exe) + } + } + + return pkg +} + +// TestPackagesFor returns package structs ptest, the package p plus +// its test files, and pxtest, the external tests of package p. +// pxtest may be nil. If there are no test files, forceTest decides +// whether this returns a new package struct or just returns p. +func TestPackagesFor(p *Package, forceTest bool) (ptest, pxtest *Package, err error) { + var imports, ximports []*Package + var stk ImportStack + stk.Push(p.ImportPath + " (test)") + rawTestImports := str.StringList(p.TestImports) + for i, path := range p.TestImports { + p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], UseVendor) + if p1.Error != nil { + return nil, nil, p1.Error + } + if len(p1.DepsErrors) > 0 { + err := p1.DepsErrors[0] + err.Pos = "" // show full import stack + return nil, nil, err + } + if str.Contains(p1.Deps, p.ImportPath) || p1.ImportPath == p.ImportPath { + // Same error that loadPackage returns (via reusePackage) in pkg.go. + // Can't change that code, because that code is only for loading the + // non-test copy of a package. + err := &PackageError{ + ImportStack: testImportStack(stk[0], p1, p.ImportPath), + Err: "import cycle not allowed in test", + IsImportCycle: true, + } + return nil, nil, err + } + p.TestImports[i] = p1.ImportPath + imports = append(imports, p1) + } + stk.Pop() + stk.Push(p.ImportPath + "_test") + pxtestNeedsPtest := false + rawXTestImports := str.StringList(p.XTestImports) + for i, path := range p.XTestImports { + p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], UseVendor) + if p1.Error != nil { + return nil, nil, p1.Error + } + if len(p1.DepsErrors) > 0 { + err := p1.DepsErrors[0] + err.Pos = "" // show full import stack + return nil, nil, err + } + if p1.ImportPath == p.ImportPath { + pxtestNeedsPtest = true + } else { + ximports = append(ximports, p1) + } + p.XTestImports[i] = p1.ImportPath + } + stk.Pop() + + // Test package. + if len(p.TestGoFiles) > 0 || forceTest { + ptest = new(Package) + *ptest = *p + ptest.GoFiles = nil + ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...) + ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...) + ptest.Target = "" + // Note: The preparation of the vet config requires that common + // indexes in ptest.Imports, ptest.Internal.Imports, and ptest.Internal.RawImports + // all line up (but RawImports can be shorter than the others). + // That is, for 0 ≤ i < len(RawImports), + // RawImports[i] is the import string in the program text, + // Imports[i] is the expanded import string (vendoring applied or relative path expanded away), + // and Internal.Imports[i] is the corresponding *Package. + // Any implicitly added imports appear in Imports and Internal.Imports + // but not RawImports (because they were not in the source code). + // We insert TestImports, imports, and rawTestImports at the start of + // these lists to preserve the alignment. + ptest.Imports = str.StringList(p.TestImports, p.Imports) + ptest.Internal.Imports = append(imports, p.Internal.Imports...) + ptest.Internal.RawImports = str.StringList(rawTestImports, p.Internal.RawImports) + ptest.Internal.ForceLibrary = true + ptest.Internal.Build = new(build.Package) + *ptest.Internal.Build = *p.Internal.Build + m := map[string][]token.Position{} + for k, v := range p.Internal.Build.ImportPos { + m[k] = append(m[k], v...) + } + for k, v := range p.Internal.Build.TestImportPos { + m[k] = append(m[k], v...) + } + ptest.Internal.Build.ImportPos = m + } else { + ptest = p + } + + // External test package. + if len(p.XTestGoFiles) > 0 { + pxtest = &Package{ + PackagePublic: PackagePublic{ + Name: p.Name + "_test", + ImportPath: p.ImportPath + "_test", + Root: p.Root, + Dir: p.Dir, + GoFiles: p.XTestGoFiles, + Imports: p.XTestImports, + }, + Internal: PackageInternal{ + LocalPrefix: p.Internal.LocalPrefix, + Build: &build.Package{ + ImportPos: p.Internal.Build.XTestImportPos, + }, + Imports: ximports, + RawImports: rawXTestImports, + + Asmflags: p.Internal.Asmflags, + Gcflags: p.Internal.Gcflags, + Ldflags: p.Internal.Ldflags, + Gccgoflags: p.Internal.Gccgoflags, + }, + } + if pxtestNeedsPtest { + pxtest.Internal.Imports = append(pxtest.Internal.Imports, ptest) + } + } + + return ptest, pxtest, nil +} + +func testImportStack(top string, p *Package, target string) []string { + stk := []string{top, p.ImportPath} +Search: + for p.ImportPath != target { + for _, p1 := range p.Internal.Imports { + if p1.ImportPath == target || str.Contains(p1.Deps, target) { + stk = append(stk, p1.ImportPath) + p = p1 + continue Search + } + } + // Can't happen, but in case it does... + stk = append(stk, "<lost path to cycle>") + break + } + return stk +}
diff --git a/vendor/cmd/go/internal/load/search.go b/vendor/cmd/go/internal/load/search.go new file mode 100644 index 0000000..595de07 --- /dev/null +++ b/vendor/cmd/go/internal/load/search.go
@@ -0,0 +1,385 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package load + +import ( + "cmd/go/internal/cfg" + "fmt" + "go/build" + "log" + "os" + "path" + "path/filepath" + "regexp" + "strings" +) + +// allPackages returns all the packages that can be found +// under the $GOPATH directories and $GOROOT matching pattern. +// The pattern is either "all" (all packages), "std" (standard packages), +// "cmd" (standard commands), or a path including "...". +func allPackages(pattern string) []string { + pkgs := MatchPackages(pattern) + if len(pkgs) == 0 { + fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) + } + return pkgs +} + +// allPackagesInFS is like allPackages but is passed a pattern +// beginning ./ or ../, meaning it should scan the tree rooted +// at the given directory. There are ... in the pattern too. +func allPackagesInFS(pattern string) []string { + pkgs := MatchPackagesInFS(pattern) + if len(pkgs) == 0 { + fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) + } + return pkgs +} + +// MatchPackages returns a list of package paths matching pattern +// (see go help packages for pattern syntax). +func MatchPackages(pattern string) []string { + match := func(string) bool { return true } + treeCanMatch := func(string) bool { return true } + if !IsMetaPackage(pattern) { + match = matchPattern(pattern) + treeCanMatch = treeCanMatchPattern(pattern) + } + + have := map[string]bool{ + "builtin": true, // ignore pseudo-package that exists only for documentation + } + if !cfg.BuildContext.CgoEnabled { + have["runtime/cgo"] = true // ignore during walk + } + var pkgs []string + + for _, src := range cfg.BuildContext.SrcDirs() { + if (pattern == "std" || pattern == "cmd") && src != cfg.GOROOTsrc { + continue + } + src = filepath.Clean(src) + string(filepath.Separator) + root := src + if pattern == "cmd" { + root += "cmd" + string(filepath.Separator) + } + filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { + if err != nil || path == src { + return nil + } + + want := true + // Avoid .foo, _foo, and testdata directory trees. + _, elem := filepath.Split(path) + if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { + want = false + } + + name := filepath.ToSlash(path[len(src):]) + if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") { + // The name "std" is only the standard library. + // If the name is cmd, it's the root of the command tree. + want = false + } + if !treeCanMatch(name) { + want = false + } + + if !fi.IsDir() { + if fi.Mode()&os.ModeSymlink != 0 && want { + if target, err := os.Stat(path); err == nil && target.IsDir() { + fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path) + } + } + return nil + } + if !want { + return filepath.SkipDir + } + + if have[name] { + return nil + } + have[name] = true + if !match(name) { + return nil + } + pkg, err := cfg.BuildContext.ImportDir(path, 0) + if err != nil { + if _, noGo := err.(*build.NoGoError); noGo { + return nil + } + } + + // If we are expanding "cmd", skip main + // packages under cmd/vendor. At least as of + // March, 2017, there is one there for the + // vendored pprof tool. + if pattern == "cmd" && strings.HasPrefix(pkg.ImportPath, "cmd/vendor") && pkg.Name == "main" { + return nil + } + + pkgs = append(pkgs, name) + return nil + }) + } + return pkgs +} + +// MatchPackagesInFS returns a list of package paths matching pattern, +// which must begin with ./ or ../ +// (see go help packages for pattern syntax). +func MatchPackagesInFS(pattern string) []string { + // Find directory to begin the scan. + // Could be smarter but this one optimization + // is enough for now, since ... is usually at the + // end of a path. + i := strings.Index(pattern, "...") + dir, _ := path.Split(pattern[:i]) + + // pattern begins with ./ or ../. + // path.Clean will discard the ./ but not the ../. + // We need to preserve the ./ for pattern matching + // and in the returned import paths. + prefix := "" + if strings.HasPrefix(pattern, "./") { + prefix = "./" + } + match := matchPattern(pattern) + + var pkgs []string + filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error { + if err != nil || !fi.IsDir() { + return nil + } + if path == dir { + // filepath.Walk starts at dir and recurses. For the recursive case, + // the path is the result of filepath.Join, which calls filepath.Clean. + // The initial case is not Cleaned, though, so we do this explicitly. + // + // This converts a path like "./io/" to "io". Without this step, running + // "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io + // package, because prepending the prefix "./" to the unclean path would + // result in "././io", and match("././io") returns false. + path = filepath.Clean(path) + } + + // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..". + _, elem := filepath.Split(path) + dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".." + if dot || strings.HasPrefix(elem, "_") || elem == "testdata" { + return filepath.SkipDir + } + + name := prefix + filepath.ToSlash(path) + if !match(name) { + return nil + } + + // We keep the directory if we can import it, or if we can't import it + // due to invalid Go source files. This means that directories containing + // parse errors will be built (and fail) instead of being silently skipped + // as not matching the pattern. Go 1.5 and earlier skipped, but that + // behavior means people miss serious mistakes. + // See golang.org/issue/11407. + if p, err := cfg.BuildContext.ImportDir(path, 0); err != nil && (p == nil || len(p.InvalidGoFiles) == 0) { + if _, noGo := err.(*build.NoGoError); !noGo { + log.Print(err) + } + return nil + } + pkgs = append(pkgs, name) + return nil + }) + return pkgs +} + +// treeCanMatchPattern(pattern)(name) reports whether +// name or children of name can possibly match pattern. +// Pattern is the same limited glob accepted by matchPattern. +func treeCanMatchPattern(pattern string) func(name string) bool { + wildCard := false + if i := strings.Index(pattern, "..."); i >= 0 { + wildCard = true + pattern = pattern[:i] + } + return func(name string) bool { + return len(name) <= len(pattern) && hasPathPrefix(pattern, name) || + wildCard && strings.HasPrefix(name, pattern) + } +} + +// matchPattern(pattern)(name) reports whether +// name matches pattern. Pattern is a limited glob +// pattern in which '...' means 'any string' and there +// is no other special syntax. +// Unfortunately, there are two special cases. Quoting "go help packages": +// +// First, /... at the end of the pattern can match an empty string, +// so that net/... matches both net and packages in its subdirectories, like net/http. +// Second, any slash-separted pattern element containing a wildcard never +// participates in a match of the "vendor" element in the path of a vendored +// package, so that ./... does not match packages in subdirectories of +// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do. +// Note, however, that a directory named vendor that itself contains code +// is not a vendored package: cmd/vendor would be a command named vendor, +// and the pattern cmd/... matches it. +func matchPattern(pattern string) func(name string) bool { + // Convert pattern to regular expression. + // The strategy for the trailing /... is to nest it in an explicit ? expression. + // The strategy for the vendor exclusion is to change the unmatchable + // vendor strings to a disallowed code point (vendorChar) and to use + // "(anything but that codepoint)*" as the implementation of the ... wildcard. + // This is a bit complicated but the obvious alternative, + // namely a hand-written search like in most shell glob matchers, + // is too easy to make accidentally exponential. + // Using package regexp guarantees linear-time matching. + + const vendorChar = "\x00" + + if strings.Contains(pattern, vendorChar) { + return func(name string) bool { return false } + } + + re := regexp.QuoteMeta(pattern) + re = replaceVendor(re, vendorChar) + switch { + case strings.HasSuffix(re, `/`+vendorChar+`/\.\.\.`): + re = strings.TrimSuffix(re, `/`+vendorChar+`/\.\.\.`) + `(/vendor|/` + vendorChar + `/\.\.\.)` + case re == vendorChar+`/\.\.\.`: + re = `(/vendor|/` + vendorChar + `/\.\.\.)` + case strings.HasSuffix(re, `/\.\.\.`): + re = strings.TrimSuffix(re, `/\.\.\.`) + `(/\.\.\.)?` + } + re = strings.Replace(re, `\.\.\.`, `[^`+vendorChar+`]*`, -1) + + reg := regexp.MustCompile(`^` + re + `$`) + + return func(name string) bool { + if strings.Contains(name, vendorChar) { + return false + } + return reg.MatchString(replaceVendor(name, vendorChar)) + } +} + +// MatchPackage(pattern, cwd)(p) reports whether package p matches pattern in the working directory cwd. +func MatchPackage(pattern, cwd string) func(*Package) bool { + switch { + case strings.HasPrefix(pattern, "./") || strings.HasPrefix(pattern, "../") || pattern == "." || pattern == "..": + // Split pattern into leading pattern-free directory path + // (including all . and .. elements) and the final pattern. + var dir string + i := strings.Index(pattern, "...") + if i < 0 { + dir, pattern = pattern, "" + } else { + j := strings.LastIndex(pattern[:i], "/") + dir, pattern = pattern[:j], pattern[j+1:] + } + dir = filepath.Join(cwd, dir) + if pattern == "" { + return func(p *Package) bool { return p.Dir == dir } + } + matchPath := matchPattern(pattern) + return func(p *Package) bool { + // Compute relative path to dir and see if it matches the pattern. + rel, err := filepath.Rel(dir, p.Dir) + if err != nil { + // Cannot make relative - e.g. different drive letters on Windows. + return false + } + rel = filepath.ToSlash(rel) + if rel == ".." || strings.HasPrefix(rel, "../") { + return false + } + return matchPath(rel) + } + case pattern == "all": + return func(p *Package) bool { return true } + case pattern == "std": + return func(p *Package) bool { return p.Standard } + case pattern == "cmd": + return func(p *Package) bool { return p.Standard && strings.HasPrefix(p.ImportPath, "cmd/") } + default: + matchPath := matchPattern(pattern) + return func(p *Package) bool { return matchPath(p.ImportPath) } + } +} + +// replaceVendor returns the result of replacing +// non-trailing vendor path elements in x with repl. +func replaceVendor(x, repl string) string { + if !strings.Contains(x, "vendor") { + return x + } + elem := strings.Split(x, "/") + for i := 0; i < len(elem)-1; i++ { + if elem[i] == "vendor" { + elem[i] = repl + } + } + return strings.Join(elem, "/") +} + +// ImportPaths returns the import paths to use for the given command line. +func ImportPaths(args []string) []string { + args = ImportPathsNoDotExpansion(args) + var out []string + for _, a := range args { + if strings.Contains(a, "...") { + if build.IsLocalImport(a) { + out = append(out, allPackagesInFS(a)...) + } else { + out = append(out, allPackages(a)...) + } + continue + } + out = append(out, a) + } + return out +} + +// ImportPathsNoDotExpansion returns the import paths to use for the given +// command line, but it does no ... expansion. +func ImportPathsNoDotExpansion(args []string) []string { + if cmdlineMatchers == nil { + SetCmdlinePatterns(args) + } + if len(args) == 0 { + return []string{"."} + } + var out []string + for _, a := range args { + // Arguments are supposed to be import paths, but + // as a courtesy to Windows developers, rewrite \ to / + // in command-line arguments. Handles .\... and so on. + if filepath.Separator == '\\' { + a = strings.Replace(a, `\`, `/`, -1) + } + + // Put argument in canonical form, but preserve leading ./. + if strings.HasPrefix(a, "./") { + a = "./" + path.Clean(a) + if a == "./." { + a = "." + } + } else { + a = path.Clean(a) + } + if IsMetaPackage(a) { + out = append(out, allPackages(a)...) + continue + } + out = append(out, a) + } + return out +} + +// IsMetaPackage checks if name is a reserved package name that expands to multiple packages. +func IsMetaPackage(name string) bool { + return name == "std" || name == "cmd" || name == "all" +}
diff --git a/vendor/cmd/go/internal/run/run.go b/vendor/cmd/go/internal/run/run.go new file mode 100644 index 0000000..ce24748 --- /dev/null +++ b/vendor/cmd/go/internal/run/run.go
@@ -0,0 +1,130 @@ +// Copyright 2011 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 run implements the ``go run'' command. +package run + +import ( + "fmt" + "os" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/go/internal/str" + "cmd/go/internal/work" +) + +var CmdRun = &base.Command{ + UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]", + Short: "compile and run Go program", + Long: ` +Run compiles and runs the main package comprising the named Go source files. +A Go source file is defined to be a file ending in a literal ".go" suffix. + +By default, 'go run' runs the compiled binary directly: 'a.out arguments...'. +If the -exec flag is given, 'go run' invokes the binary using xprog: + 'xprog a.out arguments...'. +If the -exec flag is not given, GOOS or GOARCH is different from the system +default, and a program named go_$GOOS_$GOARCH_exec can be found +on the current search path, 'go run' invokes the binary using that program, +for example 'go_nacl_386_exec a.out arguments...'. This allows execution of +cross-compiled programs when a simulator or other execution method is +available. + +For more about build flags, see 'go help build'. + +See also: go build. + `, +} + +func init() { + CmdRun.Run = runRun // break init loop + + work.AddBuildFlags(CmdRun) + CmdRun.Flag.Var((*base.StringsFlag)(&work.ExecCmd), "exec", "") +} + +func printStderr(args ...interface{}) (int, error) { + return fmt.Fprint(os.Stderr, args...) +} + +func runRun(cmd *base.Command, args []string) { + work.BuildInit() + var b work.Builder + b.Init() + b.Print = printStderr + i := 0 + for i < len(args) && strings.HasSuffix(args[i], ".go") { + i++ + } + files, cmdArgs := args[:i], args[i:] + if len(files) == 0 { + base.Fatalf("go run: no go files listed") + } + for _, file := range files { + if strings.HasSuffix(file, "_test.go") { + // GoFilesPackage is going to assign this to TestGoFiles. + // Reject since it won't be part of the build. + base.Fatalf("go run: cannot run *_test.go files (%s)", file) + } + } + p := load.GoFilesPackage(files) + if p.Error != nil { + base.Fatalf("%s", p.Error) + } + p.Internal.OmitDebug = 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[*load.PackageError]bool{} + for _, err := range p.DepsErrors { + if !printed[err] { + printed[err] = true + base.Errorf("%s", err) + } + } + } + base.ExitIfErrors() + if p.Name != "main" { + base.Fatalf("go run: cannot run non-main package") + } + p.Target = "" // must build - not up to date + var src string + if len(p.GoFiles) > 0 { + src = p.GoFiles[0] + } else if len(p.CgoFiles) > 0 { + src = p.CgoFiles[0] + } else { + // this case could only happen if the provided source uses cgo + // while cgo is disabled. + hint := "" + if !cfg.BuildContext.CgoEnabled { + hint = " (cgo is disabled)" + } + base.Fatalf("go run: no suitable source files%s", hint) + } + p.Internal.ExeName = src[:len(src)-len(".go")] // name temporary executable for first go file + a1 := b.LinkAction(work.ModeBuild, work.ModeBuild, p) + a := &work.Action{Mode: "go run", Func: buildRunProgram, Args: cmdArgs, Deps: []*work.Action{a1}} + b.Do(a) +} + +// buildRunProgram is the action for running a binary that has already +// been compiled. We ignore exit status. +func buildRunProgram(b *work.Builder, a *work.Action) error { + cmdline := str.StringList(work.FindExecCmd(), a.Deps[0].Target, a.Args) + if cfg.BuildN || cfg.BuildX { + b.Showcmd("", "%s", strings.Join(cmdline, " ")) + if cfg.BuildN { + return nil + } + } + + base.RunStdin(cmdline) + return nil +}
diff --git a/vendor/cmd/go/internal/str/path.go b/vendor/cmd/go/internal/str/path.go new file mode 100644 index 0000000..84ca9d5 --- /dev/null +++ b/vendor/cmd/go/internal/str/path.go
@@ -0,0 +1,32 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package str + +import ( + "path/filepath" + "strings" +) + +// HasFilePathPrefix reports whether the filesystem path s begins with the +// elements in prefix. +func HasFilePathPrefix(s, prefix string) bool { + sv := strings.ToUpper(filepath.VolumeName(s)) + pv := strings.ToUpper(filepath.VolumeName(prefix)) + s = s[len(sv):] + prefix = prefix[len(pv):] + switch { + default: + return false + case sv != pv: + return false + case len(s) == len(prefix): + return s == prefix + case len(s) > len(prefix): + if prefix != "" && prefix[len(prefix)-1] == filepath.Separator { + return strings.HasPrefix(s, prefix) + } + return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix + } +}
diff --git a/vendor/cmd/go/internal/str/str.go b/vendor/cmd/go/internal/str/str.go new file mode 100644 index 0000000..0413ed8 --- /dev/null +++ b/vendor/cmd/go/internal/str/str.go
@@ -0,0 +1,141 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package str provides string manipulation utilities. +package str + +import ( + "bytes" + "fmt" + "unicode" + "unicode/utf8" +) + +// StringList flattens its arguments into a single []string. +// Each argument in args must have type string or []string. +func StringList(args ...interface{}) []string { + var x []string + for _, arg := range args { + switch arg := arg.(type) { + case []string: + x = append(x, arg...) + case string: + x = append(x, arg) + default: + panic("stringList: invalid argument of type " + fmt.Sprintf("%T", arg)) + } + } + return x +} + +// ToFold returns a string with the property that +// strings.EqualFold(s, t) iff ToFold(s) == ToFold(t) +// This lets us test a large set of strings for fold-equivalent +// duplicates without making a quadratic number of calls +// to EqualFold. Note that strings.ToUpper and strings.ToLower +// do not have the desired property in some corner cases. +func ToFold(s string) string { + // Fast path: all ASCII, no upper case. + // Most paths look like this already. + for i := 0; i < len(s); i++ { + c := s[i] + if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' { + goto Slow + } + } + return s + +Slow: + var buf bytes.Buffer + for _, r := range s { + // SimpleFold(x) cycles to the next equivalent rune > x + // or wraps around to smaller values. Iterate until it wraps, + // and we've found the minimum value. + for { + r0 := r + r = unicode.SimpleFold(r0) + if r <= r0 { + break + } + } + // Exception to allow fast path above: A-Z => a-z + if 'A' <= r && r <= 'Z' { + r += 'a' - 'A' + } + buf.WriteRune(r) + } + return buf.String() +} + +// FoldDup reports a pair of strings from the list that are +// equal according to strings.EqualFold. +// It returns "", "" if there are no such strings. +func FoldDup(list []string) (string, string) { + clash := map[string]string{} + for _, s := range list { + fold := ToFold(s) + if t := clash[fold]; t != "" { + if s > t { + s, t = t, s + } + return s, t + } + clash[fold] = s + } + return "", "" +} + +// Contains reports whether x contains s. +func Contains(x []string, s string) bool { + for _, t := range x { + if t == s { + return true + } + } + return false +} + +func isSpaceByte(c byte) bool { + return c == ' ' || c == '\t' || c == '\n' || c == '\r' +} + +// SplitQuotedFields splits s into a list of fields, +// allowing single or double quotes around elements. +// There is no unescaping or other processing within +// quoted fields. +func SplitQuotedFields(s string) ([]string, error) { + // Split fields allowing '' or "" around elements. + // Quotes further inside the string do not count. + var f []string + for len(s) > 0 { + for len(s) > 0 && isSpaceByte(s[0]) { + s = s[1:] + } + if len(s) == 0 { + break + } + // Accepted quoted string. No unescaping inside. + if s[0] == '"' || s[0] == '\'' { + quote := s[0] + s = s[1:] + i := 0 + for i < len(s) && s[i] != quote { + i++ + } + if i >= len(s) { + return nil, fmt.Errorf("unterminated %c string", quote) + } + f = append(f, s[:i]) + s = s[i+1:] + continue + } + i := 0 + for i < len(s) && !isSpaceByte(s[i]) { + i++ + } + f = append(f, s[:i]) + s = s[i:] + } + return f, nil +}
diff --git a/vendor/cmd/go/internal/test/cover.go b/vendor/cmd/go/internal/test/cover.go new file mode 100644 index 0000000..12538b4 --- /dev/null +++ b/vendor/cmd/go/internal/test/cover.go
@@ -0,0 +1,84 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package test + +import ( + "cmd/go/internal/base" + "fmt" + "io" + "os" + "path/filepath" + "sync" +) + +var coverMerge struct { + f *os.File + sync.Mutex // for f.Write +} + +// initCoverProfile initializes the test coverage profile. +// It must be run before any calls to mergeCoverProfile or closeCoverProfile. +// Using this function clears the profile in case it existed from a previous run, +// or in case it doesn't exist and the test is going to fail to create it (or not run). +func initCoverProfile() { + if testCoverProfile == "" { + return + } + if !filepath.IsAbs(testCoverProfile) && testOutputDir != "" { + testCoverProfile = filepath.Join(testOutputDir, testCoverProfile) + } + + // No mutex - caller's responsibility to call with no racing goroutines. + f, err := os.Create(testCoverProfile) + if err != nil { + base.Fatalf("%v", err) + } + _, err = fmt.Fprintf(f, "mode: %s\n", testCoverMode) + if err != nil { + base.Fatalf("%v", err) + } + coverMerge.f = f +} + +// mergeCoverProfile merges file into the profile stored in testCoverProfile. +// It prints any errors it encounters to ew. +func mergeCoverProfile(ew io.Writer, file string) { + if coverMerge.f == nil { + return + } + coverMerge.Lock() + defer coverMerge.Unlock() + + expect := fmt.Sprintf("mode: %s\n", testCoverMode) + buf := make([]byte, len(expect)) + r, err := os.Open(file) + if err != nil { + // Test did not create profile, which is OK. + return + } + defer r.Close() + + n, err := io.ReadFull(r, buf) + if n == 0 { + return + } + if err != nil || string(buf) != expect { + fmt.Fprintf(ew, "error: test wrote malformed coverage profile.\n") + return + } + _, err = io.Copy(coverMerge.f, r) + if err != nil { + fmt.Fprintf(ew, "error: saving coverage profile: %v\n", err) + } +} + +func closeCoverProfile() { + if coverMerge.f == nil { + return + } + if err := coverMerge.f.Close(); err != nil { + base.Errorf("closing coverage profile: %v", err) + } +}
diff --git a/vendor/cmd/go/internal/test/test.go b/vendor/cmd/go/internal/test/test.go new file mode 100644 index 0000000..0a44058 --- /dev/null +++ b/vendor/cmd/go/internal/test/test.go
@@ -0,0 +1,2038 @@ +// Copyright 2011 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 test + +import ( + "bytes" + "crypto/sha256" + "errors" + "fmt" + "go/ast" + "go/build" + "go/doc" + "go/parser" + "go/token" + "io" + "io/ioutil" + "os" + "os/exec" + "path" + "path/filepath" + "regexp" + "sort" + "strconv" + "strings" + "sync" + "text/template" + "time" + "unicode" + "unicode/utf8" + + "cmd/go/internal/base" + "cmd/go/internal/cache" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/go/internal/str" + "cmd/go/internal/work" + "cmd/internal/test2json" +) + +// Break init loop. +func init() { + CmdTest.Run = runTest +} + +const testUsage = "test [build/test flags] [packages] [build/test flags & test binary flags]" + +var CmdTest = &base.Command{ + CustomFlags: true, + UsageLine: testUsage, + Short: "test packages", + Long: ` +'Go test' automates testing the packages named by the import paths. +It prints a summary of the test results in the format: + + ok archive/tar 0.011s + FAIL archive/zip 0.022s + ok compress/gzip 0.033s + ... + +followed by detailed output for each failed package. + +'Go test' recompiles each package along with any files with names matching +the file pattern "*_test.go". +These additional files can contain test functions, benchmark functions, and +example functions. See 'go help testfunc' for more. +Each listed package causes the execution of a separate test binary. +Files whose names begin with "_" (including "_test.go") or "." are ignored. + +Test files that declare a package with the suffix "_test" will be compiled as a +separate package, and then linked and run with the main test binary. + +The go tool will ignore a directory named "testdata", making it available +to hold ancillary data needed by the tests. + +As part of building a test binary, go test runs go vet on the package +and its test source files to identify significant problems. If go vet +finds any problems, go test reports those and does not run the test binary. +Only a high-confidence subset of the default go vet checks are used. +To disable the running of go vet, use the -vet=off flag. + +All test output and summary lines are printed to the go command's +standard output, even if the test printed them to its own standard +error. (The go command's standard error is reserved for printing +errors building the tests.) + +Go test runs in two different modes: + +The first, called local directory mode, occurs when go test is +invoked with no package arguments (for example, 'go test' or 'go +test -v'). In this mode, go test compiles the package sources and +tests found in the current directory and then runs the resulting +test binary. In this mode, caching (discussed below) is disabled. +After the package test finishes, go test prints a summary line +showing the test status ('ok' or 'FAIL'), package name, and elapsed +time. + +The second, called package list mode, occurs when go test is invoked +with explicit package arguments (for example 'go test math', 'go +test ./...', and even 'go test .'). In this mode, go test compiles +and tests each of the packages listed on the command line. If a +package test passes, go test prints only the final 'ok' summary +line. If a package test fails, go test prints the full test output. +If invoked with the -bench or -v flag, go test prints the full +output even for passing package tests, in order to display the +requested benchmark results or verbose logging. + +In package list mode only, go test caches successful package test +results to avoid unnecessary repeated running of tests. When the +result of a test can be recovered from the cache, go test will +redisplay the previous output instead of running the test binary +again. When this happens, go test prints '(cached)' in place of the +elapsed time in the summary line. + +The rule for a match in the cache is that the run involves the same +test binary and the flags on the command line come entirely from a +restricted set of 'cacheable' test flags, defined as -cpu, -list, +-parallel, -run, -short, and -v. If a run of go test has any test +or non-test flags outside this set, the result is not cached. To +disable test caching, use any test flag or argument other than the +cacheable flags. The idiomatic way to disable test caching explicitly +is to use -count=1. Tests that open files within the package's source +root (usually $GOPATH) or that consult environment variables only +match future runs in which the files and environment variables are unchanged. +A cached test result is treated as executing in no time at all, +so a successful package test result will be cached and reused +regardless of -timeout setting. + +` + strings.TrimSpace(testFlag1) + ` See 'go help testflag' for details. + +For more about build flags, see 'go help build'. +For more about specifying packages, see 'go help packages'. + +See also: go build, go vet. +`, +} + +const testFlag1 = ` +In addition to the build flags, the flags handled by 'go test' itself are: + + -args + Pass the remainder of the command line (everything after -args) + to the test binary, uninterpreted and unchanged. + Because this flag consumes the remainder of the command line, + the package list (if present) must appear before this flag. + + -c + Compile the test binary to pkg.test but do not run it + (where pkg is the last element of the package's import path). + The file name can be changed with the -o flag. + + -exec xprog + Run the test binary using xprog. The behavior is the same as + in 'go run'. See 'go help run' for details. + + -i + Install packages that are dependencies of the test. + Do not run the test. + + -json + Convert test output to JSON suitable for automated processing. + See 'go doc test2json' for the encoding details. + + -o file + Compile the test binary to the named file. + The test still runs (unless -c or -i is specified). + +The test binary also accepts flags that control execution of the test; these +flags are also accessible by 'go test'. +` + +// Usage prints the usage message for 'go test -h' and exits. +func Usage() { + os.Stderr.WriteString(testUsage + "\n\n" + + strings.TrimSpace(testFlag1) + "\n\n\t" + + strings.TrimSpace(testFlag2) + "\n") + os.Exit(2) +} + +var HelpTestflag = &base.Command{ + UsageLine: "testflag", + Short: "testing flags", + Long: ` +The 'go test' command takes both flags that apply to 'go test' itself +and flags that apply to the resulting test binary. + +Several of the flags control profiling and write an execution profile +suitable for "go tool pprof"; run "go tool pprof -h" for more +information. The --alloc_space, --alloc_objects, and --show_bytes +options of pprof control how the information is presented. + +The following flags are recognized by the 'go test' command and +control the execution of any test: + + ` + strings.TrimSpace(testFlag2) + ` +`, +} + +const testFlag2 = ` + -bench regexp + Run only those benchmarks matching a regular expression. + By default, no benchmarks are run. + To run all benchmarks, use '-bench .' or '-bench=.'. + The regular expression is split by unbracketed slash (/) + characters into a sequence of regular expressions, and each + part of a benchmark's identifier must match the corresponding + element in the sequence, if any. Possible parents of matches + are run with b.N=1 to identify sub-benchmarks. For example, + given -bench=X/Y, top-level benchmarks matching X are run + with b.N=1 to find any sub-benchmarks matching Y, which are + then run in full. + + -benchtime t + Run enough iterations of each benchmark to take t, specified + as a time.Duration (for example, -benchtime 1h30s). + The default is 1 second (1s). + + -count n + Run each test and benchmark n times (default 1). + If -cpu is set, run n times for each GOMAXPROCS value. + Examples are always run once. + + -cover + Enable coverage analysis. + Note that because coverage works by annotating the source + code before compilation, compilation and test failures with + coverage enabled may report line numbers that don't correspond + to the original sources. + + -covermode set,count,atomic + Set the mode for coverage analysis for the package[s] + being tested. The default is "set" unless -race is enabled, + in which case it is "atomic". + The values: + set: bool: does this statement run? + count: int: how many times does this statement run? + atomic: int: count, but correct in multithreaded tests; + significantly more expensive. + Sets -cover. + + -coverpkg pattern1,pattern2,pattern3 + Apply coverage analysis in each test to packages matching the patterns. + The default is for each test to analyze only the package being tested. + See 'go help packages' for a description of package patterns. + Sets -cover. + + -cpu 1,2,4 + Specify a list of GOMAXPROCS values for which the tests or + benchmarks should be executed. The default is the current value + of GOMAXPROCS. + + -failfast + Do not start new tests after the first test failure. + + -list regexp + List tests, benchmarks, or examples matching the regular expression. + No tests, benchmarks or examples will be run. This will only + list top-level tests. No subtest or subbenchmarks will be shown. + + -parallel n + Allow parallel execution of test functions that call t.Parallel. + The value of this flag is the maximum number of tests to run + simultaneously; by default, it is set to the value of GOMAXPROCS. + Note that -parallel only applies within a single test binary. + The 'go test' command may run tests for different packages + in parallel as well, according to the setting of the -p flag + (see 'go help build'). + + -run regexp + Run only those tests and examples matching the regular expression. + For tests, the regular expression is split by unbracketed slash (/) + characters into a sequence of regular expressions, and each part + of a test's identifier must match the corresponding element in + the sequence, if any. Note that possible parents of matches are + run too, so that -run=X/Y matches and runs and reports the result + of all tests matching X, even those without sub-tests matching Y, + because it must run them to look for those sub-tests. + + -short + Tell long-running tests to shorten their run time. + It is off by default but set during all.bash so that installing + the Go tree can run a sanity check but not spend time running + exhaustive tests. + + -timeout d + If a test binary runs longer than duration d, panic. + If d is 0, the timeout is disabled. + The default is 10 minutes (10m). + + -v + Verbose output: log all tests as they are run. Also print all + text from Log and Logf calls even if the test succeeds. + + -vet list + Configure the invocation of "go vet" during "go test" + to use the comma-separated list of vet checks. + If list is empty, "go test" runs "go vet" with a curated list of + checks believed to be always worth addressing. + If list is "off", "go test" does not run "go vet" at all. + +The following flags are also recognized by 'go test' and can be used to +profile the tests during execution: + + -benchmem + Print memory allocation statistics for benchmarks. + + -blockprofile block.out + Write a goroutine blocking profile to the specified file + when all tests are complete. + Writes test binary as -c would. + + -blockprofilerate n + Control the detail provided in goroutine blocking profiles by + calling runtime.SetBlockProfileRate with n. + See 'go doc runtime.SetBlockProfileRate'. + The profiler aims to sample, on average, one blocking event every + n nanoseconds the program spends blocked. By default, + if -test.blockprofile is set without this flag, all blocking events + are recorded, equivalent to -test.blockprofilerate=1. + + -coverprofile cover.out + Write a coverage profile to the file after all tests have passed. + Sets -cover. + + -cpuprofile cpu.out + Write a CPU profile to the specified file before exiting. + Writes test binary as -c would. + + -memprofile mem.out + Write a memory profile to the file after all tests have passed. + Writes test binary as -c would. + + -memprofilerate n + Enable more precise (and expensive) memory profiles by setting + runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'. + To profile all memory allocations, use -test.memprofilerate=1 + and pass --alloc_space flag to the pprof tool. + + -mutexprofile mutex.out + Write a mutex contention profile to the specified file + when all tests are complete. + Writes test binary as -c would. + + -mutexprofilefraction n + Sample 1 in n stack traces of goroutines holding a + contended mutex. + + -outputdir directory + Place output files from profiling in the specified directory, + by default the directory in which "go test" is running. + + -trace trace.out + Write an execution trace to the specified file before exiting. + +Each of these flags is also recognized with an optional 'test.' prefix, +as in -test.v. When invoking the generated test binary (the result of +'go test -c') directly, however, the prefix is mandatory. + +The 'go test' command rewrites or removes recognized flags, +as appropriate, both before and after the optional package list, +before invoking the test binary. + +For instance, the command + + go test -v -myflag testdata -cpuprofile=prof.out -x + +will compile the test binary and then run it as + + pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out + +(The -x flag is removed because it applies only to the go command's +execution, not to the test itself.) + +The test flags that generate profiles (other than for coverage) also +leave the test binary in pkg.test for use when analyzing the profiles. + +When 'go test' runs a test binary, it does so from within the +corresponding package's source code directory. Depending on the test, +it may be necessary to do the same when invoking a generated test +binary directly. + +The command-line package list, if present, must appear before any +flag not known to the go test command. Continuing the example above, +the package list would have to appear before -myflag, but could appear +on either side of -v. + +To keep an argument for a test binary from being interpreted as a +known flag or a package name, use -args (see 'go help test') which +passes the remainder of the command line through to the test binary +uninterpreted and unaltered. + +For instance, the command + + go test -v -args -x -v + +will compile the test binary and then run it as + + pkg.test -test.v -x -v + +Similarly, + + go test -args math + +will compile the test binary and then run it as + + pkg.test math + +In the first example, the -x and the second -v are passed through to the +test binary unchanged and with no effect on the go command itself. +In the second example, the argument math is passed through to the test +binary, instead of being interpreted as the package list. +` + +var HelpTestfunc = &base.Command{ + UsageLine: "testfunc", + Short: "testing functions", + Long: ` +The 'go test' command expects to find test, benchmark, and example functions +in the "*_test.go" files corresponding to the package under test. + +A test function is one named TestXxx (where Xxx does not start with a +lower case letter) and should have the signature, + + func TestXxx(t *testing.T) { ... } + +A benchmark function is one named BenchmarkXxx and should have the signature, + + func BenchmarkXxx(b *testing.B) { ... } + +An example function is similar to a test function but, instead of using +*testing.T to report success or failure, prints output to os.Stdout. +If the last comment in the function starts with "Output:" then the output +is compared exactly against the comment (see examples below). If the last +comment begins with "Unordered output:" then the output is compared to the +comment, however the order of the lines is ignored. An example with no such +comment is compiled but not executed. An example with no text after +"Output:" is compiled, executed, and expected to produce no output. + +Godoc displays the body of ExampleXxx to demonstrate the use +of the function, constant, or variable Xxx. An example of a method M with +receiver type T or *T is named ExampleT_M. There may be multiple examples +for a given function, constant, or variable, distinguished by a trailing _xxx, +where xxx is a suffix not beginning with an upper case letter. + +Here is an example of an example: + + func ExamplePrintln() { + Println("The output of\nthis example.") + // Output: The output of + // this example. + } + +Here is another example where the ordering of the output is ignored: + + func ExamplePerm() { + for _, value := range Perm(4) { + fmt.Println(value) + } + + // Unordered output: 4 + // 2 + // 1 + // 3 + // 0 + } + +The entire test file is presented as the example when it contains a single +example function, at least one other function, type, variable, or constant +declaration, and no test or benchmark functions. + +See the documentation of the testing package for more information. +`, +} + +var ( + testC bool // -c flag + testCover bool // -cover flag + testCoverMode string // -covermode flag + testCoverPaths []string // -coverpkg flag + testCoverPkgs []*load.Package // -coverpkg flag + testCoverProfile string // -coverprofile flag + testOutputDir string // -outputdir flag + testO string // -o flag + testProfile string // profiling flag that limits test to one package + testNeedBinary bool // profile needs to keep binary around + testJSON bool // -json flag + testV bool // -v flag + testTimeout string // -timeout flag + testArgs []string + testBench bool + testList bool + testShowPass bool // show passing output + testVetList string // -vet flag + pkgArgs []string + pkgs []*load.Package + + testKillTimeout = 10 * time.Minute + testCacheExpire time.Time // ignore cached test results before this time +) + +var testMainDeps = []string{ + // Dependencies for testmain. + "os", + "testing", + "testing/internal/testdeps", +} + +// testVetFlags is the list of flags to pass to vet when invoked automatically during go test. +var testVetFlags = []string{ + // TODO(rsc): Decide which tests are enabled by default. + // See golang.org/issue/18085. + // "-asmdecl", + // "-assign", + "-atomic", + "-bool", + "-buildtags", + // "-cgocall", + // "-composites", + // "-copylocks", + // "-httpresponse", + // "-lostcancel", + // "-methods", + "-nilfunc", + "-printf", + // "-rangeloops", + // "-shift", + // "-structtags", + // "-tests", + // "-unreachable", + // "-unsafeptr", + // "-unusedresult", +} + +func runTest(cmd *base.Command, args []string) { + pkgArgs, testArgs = testFlags(args) + + work.FindExecCmd() // initialize cached result + + work.BuildInit() + work.VetFlags = testVetFlags + + pkgs = load.PackagesForBuild(pkgArgs) + if len(pkgs) == 0 { + base.Fatalf("no packages to test") + } + + if testC && len(pkgs) != 1 { + base.Fatalf("cannot use -c flag with multiple packages") + } + if testO != "" && len(pkgs) != 1 { + base.Fatalf("cannot use -o flag with multiple packages") + } + if testProfile != "" && len(pkgs) != 1 { + base.Fatalf("cannot use %s flag with multiple packages", testProfile) + } + initCoverProfile() + defer closeCoverProfile() + + // If a test timeout was given and is parseable, set our kill timeout + // to that timeout plus one minute. This is a backup alarm in case + // the test wedges with a goroutine spinning and its background + // timer does not get a chance to fire. + if dt, err := time.ParseDuration(testTimeout); err == nil && dt > 0 { + testKillTimeout = dt + 1*time.Minute + } else if err == nil && dt == 0 { + // An explicit zero disables the test timeout. + // Let it have one century (almost) before we kill it. + testKillTimeout = 100 * 365 * 24 * time.Hour + } + + // show passing test output (after buffering) with -v flag. + // must buffer because tests are running in parallel, and + // otherwise the output will get mixed. + testShowPass = testV || testList + + // For 'go test -i -o x.test', we want to build x.test. Imply -c to make the logic easier. + if cfg.BuildI && testO != "" { + testC = true + } + + // Read testcache expiration time, if present. + // (We implement go clean -testcache by writing an expiration date + // instead of searching out and deleting test result cache entries.) + if dir := cache.DefaultDir(); dir != "off" { + if data, _ := ioutil.ReadFile(filepath.Join(dir, "testexpire.txt")); len(data) > 0 && data[len(data)-1] == '\n' { + if t, err := strconv.ParseInt(string(data[:len(data)-1]), 10, 64); err == nil { + testCacheExpire = time.Unix(0, t) + } + } + } + + var b work.Builder + b.Init() + + if cfg.BuildI { + cfg.BuildV = testV + + deps := make(map[string]bool) + for _, dep := range testMainDeps { + deps[dep] = true + } + + for _, p := range pkgs { + // Dependencies for each test. + for _, path := range p.Imports { + deps[path] = true + } + for _, path := range p.Vendored(p.TestImports) { + deps[path] = true + } + for _, path := range p.Vendored(p.XTestImports) { + deps[path] = true + } + } + + // translate C to runtime/cgo + if deps["C"] { + delete(deps, "C") + deps["runtime/cgo"] = true + } + // Ignore pseudo-packages. + delete(deps, "unsafe") + + all := []string{} + for path := range deps { + if !build.IsLocalImport(path) { + all = append(all, path) + } + } + sort.Strings(all) + + a := &work.Action{Mode: "go test -i"} + for _, p := range load.PackagesForBuild(all) { + a.Deps = append(a.Deps, b.CompileAction(work.ModeInstall, work.ModeInstall, p)) + } + b.Do(a) + if !testC || a.Failed { + return + } + b.Init() + } + + var builds, runs, prints []*work.Action + + if testCoverPaths != nil { + match := make([]func(*load.Package) bool, len(testCoverPaths)) + matched := make([]bool, len(testCoverPaths)) + for i := range testCoverPaths { + match[i] = load.MatchPackage(testCoverPaths[i], base.Cwd) + } + + // Select for coverage all dependencies matching the testCoverPaths patterns. + for _, p := range load.PackageList(pkgs) { + haveMatch := false + for i := range testCoverPaths { + if match[i](p) { + matched[i] = true + haveMatch = true + } + } + + // Silently ignore attempts to run coverage on + // sync/atomic when using atomic coverage mode. + // Atomic coverage mode uses sync/atomic, so + // we can't also do coverage on it. + if testCoverMode == "atomic" && p.Standard && p.ImportPath == "sync/atomic" { + continue + } + + if haveMatch { + testCoverPkgs = append(testCoverPkgs, p) + } + } + + // Warn about -coverpkg arguments that are not actually used. + for i := range testCoverPaths { + if !matched[i] { + fmt.Fprintf(os.Stderr, "warning: no packages being tested depend on matches for pattern %s\n", testCoverPaths[i]) + } + } + + // Mark all the coverage packages for rebuilding with coverage. + for _, p := range testCoverPkgs { + // There is nothing to cover in package unsafe; it comes from the compiler. + if p.ImportPath == "unsafe" { + continue + } + p.Internal.CoverMode = testCoverMode + var coverFiles []string + coverFiles = append(coverFiles, p.GoFiles...) + coverFiles = append(coverFiles, p.CgoFiles...) + coverFiles = append(coverFiles, p.TestGoFiles...) + p.Internal.CoverVars = declareCoverVars(p.ImportPath, coverFiles...) + if testCover && testCoverMode == "atomic" { + ensureImport(p, "sync/atomic") + } + } + } + + // Prepare build + run + print actions for all packages being tested. + for _, p := range pkgs { + // sync/atomic import is inserted by the cover tool. See #18486 + if testCover && testCoverMode == "atomic" { + ensureImport(p, "sync/atomic") + } + + buildTest, runTest, printTest, err := builderTest(&b, p) + if err != nil { + str := err.Error() + if strings.HasPrefix(str, "\n") { + str = str[1:] + } + failed := fmt.Sprintf("FAIL\t%s [setup failed]\n", p.ImportPath) + + if p.ImportPath != "" { + base.Errorf("# %s\n%s\n%s", p.ImportPath, str, failed) + } else { + base.Errorf("%s\n%s", str, failed) + } + continue + } + builds = append(builds, buildTest) + runs = append(runs, runTest) + prints = append(prints, printTest) + } + + // Ultimately the goal is to print the output. + root := &work.Action{Mode: "go test", Deps: prints} + + // Force the printing of results to happen in order, + // one at a time. + for i, a := range prints { + if i > 0 { + a.Deps = append(a.Deps, prints[i-1]) + } + } + + // Force benchmarks to run in serial. + if !testC && testBench { + // The first run must wait for all builds. + // Later runs must wait for the previous run's print. + for i, run := range runs { + if i == 0 { + run.Deps = append(run.Deps, builds...) + } else { + run.Deps = append(run.Deps, prints[i-1]) + } + } + } + + b.Do(root) +} + +// ensures that package p imports the named package +func ensureImport(p *load.Package, pkg string) { + for _, d := range p.Internal.Imports { + if d.Name == pkg { + return + } + } + + p1 := load.LoadPackage(pkg, &load.ImportStack{}) + if p1.Error != nil { + base.Fatalf("load %s: %v", pkg, p1.Error) + } + + p.Internal.Imports = append(p.Internal.Imports, p1) +} + +var windowsBadWords = []string{ + "install", + "patch", + "setup", + "update", +} + +func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, printAction *work.Action, err error) { + if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 { + build := b.CompileAction(work.ModeBuild, work.ModeBuild, p) + run := &work.Action{Mode: "test run", Package: p, Deps: []*work.Action{build}} + addTestVet(b, p, run, nil) + print := &work.Action{Mode: "test print", Func: builderNoTest, Package: p, Deps: []*work.Action{run}} + return build, run, print, nil + } + + // Build Package structs describing: + // ptest - package + test files + // pxtest - package of external test files + // pmain - pkg.test binary + var ptest, pxtest, pmain *load.Package + + localCover := testCover && testCoverPaths == nil + + ptest, pxtest, err = load.TestPackagesFor(p, localCover || p.Name == "main") + if err != nil { + return nil, nil, nil, err + } + + // Use last element of import path, not package name. + // They differ when package name is "main". + // But if the import path is "command-line-arguments", + // like it is during 'go run', use the package name. + var elem string + if p.ImportPath == "command-line-arguments" { + elem = p.Name + } else { + _, elem = path.Split(p.ImportPath) + } + testBinary := elem + ".test" + + // Should we apply coverage analysis locally, + // only for this package and only for this test? + // Yes, if -cover is on but -coverpkg has not specified + // a list of packages for global coverage. + if localCover { + ptest.Internal.CoverMode = testCoverMode + var coverFiles []string + coverFiles = append(coverFiles, ptest.GoFiles...) + coverFiles = append(coverFiles, ptest.CgoFiles...) + ptest.Internal.CoverVars = declareCoverVars(ptest.ImportPath, coverFiles...) + } + + testDir := b.NewObjdir() + if err := b.Mkdir(testDir); err != nil { + return nil, nil, nil, err + } + + // Action for building pkg.test. + pmain = &load.Package{ + PackagePublic: load.PackagePublic{ + Name: "main", + Dir: testDir, + GoFiles: []string{"_testmain.go"}, + ImportPath: p.ImportPath + " (testmain)", + Root: p.Root, + }, + Internal: load.PackageInternal{ + Build: &build.Package{Name: "main"}, + OmitDebug: !testC && !testNeedBinary, + + Asmflags: p.Internal.Asmflags, + Gcflags: p.Internal.Gcflags, + Ldflags: p.Internal.Ldflags, + Gccgoflags: p.Internal.Gccgoflags, + }, + } + + // The generated main also imports testing, regexp, and os. + // Also the linker introduces implicit dependencies reported by LinkerDeps. + var stk load.ImportStack + stk.Push("testmain") + deps := testMainDeps // cap==len, so safe for append + for _, d := range load.LinkerDeps(p) { + deps = append(deps, d) + } + for _, dep := range deps { + if dep == ptest.ImportPath { + pmain.Internal.Imports = append(pmain.Internal.Imports, ptest) + } else { + p1 := load.LoadImport(dep, "", nil, &stk, nil, 0) + if p1.Error != nil { + return nil, nil, nil, p1.Error + } + pmain.Internal.Imports = append(pmain.Internal.Imports, p1) + } + } + + if testCoverPkgs != nil { + // Add imports, but avoid duplicates. + seen := map[*load.Package]bool{p: true, ptest: true} + for _, p1 := range pmain.Internal.Imports { + seen[p1] = true + } + for _, p1 := range testCoverPkgs { + if !seen[p1] { + seen[p1] = true + pmain.Internal.Imports = append(pmain.Internal.Imports, p1) + } + } + } + + // Do initial scan for metadata needed for writing _testmain.go + // Use that metadata to update the list of imports for package main. + // The list of imports is used by recompileForTest and by the loop + // afterward that gathers t.Cover information. + t, err := loadTestFuncs(ptest) + if err != nil { + return nil, nil, nil, err + } + if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 { + pmain.Internal.Imports = append(pmain.Internal.Imports, ptest) + t.ImportTest = true + } + if pxtest != nil { + pmain.Internal.Imports = append(pmain.Internal.Imports, pxtest) + t.ImportXtest = true + } + + if ptest != p { + // We have made modifications to the package p being tested + // and are rebuilding p (as ptest). + // Arrange to rebuild all packages q such that + // the test depends on q and q depends on p. + // This makes sure that q sees the modifications to p. + // Strictly speaking, the rebuild is only necessary if the + // modifications to p change its export metadata, but + // determining that is a bit tricky, so we rebuild always. + recompileForTest(pmain, p, ptest, pxtest) + } + + for _, cp := range pmain.Internal.Imports { + if len(cp.Internal.CoverVars) > 0 { + t.Cover = append(t.Cover, coverInfo{cp, cp.Internal.CoverVars}) + } + } + + if !cfg.BuildN { + // writeTestmain writes _testmain.go, + // using the test description gathered in t. + if err := writeTestmain(testDir+"_testmain.go", t); err != nil { + return nil, nil, nil, err + } + } + + // Set compile objdir to testDir we've already created, + // so that the default file path stripping applies to _testmain.go. + b.CompileAction(work.ModeBuild, work.ModeBuild, pmain).Objdir = testDir + + a := b.LinkAction(work.ModeBuild, work.ModeBuild, pmain) + a.Target = testDir + testBinary + cfg.ExeSuffix + if cfg.Goos == "windows" { + // There are many reserved words on Windows that, + // if used in the name of an executable, cause Windows + // to try to ask for extra permissions. + // The word list includes setup, install, update, and patch, + // but it does not appear to be defined anywhere. + // We have run into this trying to run the + // go.codereview/patch tests. + // For package names containing those words, use test.test.exe + // instead of pkgname.test.exe. + // Note that this file name is only used in the Go command's + // temporary directory. If the -c or other flags are + // given, the code below will still use pkgname.test.exe. + // There are two user-visible effects of this change. + // First, you can actually run 'go test' in directories that + // have names that Windows thinks are installer-like, + // without getting a dialog box asking for more permissions. + // Second, in the Windows process listing during go test, + // the test shows up as test.test.exe, not pkgname.test.exe. + // That second one is a drawback, but it seems a small + // price to pay for the test running at all. + // If maintaining the list of bad words is too onerous, + // we could just do this always on Windows. + for _, bad := range windowsBadWords { + if strings.Contains(testBinary, bad) { + a.Target = testDir + "test.test" + cfg.ExeSuffix + break + } + } + } + buildAction = a + var installAction, cleanAction *work.Action + if testC || testNeedBinary { + // -c or profiling flag: create action to copy binary to ./test.out. + target := filepath.Join(base.Cwd, testBinary+cfg.ExeSuffix) + if testO != "" { + target = testO + if !filepath.IsAbs(target) { + target = filepath.Join(base.Cwd, target) + } + } + pmain.Target = target + installAction = &work.Action{ + Mode: "test build", + Func: work.BuildInstallFunc, + Deps: []*work.Action{buildAction}, + Package: pmain, + Target: target, + } + runAction = installAction // make sure runAction != nil even if not running test + } + if testC { + printAction = &work.Action{Mode: "test print (nop)", Package: p, Deps: []*work.Action{runAction}} // nop + } else { + // run test + c := new(runCache) + runAction = &work.Action{ + Mode: "test run", + Func: c.builderRunTest, + Deps: []*work.Action{buildAction}, + Package: p, + IgnoreFail: true, // run (prepare output) even if build failed + TryCache: c.tryCache, + Objdir: testDir, + } + if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 { + addTestVet(b, ptest, runAction, installAction) + } + if pxtest != nil { + addTestVet(b, pxtest, runAction, installAction) + } + cleanAction = &work.Action{ + Mode: "test clean", + Func: builderCleanTest, + Deps: []*work.Action{runAction}, + Package: p, + IgnoreFail: true, // clean even if test failed + Objdir: testDir, + } + printAction = &work.Action{ + Mode: "test print", + Func: builderPrintTest, + Deps: []*work.Action{cleanAction}, + Package: p, + IgnoreFail: true, // print even if test failed + } + } + if installAction != nil { + if runAction != installAction { + installAction.Deps = append(installAction.Deps, runAction) + } + if cleanAction != nil { + cleanAction.Deps = append(cleanAction.Deps, installAction) + } + } + + return buildAction, runAction, printAction, nil +} + +func addTestVet(b *work.Builder, p *load.Package, runAction, installAction *work.Action) { + if testVetList == "off" { + return + } + + vet := b.VetAction(work.ModeBuild, work.ModeBuild, p) + runAction.Deps = append(runAction.Deps, vet) + // Install will clean the build directory. + // Make sure vet runs first. + // The install ordering in b.VetAction does not apply here + // because we are using a custom installAction (created above). + if installAction != nil { + installAction.Deps = append(installAction.Deps, vet) + } +} + +func recompileForTest(pmain, preal, ptest, pxtest *load.Package) { + // The "test copy" of preal is ptest. + // For each package that depends on preal, make a "test copy" + // that depends on ptest. And so on, up the dependency tree. + testCopy := map[*load.Package]*load.Package{preal: ptest} + for _, p := range load.PackageList([]*load.Package{pmain}) { + if p == preal { + continue + } + // Copy on write. + didSplit := p == pmain || p == pxtest + split := func() { + if didSplit { + return + } + didSplit = true + if testCopy[p] != nil { + panic("recompileForTest loop") + } + p1 := new(load.Package) + testCopy[p] = p1 + *p1 = *p + p1.Internal.Imports = make([]*load.Package, len(p.Internal.Imports)) + copy(p1.Internal.Imports, p.Internal.Imports) + p = p1 + p.Target = "" + } + + // Update p.Internal.Imports to use test copies. + for i, imp := range p.Internal.Imports { + if p1 := testCopy[imp]; p1 != nil && p1 != imp { + split() + p.Internal.Imports[i] = p1 + } + } + } +} + +// isTestFile reports whether the source file is a set of tests and should therefore +// be excluded from coverage analysis. +func isTestFile(file string) bool { + // We don't cover tests, only the code they test. + return strings.HasSuffix(file, "_test.go") +} + +// declareCoverVars attaches the required cover variables names +// to the files, to be used when annotating the files. +func declareCoverVars(importPath string, files ...string) map[string]*load.CoverVar { + coverVars := make(map[string]*load.CoverVar) + coverIndex := 0 + // We create the cover counters as new top-level variables in the package. + // We need to avoid collisions with user variables (GoCover_0 is unlikely but still) + // and more importantly with dot imports of other covered packages, + // so we append 12 hex digits from the SHA-256 of the import path. + // The point is only to avoid accidents, not to defeat users determined to + // break things. + sum := sha256.Sum256([]byte(importPath)) + h := fmt.Sprintf("%x", sum[:6]) + for _, file := range files { + if isTestFile(file) { + continue + } + coverVars[file] = &load.CoverVar{ + File: filepath.Join(importPath, file), + Var: fmt.Sprintf("GoCover_%d_%x", coverIndex, h), + } + coverIndex++ + } + return coverVars +} + +var noTestsToRun = []byte("\ntesting: warning: no tests to run\n") + +type runCache struct { + disableCache bool // cache should be disabled for this run + + buf *bytes.Buffer + id1 cache.ActionID + id2 cache.ActionID +} + +// stdoutMu and lockedStdout provide a locked standard output +// that guarantees never to interlace writes from multiple +// goroutines, so that we can have multiple JSON streams writing +// to a lockedStdout simultaneously and know that events will +// still be intelligible. +var stdoutMu sync.Mutex + +type lockedStdout struct{} + +func (lockedStdout) Write(b []byte) (int, error) { + stdoutMu.Lock() + defer stdoutMu.Unlock() + return os.Stdout.Write(b) +} + +// builderRunTest is the action for running a test binary. +func (c *runCache) builderRunTest(b *work.Builder, a *work.Action) error { + if a.Failed { + // We were unable to build the binary. + a.Failed = false + a.TestOutput = new(bytes.Buffer) + fmt.Fprintf(a.TestOutput, "FAIL\t%s [build failed]\n", a.Package.ImportPath) + base.SetExitStatus(1) + return nil + } + + var stdout io.Writer = os.Stdout + if testJSON { + json := test2json.NewConverter(lockedStdout{}, a.Package.ImportPath, test2json.Timestamp) + defer json.Close() + stdout = json + } + + var buf bytes.Buffer + if len(pkgArgs) == 0 || testBench { + // Stream test output (no buffering) when no package has + // been given on the command line (implicit current directory) + // or when benchmarking. + // No change to stdout. + } else { + // If we're only running a single package under test or if parallelism is + // set to 1, and if we're displaying all output (testShowPass), we can + // hurry the output along, echoing it as soon as it comes in. + // We still have to copy to &buf for caching the result. This special + // case was introduced in Go 1.5 and is intentionally undocumented: + // the exact details of output buffering are up to the go command and + // subject to change. It would be nice to remove this special case + // entirely, but it is surely very helpful to see progress being made + // when tests are run on slow single-CPU ARM systems. + // + // If we're showing JSON output, then display output as soon as + // possible even when multiple tests are being run: the JSON output + // events are attributed to specific package tests, so interlacing them + // is OK. + if testShowPass && (len(pkgs) == 1 || cfg.BuildP == 1) || testJSON { + // Write both to stdout and buf, for possible saving + // to cache, and for looking for the "no tests to run" message. + stdout = io.MultiWriter(stdout, &buf) + } else { + stdout = &buf + } + } + + if c.buf == nil { + // We did not find a cached result using the link step action ID, + // so we ran the link step. Try again now with the link output + // content ID. The attempt using the action ID makes sure that + // if the link inputs don't change, we reuse the cached test + // result without even rerunning the linker. The attempt using + // the link output (test binary) content ID makes sure that if + // we have different link inputs but the same final binary, + // we still reuse the cached test result. + // c.saveOutput will store the result under both IDs. + c.tryCacheWithID(b, a, a.Deps[0].BuildContentID()) + } + if c.buf != nil { + if stdout != &buf { + stdout.Write(c.buf.Bytes()) + c.buf.Reset() + } + a.TestOutput = c.buf + return nil + } + + execCmd := work.FindExecCmd() + testlogArg := []string{} + if !c.disableCache && len(execCmd) == 0 { + testlogArg = []string{"-test.testlogfile=" + a.Objdir + "testlog.txt"} + } + args := str.StringList(execCmd, a.Deps[0].BuiltTarget(), testlogArg, testArgs) + + if testCoverProfile != "" { + // Write coverage to temporary profile, for merging later. + for i, arg := range args { + if strings.HasPrefix(arg, "-test.coverprofile=") { + args[i] = "-test.coverprofile=" + a.Objdir + "_cover_.out" + } + } + } + + if cfg.BuildN || cfg.BuildX { + b.Showcmd("", "%s", strings.Join(args, " ")) + if cfg.BuildN { + return nil + } + } + + cmd := exec.Command(args[0], args[1:]...) + cmd.Dir = a.Package.Dir + cmd.Env = base.EnvForDir(cmd.Dir, cfg.OrigEnv) + cmd.Stdout = stdout + cmd.Stderr = stdout + + // If there are any local SWIG dependencies, we want to load + // the shared library from the build directory. + if a.Package.UsesSwig() { + env := cmd.Env + found := false + prefix := "LD_LIBRARY_PATH=" + for i, v := range env { + if strings.HasPrefix(v, prefix) { + env[i] = v + ":." + found = true + break + } + } + if !found { + env = append(env, "LD_LIBRARY_PATH=.") + } + cmd.Env = env + } + + t0 := time.Now() + err := cmd.Start() + + // This is a last-ditch deadline to detect and + // stop wedged test binaries, to keep the builders + // running. + if err == nil { + tick := time.NewTimer(testKillTimeout) + base.StartSigHandlers() + done := make(chan error) + go func() { + done <- cmd.Wait() + }() + Outer: + select { + case err = <-done: + // ok + case <-tick.C: + if base.SignalTrace != nil { + // Send a quit signal in the hope that the program will print + // a stack trace and exit. Give it five seconds before resorting + // to Kill. + cmd.Process.Signal(base.SignalTrace) + select { + case err = <-done: + fmt.Fprintf(cmd.Stdout, "*** Test killed with %v: ran too long (%v).\n", base.SignalTrace, testKillTimeout) + break Outer + case <-time.After(5 * time.Second): + } + } + cmd.Process.Kill() + err = <-done + fmt.Fprintf(cmd.Stdout, "*** Test killed: ran too long (%v).\n", testKillTimeout) + } + tick.Stop() + } + out := buf.Bytes() + a.TestOutput = &buf + t := fmt.Sprintf("%.3fs", time.Since(t0).Seconds()) + + mergeCoverProfile(cmd.Stdout, a.Objdir+"_cover_.out") + + if err == nil { + norun := "" + if !testShowPass && !testJSON { + buf.Reset() + } + if bytes.HasPrefix(out, noTestsToRun[1:]) || bytes.Contains(out, noTestsToRun) { + norun = " [no tests to run]" + } + fmt.Fprintf(cmd.Stdout, "ok \t%s\t%s%s%s\n", a.Package.ImportPath, t, coveragePercentage(out), norun) + c.saveOutput(a) + } else { + base.SetExitStatus(1) + // If there was test output, assume we don't need to print the exit status. + // Buf there's no test output, do print the exit status. + if len(out) == 0 { + fmt.Fprintf(cmd.Stdout, "%s\n", err) + } + fmt.Fprintf(cmd.Stdout, "FAIL\t%s\t%s\n", a.Package.ImportPath, t) + } + + if cmd.Stdout != &buf { + buf.Reset() // cmd.Stdout was going to os.Stdout already + } + return nil +} + +// tryCache is called just before the link attempt, +// to see if the test result is cached and therefore the link is unneeded. +// It reports whether the result can be satisfied from cache. +func (c *runCache) tryCache(b *work.Builder, a *work.Action) bool { + return c.tryCacheWithID(b, a, a.Deps[0].BuildActionID()) +} + +func (c *runCache) tryCacheWithID(b *work.Builder, a *work.Action, id string) bool { + if len(pkgArgs) == 0 { + // Caching does not apply to "go test", + // only to "go test foo" (including "go test ."). + if cache.DebugTest { + fmt.Fprintf(os.Stderr, "testcache: caching disabled in local directory mode\n") + } + c.disableCache = true + return false + } + + var cacheArgs []string + for _, arg := range testArgs { + i := strings.Index(arg, "=") + if i < 0 || !strings.HasPrefix(arg, "-test.") { + if cache.DebugTest { + fmt.Fprintf(os.Stderr, "testcache: caching disabled for test argument: %s\n", arg) + } + c.disableCache = true + return false + } + switch arg[:i] { + case "-test.cpu", + "-test.list", + "-test.parallel", + "-test.run", + "-test.short", + "-test.v": + // These are cacheable. + // Note that this list is documented above, + // so if you add to this list, update the docs too. + cacheArgs = append(cacheArgs, arg) + + case "-test.timeout": + // Special case: this is cacheable but ignored during the hash. + // Do not add to cacheArgs. + + default: + // nothing else is cacheable + if cache.DebugTest { + fmt.Fprintf(os.Stderr, "testcache: caching disabled for test argument: %s\n", arg) + } + c.disableCache = true + return false + } + } + + if cache.Default() == nil { + if cache.DebugTest { + fmt.Fprintf(os.Stderr, "testcache: GOCACHE=off\n") + } + c.disableCache = true + return false + } + + // The test cache result fetch is a two-level lookup. + // + // First, we use the content hash of the test binary + // and its command-line arguments to find the + // list of environment variables and files consulted + // the last time the test was run with those arguments. + // (To avoid unnecessary links, we store this entry + // under two hashes: id1 uses the linker inputs as a + // proxy for the test binary, and id2 uses the actual + // test binary. If the linker inputs are unchanged, + // this way we avoid the link step, even though we + // do not cache link outputs.) + // + // Second, we compute a hash of the values of the + // environment variables and the content of the files + // listed in the log from the previous run. + // Then we look up test output using a combination of + // the hash from the first part (testID) and the hash of the + // test inputs (testInputsID). + // + // In order to store a new test result, we must redo the + // testInputsID computation using the log from the run + // we want to cache, and then we store that new log and + // the new outputs. + + h := cache.NewHash("testResult") + fmt.Fprintf(h, "test binary %s args %q execcmd %q", id, cacheArgs, work.ExecCmd) + testID := h.Sum() + if c.id1 == (cache.ActionID{}) { + c.id1 = testID + } else { + c.id2 = testID + } + if cache.DebugTest { + fmt.Fprintf(os.Stderr, "testcache: %s: test ID %x => %x\n", a.Package.ImportPath, id, testID) + } + + // Load list of referenced environment variables and files + // from last run of testID, and compute hash of that content. + data, entry, err := cache.Default().GetBytes(testID) + if !bytes.HasPrefix(data, testlogMagic) || data[len(data)-1] != '\n' { + if cache.DebugTest { + if err != nil { + fmt.Fprintf(os.Stderr, "testcache: %s: input list not found: %v\n", a.Package.ImportPath, err) + } else { + fmt.Fprintf(os.Stderr, "testcache: %s: input list malformed\n", a.Package.ImportPath) + } + } + return false + } + testInputsID, err := computeTestInputsID(a, data) + if err != nil { + return false + } + if cache.DebugTest { + fmt.Fprintf(os.Stderr, "testcache: %s: test ID %x => input ID %x => %x\n", a.Package.ImportPath, testID, testInputsID, testAndInputKey(testID, testInputsID)) + } + + // Parse cached result in preparation for changing run time to "(cached)". + // If we can't parse the cached result, don't use it. + data, entry, err = cache.Default().GetBytes(testAndInputKey(testID, testInputsID)) + if len(data) == 0 || data[len(data)-1] != '\n' { + if cache.DebugTest { + if err != nil { + fmt.Fprintf(os.Stderr, "testcache: %s: test output not found: %v\n", a.Package.ImportPath, err) + } else { + fmt.Fprintf(os.Stderr, "testcache: %s: test output malformed\n", a.Package.ImportPath) + } + } + return false + } + if entry.Time.Before(testCacheExpire) { + if cache.DebugTest { + fmt.Fprintf(os.Stderr, "testcache: %s: test output expired due to go clean -testcache\n", a.Package.ImportPath) + } + return false + } + i := bytes.LastIndexByte(data[:len(data)-1], '\n') + 1 + if !bytes.HasPrefix(data[i:], []byte("ok \t")) { + if cache.DebugTest { + fmt.Fprintf(os.Stderr, "testcache: %s: test output malformed\n", a.Package.ImportPath) + } + return false + } + j := bytes.IndexByte(data[i+len("ok \t"):], '\t') + if j < 0 { + if cache.DebugTest { + fmt.Fprintf(os.Stderr, "testcache: %s: test output malformed\n", a.Package.ImportPath) + } + return false + } + j += i + len("ok \t") + 1 + + // Committed to printing. + c.buf = new(bytes.Buffer) + c.buf.Write(data[:j]) + c.buf.WriteString("(cached)") + for j < len(data) && ('0' <= data[j] && data[j] <= '9' || data[j] == '.' || data[j] == 's') { + j++ + } + c.buf.Write(data[j:]) + return true +} + +var errBadTestInputs = errors.New("error parsing test inputs") +var testlogMagic = []byte("# test log\n") // known to testing/internal/testdeps/deps.go + +// computeTestInputsID computes the "test inputs ID" +// (see comment in tryCacheWithID above) for the +// test log. +func computeTestInputsID(a *work.Action, testlog []byte) (cache.ActionID, error) { + testlog = bytes.TrimPrefix(testlog, testlogMagic) + h := cache.NewHash("testInputs") + pwd := a.Package.Dir + for _, line := range bytes.Split(testlog, []byte("\n")) { + if len(line) == 0 { + continue + } + s := string(line) + i := strings.Index(s, " ") + if i < 0 { + if cache.DebugTest { + fmt.Fprintf(os.Stderr, "testcache: %s: input list malformed (%q)\n", a.Package.ImportPath, line) + } + return cache.ActionID{}, errBadTestInputs + } + op := s[:i] + name := s[i+1:] + switch op { + default: + if cache.DebugTest { + fmt.Fprintf(os.Stderr, "testcache: %s: input list malformed (%q)\n", a.Package.ImportPath, line) + } + return cache.ActionID{}, errBadTestInputs + case "getenv": + fmt.Fprintf(h, "env %s %x\n", name, hashGetenv(name)) + case "chdir": + pwd = name // always absolute + fmt.Fprintf(h, "cbdir %s %x\n", name, hashStat(name)) + case "stat": + if !filepath.IsAbs(name) { + name = filepath.Join(pwd, name) + } + if !inDir(name, a.Package.Root) { + // Do not recheck files outside the GOPATH or GOROOT root. + break + } + fmt.Fprintf(h, "stat %s %x\n", name, hashStat(name)) + case "open": + if !filepath.IsAbs(name) { + name = filepath.Join(pwd, name) + } + if !inDir(name, a.Package.Root) { + // Do not recheck files outside the GOPATH or GOROOT root. + break + } + fh, err := hashOpen(name) + if err != nil { + if cache.DebugTest { + fmt.Fprintf(os.Stderr, "testcache: %s: input file %s: %s\n", a.Package.ImportPath, name, err) + } + return cache.ActionID{}, err + } + fmt.Fprintf(h, "open %s %x\n", name, fh) + } + } + sum := h.Sum() + return sum, nil +} + +func inDir(path, dir string) bool { + if str.HasFilePathPrefix(path, dir) { + return true + } + xpath, err1 := filepath.EvalSymlinks(path) + xdir, err2 := filepath.EvalSymlinks(dir) + if err1 == nil && err2 == nil && str.HasFilePathPrefix(xpath, xdir) { + return true + } + return false +} + +func hashGetenv(name string) cache.ActionID { + h := cache.NewHash("getenv") + v, ok := os.LookupEnv(name) + if !ok { + h.Write([]byte{0}) + } else { + h.Write([]byte{1}) + h.Write([]byte(v)) + } + return h.Sum() +} + +const modTimeCutoff = 2 * time.Second + +var errFileTooNew = errors.New("file used as input is too new") + +func hashOpen(name string) (cache.ActionID, error) { + h := cache.NewHash("open") + info, err := os.Stat(name) + if err != nil { + fmt.Fprintf(h, "err %v\n", err) + return h.Sum(), nil + } + hashWriteStat(h, info) + if info.IsDir() { + names, err := ioutil.ReadDir(name) + if err != nil { + fmt.Fprintf(h, "err %v\n", err) + } + for _, f := range names { + fmt.Fprintf(h, "file %s ", f.Name()) + hashWriteStat(h, f) + } + } else if info.Mode().IsRegular() { + // Because files might be very large, do not attempt + // to hash the entirety of their content. Instead assume + // the mtime and size recorded in hashWriteStat above + // are good enough. + // + // To avoid problems for very recent files where a new + // write might not change the mtime due to file system + // mtime precision, reject caching if a file was read that + // is less than modTimeCutoff old. + if time.Since(info.ModTime()) < modTimeCutoff { + return cache.ActionID{}, errFileTooNew + } + } + return h.Sum(), nil +} + +func hashStat(name string) cache.ActionID { + h := cache.NewHash("stat") + if info, err := os.Stat(name); err != nil { + fmt.Fprintf(h, "err %v\n", err) + } else { + hashWriteStat(h, info) + } + if info, err := os.Lstat(name); err != nil { + fmt.Fprintf(h, "err %v\n", err) + } else { + hashWriteStat(h, info) + } + return h.Sum() +} + +func hashWriteStat(h io.Writer, info os.FileInfo) { + fmt.Fprintf(h, "stat %d %x %v %v\n", info.Size(), uint64(info.Mode()), info.ModTime(), info.IsDir()) +} + +// testAndInputKey returns the actual cache key for the pair (testID, testInputsID). +func testAndInputKey(testID, testInputsID cache.ActionID) cache.ActionID { + return cache.Subkey(testID, fmt.Sprintf("inputs:%x", testInputsID)) +} + +func (c *runCache) saveOutput(a *work.Action) { + if c.id1 == (cache.ActionID{}) && c.id2 == (cache.ActionID{}) { + return + } + + // See comment about two-level lookup in tryCacheWithID above. + testlog, err := ioutil.ReadFile(a.Objdir + "testlog.txt") + if err != nil || !bytes.HasPrefix(testlog, testlogMagic) || testlog[len(testlog)-1] != '\n' { + if cache.DebugTest { + if err != nil { + fmt.Fprintf(os.Stderr, "testcache: %s: reading testlog: %v\n", a.Package.ImportPath, err) + } else { + fmt.Fprintf(os.Stderr, "testcache: %s: reading testlog: malformed\n", a.Package.ImportPath) + } + } + return + } + testInputsID, err := computeTestInputsID(a, testlog) + if err != nil { + return + } + if c.id1 != (cache.ActionID{}) { + if cache.DebugTest { + fmt.Fprintf(os.Stderr, "testcache: %s: save test ID %x => input ID %x => %x\n", a.Package.ImportPath, c.id1, testInputsID, testAndInputKey(c.id1, testInputsID)) + } + cache.Default().PutNoVerify(c.id1, bytes.NewReader(testlog)) + cache.Default().PutNoVerify(testAndInputKey(c.id1, testInputsID), bytes.NewReader(a.TestOutput.Bytes())) + } + if c.id2 != (cache.ActionID{}) { + if cache.DebugTest { + fmt.Fprintf(os.Stderr, "testcache: %s: save test ID %x => input ID %x => %x\n", a.Package.ImportPath, c.id2, testInputsID, testAndInputKey(c.id2, testInputsID)) + } + cache.Default().PutNoVerify(c.id2, bytes.NewReader(testlog)) + cache.Default().PutNoVerify(testAndInputKey(c.id2, testInputsID), bytes.NewReader(a.TestOutput.Bytes())) + } +} + +// coveragePercentage returns the coverage results (if enabled) for the +// test. It uncovers the data by scanning the output from the test run. +func coveragePercentage(out []byte) string { + if !testCover { + return "" + } + // The string looks like + // test coverage for encoding/binary: 79.9% of statements + // Extract the piece from the percentage to the end of the line. + re := regexp.MustCompile(`coverage: (.*)\n`) + matches := re.FindSubmatch(out) + if matches == nil { + // Probably running "go test -cover" not "go test -cover fmt". + // The coverage output will appear in the output directly. + return "" + } + return fmt.Sprintf("\tcoverage: %s", matches[1]) +} + +// builderCleanTest is the action for cleaning up after a test. +func builderCleanTest(b *work.Builder, a *work.Action) error { + if cfg.BuildWork { + return nil + } + if cfg.BuildX { + b.Showcmd("", "rm -r %s", a.Objdir) + } + os.RemoveAll(a.Objdir) + return nil +} + +// builderPrintTest is the action for printing a test result. +func builderPrintTest(b *work.Builder, a *work.Action) error { + clean := a.Deps[0] + run := clean.Deps[0] + if run.TestOutput != nil { + os.Stdout.Write(run.TestOutput.Bytes()) + run.TestOutput = nil + } + return nil +} + +// builderNoTest is the action for testing a package with no test files. +func builderNoTest(b *work.Builder, a *work.Action) error { + var stdout io.Writer = os.Stdout + if testJSON { + json := test2json.NewConverter(lockedStdout{}, a.Package.ImportPath, test2json.Timestamp) + defer json.Close() + stdout = json + } + fmt.Fprintf(stdout, "? \t%s\t[no test files]\n", a.Package.ImportPath) + return nil +} + +// isTestFunc tells whether fn has the type of a testing function. arg +// specifies the parameter type we look for: B, M or T. +func isTestFunc(fn *ast.FuncDecl, arg string) bool { + if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 || + fn.Type.Params.List == nil || + len(fn.Type.Params.List) != 1 || + len(fn.Type.Params.List[0].Names) > 1 { + return false + } + ptr, ok := fn.Type.Params.List[0].Type.(*ast.StarExpr) + if !ok { + return false + } + // We can't easily check that the type is *testing.M + // because we don't know how testing has been imported, + // but at least check that it's *M or *something.M. + // Same applies for B and T. + if name, ok := ptr.X.(*ast.Ident); ok && name.Name == arg { + return true + } + if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == arg { + return true + } + return false +} + +// isTest tells whether name looks like a test (or benchmark, according to prefix). +// It is a Test (say) if there is a character after Test that is not a lower-case letter. +// We don't want TesticularCancer. +func isTest(name, prefix string) bool { + if !strings.HasPrefix(name, prefix) { + return false + } + if len(name) == len(prefix) { // "Test" is ok + return true + } + rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) + return !unicode.IsLower(rune) +} + +type coverInfo struct { + Package *load.Package + Vars map[string]*load.CoverVar +} + +// loadTestFuncs returns the testFuncs describing the tests that will be run. +func loadTestFuncs(ptest *load.Package) (*testFuncs, error) { + t := &testFuncs{ + Package: ptest, + } + for _, file := range ptest.TestGoFiles { + if err := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); err != nil { + return nil, err + } + } + for _, file := range ptest.XTestGoFiles { + if err := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); err != nil { + return nil, err + } + } + return t, nil +} + +// writeTestmain writes the _testmain.go file for t to the file named out. +func writeTestmain(out string, t *testFuncs) error { + f, err := os.Create(out) + if err != nil { + return err + } + defer f.Close() + + return testmainTmpl.Execute(f, t) +} + +type testFuncs struct { + Tests []testFunc + Benchmarks []testFunc + Examples []testFunc + TestMain *testFunc + Package *load.Package + ImportTest bool + NeedTest bool + ImportXtest bool + NeedXtest bool + Cover []coverInfo +} + +func (t *testFuncs) CoverMode() string { + return testCoverMode +} + +func (t *testFuncs) CoverEnabled() bool { + return testCover +} + +// ImportPath returns the import path of the package being tested, if it is within GOPATH. +// This is printed by the testing package when running benchmarks. +func (t *testFuncs) ImportPath() string { + pkg := t.Package.ImportPath + if strings.HasPrefix(pkg, "_/") { + return "" + } + if pkg == "command-line-arguments" { + return "" + } + return pkg +} + +// Covered returns a string describing which packages are being tested for coverage. +// If the covered package is the same as the tested package, it returns the empty string. +// Otherwise it is a comma-separated human-readable list of packages beginning with +// " in", ready for use in the coverage message. +func (t *testFuncs) Covered() string { + if testCoverPaths == nil { + return "" + } + return " in " + strings.Join(testCoverPaths, ", ") +} + +// Tested returns the name of the package being tested. +func (t *testFuncs) Tested() string { + return t.Package.Name +} + +type testFunc struct { + Package string // imported package name (_test or _xtest) + Name string // function name + Output string // output, for examples + Unordered bool // output is allowed to be unordered. +} + +var testFileSet = token.NewFileSet() + +func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error { + f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments) + if err != nil { + return base.ExpandScanner(err) + } + for _, d := range f.Decls { + n, ok := d.(*ast.FuncDecl) + if !ok { + continue + } + if n.Recv != nil { + continue + } + name := n.Name.String() + switch { + case name == "TestMain": + if isTestFunc(n, "T") { + t.Tests = append(t.Tests, testFunc{pkg, name, "", false}) + *doImport, *seen = true, true + continue + } + err := checkTestFunc(n, "M") + if err != nil { + return err + } + if t.TestMain != nil { + return errors.New("multiple definitions of TestMain") + } + t.TestMain = &testFunc{pkg, name, "", false} + *doImport, *seen = true, true + case isTest(name, "Test"): + err := checkTestFunc(n, "T") + if err != nil { + return err + } + t.Tests = append(t.Tests, testFunc{pkg, name, "", false}) + *doImport, *seen = true, true + case isTest(name, "Benchmark"): + err := checkTestFunc(n, "B") + if err != nil { + return err + } + t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, "", false}) + *doImport, *seen = true, true + } + } + ex := doc.Examples(f) + sort.Slice(ex, func(i, j int) bool { return ex[i].Order < ex[j].Order }) + for _, e := range ex { + *doImport = true // import test file whether executed or not + if e.Output == "" && !e.EmptyOutput { + // Don't run examples with no output. + continue + } + t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output, e.Unordered}) + *seen = true + } + return nil +} + +func checkTestFunc(fn *ast.FuncDecl, arg string) error { + if !isTestFunc(fn, arg) { + name := fn.Name.String() + pos := testFileSet.Position(fn.Pos()) + return fmt.Errorf("%s: wrong signature for %s, must be: func %s(%s *testing.%s)", pos, name, name, strings.ToLower(arg), arg) + } + return nil +} + +var testmainTmpl = template.Must(template.New("main").Parse(` +package main + +import ( +{{if not .TestMain}} + "os" +{{end}} + "testing" + "testing/internal/testdeps" + +{{if .ImportTest}} + {{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}} +{{end}} +{{if .ImportXtest}} + {{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}} +{{end}} +{{range $i, $p := .Cover}} + _cover{{$i}} {{$p.Package.ImportPath | printf "%q"}} +{{end}} +) + +var tests = []testing.InternalTest{ +{{range .Tests}} + {"{{.Name}}", {{.Package}}.{{.Name}}}, +{{end}} +} + +var benchmarks = []testing.InternalBenchmark{ +{{range .Benchmarks}} + {"{{.Name}}", {{.Package}}.{{.Name}}}, +{{end}} +} + +var examples = []testing.InternalExample{ +{{range .Examples}} + {"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}}, +{{end}} +} + +func init() { + testdeps.ImportPath = {{.ImportPath | printf "%q"}} +} + +{{if .CoverEnabled}} + +// Only updated by init functions, so no need for atomicity. +var ( + coverCounters = make(map[string][]uint32) + coverBlocks = make(map[string][]testing.CoverBlock) +) + +func init() { + {{range $i, $p := .Cover}} + {{range $file, $cover := $p.Vars}} + coverRegisterFile({{printf "%q" $cover.File}}, _cover{{$i}}.{{$cover.Var}}.Count[:], _cover{{$i}}.{{$cover.Var}}.Pos[:], _cover{{$i}}.{{$cover.Var}}.NumStmt[:]) + {{end}} + {{end}} +} + +func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts []uint16) { + if 3*len(counter) != len(pos) || len(counter) != len(numStmts) { + panic("coverage: mismatched sizes") + } + if coverCounters[fileName] != nil { + // Already registered. + return + } + coverCounters[fileName] = counter + block := make([]testing.CoverBlock, len(counter)) + for i := range counter { + block[i] = testing.CoverBlock{ + Line0: pos[3*i+0], + Col0: uint16(pos[3*i+2]), + Line1: pos[3*i+1], + Col1: uint16(pos[3*i+2]>>16), + Stmts: numStmts[i], + } + } + coverBlocks[fileName] = block +} +{{end}} + +func main() { +{{if .CoverEnabled}} + testing.RegisterCover(testing.Cover{ + Mode: {{printf "%q" .CoverMode}}, + Counters: coverCounters, + Blocks: coverBlocks, + CoveredPackages: {{printf "%q" .Covered}}, + }) +{{end}} + m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, examples) +{{with .TestMain}} + {{.Package}}.{{.Name}}(m) +{{else}} + os.Exit(m.Run()) +{{end}} +} + +`))
diff --git a/vendor/cmd/go/internal/test/testflag.go b/vendor/cmd/go/internal/test/testflag.go new file mode 100644 index 0000000..8a686b7 --- /dev/null +++ b/vendor/cmd/go/internal/test/testflag.go
@@ -0,0 +1,232 @@ +// Copyright 2011 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 test + +import ( + "flag" + "os" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/cmdflag" + "cmd/go/internal/str" + "cmd/go/internal/work" +) + +const cmd = "test" + +// The flag handling part of go test is large and distracting. +// We can't use the flag package because some of the flags from +// our command line are for us, and some are for 6.out, and +// some are for both. + +// testFlagDefn is the set of flags we process. +var testFlagDefn = []*cmdflag.Defn{ + // local. + {Name: "c", BoolVar: &testC}, + {Name: "i", BoolVar: &cfg.BuildI}, + {Name: "o"}, + {Name: "cover", BoolVar: &testCover}, + {Name: "covermode"}, + {Name: "coverpkg"}, + {Name: "exec"}, + {Name: "json", BoolVar: &testJSON}, + {Name: "vet"}, + + // Passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v. + {Name: "bench", PassToTest: true}, + {Name: "benchmem", BoolVar: new(bool), PassToTest: true}, + {Name: "benchtime", PassToTest: true}, + {Name: "blockprofile", PassToTest: true}, + {Name: "blockprofilerate", PassToTest: true}, + {Name: "count", PassToTest: true}, + {Name: "coverprofile", PassToTest: true}, + {Name: "cpu", PassToTest: true}, + {Name: "cpuprofile", PassToTest: true}, + {Name: "failfast", BoolVar: new(bool), PassToTest: true}, + {Name: "list", PassToTest: true}, + {Name: "memprofile", PassToTest: true}, + {Name: "memprofilerate", PassToTest: true}, + {Name: "mutexprofile", PassToTest: true}, + {Name: "mutexprofilefraction", PassToTest: true}, + {Name: "outputdir", PassToTest: true}, + {Name: "parallel", PassToTest: true}, + {Name: "run", PassToTest: true}, + {Name: "short", BoolVar: new(bool), PassToTest: true}, + {Name: "timeout", PassToTest: true}, + {Name: "trace", PassToTest: true}, + {Name: "v", BoolVar: &testV, PassToTest: true}, +} + +// add build flags to testFlagDefn +func init() { + var cmd base.Command + work.AddBuildFlags(&cmd) + cmd.Flag.VisitAll(func(f *flag.Flag) { + if f.Name == "v" { + // test overrides the build -v flag + return + } + testFlagDefn = append(testFlagDefn, &cmdflag.Defn{ + Name: f.Name, + Value: f.Value, + }) + }) +} + +// testFlags processes the command line, grabbing -x and -c, rewriting known flags +// to have "test" before them, and reading the command line for the 6.out. +// Unfortunately for us, we need to do our own flag processing because go test +// grabs some flags but otherwise its command line is just a holding place for +// pkg.test's arguments. +// We allow known flags both before and after the package name list, +// to allow both +// go test fmt -custom-flag-for-fmt-test +// go test -x math +func testFlags(args []string) (packageNames, passToTest []string) { + inPkg := false + var explicitArgs []string + for i := 0; i < len(args); i++ { + if !strings.HasPrefix(args[i], "-") { + if !inPkg && packageNames == nil { + // First package name we've seen. + inPkg = true + } + if inPkg { + packageNames = append(packageNames, args[i]) + continue + } + } + + if inPkg { + // Found an argument beginning with "-"; end of package list. + inPkg = false + } + + f, value, extraWord := cmdflag.Parse(cmd, testFlagDefn, args, i) + if f == nil { + // This is a flag we do not know; we must assume + // that any args we see after this might be flag + // arguments, not package names. + inPkg = false + if packageNames == nil { + // make non-nil: we have seen the empty package list + packageNames = []string{} + } + if args[i] == "-args" || args[i] == "--args" { + // -args or --args signals that everything that follows + // should be passed to the test. + explicitArgs = args[i+1:] + break + } + passToTest = append(passToTest, args[i]) + continue + } + if f.Value != nil { + if err := f.Value.Set(value); err != nil { + base.Fatalf("invalid flag argument for -%s: %v", f.Name, err) + } + } else { + // Test-only flags. + // Arguably should be handled by f.Value, but aren't. + switch f.Name { + // bool flags. + case "c", "i", "v", "cover", "json": + cmdflag.SetBool(cmd, f.BoolVar, value) + if f.Name == "json" && testJSON { + passToTest = append(passToTest, "-test.v=true") + } + case "o": + testO = value + testNeedBinary = true + case "exec": + xcmd, err := str.SplitQuotedFields(value) + if err != nil { + base.Fatalf("invalid flag argument for -%s: %v", f.Name, err) + } + work.ExecCmd = xcmd + case "bench": + // record that we saw the flag; don't care about the value + testBench = true + case "list": + testList = true + case "timeout": + testTimeout = value + case "blockprofile", "cpuprofile", "memprofile", "mutexprofile": + testProfile = "-" + f.Name + testNeedBinary = true + case "trace": + testProfile = "-trace" + case "coverpkg": + testCover = true + if value == "" { + testCoverPaths = nil + } else { + testCoverPaths = strings.Split(value, ",") + } + case "coverprofile": + testCover = true + testCoverProfile = value + case "covermode": + switch value { + case "set", "count", "atomic": + testCoverMode = value + default: + base.Fatalf("invalid flag argument for -covermode: %q", value) + } + testCover = true + case "outputdir": + testOutputDir = value + case "vet": + testVetList = value + } + } + if extraWord { + i++ + } + if f.PassToTest { + passToTest = append(passToTest, "-test."+f.Name+"="+value) + } + } + + if testCoverMode == "" { + testCoverMode = "set" + if cfg.BuildRace { + // Default coverage mode is atomic when -race is set. + testCoverMode = "atomic" + } + } + + if testVetList != "" && testVetList != "off" { + if strings.Contains(testVetList, "=") { + base.Fatalf("-vet argument cannot contain equal signs") + } + if strings.Contains(testVetList, " ") { + base.Fatalf("-vet argument is comma-separated list, cannot contain spaces") + } + list := strings.Split(testVetList, ",") + for i, arg := range list { + list[i] = "-" + arg + } + testVetFlags = list + } + + if cfg.BuildRace && testCoverMode != "atomic" { + base.Fatalf(`-covermode must be "atomic", not %q, when -race is enabled`, testCoverMode) + } + + // Tell the test what directory we're running in, so it can write the profiles there. + if testProfile != "" && testOutputDir == "" { + dir, err := os.Getwd() + if err != nil { + base.Fatalf("error from os.Getwd: %s", err) + } + passToTest = append(passToTest, "-test.outputdir", dir) + } + + passToTest = append(passToTest, explicitArgs...) + return +}
diff --git a/vendor/cmd/go/internal/tool/tool.go b/vendor/cmd/go/internal/tool/tool.go new file mode 100644 index 0000000..db92884 --- /dev/null +++ b/vendor/cmd/go/internal/tool/tool.go
@@ -0,0 +1,119 @@ +// Copyright 2011 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 tool implements the ``go tool'' command. +package tool + +import ( + "fmt" + "os" + "os/exec" + "sort" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" +) + +var CmdTool = &base.Command{ + Run: runTool, + UsageLine: "tool [-n] command [args...]", + Short: "run specified go tool", + Long: ` +Tool runs the go tool command identified by the arguments. +With no arguments it prints the list of known tools. + +The -n flag causes tool to print the command that would be +executed but not execute it. + +For more about each tool command, see 'go doc cmd/<command>'. +`, +} + +var toolN bool + +func init() { + CmdTool.Flag.BoolVar(&toolN, "n", false, "") +} + +func runTool(cmd *base.Command, args []string) { + if len(args) == 0 { + listTools() + return + } + toolName := args[0] + // The tool name must be lower-case letters, numbers or underscores. + for _, c := range toolName { + switch { + case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_': + default: + fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\n", toolName) + base.SetExitStatus(2) + return + } + } + toolPath := base.Tool(toolName) + if toolPath == "" { + return + } + if toolN { + cmd := toolPath + if len(args) > 1 { + cmd += " " + strings.Join(args[1:], " ") + } + fmt.Printf("%s\n", cmd) + return + } + args[0] = toolPath // in case the tool wants to re-exec itself, e.g. cmd/dist + toolCmd := &exec.Cmd{ + Path: toolPath, + Args: args, + Stdin: os.Stdin, + Stdout: os.Stdout, + Stderr: os.Stderr, + // Set $GOROOT, mainly for go tool dist. + Env: base.MergeEnvLists([]string{"GOROOT=" + cfg.GOROOT}, os.Environ()), + } + err := toolCmd.Run() + 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 + // or we're printing command lines too (-x mode). + // Assume if command exited cleanly (even with non-zero status) + // it printed any messages it wanted to print. + if e, ok := err.(*exec.ExitError); !ok || !e.Exited() || cfg.BuildX { + fmt.Fprintf(os.Stderr, "go tool %s: %s\n", toolName, err) + } + base.SetExitStatus(1) + return + } +} + +// listTools prints a list of the available tools in the tools directory. +func listTools() { + f, err := os.Open(base.ToolDir) + if err != nil { + fmt.Fprintf(os.Stderr, "go tool: no tool directory: %s\n", err) + base.SetExitStatus(2) + return + } + defer f.Close() + names, err := f.Readdirnames(-1) + if err != nil { + fmt.Fprintf(os.Stderr, "go tool: can't read directory: %s\n", err) + base.SetExitStatus(2) + return + } + + sort.Strings(names) + for _, name := range names { + // Unify presentation by going to lower case. + name = strings.ToLower(name) + // If it's windows, don't show the .exe suffix. + if base.ToolIsWindows && strings.HasSuffix(name, base.ToolWindowsExtension) { + name = name[:len(name)-len(base.ToolWindowsExtension)] + } + fmt.Println(name) + } +}
diff --git a/vendor/cmd/go/internal/version/version.go b/vendor/cmd/go/internal/version/version.go new file mode 100644 index 0000000..c3f7d73 --- /dev/null +++ b/vendor/cmd/go/internal/version/version.go
@@ -0,0 +1,28 @@ +// Copyright 2011 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 version implements the ``go version'' command. +package version + +import ( + "fmt" + "runtime" + + "cmd/go/internal/base" +) + +var CmdVersion = &base.Command{ + Run: runVersion, + UsageLine: "version", + Short: "print Go version", + Long: `Version prints the Go version, as reported by runtime.Version.`, +} + +func runVersion(cmd *base.Command, args []string) { + if len(args) != 0 { + cmd.Usage() + } + + fmt.Printf("go version %s %s/%s\n", runtime.Version(), runtime.GOOS, runtime.GOARCH) +}
diff --git a/vendor/cmd/go/internal/vet/vet.go b/vendor/cmd/go/internal/vet/vet.go new file mode 100644 index 0000000..3d095d4 --- /dev/null +++ b/vendor/cmd/go/internal/vet/vet.go
@@ -0,0 +1,77 @@ +// Copyright 2011 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 vet implements the ``go vet'' command. +package vet + +import ( + "cmd/go/internal/base" + "cmd/go/internal/load" + "cmd/go/internal/work" + "path/filepath" +) + +var CmdVet = &base.Command{ + Run: runVet, + CustomFlags: true, + UsageLine: "vet [-n] [-x] [build flags] [vet flags] [packages]", + Short: "report likely mistakes in packages", + Long: ` +Vet runs the Go vet command on the packages named by the import paths. + +For more about vet and its flags, see 'go doc cmd/vet'. +For more about specifying packages, see 'go help packages'. + +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + +The build flags supported by go vet are those that control package resolution +and execution, such as -n, -x, -v, -tags, and -toolexec. +For more about these flags, see 'go help build'. + +See also: go fmt, go fix. + `, +} + +func runVet(cmd *base.Command, args []string) { + vetFlags, pkgArgs := vetFlags(args) + + work.BuildInit() + work.VetFlags = vetFlags + if vetTool != "" { + var err error + work.VetTool, err = filepath.Abs(vetTool) + if err != nil { + base.Fatalf("%v", err) + } + } + + pkgs := load.PackagesForBuild(pkgArgs) + if len(pkgs) == 0 { + base.Fatalf("no packages to vet") + } + + var b work.Builder + b.Init() + + root := &work.Action{Mode: "go vet"} + for _, p := range pkgs { + ptest, pxtest, err := load.TestPackagesFor(p, false) + if err != nil { + base.Errorf("%v", err) + continue + } + if len(ptest.GoFiles) == 0 && pxtest == nil { + base.Errorf("go vet %s: no Go files in %s", p.ImportPath, p.Dir) + continue + } + if len(ptest.GoFiles) > 0 { + root.Deps = append(root.Deps, b.VetAction(work.ModeBuild, work.ModeBuild, ptest)) + } + if pxtest != nil { + root.Deps = append(root.Deps, b.VetAction(work.ModeBuild, work.ModeBuild, pxtest)) + } + } + b.Do(root) +}
diff --git a/vendor/cmd/go/internal/vet/vetflag.go b/vendor/cmd/go/internal/vet/vetflag.go new file mode 100644 index 0000000..d4664cc --- /dev/null +++ b/vendor/cmd/go/internal/vet/vetflag.go
@@ -0,0 +1,108 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package vet + +import ( + "flag" + "fmt" + "os" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/cmdflag" + "cmd/go/internal/work" +) + +const cmd = "vet" + +// vetFlagDefn is the set of flags we process. +var vetFlagDefn = []*cmdflag.Defn{ + // Note: Some flags, in particular -tags and -v, are known to + // vet but also defined as build flags. This works fine, so we + // don't define them here but use AddBuildFlags to init them. + // However some, like -x, are known to the build but not + // to vet. We handle them in vetFlags. + + // local. + {Name: "all", BoolVar: new(bool)}, + {Name: "asmdecl", BoolVar: new(bool)}, + {Name: "assign", BoolVar: new(bool)}, + {Name: "atomic", BoolVar: new(bool)}, + {Name: "bool", BoolVar: new(bool)}, + {Name: "buildtags", BoolVar: new(bool)}, + {Name: "cgocall", BoolVar: new(bool)}, + {Name: "composites", BoolVar: new(bool)}, + {Name: "copylocks", BoolVar: new(bool)}, + {Name: "httpresponse", BoolVar: new(bool)}, + {Name: "lostcancel", BoolVar: new(bool)}, + {Name: "methods", BoolVar: new(bool)}, + {Name: "nilfunc", BoolVar: new(bool)}, + {Name: "printf", BoolVar: new(bool)}, + {Name: "printfuncs"}, + {Name: "rangeloops", BoolVar: new(bool)}, + {Name: "shadow", BoolVar: new(bool)}, + {Name: "shadowstrict", BoolVar: new(bool)}, + {Name: "shift", BoolVar: new(bool)}, + {Name: "source", BoolVar: new(bool)}, + {Name: "structtags", BoolVar: new(bool)}, + {Name: "tests", BoolVar: new(bool)}, + {Name: "unreachable", BoolVar: new(bool)}, + {Name: "unsafeptr", BoolVar: new(bool)}, + {Name: "unusedfuncs"}, + {Name: "unusedresult", BoolVar: new(bool)}, + {Name: "unusedstringmethods"}, +} + +var vetTool string + +// add build flags to vetFlagDefn. +func init() { + var cmd base.Command + work.AddBuildFlags(&cmd) + cmd.Flag.StringVar(&vetTool, "vettool", "", "path to vet tool binary") // for cmd/vet tests; undocumented for now + cmd.Flag.VisitAll(func(f *flag.Flag) { + vetFlagDefn = append(vetFlagDefn, &cmdflag.Defn{ + Name: f.Name, + Value: f.Value, + }) + }) +} + +// vetFlags processes the command line, splitting it at the first non-flag +// into the list of flags and list of packages. +func vetFlags(args []string) (passToVet, packageNames []string) { + for i := 0; i < len(args); i++ { + if !strings.HasPrefix(args[i], "-") { + return args[:i], args[i:] + } + + f, value, extraWord := cmdflag.Parse(cmd, vetFlagDefn, args, i) + if f == nil { + fmt.Fprintf(os.Stderr, "vet: flag %q not defined\n", args[i]) + fmt.Fprintf(os.Stderr, "Run \"go help vet\" for more information\n") + os.Exit(2) + } + if f.Value != nil { + if err := f.Value.Set(value); err != nil { + base.Fatalf("invalid flag argument for -%s: %v", f.Name, err) + } + switch f.Name { + // Flags known to the build but not to vet, so must be dropped. + case "x", "n", "vettool": + if extraWord { + args = append(args[:i], args[i+2:]...) + extraWord = false + } else { + args = append(args[:i], args[i+1:]...) + } + i-- + } + } + if extraWord { + i++ + } + } + return args, nil +}
diff --git a/vendor/cmd/go/internal/web/bootstrap.go b/vendor/cmd/go/internal/web/bootstrap.go new file mode 100644 index 0000000..d1d4621 --- /dev/null +++ b/vendor/cmd/go/internal/web/bootstrap.go
@@ -0,0 +1,37 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build cmd_go_bootstrap + +// This code is compiled only into the bootstrap 'go' binary. +// These stubs avoid importing packages with large dependency +// trees, like the use of "net/http" in vcs.go. + +package web + +import ( + "errors" + "io" +) + +var errHTTP = errors.New("no http in bootstrap go command") + +type HTTPError struct { + StatusCode int +} + +func (e *HTTPError) Error() string { + panic("unreachable") +} + +func Get(url string) ([]byte, error) { + return nil, errHTTP +} + +func GetMaybeInsecure(importPath string, security SecurityMode) (string, io.ReadCloser, error) { + return "", nil, errHTTP +} + +func QueryEscape(s string) string { panic("unreachable") } +func OpenBrowser(url string) bool { panic("unreachable") }
diff --git a/vendor/cmd/go/internal/web/http.go b/vendor/cmd/go/internal/web/http.go new file mode 100644 index 0000000..6e347fb --- /dev/null +++ b/vendor/cmd/go/internal/web/http.go
@@ -0,0 +1,122 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !cmd_go_bootstrap + +// This code is compiled into the real 'go' binary, but it is not +// compiled into the binary that is built during all.bash, so as +// to avoid needing to build net (and thus use cgo) during the +// bootstrap process. + +package web + +import ( + "crypto/tls" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "net/url" + "time" + + "cmd/go/internal/cfg" + "cmd/internal/browser" +) + +// httpClient is the default HTTP client, but a variable so it can be +// changed by tests, without modifying http.DefaultClient. +var httpClient = http.DefaultClient + +// impatientInsecureHTTPClient is used in -insecure mode, +// when we're connecting to https servers that might not be there +// or might be using self-signed certificates. +var impatientInsecureHTTPClient = &http.Client{ + Timeout: 5 * time.Second, + Transport: &http.Transport{ + Proxy: http.ProxyFromEnvironment, + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + }, +} + +type HTTPError struct { + status string + StatusCode int + url string +} + +func (e *HTTPError) Error() string { + return fmt.Sprintf("%s: %s", e.url, e.status) +} + +// Get returns the data from an HTTP GET request for the given URL. +func Get(url string) ([]byte, error) { + resp, err := httpClient.Get(url) + if err != nil { + return nil, err + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + err := &HTTPError{status: resp.Status, StatusCode: resp.StatusCode, url: url} + + return nil, err + } + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("%s: %v", url, err) + } + return b, nil +} + +// GetMaybeInsecure returns the body of either the importPath's +// https resource or, if unavailable and permitted by the security mode, the http resource. +func GetMaybeInsecure(importPath string, security SecurityMode) (urlStr string, body io.ReadCloser, err error) { + fetch := func(scheme string) (urlStr string, res *http.Response, err error) { + u, err := url.Parse(scheme + "://" + importPath) + if err != nil { + return "", nil, err + } + u.RawQuery = "go-get=1" + urlStr = u.String() + if cfg.BuildV { + log.Printf("Fetching %s", urlStr) + } + if security == Insecure && scheme == "https" { // fail earlier + res, err = impatientInsecureHTTPClient.Get(urlStr) + } else { + res, err = httpClient.Get(urlStr) + } + return + } + closeBody := func(res *http.Response) { + if res != nil { + res.Body.Close() + } + } + urlStr, res, err := fetch("https") + if err != nil { + if cfg.BuildV { + log.Printf("https fetch failed: %v", err) + } + if security == Insecure { + closeBody(res) + urlStr, res, err = fetch("http") + } + } + if err != nil { + closeBody(res) + return "", nil, err + } + // Note: accepting a non-200 OK here, so people can serve a + // meta import in their http 404 page. + if cfg.BuildV { + log.Printf("Parsing meta tags from %s (status code %d)", urlStr, res.StatusCode) + } + return urlStr, res.Body, nil +} + +func QueryEscape(s string) string { return url.QueryEscape(s) } +func OpenBrowser(url string) bool { return browser.Open(url) }
diff --git a/vendor/cmd/go/internal/web/security.go b/vendor/cmd/go/internal/web/security.go new file mode 100644 index 0000000..1dc6f1b --- /dev/null +++ b/vendor/cmd/go/internal/web/security.go
@@ -0,0 +1,16 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package web defines helper routines for accessing HTTP/HTTPS resources. +package web + +// SecurityMode specifies whether a function should make network +// calls using insecure transports (eg, plain text HTTP). +// The zero value is "secure". +type SecurityMode int + +const ( + Secure SecurityMode = iota + Insecure +)
diff --git a/vendor/cmd/go/internal/work/action.go b/vendor/cmd/go/internal/work/action.go new file mode 100644 index 0000000..9f1f8f8 --- /dev/null +++ b/vendor/cmd/go/internal/work/action.go
@@ -0,0 +1,749 @@ +// Copyright 2011 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. + +// Action graph creation (planning). + +package work + +import ( + "bufio" + "bytes" + "container/heap" + "debug/elf" + "encoding/json" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + "sync" + + "cmd/go/internal/base" + "cmd/go/internal/cache" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/internal/buildid" +) + +// A Builder holds global state about a build. +// It does not hold per-package state, because we +// build packages in parallel, and the builder is shared. +type Builder struct { + WorkDir string // the temporary work directory (ends in filepath.Separator) + actionCache map[cacheKey]*Action // a cache of already-constructed actions + mkdirCache map[string]bool // a cache of created directories + flagCache map[[2]string]bool // a cache of supported compiler flags + Print func(args ...interface{}) (int, error) + + ComputeStaleOnly bool // compute staleness for go list; no actual build + + objdirSeq int // counter for NewObjdir + pkgSeq int + + output sync.Mutex + scriptDir string // current directory in printed script + + exec sync.Mutex + readySema chan bool + ready actionQueue + + id sync.Mutex + toolIDCache map[string]string // tool name -> tool ID + buildIDCache map[string]string // file name -> build ID +} + +// NOTE: Much of Action would not need to be exported if not for test. +// Maybe test functionality should move into this package too? + +// An Action represents a single action in the action graph. +type Action struct { + Mode string // description of action operation + Package *load.Package // the package this action works on + Deps []*Action // actions that must happen before this one + Func func(*Builder, *Action) error // the action itself (nil = no-op) + IgnoreFail bool // whether to run f even if dependencies fail + TestOutput *bytes.Buffer // test output buffer + Args []string // additional args for runProgram + + triggers []*Action // inverse of deps + + buggyInstall bool // is this a buggy install (see -linkshared)? + + TryCache func(*Builder, *Action) bool // callback for cache bypass + + // Generated files, directories. + Objdir string // directory for intermediate objects + Target string // goal of the action: the created package or executable + built string // the actual created package or executable + actionID cache.ActionID // cache ID of action input + buildID string // build ID of action output + + needVet bool // Mode=="build": need to fill in vet config + vetCfg *vetConfig // vet config + output []byte // output redirect buffer (nil means use b.Print) + + // Execution state. + pending int // number of deps yet to complete + priority int // relative execution priority + Failed bool // whether the action failed +} + +// BuildActionID returns the action ID section of a's build ID. +func (a *Action) BuildActionID() string { return actionID(a.buildID) } + +// BuildContentID returns the content ID section of a's build ID. +func (a *Action) BuildContentID() string { return contentID(a.buildID) } + +// BuildID returns a's build ID. +func (a *Action) BuildID() string { return a.buildID } + +// BuiltTarget returns the actual file that was built. This differs +// from Target when the result was cached. +func (a *Action) BuiltTarget() string { return a.built } + +// An actionQueue is a priority queue of actions. +type actionQueue []*Action + +// Implement heap.Interface +func (q *actionQueue) Len() int { return len(*q) } +func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] } +func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority } +func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*Action)) } +func (q *actionQueue) Pop() interface{} { + n := len(*q) - 1 + x := (*q)[n] + *q = (*q)[:n] + return x +} + +func (q *actionQueue) push(a *Action) { + heap.Push(q, a) +} + +func (q *actionQueue) pop() *Action { + return heap.Pop(q).(*Action) +} + +type actionJSON struct { + ID int + Mode string + Package string + Deps []int `json:",omitempty"` + IgnoreFail bool `json:",omitempty"` + Args []string `json:",omitempty"` + Link bool `json:",omitempty"` + Objdir string `json:",omitempty"` + Target string `json:",omitempty"` + Priority int `json:",omitempty"` + Failed bool `json:",omitempty"` + Built string `json:",omitempty"` +} + +// cacheKey is the key for the action cache. +type cacheKey struct { + mode string + p *load.Package +} + +func actionGraphJSON(a *Action) string { + var workq []*Action + var inWorkq = make(map[*Action]int) + + add := func(a *Action) { + if _, ok := inWorkq[a]; ok { + return + } + inWorkq[a] = len(workq) + workq = append(workq, a) + } + add(a) + + for i := 0; i < len(workq); i++ { + for _, dep := range workq[i].Deps { + add(dep) + } + } + + var list []*actionJSON + for id, a := range workq { + aj := &actionJSON{ + Mode: a.Mode, + ID: id, + IgnoreFail: a.IgnoreFail, + Args: a.Args, + Objdir: a.Objdir, + Target: a.Target, + Failed: a.Failed, + Priority: a.priority, + Built: a.built, + } + if a.Package != nil { + // TODO(rsc): Make this a unique key for a.Package somehow. + aj.Package = a.Package.ImportPath + } + for _, a1 := range a.Deps { + aj.Deps = append(aj.Deps, inWorkq[a1]) + } + list = append(list, aj) + } + + js, err := json.MarshalIndent(list, "", "\t") + if err != nil { + fmt.Fprintf(os.Stderr, "go: writing debug action graph: %v\n", err) + return "" + } + return string(js) +} + +// BuildMode specifies the build mode: +// are we just building things or also installing the results? +type BuildMode int + +const ( + ModeBuild BuildMode = iota + ModeInstall + ModeBuggyInstall +) + +func (b *Builder) Init() { + var err error + b.Print = func(a ...interface{}) (int, error) { + return fmt.Fprint(os.Stderr, a...) + } + b.actionCache = make(map[cacheKey]*Action) + b.mkdirCache = make(map[string]bool) + b.toolIDCache = make(map[string]string) + b.buildIDCache = make(map[string]string) + + if cfg.BuildN { + b.WorkDir = "$WORK" + } else { + b.WorkDir, err = ioutil.TempDir(os.Getenv("GOTMPDIR"), "go-build") + if err != nil { + base.Fatalf("%s", err) + } + if cfg.BuildX || cfg.BuildWork { + fmt.Fprintf(os.Stderr, "WORK=%s\n", b.WorkDir) + } + if !cfg.BuildWork { + workdir := b.WorkDir + base.AtExit(func() { os.RemoveAll(workdir) }) + } + } + + if _, ok := cfg.OSArchSupportsCgo[cfg.Goos+"/"+cfg.Goarch]; !ok && cfg.BuildContext.Compiler == "gc" { + fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", cfg.Goos, cfg.Goarch) + os.Exit(2) + } + for _, tag := range cfg.BuildContext.BuildTags { + if strings.Contains(tag, ",") { + fmt.Fprintf(os.Stderr, "cmd/go: -tags space-separated list contains comma\n") + os.Exit(2) + } + } +} + +// NewObjdir returns the name of a fresh object directory under b.WorkDir. +// It is up to the caller to call b.Mkdir on the result at an appropriate time. +// The result ends in a slash, so that file names in that directory +// can be constructed with direct string addition. +// +// NewObjdir must be called only from a single goroutine at a time, +// so it is safe to call during action graph construction, but it must not +// be called during action graph execution. +func (b *Builder) NewObjdir() string { + b.objdirSeq++ + return filepath.Join(b.WorkDir, fmt.Sprintf("b%03d", b.objdirSeq)) + string(filepath.Separator) +} + +// readpkglist returns the list of packages that were built into the shared library +// at shlibpath. For the native toolchain this list is stored, newline separated, in +// an ELF note with name "Go\x00\x00" and type 1. For GCCGO it is extracted from the +// .go_export section. +func readpkglist(shlibpath string) (pkgs []*load.Package) { + var stk load.ImportStack + if cfg.BuildToolchainName == "gccgo" { + f, _ := elf.Open(shlibpath) + sect := f.Section(".go_export") + data, _ := sect.Data() + scanner := bufio.NewScanner(bytes.NewBuffer(data)) + for scanner.Scan() { + t := scanner.Text() + if strings.HasPrefix(t, "pkgpath ") { + t = strings.TrimPrefix(t, "pkgpath ") + t = strings.TrimSuffix(t, ";") + pkgs = append(pkgs, load.LoadPackage(t, &stk)) + } + } + } else { + pkglistbytes, err := buildid.ReadELFNote(shlibpath, "Go\x00\x00", 1) + if err != nil { + base.Fatalf("readELFNote failed: %v", err) + } + scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes)) + for scanner.Scan() { + t := scanner.Text() + pkgs = append(pkgs, load.LoadPackage(t, &stk)) + } + } + return +} + +// cacheAction looks up {mode, p} in the cache and returns the resulting action. +// If the cache has no such action, f() is recorded and returned. +// TODO(rsc): Change the second key from *load.Package to interface{}, +// to make the caching in linkShared less awkward? +func (b *Builder) cacheAction(mode string, p *load.Package, f func() *Action) *Action { + a := b.actionCache[cacheKey{mode, p}] + if a == nil { + a = f() + b.actionCache[cacheKey{mode, p}] = a + } + return a +} + +// AutoAction returns the "right" action for go build or go install of p. +func (b *Builder) AutoAction(mode, depMode BuildMode, p *load.Package) *Action { + if p.Name == "main" { + return b.LinkAction(mode, depMode, p) + } + return b.CompileAction(mode, depMode, p) +} + +// CompileAction returns the action for compiling and possibly installing +// (according to mode) the given package. The resulting action is only +// for building packages (archives), never for linking executables. +// depMode is the action (build or install) to use when building dependencies. +// To turn package main into an executable, call b.Link instead. +func (b *Builder) CompileAction(mode, depMode BuildMode, p *load.Package) *Action { + if mode != ModeBuild && p.Internal.Local && p.Target == "" { + // Imported via local path. No permanent target. + mode = ModeBuild + } + if mode != ModeBuild && p.Name == "main" { + // We never install the .a file for a main package. + mode = ModeBuild + } + + // Construct package build action. + a := b.cacheAction("build", p, func() *Action { + a := &Action{ + Mode: "build", + Package: p, + Func: (*Builder).build, + Objdir: b.NewObjdir(), + } + + for _, p1 := range p.Internal.Imports { + a.Deps = append(a.Deps, b.CompileAction(depMode, depMode, p1)) + } + + if p.Standard { + switch p.ImportPath { + case "builtin", "unsafe": + // Fake packages - nothing to build. + a.Mode = "built-in package" + a.Func = nil + return a + } + + // gccgo standard library is "fake" too. + if cfg.BuildToolchainName == "gccgo" { + // the target name is needed for cgo. + a.Mode = "gccgo stdlib" + a.Target = p.Target + a.Func = nil + return a + } + } + + return a + }) + + // Construct install action. + if mode == ModeInstall || mode == ModeBuggyInstall { + a = b.installAction(a, mode) + } + + return a +} + +// VetAction returns the action for running go vet on package p. +// It depends on the action for compiling p. +// If the caller may be causing p to be installed, it is up to the caller +// to make sure that the install depends on (runs after) vet. +func (b *Builder) VetAction(mode, depMode BuildMode, p *load.Package) *Action { + // Construct vet action. + a := b.cacheAction("vet", p, func() *Action { + a1 := b.CompileAction(mode, depMode, p) + + // vet expects to be able to import "fmt". + var stk load.ImportStack + stk.Push("vet") + p1 := load.LoadPackage("fmt", &stk) + stk.Pop() + aFmt := b.CompileAction(ModeBuild, depMode, p1) + + a := &Action{ + Mode: "vet", + Package: p, + Deps: []*Action{a1, aFmt}, + Objdir: a1.Objdir, + } + if a1.Func == nil { + // Built-in packages like unsafe. + return a + } + a1.needVet = true + a.Func = (*Builder).vet + + return a + }) + return a +} + +// LinkAction returns the action for linking p into an executable +// and possibly installing the result (according to mode). +// depMode is the action (build or install) to use when compiling dependencies. +func (b *Builder) LinkAction(mode, depMode BuildMode, p *load.Package) *Action { + // Construct link action. + a := b.cacheAction("link", p, func() *Action { + a := &Action{ + Mode: "link", + Package: p, + } + + a1 := b.CompileAction(ModeBuild, depMode, p) + a.Func = (*Builder).link + a.Deps = []*Action{a1} + a.Objdir = a1.Objdir + + // An executable file. (This is the name of a temporary file.) + // Because we run the temporary file in 'go run' and 'go test', + // the name will show up in ps listings. If the caller has specified + // a name, use that instead of a.out. The binary is generated + // in an otherwise empty subdirectory named exe to avoid + // naming conflicts. The only possible conflict is if we were + // to create a top-level package named exe. + name := "a.out" + if p.Internal.ExeName != "" { + name = p.Internal.ExeName + } else if (cfg.Goos == "darwin" || cfg.Goos == "windows") && cfg.BuildBuildmode == "c-shared" && p.Target != "" { + // On OS X, the linker output name gets recorded in the + // shared library's LC_ID_DYLIB load command. + // The code invoking the linker knows to pass only the final + // path element. Arrange that the path element matches what + // we'll install it as; otherwise the library is only loadable as "a.out". + // On Windows, DLL file name is recorded in PE file + // export section, so do like on OS X. + _, name = filepath.Split(p.Target) + } + a.Target = a.Objdir + filepath.Join("exe", name) + cfg.ExeSuffix + a.built = a.Target + b.addTransitiveLinkDeps(a, a1, "") + + // Sequence the build of the main package (a1) strictly after the build + // of all other dependencies that go into the link. It is likely to be after + // them anyway, but just make sure. This is required by the build ID-based + // shortcut in (*Builder).useCache(a1), which will call b.linkActionID(a). + // In order for that linkActionID call to compute the right action ID, all the + // dependencies of a (except a1) must have completed building and have + // recorded their build IDs. + a1.Deps = append(a1.Deps, &Action{Mode: "nop", Deps: a.Deps[1:]}) + return a + }) + + if mode == ModeInstall || mode == ModeBuggyInstall { + a = b.installAction(a, mode) + } + + return a +} + +// installAction returns the action for installing the result of a1. +func (b *Builder) installAction(a1 *Action, mode BuildMode) *Action { + // Because we overwrite the build action with the install action below, + // a1 may already be an install action fetched from the "build" cache key, + // and the caller just doesn't realize. + if strings.HasSuffix(a1.Mode, "-install") { + if a1.buggyInstall && mode == ModeInstall { + // Congratulations! The buggy install is now a proper install. + a1.buggyInstall = false + } + return a1 + } + + // If there's no actual action to build a1, + // there's nothing to install either. + // This happens if a1 corresponds to reusing an already-built object. + if a1.Func == nil { + return a1 + } + + p := a1.Package + return b.cacheAction(a1.Mode+"-install", p, func() *Action { + // The install deletes the temporary build result, + // so we need all other actions, both past and future, + // that attempt to depend on the build to depend instead + // on the install. + + // Make a private copy of a1 (the build action), + // no longer accessible to any other rules. + buildAction := new(Action) + *buildAction = *a1 + + // Overwrite a1 with the install action. + // This takes care of updating past actions that + // point at a1 for the build action; now they will + // point at a1 and get the install action. + // We also leave a1 in the action cache as the result + // for "build", so that actions not yet created that + // try to depend on the build will instead depend + // on the install. + *a1 = Action{ + Mode: buildAction.Mode + "-install", + Func: BuildInstallFunc, + Package: p, + Objdir: buildAction.Objdir, + Deps: []*Action{buildAction}, + Target: p.Target, + built: p.Target, + + buggyInstall: mode == ModeBuggyInstall, + } + + b.addInstallHeaderAction(a1) + return a1 + }) +} + +// addTransitiveLinkDeps adds to the link action a all packages +// that are transitive dependencies of a1.Deps. +// That is, if a is a link of package main, a1 is the compile of package main +// and a1.Deps is the actions for building packages directly imported by +// package main (what the compiler needs). The linker needs all packages +// transitively imported by the whole program; addTransitiveLinkDeps +// makes sure those are present in a.Deps. +// If shlib is non-empty, then a corresponds to the build and installation of shlib, +// so any rebuild of shlib should not be added as a dependency. +func (b *Builder) addTransitiveLinkDeps(a, a1 *Action, shlib string) { + // Expand Deps to include all built packages, for the linker. + // Use breadth-first search to find rebuilt-for-test packages + // before the standard ones. + // TODO(rsc): Eliminate the standard ones from the action graph, + // which will require doing a little bit more rebuilding. + workq := []*Action{a1} + haveDep := map[string]bool{} + if a1.Package != nil { + haveDep[a1.Package.ImportPath] = true + } + for i := 0; i < len(workq); i++ { + a1 := workq[i] + for _, a2 := range a1.Deps { + // TODO(rsc): Find a better discriminator than the Mode strings, once the dust settles. + if a2.Package == nil || (a2.Mode != "build-install" && a2.Mode != "build") || haveDep[a2.Package.ImportPath] { + continue + } + haveDep[a2.Package.ImportPath] = true + a.Deps = append(a.Deps, a2) + if a2.Mode == "build-install" { + a2 = a2.Deps[0] // walk children of "build" action + } + workq = append(workq, a2) + } + } + + // If this is go build -linkshared, then the link depends on the shared libraries + // in addition to the packages themselves. (The compile steps do not.) + if cfg.BuildLinkshared { + haveShlib := map[string]bool{shlib: true} + for _, a1 := range a.Deps { + p1 := a1.Package + if p1 == nil || p1.Shlib == "" || haveShlib[filepath.Base(p1.Shlib)] { + continue + } + haveShlib[filepath.Base(p1.Shlib)] = true + // TODO(rsc): The use of ModeInstall here is suspect, but if we only do ModeBuild, + // we'll end up building an overall library or executable that depends at runtime + // on other libraries that are out-of-date, which is clearly not good either. + // We call it ModeBuggyInstall to make clear that this is not right. + a.Deps = append(a.Deps, b.linkSharedAction(ModeBuggyInstall, ModeBuggyInstall, p1.Shlib, nil)) + } + } +} + +// addInstallHeaderAction adds an install header action to a, if needed. +// The action a should be an install action as generated by either +// b.CompileAction or b.LinkAction with mode=ModeInstall, +// and so a.Deps[0] is the corresponding build action. +func (b *Builder) addInstallHeaderAction(a *Action) { + // Install header for cgo in c-archive and c-shared modes. + p := a.Package + if p.UsesCgo() && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") { + hdrTarget := a.Target[:len(a.Target)-len(filepath.Ext(a.Target))] + ".h" + if cfg.BuildContext.Compiler == "gccgo" { + // For the header file, remove the "lib" + // added by go/build, so we generate pkg.h + // rather than libpkg.h. + dir, file := filepath.Split(hdrTarget) + file = strings.TrimPrefix(file, "lib") + hdrTarget = filepath.Join(dir, file) + } + ah := &Action{ + Mode: "install header", + Package: a.Package, + Deps: []*Action{a.Deps[0]}, + Func: (*Builder).installHeader, + Objdir: a.Deps[0].Objdir, + Target: hdrTarget, + } + a.Deps = append(a.Deps, ah) + } +} + +// buildmodeShared takes the "go build" action a1 into the building of a shared library of a1.Deps. +// That is, the input a1 represents "go build pkgs" and the result represents "go build -buidmode=shared pkgs". +func (b *Builder) buildmodeShared(mode, depMode BuildMode, args []string, pkgs []*load.Package, a1 *Action) *Action { + name, err := libname(args, pkgs) + if err != nil { + base.Fatalf("%v", err) + } + return b.linkSharedAction(mode, depMode, name, a1) +} + +// linkSharedAction takes a grouping action a1 corresponding to a list of built packages +// and returns an action that links them together into a shared library with the name shlib. +// If a1 is nil, shlib should be an absolute path to an existing shared library, +// and then linkSharedAction reads that library to find out the package list. +func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Action) *Action { + fullShlib := shlib + shlib = filepath.Base(shlib) + a := b.cacheAction("build-shlib "+shlib, nil, func() *Action { + if a1 == nil { + // TODO(rsc): Need to find some other place to store config, + // not in pkg directory. See golang.org/issue/22196. + pkgs := readpkglist(fullShlib) + a1 = &Action{ + Mode: "shlib packages", + } + for _, p := range pkgs { + a1.Deps = append(a1.Deps, b.CompileAction(mode, depMode, p)) + } + } + + // Fake package to hold ldflags. + // As usual shared libraries are a kludgy, abstraction-violating special case: + // we let them use the flags specified for the command-line arguments. + p := &load.Package{} + p.Internal.CmdlinePkg = true + p.Internal.Ldflags = load.BuildLdflags.For(p) + p.Internal.Gccgoflags = load.BuildGccgoflags.For(p) + + // Add implicit dependencies to pkgs list. + // Currently buildmode=shared forces external linking mode, and + // external linking mode forces an import of runtime/cgo (and + // math on arm). So if it was not passed on the command line and + // it is not present in another shared library, add it here. + // TODO(rsc): Maybe this should only happen if "runtime" is in the original package set. + // TODO(rsc): This should probably be changed to use load.LinkerDeps(p). + // TODO(rsc): We don't add standard library imports for gccgo + // because they are all always linked in anyhow. + // Maybe load.LinkerDeps should be used and updated. + a := &Action{ + Mode: "go build -buildmode=shared", + Package: p, + Objdir: b.NewObjdir(), + Func: (*Builder).linkShared, + Deps: []*Action{a1}, + } + a.Target = filepath.Join(a.Objdir, shlib) + if cfg.BuildToolchainName != "gccgo" { + add := func(a1 *Action, pkg string, force bool) { + for _, a2 := range a1.Deps { + if a2.Package != nil && a2.Package.ImportPath == pkg { + return + } + } + var stk load.ImportStack + p := load.LoadPackage(pkg, &stk) + if p.Error != nil { + base.Fatalf("load %s: %v", pkg, p.Error) + } + // Assume that if pkg (runtime/cgo or math) + // is already accounted for in a different shared library, + // then that shared library also contains runtime, + // so that anything we do will depend on that library, + // so we don't need to include pkg in our shared library. + if force || p.Shlib == "" || filepath.Base(p.Shlib) == pkg { + a1.Deps = append(a1.Deps, b.CompileAction(depMode, depMode, p)) + } + } + add(a1, "runtime/cgo", false) + if cfg.Goarch == "arm" { + add(a1, "math", false) + } + + // The linker step still needs all the usual linker deps. + // (For example, the linker always opens runtime.a.) + for _, dep := range load.LinkerDeps(nil) { + add(a, dep, true) + } + } + b.addTransitiveLinkDeps(a, a1, shlib) + return a + }) + + // Install result. + if (mode == ModeInstall || mode == ModeBuggyInstall) && a.Func != nil { + buildAction := a + + a = b.cacheAction("install-shlib "+shlib, nil, func() *Action { + // Determine the eventual install target. + // The install target is root/pkg/shlib, where root is the source root + // in which all the packages lie. + // TODO(rsc): Perhaps this cross-root check should apply to the full + // transitive package dependency list, not just the ones named + // on the command line? + pkgDir := a1.Deps[0].Package.Internal.Build.PkgTargetRoot + for _, a2 := range a1.Deps { + if dir := a2.Package.Internal.Build.PkgTargetRoot; dir != pkgDir { + base.Fatalf("installing shared library: cannot use packages %s and %s from different roots %s and %s", + a1.Deps[0].Package.ImportPath, + a2.Package.ImportPath, + pkgDir, + dir) + } + } + // TODO(rsc): Find out and explain here why gccgo is different. + if cfg.BuildToolchainName == "gccgo" { + pkgDir = filepath.Join(pkgDir, "shlibs") + } + target := filepath.Join(pkgDir, shlib) + + a := &Action{ + Mode: "go install -buildmode=shared", + Objdir: buildAction.Objdir, + Func: BuildInstallFunc, + Deps: []*Action{buildAction}, + Target: target, + } + for _, a2 := range buildAction.Deps[0].Deps { + p := a2.Package + if p.Target == "" { + continue + } + a.Deps = append(a.Deps, &Action{ + Mode: "shlibname", + Package: p, + Func: (*Builder).installShlibname, + Target: strings.TrimSuffix(p.Target, ".a") + ".shlibname", + Deps: []*Action{a.Deps[0]}, + }) + } + return a + }) + } + + return a +}
diff --git a/vendor/cmd/go/internal/work/build.go b/vendor/cmd/go/internal/work/build.go new file mode 100644 index 0000000..57b7b00 --- /dev/null +++ b/vendor/cmd/go/internal/work/build.go
@@ -0,0 +1,536 @@ +// Copyright 2011 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 work + +import ( + "errors" + "fmt" + "go/build" + "os" + "os/exec" + "path" + "path/filepath" + "runtime" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/load" +) + +var CmdBuild = &base.Command{ + UsageLine: "build [-o output] [-i] [build flags] [packages]", + Short: "compile packages and dependencies", + Long: ` +Build compiles the packages named by the import paths, +along with their dependencies, but it does not install the results. + +If the arguments to build are a list of .go files, build treats +them as a list of source files specifying a single package. + +When compiling a single main package, build writes +the resulting executable to an output file named after +the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe') +or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe'). +The '.exe' suffix is added when writing a Windows executable. + +When compiling multiple packages or a single non-main package, +build compiles the packages but discards the resulting object, +serving only as a check that the packages can be built. + +When compiling packages, build ignores files that end in '_test.go'. + +The -o flag, only allowed when compiling a single package, +forces build to write the resulting executable or object +to the named output file, instead of the default behavior described +in the last two paragraphs. + +The -i flag installs the packages that are dependencies of the target. + +The build flags are shared by the build, clean, get, install, list, run, +and test commands: + + -a + force rebuilding of packages that are already up-to-date. + -n + print the commands but do not run them. + -p n + the number of programs, such as build commands or + test binaries, that can be run in parallel. + The default is the number of CPUs available. + -race + enable data race detection. + Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. + -msan + enable interoperation with memory sanitizer. + Supported only on linux/amd64, + and only with Clang/LLVM as the host C compiler. + -v + print the names of packages as they are compiled. + -work + print the name of the temporary work directory and + do not delete it when exiting. + -x + print the commands. + + -asmflags '[pattern=]arg list' + arguments to pass on each go tool asm invocation. + -buildmode mode + build mode to use. See 'go help buildmode' for more. + -compiler name + name of compiler to use, as in runtime.Compiler (gccgo or gc). + -gccgoflags '[pattern=]arg list' + arguments to pass on each gccgo compiler/linker invocation. + -gcflags '[pattern=]arg list' + arguments to pass on each go tool compile invocation. + -installsuffix suffix + a suffix to use in the name of the package installation directory, + in order to keep output separate from default builds. + If using the -race flag, the install suffix is automatically set to race + or, if set explicitly, has _race appended to it. Likewise for the -msan + flag. Using a -buildmode option that requires non-default compile flags + has a similar effect. + -ldflags '[pattern=]arg list' + arguments to pass on each go tool link invocation. + -linkshared + link against shared libraries previously created with + -buildmode=shared. + -pkgdir dir + install and load all packages from dir instead of the usual locations. + For example, when building with a non-standard configuration, + use -pkgdir to keep generated packages in a separate location. + -tags 'tag list' + a space-separated list of build tags to consider satisfied during the + build. For more information about build tags, see the description of + build constraints in the documentation for the go/build package. + -toolexec 'cmd args' + a program to use to invoke toolchain programs like vet and asm. + For example, instead of running asm, the go command will run + 'cmd args /path/to/asm <arguments for asm>'. + +The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a +space-separated list of arguments to pass to an underlying tool +during the build. To embed spaces in an element in the list, surround +it with either single or double quotes. The argument list may be +preceded by a package pattern and an equal sign, which restricts +the use of that argument list to the building of packages matching +that pattern (see 'go help packages' for a description of package +patterns). Without a pattern, the argument list applies only to the +packages named on the command line. The flags may be repeated +with different patterns in order to specify different arguments for +different sets of packages. If a package matches patterns given in +multiple flags, the latest match on the command line wins. +For example, 'go build -gcflags=-S fmt' prints the disassembly +only for package fmt, while 'go build -gcflags=all=-S fmt' +prints the disassembly for fmt and all its dependencies. + +For more about specifying packages, see 'go help packages'. +For more about where packages and binaries are installed, +run 'go help gopath'. +For more about calling between Go and C/C++, run 'go help c'. + +Note: Build adheres to certain conventions such as those described +by 'go help gopath'. Not all projects can follow these conventions, +however. Installations that have their own conventions or that use +a separate software build system may choose to use lower-level +invocations such as 'go tool compile' and 'go tool link' to avoid +some of the overheads and design decisions of the build tool. + +See also: go install, go get, go clean. + `, +} + +const concurrentGCBackendCompilationEnabledByDefault = true + +func init() { + // break init cycle + CmdBuild.Run = runBuild + CmdInstall.Run = runInstall + + CmdBuild.Flag.BoolVar(&cfg.BuildI, "i", false, "") + CmdBuild.Flag.StringVar(&cfg.BuildO, "o", "", "output file") + + CmdInstall.Flag.BoolVar(&cfg.BuildI, "i", false, "") + + AddBuildFlags(CmdBuild) + AddBuildFlags(CmdInstall) +} + +// Note that flags consulted by other parts of the code +// (for example, buildV) are in cmd/go/internal/cfg. + +var ( + forcedAsmflags []string // internally-forced flags for cmd/asm + forcedGcflags []string // internally-forced flags for cmd/compile + forcedLdflags []string // internally-forced flags for cmd/link + forcedGccgoflags []string // internally-forced flags for gccgo +) + +var BuildToolchain toolchain = noToolchain{} +var ldBuildmode string + +// buildCompiler implements flag.Var. +// It implements Set by updating both +// BuildToolchain and buildContext.Compiler. +type buildCompiler struct{} + +func (c buildCompiler) Set(value string) error { + switch value { + case "gc": + BuildToolchain = gcToolchain{} + case "gccgo": + BuildToolchain = gccgoToolchain{} + default: + return fmt.Errorf("unknown compiler %q", value) + } + cfg.BuildToolchainName = value + cfg.BuildToolchainCompiler = BuildToolchain.compiler + cfg.BuildToolchainLinker = BuildToolchain.linker + cfg.BuildContext.Compiler = value + return nil +} + +func (c buildCompiler) String() string { + return cfg.BuildContext.Compiler +} + +func init() { + switch build.Default.Compiler { + case "gc", "gccgo": + buildCompiler{}.Set(build.Default.Compiler) + } +} + +// addBuildFlags adds the flags common to the build, clean, get, +// install, list, run, and test commands. +func AddBuildFlags(cmd *base.Command) { + cmd.Flag.BoolVar(&cfg.BuildA, "a", false, "") + cmd.Flag.BoolVar(&cfg.BuildN, "n", false, "") + cmd.Flag.IntVar(&cfg.BuildP, "p", cfg.BuildP, "") + cmd.Flag.BoolVar(&cfg.BuildV, "v", false, "") + cmd.Flag.BoolVar(&cfg.BuildX, "x", false, "") + + cmd.Flag.Var(&load.BuildAsmflags, "asmflags", "") + cmd.Flag.Var(buildCompiler{}, "compiler", "") + cmd.Flag.StringVar(&cfg.BuildBuildmode, "buildmode", "default", "") + cmd.Flag.Var(&load.BuildGcflags, "gcflags", "") + cmd.Flag.Var(&load.BuildGccgoflags, "gccgoflags", "") + cmd.Flag.StringVar(&cfg.BuildContext.InstallSuffix, "installsuffix", "", "") + cmd.Flag.Var(&load.BuildLdflags, "ldflags", "") + cmd.Flag.BoolVar(&cfg.BuildLinkshared, "linkshared", false, "") + cmd.Flag.StringVar(&cfg.BuildPkgdir, "pkgdir", "", "") + cmd.Flag.BoolVar(&cfg.BuildRace, "race", false, "") + cmd.Flag.BoolVar(&cfg.BuildMSan, "msan", false, "") + cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildContext.BuildTags), "tags", "") + cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "") + cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "") + + // Undocumented, unstable debugging flags. + cmd.Flag.StringVar(&cfg.DebugActiongraph, "debug-actiongraph", "", "") + cmd.Flag.Var(&load.DebugDeprecatedImportcfg, "debug-deprecated-importcfg", "") +} + +// fileExtSplit expects a filename and returns the name +// and ext (without the dot). If the file has no +// extension, ext will be empty. +func fileExtSplit(file string) (name, ext string) { + dotExt := filepath.Ext(file) + name = file[:len(file)-len(dotExt)] + if dotExt != "" { + ext = dotExt[1:] + } + return +} + +func pkgsMain(pkgs []*load.Package) (res []*load.Package) { + for _, p := range pkgs { + if p.Name == "main" { + res = append(res, p) + } + } + return res +} + +func pkgsNotMain(pkgs []*load.Package) (res []*load.Package) { + for _, p := range pkgs { + if p.Name != "main" { + res = append(res, p) + } + } + return res +} + +func oneMainPkg(pkgs []*load.Package) []*load.Package { + if len(pkgs) != 1 || pkgs[0].Name != "main" { + base.Fatalf("-buildmode=%s requires exactly one main package", cfg.BuildBuildmode) + } + return pkgs +} + +var pkgsFilter = func(pkgs []*load.Package) []*load.Package { return pkgs } + +var runtimeVersion = runtime.Version() + +func runBuild(cmd *base.Command, args []string) { + BuildInit() + var b Builder + b.Init() + + pkgs := load.PackagesForBuild(args) + + if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" { + _, cfg.BuildO = path.Split(pkgs[0].ImportPath) + cfg.BuildO += cfg.ExeSuffix + } + + // Special case -o /dev/null by not writing at all. + if cfg.BuildO == os.DevNull { + cfg.BuildO = "" + } + + // sanity check some often mis-used options + switch cfg.BuildContext.Compiler { + case "gccgo": + if load.BuildGcflags.Present() { + fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags") + } + if load.BuildLdflags.Present() { + fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags") + } + case "gc": + if load.BuildGccgoflags.Present() { + fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags") + } + } + + depMode := ModeBuild + if cfg.BuildI { + depMode = ModeInstall + } + + pkgs = pkgsFilter(load.Packages(args)) + + if cfg.BuildO != "" { + if len(pkgs) > 1 { + base.Fatalf("go build: cannot use -o with multiple packages") + } else if len(pkgs) == 0 { + base.Fatalf("no packages to build") + } + p := pkgs[0] + p.Target = cfg.BuildO + p.Stale = true // must build - not up to date + p.StaleReason = "build -o flag in use" + a := b.AutoAction(ModeInstall, depMode, p) + b.Do(a) + return + } + + a := &Action{Mode: "go build"} + for _, p := range pkgs { + a.Deps = append(a.Deps, b.AutoAction(ModeBuild, depMode, p)) + } + if cfg.BuildBuildmode == "shared" { + a = b.buildmodeShared(ModeBuild, depMode, args, pkgs, a) + } + b.Do(a) +} + +var CmdInstall = &base.Command{ + UsageLine: "install [-i] [build flags] [packages]", + Short: "compile and install packages and dependencies", + Long: ` +Install compiles and installs the packages named by the import paths. + +The -i flag installs the dependencies of the named packages as well. + +For more about the build flags, see 'go help build'. +For more about specifying packages, see 'go help packages'. + +See also: go build, go get, go clean. + `, +} + +// libname returns the filename to use for the shared library when using +// -buildmode=shared. The rules we use are: +// Use arguments for special 'meta' packages: +// std --> libstd.so +// std cmd --> libstd,cmd.so +// A single non-meta argument with trailing "/..." is special cased: +// foo/... --> libfoo.so +// (A relative path like "./..." expands the "." first) +// Use import paths for other cases, changing '/' to '-': +// somelib --> libsubdir-somelib.so +// ./ or ../ --> libsubdir-somelib.so +// gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so +// a/... b/... ---> liba/c,b/d.so - all matching import paths +// Name parts are joined with ','. +func libname(args []string, pkgs []*load.Package) (string, error) { + var libname string + appendName := func(arg string) { + if libname == "" { + libname = arg + } else { + libname += "," + arg + } + } + var haveNonMeta bool + for _, arg := range args { + if load.IsMetaPackage(arg) { + appendName(arg) + } else { + haveNonMeta = true + } + } + if len(libname) == 0 { // non-meta packages only. use import paths + if len(args) == 1 && strings.HasSuffix(args[0], "/...") { + // Special case of "foo/..." as mentioned above. + arg := strings.TrimSuffix(args[0], "/...") + if build.IsLocalImport(arg) { + cwd, _ := os.Getwd() + bp, _ := cfg.BuildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly) + if bp.ImportPath != "" && bp.ImportPath != "." { + arg = bp.ImportPath + } + } + appendName(strings.Replace(arg, "/", "-", -1)) + } else { + for _, pkg := range pkgs { + appendName(strings.Replace(pkg.ImportPath, "/", "-", -1)) + } + } + } else if haveNonMeta { // have both meta package and a non-meta one + return "", errors.New("mixing of meta and non-meta packages is not allowed") + } + // TODO(mwhudson): Needs to change for platforms that use different naming + // conventions... + return "lib" + libname + ".so", nil +} + +func runInstall(cmd *base.Command, args []string) { + BuildInit() + InstallPackages(args, false) +} + +func InstallPackages(args []string, forGet bool) { + if cfg.GOBIN != "" && !filepath.IsAbs(cfg.GOBIN) { + base.Fatalf("cannot install, GOBIN must be an absolute path") + } + + pkgs := pkgsFilter(load.PackagesForBuild(args)) + + for _, p := range pkgs { + if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") { + switch { + case p.Internal.GobinSubdir: + base.Errorf("go %s: cannot install cross-compiled binaries when GOBIN is set", cfg.CmdName) + case p.Internal.CmdlineFiles: + base.Errorf("go %s: no install location for .go files listed on command line (GOBIN not set)", cfg.CmdName) + case p.ConflictDir != "": + base.Errorf("go %s: no install location for %s: hidden by %s", cfg.CmdName, p.Dir, p.ConflictDir) + default: + base.Errorf("go %s: no install location for directory %s outside GOPATH\n"+ + "\tFor more details see: 'go help gopath'", cfg.CmdName, p.Dir) + } + } + } + base.ExitIfErrors() + + var b Builder + b.Init() + depMode := ModeBuild + if cfg.BuildI { + depMode = ModeInstall + } + a := &Action{Mode: "go install"} + var tools []*Action + for _, p := range pkgs { + // During 'go get', don't attempt (and fail) to install packages with only tests. + // TODO(rsc): It's not clear why 'go get' should be different from 'go install' here. See #20760. + if forGet && len(p.GoFiles)+len(p.CgoFiles) == 0 && len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 { + continue + } + // If p is a tool, delay the installation until the end of the build. + // This avoids installing assemblers/compilers that are being executed + // by other steps in the build. + a1 := b.AutoAction(ModeInstall, depMode, p) + if load.InstallTargetDir(p) == load.ToTool { + a.Deps = append(a.Deps, a1.Deps...) + a1.Deps = append(a1.Deps, a) + tools = append(tools, a1) + continue + } + a.Deps = append(a.Deps, a1) + } + if len(tools) > 0 { + a = &Action{ + Mode: "go install (tools)", + Deps: tools, + } + } + + if cfg.BuildBuildmode == "shared" { + // Note: If buildmode=shared then only non-main packages + // are present in the pkgs list, so all the special case code about + // tools above did not apply, and a is just a simple Action + // with a list of Deps, one per package named in pkgs, + // the same as in runBuild. + a = b.buildmodeShared(ModeInstall, ModeInstall, args, pkgs, a) + } + + b.Do(a) + base.ExitIfErrors() + + // Success. If this command is 'go install' with no arguments + // and the current directory (the implicit argument) is a command, + // remove any leftover command binary from a previous 'go build'. + // The binary is installed; it's not needed here anymore. + // And worse it might be a stale copy, which you don't want to find + // instead of the installed one if $PATH contains dot. + // One way to view this behavior is that it is as if 'go install' first + // runs 'go build' and the moves the generated file to the install dir. + // See issue 9645. + if len(args) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" { + // Compute file 'go build' would have created. + // If it exists and is an executable file, remove it. + _, targ := filepath.Split(pkgs[0].ImportPath) + targ += cfg.ExeSuffix + if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target { // maybe $GOBIN is the current directory + fi, err := os.Stat(targ) + if err == nil { + m := fi.Mode() + if m.IsRegular() { + if m&0111 != 0 || cfg.Goos == "windows" { // windows never sets executable bit + os.Remove(targ) + } + } + } + } + } +} + +// ExecCmd is the command to use to run user binaries. +// Normally it is empty, meaning run the binaries directly. +// If cross-compiling and running on a remote system or +// simulator, it is typically go_GOOS_GOARCH_exec, with +// the target GOOS and GOARCH substituted. +// The -exec flag overrides these defaults. +var ExecCmd []string + +// FindExecCmd derives the value of ExecCmd to use. +// It returns that value and leaves ExecCmd set for direct use. +func FindExecCmd() []string { + if ExecCmd != nil { + return ExecCmd + } + ExecCmd = []string{} // avoid work the second time + if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH { + return ExecCmd + } + path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", cfg.Goos, cfg.Goarch)) + if err == nil { + ExecCmd = []string{path} + } + return ExecCmd +}
diff --git a/vendor/cmd/go/internal/work/build_test.go b/vendor/cmd/go/internal/work/build_test.go new file mode 100644 index 0000000..3f5ba37 --- /dev/null +++ b/vendor/cmd/go/internal/work/build_test.go
@@ -0,0 +1,232 @@ +// Copyright 2016 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 work + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "reflect" + "runtime" + "strings" + "testing" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/load" +) + +func TestRemoveDevNull(t *testing.T) { + fi, err := os.Lstat(os.DevNull) + if err != nil { + t.Skip(err) + } + if fi.Mode().IsRegular() { + t.Errorf("Lstat(%s).Mode().IsRegular() = true; expected false", os.DevNull) + } + mayberemovefile(os.DevNull) + _, err = os.Lstat(os.DevNull) + if err != nil { + t.Errorf("mayberemovefile(%s) did remove it; oops", os.DevNull) + } +} + +func TestSplitPkgConfigOutput(t *testing.T) { + for _, test := range []struct { + in []byte + want []string + }{ + {[]byte(`-r:foo -L/usr/white\ space/lib -lfoo\ bar -lbar\ baz`), []string{"-r:foo", "-L/usr/white space/lib", "-lfoo bar", "-lbar baz"}}, + {[]byte(`-lextra\ fun\ arg\\`), []string{`-lextra fun arg\`}}, + {[]byte(`broken flag\`), []string{"broken", "flag"}}, + {[]byte("\textra whitespace\r\n"), []string{"extra", "whitespace"}}, + {[]byte(" \r\n "), nil}, + } { + got := splitPkgConfigOutput(test.in) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("splitPkgConfigOutput(%v) = %v; want %v", test.in, got, test.want) + } + } +} + +func TestSharedLibName(t *testing.T) { + // TODO(avdva) - make these values platform-specific + prefix := "lib" + suffix := ".so" + testData := []struct { + args []string + pkgs []*load.Package + expected string + expectErr bool + rootedAt string + }{ + { + args: []string{"std"}, + pkgs: []*load.Package{}, + expected: "std", + }, + { + args: []string{"std", "cmd"}, + pkgs: []*load.Package{}, + expected: "std,cmd", + }, + { + args: []string{}, + pkgs: []*load.Package{pkgImportPath("gopkg.in/somelib")}, + expected: "gopkg.in-somelib", + }, + { + args: []string{"./..."}, + pkgs: []*load.Package{pkgImportPath("somelib")}, + expected: "somelib", + rootedAt: "somelib", + }, + { + args: []string{"../somelib", "../somelib"}, + pkgs: []*load.Package{pkgImportPath("somelib")}, + expected: "somelib", + }, + { + args: []string{"../lib1", "../lib2"}, + pkgs: []*load.Package{pkgImportPath("gopkg.in/lib1"), pkgImportPath("gopkg.in/lib2")}, + expected: "gopkg.in-lib1,gopkg.in-lib2", + }, + { + args: []string{"./..."}, + pkgs: []*load.Package{ + pkgImportPath("gopkg.in/dir/lib1"), + pkgImportPath("gopkg.in/lib2"), + pkgImportPath("gopkg.in/lib3"), + }, + expected: "gopkg.in", + rootedAt: "gopkg.in", + }, + { + args: []string{"std", "../lib2"}, + pkgs: []*load.Package{}, + expectErr: true, + }, + { + args: []string{"all", "./"}, + pkgs: []*load.Package{}, + expectErr: true, + }, + { + args: []string{"cmd", "fmt"}, + pkgs: []*load.Package{}, + expectErr: true, + }, + } + for _, data := range testData { + func() { + if data.rootedAt != "" { + tmpGopath, err := ioutil.TempDir("", "gopath") + if err != nil { + t.Fatal(err) + } + oldGopath := cfg.BuildContext.GOPATH + defer func() { + cfg.BuildContext.GOPATH = oldGopath + os.Chdir(base.Cwd) + err := os.RemoveAll(tmpGopath) + if err != nil { + t.Error(err) + } + }() + root := filepath.Join(tmpGopath, "src", data.rootedAt) + err = os.MkdirAll(root, 0755) + if err != nil { + t.Fatal(err) + } + cfg.BuildContext.GOPATH = tmpGopath + os.Chdir(root) + } + computed, err := libname(data.args, data.pkgs) + if err != nil { + if !data.expectErr { + t.Errorf("libname returned an error %q, expected a name", err.Error()) + } + } else if data.expectErr { + t.Errorf("libname returned %q, expected an error", computed) + } else { + expected := prefix + data.expected + suffix + if expected != computed { + t.Errorf("libname returned %q, expected %q", computed, expected) + } + } + }() + } +} + +func pkgImportPath(pkgpath string) *load.Package { + return &load.Package{ + PackagePublic: load.PackagePublic{ + ImportPath: pkgpath, + }, + } +} + +// When installing packages, the installed package directory should +// respect the SetGID bit and group name of the destination +// directory. +// See https://golang.org/issue/18878. +func TestRespectSetgidDir(t *testing.T) { + switch runtime.GOOS { + case "nacl": + t.Skip("can't set SetGID bit with chmod on nacl") + case "darwin": + if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" { + t.Skip("can't set SetGID bit with chmod on iOS") + } + } + + var b Builder + + // Check that `cp` is called instead of `mv` by looking at the output + // of `(*Builder).ShowCmd` afterwards as a sanity check. + cfg.BuildX = true + var cmdBuf bytes.Buffer + b.Print = func(a ...interface{}) (int, error) { + return cmdBuf.WriteString(fmt.Sprint(a...)) + } + + setgiddir, err := ioutil.TempDir("", "SetGroupID") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(setgiddir) + + if runtime.GOOS == "freebsd" { + err = os.Chown(setgiddir, os.Getuid(), os.Getgid()) + if err != nil { + t.Fatal(err) + } + } + + // Change setgiddir's permissions to include the SetGID bit. + if err := os.Chmod(setgiddir, 0755|os.ModeSetgid); err != nil { + t.Fatal(err) + } + + pkgfile, err := ioutil.TempFile("", "pkgfile") + if err != nil { + t.Fatalf("ioutil.TempFile(\"\", \"pkgfile\"): %v", err) + } + defer os.Remove(pkgfile.Name()) + defer pkgfile.Close() + + dirGIDFile := filepath.Join(setgiddir, "setgid") + if err := b.moveOrCopyFile(nil, dirGIDFile, pkgfile.Name(), 0666, true); err != nil { + t.Fatalf("moveOrCopyFile: %v", err) + } + + got := strings.TrimSpace(cmdBuf.String()) + want := b.fmtcmd("", "cp %s %s", pkgfile.Name(), dirGIDFile) + if got != want { + t.Fatalf("moveOrCopyFile(%q, %q): want %q, got %q", dirGIDFile, pkgfile.Name(), want, got) + } +}
diff --git a/vendor/cmd/go/internal/work/buildid.go b/vendor/cmd/go/internal/work/buildid.go new file mode 100644 index 0000000..39ca20e --- /dev/null +++ b/vendor/cmd/go/internal/work/buildid.go
@@ -0,0 +1,616 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package work + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "os/exec" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/cache" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/go/internal/str" + "cmd/internal/buildid" +) + +// Build IDs +// +// Go packages and binaries are stamped with build IDs that record both +// the action ID, which is a hash of the inputs to the action that produced +// the packages or binary, and the content ID, which is a hash of the action +// output, namely the archive or binary itself. The hash is the same one +// used by the build artifact cache (see cmd/go/internal/cache), but +// truncated when stored in packages and binaries, as the full length is not +// needed and is a bit unwieldy. The precise form is +// +// actionID/[.../]contentID +// +// where the actionID and contentID are prepared by hashToString below. +// and are found by looking for the first or last slash. +// Usually the buildID is simply actionID/contentID, but see below for an +// exception. +// +// The build ID serves two primary purposes. +// +// 1. The action ID half allows installed packages and binaries to serve as +// one-element cache entries. If we intend to build math.a with a given +// set of inputs summarized in the action ID, and the installed math.a already +// has that action ID, we can reuse the installed math.a instead of rebuilding it. +// +// 2. The content ID half allows the easy preparation of action IDs for steps +// that consume a particular package or binary. The content hash of every +// input file for a given action must be included in the action ID hash. +// Storing the content ID in the build ID lets us read it from the file with +// minimal I/O, instead of reading and hashing the entire file. +// This is especially effective since packages and binaries are typically +// the largest inputs to an action. +// +// Separating action ID from content ID is important for reproducible builds. +// The compiler is compiled with itself. If an output were represented by its +// own action ID (instead of content ID) when computing the action ID of +// the next step in the build process, then the compiler could never have its +// own input action ID as its output action ID (short of a miraculous hash collision). +// Instead we use the content IDs to compute the next action ID, and because +// the content IDs converge, so too do the action IDs and therefore the +// build IDs and the overall compiler binary. See cmd/dist's cmdbootstrap +// for the actual convergence sequence. +// +// The “one-element cache” purpose is a bit more complex for installed +// binaries. For a binary, like cmd/gofmt, there are two steps: compile +// cmd/gofmt/*.go into main.a, and then link main.a into the gofmt binary. +// We do not install gofmt's main.a, only the gofmt binary. Being able to +// decide that the gofmt binary is up-to-date means computing the action ID +// for the final link of the gofmt binary and comparing it against the +// already-installed gofmt binary. But computing the action ID for the link +// means knowing the content ID of main.a, which we did not keep. +// To sidestep this problem, each binary actually stores an expanded build ID: +// +// actionID(binary)/actionID(main.a)/contentID(main.a)/contentID(binary) +// +// (Note that this can be viewed equivalently as: +// +// actionID(binary)/buildID(main.a)/contentID(binary) +// +// Storing the buildID(main.a) in the middle lets the computations that care +// about the prefix or suffix halves ignore the middle and preserves the +// original build ID as a contiguous string.) +// +// During the build, when it's time to build main.a, the gofmt binary has the +// information needed to decide whether the eventual link would produce +// the same binary: if the action ID for main.a's inputs matches and then +// the action ID for the link step matches when assuming the given main.a +// content ID, then the binary as a whole is up-to-date and need not be rebuilt. +// +// This is all a bit complex and may be simplified once we can rely on the +// main cache, but at least at the start we will be using the content-based +// staleness determination without a cache beyond the usual installed +// package and binary locations. + +const buildIDSeparator = "/" + +// actionID returns the action ID half of a build ID. +func actionID(buildID string) string { + i := strings.Index(buildID, buildIDSeparator) + if i < 0 { + return buildID + } + return buildID[:i] +} + +// contentID returns the content ID half of a build ID. +func contentID(buildID string) string { + return buildID[strings.LastIndex(buildID, buildIDSeparator)+1:] +} + +// hashToString converts the hash h to a string to be recorded +// in package archives and binaries as part of the build ID. +// We use the first 96 bits of the hash and encode it in base64, +// resulting in a 16-byte string. Because this is only used for +// detecting the need to rebuild installed files (not for lookups +// in the object file cache), 96 bits are sufficient to drive the +// probability of a false "do not need to rebuild" decision to effectively zero. +// We embed two different hashes in archives and four in binaries, +// so cutting to 16 bytes is a significant savings when build IDs are displayed. +// (16*4+3 = 67 bytes compared to 64*4+3 = 259 bytes for the +// more straightforward option of printing the entire h in hex). +func hashToString(h [cache.HashSize]byte) string { + const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" + const chunks = 5 + var dst [chunks * 4]byte + for i := 0; i < chunks; i++ { + v := uint32(h[3*i])<<16 | uint32(h[3*i+1])<<8 | uint32(h[3*i+2]) + dst[4*i+0] = b64[(v>>18)&0x3F] + dst[4*i+1] = b64[(v>>12)&0x3F] + dst[4*i+2] = b64[(v>>6)&0x3F] + dst[4*i+3] = b64[v&0x3F] + } + return string(dst[:]) +} + +// toolID returns the unique ID to use for the current copy of the +// named tool (asm, compile, cover, link). +// +// It is important that if the tool changes (for example a compiler bug is fixed +// and the compiler reinstalled), toolID returns a different string, so that old +// package archives look stale and are rebuilt (with the fixed compiler). +// This suggests using a content hash of the tool binary, as stored in the build ID. +// +// Unfortunately, we can't just open the tool binary, because the tool might be +// invoked via a wrapper program specified by -toolexec and we don't know +// what the wrapper program does. In particular, we want "-toolexec toolstash" +// to continue working: it does no good if "-toolexec toolstash" is executing a +// stashed copy of the compiler but the go command is acting as if it will run +// the standard copy of the compiler. The solution is to ask the tool binary to tell +// us its own build ID using the "-V=full" flag now supported by all tools. +// Then we know we're getting the build ID of the compiler that will actually run +// during the build. (How does the compiler binary know its own content hash? +// We store it there using updateBuildID after the standard link step.) +// +// A final twist is that we'd prefer to have reproducible builds for release toolchains. +// It should be possible to cross-compile for Windows from either Linux or Mac +// or Windows itself and produce the same binaries, bit for bit. If the tool ID, +// which influences the action ID half of the build ID, is based on the content ID, +// then the Linux compiler binary and Mac compiler binary will have different tool IDs +// and therefore produce executables with different action IDs. +// To avoids this problem, for releases we use the release version string instead +// of the compiler binary's content hash. This assumes that all compilers built +// on all different systems are semantically equivalent, which is of course only true +// modulo bugs. (Producing the exact same executables also requires that the different +// build setups agree on details like $GOROOT and file name paths, but at least the +// tool IDs do not make it impossible.) +func (b *Builder) toolID(name string) string { + b.id.Lock() + id := b.toolIDCache[name] + b.id.Unlock() + + if id != "" { + return id + } + + cmdline := str.StringList(cfg.BuildToolexec, base.Tool(name), "-V=full") + cmd := exec.Command(cmdline[0], cmdline[1:]...) + cmd.Env = base.EnvForDir(cmd.Dir, os.Environ()) + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + base.Fatalf("go tool %s: %v\n%s%s", name, err, stdout.Bytes(), stderr.Bytes()) + } + + line := stdout.String() + f := strings.Fields(line) + if len(f) < 3 || f[0] != name || f[1] != "version" || f[2] == "devel" && !strings.HasPrefix(f[len(f)-1], "buildID=") { + base.Fatalf("go tool %s -V=full: unexpected output:\n\t%s", name, line) + } + if f[2] == "devel" { + // On the development branch, use the content ID part of the build ID. + id = contentID(f[len(f)-1]) + } else { + // For a release, the output is like: "compile version go1.9.1". Use the whole line. + id = f[2] + } + + b.id.Lock() + b.toolIDCache[name] = id + b.id.Unlock() + + return id +} + +// gccToolID returns the unique ID to use for a tool that is invoked +// by the GCC driver. This is in particular gccgo, but this can also +// be used for gcc, g++, gfortran, etc.; those tools all use the GCC +// driver under different names. The approach used here should also +// work for sufficiently new versions of clang. Unlike toolID, the +// name argument is the program to run. The language argument is the +// type of input file as passed to the GCC driver's -x option. +// +// For these tools we have no -V=full option to dump the build ID, +// but we can run the tool with -v -### to reliably get the compiler proper +// and hash that. That will work in the presence of -toolexec. +// +// In order to get reproducible builds for released compilers, we +// detect a released compiler by the absence of "experimental" in the +// --version output, and in that case we just use the version string. +func (b *Builder) gccgoToolID(name, language string) (string, error) { + key := name + "." + language + b.id.Lock() + id := b.toolIDCache[key] + b.id.Unlock() + + if id != "" { + return id, nil + } + + // Invoke the driver with -### to see the subcommands and the + // version strings. Use -x to set the language. Pretend to + // compile an empty file on standard input. + cmdline := str.StringList(cfg.BuildToolexec, name, "-###", "-x", language, "-c", "-") + cmd := exec.Command(cmdline[0], cmdline[1:]...) + cmd.Env = base.EnvForDir(cmd.Dir, os.Environ()) + out, err := cmd.CombinedOutput() + if err != nil { + return "", fmt.Errorf("%s: %v; output: %q", name, err, out) + } + + version := "" + lines := strings.Split(string(out), "\n") + for _, line := range lines { + if fields := strings.Fields(line); len(fields) > 1 && fields[1] == "version" { + version = line + break + } + } + if version == "" { + return "", fmt.Errorf("%s: can not find version number in %q", name, out) + } + + if !strings.Contains(version, "experimental") { + // This is a release. Use this line as the tool ID. + id = version + } else { + // This is a development version. The first line with + // a leading space is the compiler proper. + compiler := "" + for _, line := range lines { + if len(line) > 1 && line[0] == ' ' { + compiler = line + break + } + } + if compiler == "" { + return "", fmt.Errorf("%s: can not find compilation command in %q", name, out) + } + + fields := strings.Fields(compiler) + if len(fields) == 0 { + return "", fmt.Errorf("%s: compilation command confusion %q", name, out) + } + exe := fields[0] + if !strings.ContainsAny(exe, `/\`) { + if lp, err := exec.LookPath(exe); err == nil { + exe = lp + } + } + if _, err := os.Stat(exe); err != nil { + return "", fmt.Errorf("%s: can not find compiler %q: %v; output %q", name, exe, err, out) + } + id = b.fileHash(exe) + } + + b.id.Lock() + b.toolIDCache[name] = id + b.id.Unlock() + + return id, nil +} + +// gccgoBuildIDELFFile creates an assembler file that records the +// action's build ID in an SHF_EXCLUDE section. +func (b *Builder) gccgoBuildIDELFFile(a *Action) (string, error) { + sfile := a.Objdir + "_buildid.s" + + var buf bytes.Buffer + fmt.Fprintf(&buf, "\t"+`.section .go.buildid,"e"`+"\n") + fmt.Fprintf(&buf, "\t.byte ") + for i := 0; i < len(a.buildID); i++ { + if i > 0 { + if i%8 == 0 { + fmt.Fprintf(&buf, "\n\t.byte ") + } else { + fmt.Fprintf(&buf, ",") + } + } + fmt.Fprintf(&buf, "%#02x", a.buildID[i]) + } + fmt.Fprintf(&buf, "\n") + fmt.Fprintf(&buf, "\t"+`.section .note.GNU-stack,"",@progbits`+"\n") + fmt.Fprintf(&buf, "\t"+`.section .note.GNU-split-stack,"",@progbits`+"\n") + + if cfg.BuildN || cfg.BuildX { + for _, line := range bytes.Split(buf.Bytes(), []byte("\n")) { + b.Showcmd("", "echo '%s' >> %s", line, sfile) + } + if cfg.BuildN { + return sfile, nil + } + } + + if err := ioutil.WriteFile(sfile, buf.Bytes(), 0666); err != nil { + return "", err + } + + return sfile, nil +} + +// buildID returns the build ID found in the given file. +// If no build ID is found, buildID returns the content hash of the file. +func (b *Builder) buildID(file string) string { + b.id.Lock() + id := b.buildIDCache[file] + b.id.Unlock() + + if id != "" { + return id + } + + id, err := buildid.ReadFile(file) + if err != nil { + id = b.fileHash(file) + } + + b.id.Lock() + b.buildIDCache[file] = id + b.id.Unlock() + + return id +} + +// fileHash returns the content hash of the named file. +func (b *Builder) fileHash(file string) string { + sum, err := cache.FileHash(file) + if err != nil { + return "" + } + return hashToString(sum) +} + +// useCache tries to satisfy the action a, which has action ID actionHash, +// by using a cached result from an earlier build. At the moment, the only +// cached result is the installed package or binary at target. +// If useCache decides that the cache can be used, it sets a.buildID +// and a.built for use by parent actions and then returns true. +// Otherwise it sets a.buildID to a temporary build ID for use in the build +// and returns false. When useCache returns false the expectation is that +// the caller will build the target and then call updateBuildID to finish the +// build ID computation. +// When useCache returns false, it may have initiated buffering of output +// during a's work. The caller should defer b.flushOutput(a), to make sure +// that flushOutput is eventually called regardless of whether the action +// succeeds. The flushOutput call must happen after updateBuildID. +func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID, target string) bool { + // The second half of the build ID here is a placeholder for the content hash. + // It's important that the overall buildID be unlikely verging on impossible + // to appear in the output by chance, but that should be taken care of by + // the actionID half; if it also appeared in the input that would be like an + // engineered 96-bit partial SHA256 collision. + a.actionID = actionHash + actionID := hashToString(actionHash) + contentID := actionID // temporary placeholder, likely unique + a.buildID = actionID + buildIDSeparator + contentID + + // Executable binaries also record the main build ID in the middle. + // See "Build IDs" comment above. + if a.Mode == "link" { + mainpkg := a.Deps[0] + a.buildID = actionID + buildIDSeparator + mainpkg.buildID + buildIDSeparator + contentID + } + + // Check to see if target exists and matches the expected action ID. + // If so, it's up to date and we can reuse it instead of rebuilding it. + var buildID string + if target != "" && !cfg.BuildA { + var err error + buildID, err = buildid.ReadFile(target) + if err != nil && b.ComputeStaleOnly { + if p != nil && !p.Stale { + p.Stale = true + p.StaleReason = "target missing" + } + return true + } + if strings.HasPrefix(buildID, actionID+buildIDSeparator) { + a.buildID = buildID + a.built = target + // Poison a.Target to catch uses later in the build. + a.Target = "DO NOT USE - " + a.Mode + return true + } + } + + // Special case for building a main package: if the only thing we + // want the package for is to link a binary, and the binary is + // already up-to-date, then to avoid a rebuild, report the package + // as up-to-date as well. See "Build IDs" comment above. + // TODO(rsc): Rewrite this code to use a TryCache func on the link action. + if target != "" && !cfg.BuildA && a.Mode == "build" && len(a.triggers) == 1 && a.triggers[0].Mode == "link" { + buildID, err := buildid.ReadFile(target) + if err == nil { + id := strings.Split(buildID, buildIDSeparator) + if len(id) == 4 && id[1] == actionID { + // Temporarily assume a.buildID is the package build ID + // stored in the installed binary, and see if that makes + // the upcoming link action ID a match. If so, report that + // we built the package, safe in the knowledge that the + // link step will not ask us for the actual package file. + // Note that (*Builder).LinkAction arranged that all of + // a.triggers[0]'s dependencies other than a are also + // dependencies of a, so that we can be sure that, + // other than a.buildID, b.linkActionID is only accessing + // build IDs of completed actions. + oldBuildID := a.buildID + a.buildID = id[1] + buildIDSeparator + id[2] + linkID := hashToString(b.linkActionID(a.triggers[0])) + if id[0] == linkID { + // Poison a.Target to catch uses later in the build. + a.Target = "DO NOT USE - main build pseudo-cache Target" + a.built = "DO NOT USE - main build pseudo-cache built" + return true + } + // Otherwise restore old build ID for main build. + a.buildID = oldBuildID + } + } + } + + // Special case for linking a test binary: if the only thing we + // want the binary for is to run the test, and the test result is cached, + // then to avoid the link step, report the link as up-to-date. + // We avoid the nested build ID problem in the previous special case + // by recording the test results in the cache under the action ID half. + if !cfg.BuildA && len(a.triggers) == 1 && a.triggers[0].TryCache != nil && a.triggers[0].TryCache(b, a.triggers[0]) { + a.Target = "DO NOT USE - pseudo-cache Target" + a.built = "DO NOT USE - pseudo-cache built" + return true + } + + if b.ComputeStaleOnly { + // Invoked during go list only to compute and record staleness. + if p := a.Package; p != nil && !p.Stale { + p.Stale = true + if cfg.BuildA { + p.StaleReason = "build -a flag in use" + } else { + p.StaleReason = "build ID mismatch" + for _, p1 := range p.Internal.Imports { + if p1.Stale && p1.StaleReason != "" { + if strings.HasPrefix(p1.StaleReason, "stale dependency: ") { + p.StaleReason = p1.StaleReason + break + } + if strings.HasPrefix(p.StaleReason, "build ID mismatch") { + p.StaleReason = "stale dependency: " + p1.ImportPath + } + } + } + } + } + return true + } + + // Check the build artifact cache. + // We treat hits in this cache as being "stale" for the purposes of go list + // (in effect, "stale" means whether p.Target is up-to-date), + // but we're still happy to use results from the build artifact cache. + if c := cache.Default(); c != nil { + if !cfg.BuildA { + entry, err := c.Get(actionHash) + if err == nil { + file := c.OutputFile(entry.OutputID) + info, err1 := os.Stat(file) + buildID, err2 := buildid.ReadFile(file) + if err1 == nil && err2 == nil && info.Size() == entry.Size { + stdout, stdoutEntry, err := c.GetBytes(cache.Subkey(a.actionID, "stdout")) + if err == nil { + if len(stdout) > 0 { + if cfg.BuildX || cfg.BuildN { + b.Showcmd("", "%s # internal", joinUnambiguously(str.StringList("cat", c.OutputFile(stdoutEntry.OutputID)))) + } + if !cfg.BuildN { + b.Print(string(stdout)) + } + } + a.built = file + a.Target = "DO NOT USE - using cache" + a.buildID = buildID + return true + } + } + } + } + + // Begin saving output for later writing to cache. + a.output = []byte{} + } + + return false +} + +// flushOutput flushes the output being queued in a. +func (b *Builder) flushOutput(a *Action) { + b.Print(string(a.output)) + a.output = nil +} + +// updateBuildID updates the build ID in the target written by action a. +// It requires that useCache was called for action a and returned false, +// and that the build was then carried out and given the temporary +// a.buildID to record as the build ID in the resulting package or binary. +// updateBuildID computes the final content ID and updates the build IDs +// in the binary. +// +// Keep in sync with src/cmd/buildid/buildid.go +func (b *Builder) updateBuildID(a *Action, target string, rewrite bool) error { + if cfg.BuildX || cfg.BuildN { + if rewrite { + b.Showcmd("", "%s # internal", joinUnambiguously(str.StringList(base.Tool("buildid"), "-w", target))) + } + if cfg.BuildN { + return nil + } + } + + // Find occurrences of old ID and compute new content-based ID. + r, err := os.Open(target) + if err != nil { + return err + } + matches, hash, err := buildid.FindAndHash(r, a.buildID, 0) + r.Close() + if err != nil { + return err + } + newID := a.buildID[:strings.LastIndex(a.buildID, buildIDSeparator)] + buildIDSeparator + hashToString(hash) + if len(newID) != len(a.buildID) { + return fmt.Errorf("internal error: build ID length mismatch %q vs %q", a.buildID, newID) + } + + // Replace with new content-based ID. + a.buildID = newID + if len(matches) == 0 { + // Assume the user specified -buildid= to override what we were going to choose. + return nil + } + + if rewrite { + w, err := os.OpenFile(target, os.O_WRONLY, 0) + if err != nil { + return err + } + err = buildid.Rewrite(w, matches, newID) + if err != nil { + w.Close() + return err + } + if err := w.Close(); err != nil { + return err + } + } + + // Cache package builds, but not binaries (link steps). + // The expectation is that binaries are not reused + // nearly as often as individual packages, and they're + // much larger, so the cache-footprint-to-utility ratio + // of binaries is much lower for binaries. + // Not caching the link step also makes sure that repeated "go run" at least + // always rerun the linker, so that they don't get too fast. + // (We don't want people thinking go is a scripting language.) + // Note also that if we start caching binaries, then we will + // copy the binaries out of the cache to run them, and then + // that will mean the go process is itself writing a binary + // and then executing it, so we will need to defend against + // ETXTBSY problems as discussed in exec.go and golang.org/issue/22220. + if c := cache.Default(); c != nil && a.Mode == "build" { + r, err := os.Open(target) + if err == nil { + if a.output == nil { + panic("internal error: a.output not set") + } + outputID, _, err := c.Put(a.actionID, r) + if err == nil && cfg.BuildX { + b.Showcmd("", "%s # internal", joinUnambiguously(str.StringList("cp", target, c.OutputFile(outputID)))) + } + c.PutBytes(cache.Subkey(a.actionID, "stdout"), a.output) + r.Close() + } + } + + return nil +}
diff --git a/vendor/cmd/go/internal/work/exec.go b/vendor/cmd/go/internal/work/exec.go new file mode 100644 index 0000000..c4c1500 --- /dev/null +++ b/vendor/cmd/go/internal/work/exec.go
@@ -0,0 +1,2422 @@ +// Copyright 2011 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. + +// Action graph execution. + +package work + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "regexp" + "runtime" + "strconv" + "strings" + "sync" + "time" + + "cmd/go/internal/base" + "cmd/go/internal/cache" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/go/internal/str" +) + +// actionList returns the list of actions in the dag rooted at root +// as visited in a depth-first post-order traversal. +func actionList(root *Action) []*Action { + seen := map[*Action]bool{} + all := []*Action{} + var walk func(*Action) + walk = func(a *Action) { + if seen[a] { + return + } + seen[a] = true + for _, a1 := range a.Deps { + walk(a1) + } + all = append(all, a) + } + walk(root) + return all +} + +// do runs the action graph rooted at root. +func (b *Builder) Do(root *Action) { + if c := cache.Default(); c != nil && !b.ComputeStaleOnly { + // If we're doing real work, take time at the end to trim the cache. + defer c.Trim() + } + + // Build list of all actions, assigning depth-first post-order priority. + // The original implementation here was a true queue + // (using a channel) but it had the effect of getting + // distracted by low-level leaf actions to the detriment + // of completing higher-level actions. The order of + // work does not matter much to overall execution time, + // but when running "go test std" it is nice to see each test + // results as soon as possible. The priorities assigned + // ensure that, all else being equal, the execution prefers + // to do what it would have done first in a simple depth-first + // dependency order traversal. + all := actionList(root) + for i, a := range all { + a.priority = i + } + + if cfg.DebugActiongraph != "" { + js := actionGraphJSON(root) + if err := ioutil.WriteFile(cfg.DebugActiongraph, []byte(js), 0666); err != nil { + fmt.Fprintf(os.Stderr, "go: writing action graph: %v\n", err) + base.SetExitStatus(1) + } + } + + b.readySema = make(chan bool, len(all)) + + // Initialize per-action execution state. + for _, a := range all { + for _, a1 := range a.Deps { + a1.triggers = append(a1.triggers, a) + } + a.pending = len(a.Deps) + if a.pending == 0 { + b.ready.push(a) + b.readySema <- true + } + } + + // Handle runs a single action and takes care of triggering + // any actions that are runnable as a result. + handle := func(a *Action) { + var err error + + if a.Func != nil && (!a.Failed || a.IgnoreFail) { + if err == nil { + err = a.Func(b, a) + } + } + + // The actions run in parallel but all the updates to the + // shared work state are serialized through b.exec. + b.exec.Lock() + defer b.exec.Unlock() + + if err != nil { + if err == errPrintedOutput { + base.SetExitStatus(2) + } else { + base.Errorf("%s", err) + } + a.Failed = true + } + + for _, a0 := range a.triggers { + if a.Failed { + a0.Failed = true + } + if a0.pending--; a0.pending == 0 { + b.ready.push(a0) + b.readySema <- true + } + } + + if a == root { + close(b.readySema) + } + } + + var wg sync.WaitGroup + + // Kick off goroutines according to parallelism. + // If we are using the -n flag (just printing commands) + // drop the parallelism to 1, both to make the output + // deterministic and because there is no real work anyway. + par := cfg.BuildP + if cfg.BuildN { + par = 1 + } + for i := 0; i < par; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for { + select { + case _, ok := <-b.readySema: + if !ok { + return + } + // Receiving a value from b.readySema entitles + // us to take from the ready queue. + b.exec.Lock() + a := b.ready.pop() + b.exec.Unlock() + handle(a) + case <-base.Interrupted: + base.SetExitStatus(1) + return + } + } + }() + } + + wg.Wait() +} + +// buildActionID computes the action ID for a build action. +func (b *Builder) buildActionID(a *Action) cache.ActionID { + p := a.Package + h := cache.NewHash("build " + p.ImportPath) + + // Configuration independent of compiler toolchain. + // Note: buildmode has already been accounted for in buildGcflags + // and should not be inserted explicitly. Most buildmodes use the + // same compiler settings and can reuse each other's results. + // If not, the reason is already recorded in buildGcflags. + fmt.Fprintf(h, "compile\n") + // The compiler hides the exact value of $GOROOT + // when building things in GOROOT, + // but it does not hide the exact value of $GOPATH. + // Include the full dir in that case. + // Assume b.WorkDir is being trimmed properly. + if !p.Goroot && !strings.HasPrefix(p.Dir, b.WorkDir) { + fmt.Fprintf(h, "dir %s\n", p.Dir) + } + fmt.Fprintf(h, "goos %s goarch %s\n", cfg.Goos, cfg.Goarch) + fmt.Fprintf(h, "import %q\n", p.ImportPath) + fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix) + if len(p.CgoFiles)+len(p.SwigFiles) > 0 { + fmt.Fprintf(h, "cgo %q\n", b.toolID("cgo")) + cppflags, cflags, cxxflags, fflags, _, _ := b.CFlags(p) + fmt.Fprintf(h, "CC=%q %q %q\n", b.ccExe(), cppflags, cflags) + if len(p.CXXFiles)+len(p.SwigFiles) > 0 { + fmt.Fprintf(h, "CXX=%q %q\n", b.cxxExe(), cxxflags) + } + if len(p.FFiles) > 0 { + fmt.Fprintf(h, "FC=%q %q\n", b.fcExe(), fflags) + } + // TODO(rsc): Should we include the SWIG version or Fortran/GCC/G++/Objective-C compiler versions? + } + if p.Internal.CoverMode != "" { + fmt.Fprintf(h, "cover %q %q\n", p.Internal.CoverMode, b.toolID("cover")) + } + + // Configuration specific to compiler toolchain. + switch cfg.BuildToolchainName { + default: + base.Fatalf("buildActionID: unknown build toolchain %q", cfg.BuildToolchainName) + case "gc": + fmt.Fprintf(h, "compile %s %q %q\n", b.toolID("compile"), forcedGcflags, p.Internal.Gcflags) + if len(p.SFiles) > 0 { + fmt.Fprintf(h, "asm %q %q %q\n", b.toolID("asm"), forcedAsmflags, p.Internal.Asmflags) + } + fmt.Fprintf(h, "GO$GOARCH=%s\n", os.Getenv("GO"+strings.ToUpper(cfg.BuildContext.GOARCH))) // GO386, GOARM, etc + + // TODO(rsc): Convince compiler team not to add more magic environment variables, + // or perhaps restrict the environment variables passed to subprocesses. + magic := []string{ + "GOCLOBBERDEADHASH", + "GOSSAFUNC", + "GO_SSA_PHI_LOC_CUTOFF", + "GOSSAHASH", + } + for _, env := range magic { + if x := os.Getenv(env); x != "" { + fmt.Fprintf(h, "magic %s=%s\n", env, x) + } + } + if os.Getenv("GOSSAHASH") != "" { + for i := 0; ; i++ { + env := fmt.Sprintf("GOSSAHASH%d", i) + x := os.Getenv(env) + if x == "" { + break + } + fmt.Fprintf(h, "magic %s=%s\n", env, x) + } + } + if os.Getenv("GSHS_LOGFILE") != "" { + // Clumsy hack. Compiler writes to this log file, + // so do not allow use of cache at all. + // We will still write to the cache but it will be + // essentially unfindable. + fmt.Fprintf(h, "nocache %d\n", time.Now().UnixNano()) + } + + case "gccgo": + id, err := b.gccgoToolID(BuildToolchain.compiler(), "go") + if err != nil { + base.Fatalf("%v", err) + } + fmt.Fprintf(h, "compile %s %q %q\n", id, forcedGccgoflags, p.Internal.Gccgoflags) + fmt.Fprintf(h, "pkgpath %s\n", gccgoPkgpath(p)) + if len(p.SFiles) > 0 { + id, err = b.gccgoToolID(BuildToolchain.compiler(), "assembler-with-cpp") + // Ignore error; different assembler versions + // are unlikely to make any difference anyhow. + fmt.Fprintf(h, "asm %q\n", id) + } + } + + // Input files. + inputFiles := str.StringList( + p.GoFiles, + p.CgoFiles, + p.CFiles, + p.CXXFiles, + p.FFiles, + p.MFiles, + p.HFiles, + p.SFiles, + p.SysoFiles, + p.SwigFiles, + p.SwigCXXFiles, + ) + for _, file := range inputFiles { + fmt.Fprintf(h, "file %s %s\n", file, b.fileHash(filepath.Join(p.Dir, file))) + } + for _, a1 := range a.Deps { + p1 := a1.Package + if p1 != nil { + fmt.Fprintf(h, "import %s %s\n", p1.ImportPath, contentID(a1.buildID)) + } + } + + return h.Sum() +} + +// build is the action for building a single package. +// Note that any new influence on this logic must be reported in b.buildActionID above as well. +func (b *Builder) build(a *Action) (err error) { + p := a.Package + cached := false + if !p.BinaryOnly { + if b.useCache(a, p, b.buildActionID(a), p.Target) { + // If this build triggers a header install, run cgo to get the header. + // TODO(rsc): Once we can cache multiple file outputs from an action, + // the header should be cached, and then this awful test can be deleted. + // Need to look for install header actions depending on this action, + // or depending on a link that depends on this action. + needHeader := false + if (a.Package.UsesCgo() || a.Package.UsesSwig()) && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") { + for _, t1 := range a.triggers { + if t1.Mode == "install header" { + needHeader = true + goto CheckedHeader + } + } + for _, t1 := range a.triggers { + for _, t2 := range t1.triggers { + if t2.Mode == "install header" { + needHeader = true + goto CheckedHeader + } + } + } + } + CheckedHeader: + if b.ComputeStaleOnly || !a.needVet && !needHeader { + return nil + } + cached = true + } + defer b.flushOutput(a) + } + + defer func() { + if err != nil && err != errPrintedOutput { + err = fmt.Errorf("go build %s: %v", a.Package.ImportPath, err) + } + }() + if cfg.BuildN { + // In -n mode, print a banner between packages. + // The banner is five lines so that when changes to + // different sections of the bootstrap script have to + // be merged, the banners give patch something + // to use to find its context. + b.Print("\n#\n# " + a.Package.ImportPath + "\n#\n\n") + } + + if cfg.BuildV { + b.Print(a.Package.ImportPath + "\n") + } + + if a.Package.BinaryOnly { + _, err := os.Stat(a.Package.Target) + if err == nil { + a.built = a.Package.Target + a.Target = a.Package.Target + a.buildID = b.fileHash(a.Package.Target) + a.Package.Stale = false + a.Package.StaleReason = "binary-only package" + return nil + } + if b.ComputeStaleOnly { + a.Package.Stale = true + a.Package.StaleReason = "missing or invalid binary-only package" + return nil + } + return fmt.Errorf("missing or invalid binary-only package") + } + + if err := b.Mkdir(a.Objdir); err != nil { + return err + } + objdir := a.Objdir + + // make target directory + dir, _ := filepath.Split(a.Target) + if dir != "" { + if err := b.Mkdir(dir); err != nil { + return err + } + } + + var gofiles, cgofiles, cfiles, sfiles, cxxfiles, objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string + + gofiles = append(gofiles, a.Package.GoFiles...) + cgofiles = append(cgofiles, a.Package.CgoFiles...) + cfiles = append(cfiles, a.Package.CFiles...) + sfiles = append(sfiles, a.Package.SFiles...) + cxxfiles = append(cxxfiles, a.Package.CXXFiles...) + + if a.Package.UsesCgo() || a.Package.UsesSwig() { + if pcCFLAGS, pcLDFLAGS, err = b.getPkgConfigFlags(a.Package); err != nil { + return + } + } + + // Run SWIG on each .swig and .swigcxx file. + // Each run will generate two files, a .go file and a .c or .cxx file. + // The .go file will use import "C" and is to be processed by cgo. + if a.Package.UsesSwig() { + outGo, outC, outCXX, err := b.swig(a, a.Package, objdir, pcCFLAGS) + if err != nil { + return err + } + cgofiles = append(cgofiles, outGo...) + cfiles = append(cfiles, outC...) + cxxfiles = append(cxxfiles, outCXX...) + } + + // If we're doing coverage, preprocess the .go files and put them in the work directory + if a.Package.Internal.CoverMode != "" { + for i, file := range str.StringList(gofiles, cgofiles) { + var sourceFile string + var coverFile string + var key string + if strings.HasSuffix(file, ".cgo1.go") { + // cgo files have absolute paths + base := filepath.Base(file) + sourceFile = file + coverFile = objdir + base + key = strings.TrimSuffix(base, ".cgo1.go") + ".go" + } else { + sourceFile = filepath.Join(a.Package.Dir, file) + coverFile = objdir + file + key = file + } + coverFile = strings.TrimSuffix(coverFile, ".go") + ".cover.go" + cover := a.Package.Internal.CoverVars[key] + if cover == nil || base.IsTestFile(file) { + // Not covering this file. + continue + } + if err := b.cover(a, coverFile, sourceFile, 0666, cover.Var); err != nil { + return err + } + if i < len(gofiles) { + gofiles[i] = coverFile + } else { + cgofiles[i-len(gofiles)] = coverFile + } + } + } + + // Run cgo. + if a.Package.UsesCgo() || a.Package.UsesSwig() { + // In a package using cgo, cgo compiles the C, C++ and assembly files with gcc. + // There is one exception: runtime/cgo's job is to bridge the + // cgo and non-cgo worlds, so it necessarily has files in both. + // In that case gcc only gets the gcc_* files. + var gccfiles []string + gccfiles = append(gccfiles, cfiles...) + cfiles = nil + if a.Package.Standard && a.Package.ImportPath == "runtime/cgo" { + filter := func(files, nongcc, gcc []string) ([]string, []string) { + for _, f := range files { + if strings.HasPrefix(f, "gcc_") { + gcc = append(gcc, f) + } else { + nongcc = append(nongcc, f) + } + } + return nongcc, gcc + } + sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles) + } else { + for _, sfile := range sfiles { + data, err := ioutil.ReadFile(filepath.Join(a.Package.Dir, sfile)) + if err == nil { + if bytes.HasPrefix(data, []byte("TEXT")) || bytes.Contains(data, []byte("\nTEXT")) || + bytes.HasPrefix(data, []byte("DATA")) || bytes.Contains(data, []byte("\nDATA")) || + bytes.HasPrefix(data, []byte("GLOBL")) || bytes.Contains(data, []byte("\nGLOBL")) { + return fmt.Errorf("package using cgo has Go assembly file %s", sfile) + } + } + } + gccfiles = append(gccfiles, sfiles...) + sfiles = nil + } + + outGo, outObj, err := b.cgo(a, base.Tool("cgo"), objdir, pcCFLAGS, pcLDFLAGS, mkAbsFiles(a.Package.Dir, cgofiles), gccfiles, cxxfiles, a.Package.MFiles, a.Package.FFiles) + if err != nil { + return err + } + if cfg.BuildToolchainName == "gccgo" { + cgoObjects = append(cgoObjects, a.Objdir+"_cgo_flags") + } + cgoObjects = append(cgoObjects, outObj...) + gofiles = append(gofiles, outGo...) + } + if cached && !a.needVet { + return nil + } + + // Sanity check only, since Package.load already checked as well. + if len(gofiles) == 0 { + return &load.NoGoError{Package: a.Package} + } + + // Prepare Go vet config if needed. + var vcfg *vetConfig + if a.needVet { + // Pass list of absolute paths to vet, + // so that vet's error messages will use absolute paths, + // so that we can reformat them relative to the directory + // in which the go command is invoked. + vcfg = &vetConfig{ + Compiler: cfg.BuildToolchainName, + Dir: a.Package.Dir, + GoFiles: mkAbsFiles(a.Package.Dir, gofiles), + ImportPath: a.Package.ImportPath, + ImportMap: make(map[string]string), + PackageFile: make(map[string]string), + } + a.vetCfg = vcfg + for i, raw := range a.Package.Internal.RawImports { + final := a.Package.Imports[i] + vcfg.ImportMap[raw] = final + } + } + + // Prepare Go import config. + // We start it off with a comment so it can't be empty, so icfg.Bytes() below is never nil. + // It should never be empty anyway, but there have been bugs in the past that resulted + // in empty configs, which then unfortunately turn into "no config passed to compiler", + // and the compiler falls back to looking in pkg itself, which mostly works, + // except when it doesn't. + var icfg bytes.Buffer + fmt.Fprintf(&icfg, "# import config\n") + + for i, raw := range a.Package.Internal.RawImports { + final := a.Package.Imports[i] + if final != raw { + fmt.Fprintf(&icfg, "importmap %s=%s\n", raw, final) + } + } + + // Compute the list of mapped imports in the vet config + // so that we can add any missing mappings below. + var vcfgMapped map[string]bool + if vcfg != nil { + vcfgMapped = make(map[string]bool) + for _, p := range vcfg.ImportMap { + vcfgMapped[p] = true + } + } + + for _, a1 := range a.Deps { + p1 := a1.Package + if p1 == nil || p1.ImportPath == "" || a1.built == "" { + continue + } + fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, a1.built) + if vcfg != nil { + // Add import mapping if needed + // (for imports like "runtime/cgo" that appear only in generated code). + if !vcfgMapped[p1.ImportPath] { + vcfg.ImportMap[p1.ImportPath] = p1.ImportPath + } + vcfg.PackageFile[p1.ImportPath] = a1.built + } + } + + if cached { + // The cached package file is OK, so we don't need to run the compile. + // We've only going through the motions to prepare the vet configuration, + // which is now complete. + return nil + } + + // Compile Go. + objpkg := objdir + "_pkg_.a" + ofile, out, err := BuildToolchain.gc(b, a, objpkg, icfg.Bytes(), len(sfiles) > 0, gofiles) + if len(out) > 0 { + b.showOutput(a, a.Package.Dir, a.Package.ImportPath, b.processOutput(out)) + if err != nil { + return errPrintedOutput + } + } + if err != nil { + return err + } + if ofile != objpkg { + objects = append(objects, ofile) + } + + // Copy .h files named for goos or goarch or goos_goarch + // to names using GOOS and GOARCH. + // For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h. + _goos_goarch := "_" + cfg.Goos + "_" + cfg.Goarch + _goos := "_" + cfg.Goos + _goarch := "_" + cfg.Goarch + for _, file := range a.Package.HFiles { + name, ext := fileExtSplit(file) + switch { + case strings.HasSuffix(name, _goos_goarch): + targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOARCH." + ext + if err := b.copyFile(a, objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil { + return err + } + case strings.HasSuffix(name, _goarch): + targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext + if err := b.copyFile(a, objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil { + return err + } + case strings.HasSuffix(name, _goos): + targ := file[:len(name)-len(_goos)] + "_GOOS." + ext + if err := b.copyFile(a, objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil { + return err + } + } + } + + for _, file := range cfiles { + out := file[:len(file)-len(".c")] + ".o" + if err := BuildToolchain.cc(b, a, objdir+out, file); err != nil { + return err + } + objects = append(objects, out) + } + + // Assemble .s files. + if len(sfiles) > 0 { + ofiles, err := BuildToolchain.asm(b, a, sfiles) + if err != nil { + return err + } + objects = append(objects, ofiles...) + } + + // For gccgo on ELF systems, we write the build ID as an assembler file. + // This lets us set the the SHF_EXCLUDE flag. + // This is read by readGccgoArchive in cmd/internal/buildid/buildid.go. + if a.buildID != "" && cfg.BuildToolchainName == "gccgo" { + switch cfg.Goos { + case "android", "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris": + asmfile, err := b.gccgoBuildIDELFFile(a) + if err != nil { + return err + } + ofiles, err := BuildToolchain.asm(b, a, []string{asmfile}) + if err != nil { + return err + } + objects = append(objects, ofiles...) + } + } + + // NOTE(rsc): On Windows, it is critically important that the + // gcc-compiled objects (cgoObjects) be listed after the ordinary + // objects in the archive. I do not know why this is. + // https://golang.org/issue/2601 + objects = append(objects, cgoObjects...) + + // Add system object files. + for _, syso := range a.Package.SysoFiles { + objects = append(objects, filepath.Join(a.Package.Dir, syso)) + } + + // Pack into archive in objdir directory. + // If the Go compiler wrote an archive, we only need to add the + // object files for non-Go sources to the archive. + // If the Go compiler wrote an archive and the package is entirely + // Go sources, there is no pack to execute at all. + if len(objects) > 0 { + if err := BuildToolchain.pack(b, a, objpkg, objects); err != nil { + return err + } + } + + if err := b.updateBuildID(a, objpkg, true); err != nil { + return err + } + + a.built = objpkg + return nil +} + +type vetConfig struct { + Compiler string + Dir string + GoFiles []string + ImportMap map[string]string + PackageFile map[string]string + ImportPath string + + SucceedOnTypecheckFailure bool +} + +// VetTool is the path to an alternate vet tool binary. +// The caller is expected to set it (if needed) before executing any vet actions. +var VetTool string + +// VetFlags are the flags to pass to vet. +// The caller is expected to set them before executing any vet actions. +var VetFlags []string + +func (b *Builder) vet(a *Action) error { + // a.Deps[0] is the build of the package being vetted. + // a.Deps[1] is the build of the "fmt" package. + + vcfg := a.Deps[0].vetCfg + if vcfg == nil { + // Vet config should only be missing if the build failed. + if !a.Deps[0].Failed { + return fmt.Errorf("vet config not found") + } + return nil + } + + if vcfg.ImportMap["fmt"] == "" { + a1 := a.Deps[1] + vcfg.ImportMap["fmt"] = "fmt" + vcfg.PackageFile["fmt"] = a1.built + } + + // During go test, ignore type-checking failures during vet. + // We only run vet if the compilation has succeeded, + // so at least for now assume the bug is in vet. + // We know of at least #18395. + // TODO(rsc,gri): Try to remove this for Go 1.11. + vcfg.SucceedOnTypecheckFailure = cfg.CmdName == "test" + + js, err := json.MarshalIndent(vcfg, "", "\t") + if err != nil { + return fmt.Errorf("internal error marshaling vet config: %v", err) + } + js = append(js, '\n') + if err := b.writeFile(a.Objdir+"vet.cfg", js); err != nil { + return err + } + + var env []string + if cfg.BuildToolchainName == "gccgo" { + env = append(env, "GCCGO="+BuildToolchain.compiler()) + } + + p := a.Package + tool := VetTool + if tool == "" { + tool = base.Tool("vet") + } + return b.run(a, p.Dir, p.ImportPath, env, cfg.BuildToolexec, tool, VetFlags, a.Objdir+"vet.cfg") +} + +// linkActionID computes the action ID for a link action. +func (b *Builder) linkActionID(a *Action) cache.ActionID { + p := a.Package + h := cache.NewHash("link " + p.ImportPath) + + // Toolchain-independent configuration. + fmt.Fprintf(h, "link\n") + fmt.Fprintf(h, "buildmode %s goos %s goarch %s\n", cfg.BuildBuildmode, cfg.Goos, cfg.Goarch) + fmt.Fprintf(h, "import %q\n", p.ImportPath) + fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix) + + // Toolchain-dependent configuration, shared with b.linkSharedActionID. + b.printLinkerConfig(h, p) + + // Input files. + for _, a1 := range a.Deps { + p1 := a1.Package + if p1 != nil { + if a1.built != "" || a1.buildID != "" { + buildID := a1.buildID + if buildID == "" { + buildID = b.buildID(a1.built) + } + fmt.Fprintf(h, "packagefile %s=%s\n", p1.ImportPath, contentID(buildID)) + } + // Because we put package main's full action ID into the binary's build ID, + // we must also put the full action ID into the binary's action ID hash. + if p1.Name == "main" { + fmt.Fprintf(h, "packagemain %s\n", a1.buildID) + } + if p1.Shlib != "" { + fmt.Fprintf(h, "packageshlib %s=%s\n", p1.ImportPath, contentID(b.buildID(p1.Shlib))) + } + } + } + + return h.Sum() +} + +// printLinkerConfig prints the linker config into the hash h, +// as part of the computation of a linker-related action ID. +func (b *Builder) printLinkerConfig(h io.Writer, p *load.Package) { + switch cfg.BuildToolchainName { + default: + base.Fatalf("linkActionID: unknown toolchain %q", cfg.BuildToolchainName) + + case "gc": + fmt.Fprintf(h, "link %s %q %s\n", b.toolID("link"), forcedLdflags, ldBuildmode) + if p != nil { + fmt.Fprintf(h, "linkflags %q\n", p.Internal.Ldflags) + } + fmt.Fprintf(h, "GO$GOARCH=%s\n", os.Getenv("GO"+strings.ToUpper(cfg.BuildContext.GOARCH))) // GO386, GOARM, etc + + // The linker writes source file paths that say GOROOT_FINAL. + fmt.Fprintf(h, "GOROOT=%s\n", cfg.GOROOT_FINAL) + + // TODO(rsc): Convince linker team not to add more magic environment variables, + // or perhaps restrict the environment variables passed to subprocesses. + magic := []string{ + "GO_EXTLINK_ENABLED", + } + for _, env := range magic { + if x := os.Getenv(env); x != "" { + fmt.Fprintf(h, "magic %s=%s\n", env, x) + } + } + + // TODO(rsc): Do cgo settings and flags need to be included? + // Or external linker settings and flags? + + case "gccgo": + id, err := b.gccgoToolID(BuildToolchain.linker(), "go") + if err != nil { + base.Fatalf("%v", err) + } + fmt.Fprintf(h, "link %s %s\n", id, ldBuildmode) + // TODO(iant): Should probably include cgo flags here. + } +} + +// link is the action for linking a single command. +// Note that any new influence on this logic must be reported in b.linkActionID above as well. +func (b *Builder) link(a *Action) (err error) { + if b.useCache(a, a.Package, b.linkActionID(a), a.Package.Target) { + return nil + } + defer b.flushOutput(a) + + if err := b.Mkdir(a.Objdir); err != nil { + return err + } + + importcfg := a.Objdir + "importcfg.link" + if err := b.writeLinkImportcfg(a, importcfg); err != nil { + return err + } + + // make target directory + dir, _ := filepath.Split(a.Target) + if dir != "" { + if err := b.Mkdir(dir); err != nil { + return err + } + } + + if err := BuildToolchain.ld(b, a, a.Target, importcfg, a.Deps[0].built); err != nil { + return err + } + + // Update the binary with the final build ID. + // But if OmitDebug is set, don't rewrite the binary, because we set OmitDebug + // on binaries that we are going to run and then delete. + // There's no point in doing work on such a binary. + // Worse, opening the binary for write here makes it + // essentially impossible to safely fork+exec due to a fundamental + // incompatibility between ETXTBSY and threads on modern Unix systems. + // See golang.org/issue/22220. + // We still call updateBuildID to update a.buildID, which is important + // for test result caching, but passing rewrite=false (final arg) + // means we don't actually rewrite the binary, nor store the + // result into the cache. + // Not calling updateBuildID means we also don't insert these + // binaries into the build object cache. That's probably a net win: + // less cache space wasted on large binaries we are not likely to + // need again. (On the other hand it does make repeated go test slower.) + if err := b.updateBuildID(a, a.Target, !a.Package.Internal.OmitDebug); err != nil { + return err + } + + a.built = a.Target + return nil +} + +func (b *Builder) writeLinkImportcfg(a *Action, file string) error { + // Prepare Go import cfg. + var icfg bytes.Buffer + for _, a1 := range a.Deps { + p1 := a1.Package + if p1 == nil { + continue + } + fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, a1.built) + if p1.Shlib != "" { + fmt.Fprintf(&icfg, "packageshlib %s=%s\n", p1.ImportPath, p1.Shlib) + } + } + return b.writeFile(file, icfg.Bytes()) +} + +// PkgconfigCmd returns a pkg-config binary name +// defaultPkgConfig is defined in zdefaultcc.go, written by cmd/dist. +func (b *Builder) PkgconfigCmd() string { + return envList("PKG_CONFIG", cfg.DefaultPkgConfig)[0] +} + +// splitPkgConfigOutput parses the pkg-config output into a slice of +// flags. pkg-config always uses \ to escape special characters. +func splitPkgConfigOutput(out []byte) []string { + if len(out) == 0 { + return nil + } + var flags []string + flag := make([]byte, len(out)) + r, w := 0, 0 + for r < len(out) { + switch out[r] { + case ' ', '\t', '\r', '\n': + if w > 0 { + flags = append(flags, string(flag[:w])) + } + w = 0 + case '\\': + r++ + fallthrough + default: + if r < len(out) { + flag[w] = out[r] + w++ + } + } + r++ + } + if w > 0 { + flags = append(flags, string(flag[:w])) + } + return flags +} + +// Calls pkg-config if needed and returns the cflags/ldflags needed to build the package. +func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string, err error) { + if pkgs := p.CgoPkgConfig; len(pkgs) > 0 { + var pcflags []string + for len(pkgs) > 0 && strings.HasPrefix(pkgs[0], "--") { + pcflags = append(pcflags, pkgs[0]) + pkgs = pkgs[1:] + } + for _, pkg := range pkgs { + if !load.SafeArg(pkg) { + return nil, nil, fmt.Errorf("invalid pkg-config package name: %s", pkg) + } + } + var out []byte + out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs) + if err != nil { + b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+strings.Join(pkgs, " "), string(out)) + b.Print(err.Error() + "\n") + return nil, nil, errPrintedOutput + } + if len(out) > 0 { + cflags = splitPkgConfigOutput(out) + if err := checkCompilerFlags("CFLAGS", "pkg-config --cflags", cflags); err != nil { + return nil, nil, err + } + } + out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--libs", pcflags, "--", pkgs) + if err != nil { + b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+strings.Join(pkgs, " "), string(out)) + b.Print(err.Error() + "\n") + return nil, nil, errPrintedOutput + } + if len(out) > 0 { + ldflags = strings.Fields(string(out)) + if err := checkLinkerFlags("LDFLAGS", "pkg-config --libs", ldflags); err != nil { + return nil, nil, err + } + } + } + + return +} + +func (b *Builder) installShlibname(a *Action) error { + // TODO: BuildN + a1 := a.Deps[0] + err := ioutil.WriteFile(a.Target, []byte(filepath.Base(a1.Target)+"\n"), 0666) + if err != nil { + return err + } + if cfg.BuildX { + b.Showcmd("", "echo '%s' > %s # internal", filepath.Base(a1.Target), a.Target) + } + return nil +} + +func (b *Builder) linkSharedActionID(a *Action) cache.ActionID { + h := cache.NewHash("linkShared") + + // Toolchain-independent configuration. + fmt.Fprintf(h, "linkShared\n") + fmt.Fprintf(h, "goos %s goarch %s\n", cfg.Goos, cfg.Goarch) + + // Toolchain-dependent configuration, shared with b.linkActionID. + b.printLinkerConfig(h, nil) + + // Input files. + for _, a1 := range a.Deps { + p1 := a1.Package + if a1.built == "" { + continue + } + if p1 != nil { + fmt.Fprintf(h, "packagefile %s=%s\n", p1.ImportPath, contentID(b.buildID(a1.built))) + if p1.Shlib != "" { + fmt.Fprintf(h, "packageshlib %s=%s\n", p1.ImportPath, contentID(b.buildID(p1.Shlib))) + } + } + } + // Files named on command line are special. + for _, a1 := range a.Deps[0].Deps { + p1 := a1.Package + fmt.Fprintf(h, "top %s=%s\n", p1.ImportPath, contentID(b.buildID(a1.built))) + } + + return h.Sum() +} + +func (b *Builder) linkShared(a *Action) (err error) { + if b.useCache(a, nil, b.linkSharedActionID(a), a.Target) { + return nil + } + defer b.flushOutput(a) + + if err := b.Mkdir(a.Objdir); err != nil { + return err + } + + importcfg := a.Objdir + "importcfg.link" + if err := b.writeLinkImportcfg(a, importcfg); err != nil { + return err + } + + // TODO(rsc): There is a missing updateBuildID here, + // but we have to decide where to store the build ID in these files. + a.built = a.Target + return BuildToolchain.ldShared(b, a, a.Deps[0].Deps, a.Target, importcfg, a.Deps) +} + +// BuildInstallFunc is the action for installing a single package or executable. +func BuildInstallFunc(b *Builder, a *Action) (err error) { + defer func() { + if err != nil && err != errPrintedOutput { + // a.Package == nil is possible for the go install -buildmode=shared + // action that installs libmangledname.so, which corresponds to + // a list of packages, not just one. + sep, path := "", "" + if a.Package != nil { + sep, path = " ", a.Package.ImportPath + } + err = fmt.Errorf("go %s%s%s: %v", cfg.CmdName, sep, path, err) + } + }() + + a1 := a.Deps[0] + a.buildID = a1.buildID + + // If we are using the eventual install target as an up-to-date + // cached copy of the thing we built, then there's no need to + // copy it into itself (and that would probably fail anyway). + // In this case a1.built == a.Target because a1.built == p.Target, + // so the built target is not in the a1.Objdir tree that b.cleanup(a1) removes. + if a1.built == a.Target { + a.built = a.Target + b.cleanup(a1) + // Whether we're smart enough to avoid a complete rebuild + // depends on exactly what the staleness and rebuild algorithms + // are, as well as potentially the state of the Go build cache. + // We don't really want users to be able to infer (or worse start depending on) + // those details from whether the modification time changes during + // "go install", so do a best-effort update of the file times to make it + // look like we rewrote a.Target even if we did not. Updating the mtime + // may also help other mtime-based systems that depend on our + // previous mtime updates that happened more often. + // This is still not perfect - we ignore the error result, and if the file was + // unwritable for some reason then pretending to have written it is also + // confusing - but it's probably better than not doing the mtime update. + // + // But don't do that for the special case where building an executable + // with -linkshared implicitly installs all its dependent libraries. + // We want to hide that awful detail as much as possible, so don't + // advertise it by touching the mtimes (usually the libraries are up + // to date). + if !a.buggyInstall { + now := time.Now() + os.Chtimes(a.Target, now, now) + } + return nil + } + if b.ComputeStaleOnly { + return nil + } + + if err := b.Mkdir(a.Objdir); err != nil { + return err + } + + perm := os.FileMode(0666) + if a1.Mode == "link" { + switch cfg.BuildBuildmode { + case "c-archive", "c-shared", "plugin": + default: + perm = 0777 + } + } + + // make target directory + dir, _ := filepath.Split(a.Target) + if dir != "" { + if err := b.Mkdir(dir); err != nil { + return err + } + } + + defer b.cleanup(a1) + + return b.moveOrCopyFile(a, a.Target, a1.built, perm, false) +} + +// cleanup removes a's object dir to keep the amount of +// on-disk garbage down in a large build. On an operating system +// with aggressive buffering, cleaning incrementally like +// this keeps the intermediate objects from hitting the disk. +func (b *Builder) cleanup(a *Action) { + if !cfg.BuildWork { + if cfg.BuildX { + b.Showcmd("", "rm -r %s", a.Objdir) + } + os.RemoveAll(a.Objdir) + } +} + +// moveOrCopyFile is like 'mv src dst' or 'cp src dst'. +func (b *Builder) moveOrCopyFile(a *Action, dst, src string, perm os.FileMode, force bool) error { + if cfg.BuildN { + b.Showcmd("", "mv %s %s", src, dst) + return nil + } + + // If we can update the mode and rename to the dst, do it. + // Otherwise fall back to standard copy. + + // If the source is in the build cache, we need to copy it. + if strings.HasPrefix(src, cache.DefaultDir()) { + return b.copyFile(a, dst, src, perm, force) + } + + // On Windows, always copy the file, so that we respect the NTFS + // permissions of the parent folder. https://golang.org/issue/22343. + // What matters here is not cfg.Goos (the system we are building + // for) but runtime.GOOS (the system we are building on). + if runtime.GOOS == "windows" { + return b.copyFile(a, dst, src, perm, force) + } + + // If the destination directory has the group sticky bit set, + // we have to copy the file to retain the correct permissions. + // https://golang.org/issue/18878 + if fi, err := os.Stat(filepath.Dir(dst)); err == nil { + if fi.IsDir() && (fi.Mode()&os.ModeSetgid) != 0 { + return b.copyFile(a, dst, src, perm, force) + } + } + + // The perm argument is meant to be adjusted according to umask, + // but we don't know what the umask is. + // Create a dummy file to find out. + // This avoids build tags and works even on systems like Plan 9 + // where the file mask computation incorporates other information. + mode := perm + f, err := os.OpenFile(filepath.Clean(dst)+"-go-tmp-umask", os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) + if err == nil { + fi, err := f.Stat() + if err == nil { + mode = fi.Mode() & 0777 + } + name := f.Name() + f.Close() + os.Remove(name) + } + + if err := os.Chmod(src, mode); err == nil { + if err := os.Rename(src, dst); err == nil { + if cfg.BuildX { + b.Showcmd("", "mv %s %s", src, dst) + } + return nil + } + } + + return b.copyFile(a, dst, src, perm, force) +} + +// copyFile is like 'cp src dst'. +func (b *Builder) copyFile(a *Action, dst, src string, perm os.FileMode, force bool) error { + if cfg.BuildN || cfg.BuildX { + b.Showcmd("", "cp %s %s", src, dst) + if cfg.BuildN { + return nil + } + } + + sf, err := os.Open(src) + if err != nil { + return err + } + defer sf.Close() + + // Be careful about removing/overwriting dst. + // Do not remove/overwrite if dst exists and is a directory + // or a non-object file. + if fi, err := os.Stat(dst); err == nil { + if fi.IsDir() { + return fmt.Errorf("build output %q already exists and is a directory", dst) + } + if !force && fi.Mode().IsRegular() && !isObject(dst) { + return fmt.Errorf("build output %q already exists and is not an object file", dst) + } + } + + // On Windows, remove lingering ~ file from last attempt. + if base.ToolIsWindows { + if _, err := os.Stat(dst + "~"); err == nil { + os.Remove(dst + "~") + } + } + + mayberemovefile(dst) + df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) + if err != nil && base.ToolIsWindows { + // Windows does not allow deletion of a binary file + // while it is executing. Try to move it out of the way. + // If the move fails, which is likely, we'll try again the + // next time we do an install of this binary. + if err := os.Rename(dst, dst+"~"); err == nil { + os.Remove(dst + "~") + } + df, err = os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) + } + if err != nil { + return err + } + + _, err = io.Copy(df, sf) + df.Close() + if err != nil { + mayberemovefile(dst) + return fmt.Errorf("copying %s to %s: %v", src, dst, err) + } + return nil +} + +// writeFile writes the text to file. +func (b *Builder) writeFile(file string, text []byte) error { + if cfg.BuildN || cfg.BuildX { + b.Showcmd("", "cat >%s << 'EOF' # internal\n%sEOF", file, text) + } + if cfg.BuildN { + return nil + } + return ioutil.WriteFile(file, text, 0666) +} + +// Install the cgo export header file, if there is one. +func (b *Builder) installHeader(a *Action) error { + src := a.Objdir + "_cgo_install.h" + if _, err := os.Stat(src); os.IsNotExist(err) { + // If the file does not exist, there are no exported + // functions, and we do not install anything. + // TODO(rsc): Once we know that caching is rebuilding + // at the right times (not missing rebuilds), here we should + // probably delete the installed header, if any. + if cfg.BuildX { + b.Showcmd("", "# %s not created", src) + } + return nil + } + + dir, _ := filepath.Split(a.Target) + if dir != "" { + if err := b.Mkdir(dir); err != nil { + return err + } + } + + return b.moveOrCopyFile(a, a.Target, src, 0666, true) +} + +// cover runs, in effect, +// go tool cover -mode=b.coverMode -var="varName" -o dst.go src.go +func (b *Builder) cover(a *Action, dst, src string, perm os.FileMode, varName string) error { + return b.run(a, a.Objdir, "cover "+a.Package.ImportPath, nil, + cfg.BuildToolexec, + base.Tool("cover"), + "-mode", a.Package.Internal.CoverMode, + "-var", varName, + "-o", dst, + src) +} + +var objectMagic = [][]byte{ + {'!', '<', 'a', 'r', 'c', 'h', '>', '\n'}, // Package archive + {'\x7F', 'E', 'L', 'F'}, // ELF + {0xFE, 0xED, 0xFA, 0xCE}, // Mach-O big-endian 32-bit + {0xFE, 0xED, 0xFA, 0xCF}, // Mach-O big-endian 64-bit + {0xCE, 0xFA, 0xED, 0xFE}, // Mach-O little-endian 32-bit + {0xCF, 0xFA, 0xED, 0xFE}, // Mach-O little-endian 64-bit + {0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00}, // PE (Windows) as generated by 6l/8l and gcc + {0x00, 0x00, 0x01, 0xEB}, // Plan 9 i386 + {0x00, 0x00, 0x8a, 0x97}, // Plan 9 amd64 + {0x00, 0x00, 0x06, 0x47}, // Plan 9 arm +} + +func isObject(s string) bool { + f, err := os.Open(s) + if err != nil { + return false + } + defer f.Close() + buf := make([]byte, 64) + io.ReadFull(f, buf) + for _, magic := range objectMagic { + if bytes.HasPrefix(buf, magic) { + return true + } + } + return false +} + +// mayberemovefile removes a file only if it is a regular file +// When running as a user with sufficient privileges, we may delete +// even device files, for example, which is not intended. +func mayberemovefile(s string) { + if fi, err := os.Lstat(s); err == nil && !fi.Mode().IsRegular() { + return + } + os.Remove(s) +} + +// fmtcmd formats a command in the manner of fmt.Sprintf but also: +// +// If dir is non-empty and the script is not in dir right now, +// fmtcmd inserts "cd dir\n" before the command. +// +// fmtcmd replaces the value of b.WorkDir with $WORK. +// fmtcmd replaces the value of goroot with $GOROOT. +// fmtcmd replaces the value of b.gobin with $GOBIN. +// +// fmtcmd replaces the name of the current directory with dot (.) +// but only when it is at the beginning of a space-separated token. +// +func (b *Builder) fmtcmd(dir string, format string, args ...interface{}) string { + cmd := fmt.Sprintf(format, args...) + if dir != "" && dir != "/" { + cmd = strings.Replace(" "+cmd, " "+dir, " .", -1)[1:] + if b.scriptDir != dir { + b.scriptDir = dir + cmd = "cd " + dir + "\n" + cmd + } + } + if b.WorkDir != "" { + cmd = strings.Replace(cmd, b.WorkDir, "$WORK", -1) + } + return cmd +} + +// showcmd prints the given command to standard output +// for the implementation of -n or -x. +func (b *Builder) Showcmd(dir string, format string, args ...interface{}) { + b.output.Lock() + defer b.output.Unlock() + b.Print(b.fmtcmd(dir, format, args...) + "\n") +} + +// showOutput prints "# desc" followed by the given output. +// The output is expected to contain references to 'dir', usually +// the source directory for the package that has failed to build. +// showOutput rewrites mentions of dir with a relative path to dir +// when the relative path is shorter. This is usually more pleasant. +// For example, if fmt doesn't compile and we are in src/html, +// the output is +// +// $ go build +// # fmt +// ../fmt/print.go:1090: undefined: asdf +// $ +// +// instead of +// +// $ go build +// # fmt +// /usr/gopher/go/src/fmt/print.go:1090: undefined: asdf +// $ +// +// showOutput also replaces references to the work directory with $WORK. +// +// If a is not nil and a.output is not nil, showOutput appends to that slice instead of +// printing to b.Print. +// +func (b *Builder) showOutput(a *Action, dir, desc, out string) { + prefix := "# " + desc + suffix := "\n" + out + if reldir := base.ShortPath(dir); reldir != dir { + suffix = strings.Replace(suffix, " "+dir, " "+reldir, -1) + suffix = strings.Replace(suffix, "\n"+dir, "\n"+reldir, -1) + } + suffix = strings.Replace(suffix, " "+b.WorkDir, " $WORK", -1) + + if a != nil && a.output != nil { + a.output = append(a.output, prefix...) + a.output = append(a.output, suffix...) + return + } + + b.output.Lock() + defer b.output.Unlock() + b.Print(prefix, suffix) +} + +// errPrintedOutput is a special error indicating that a command failed +// but that it generated output as well, and that output has already +// been printed, so there's no point showing 'exit status 1' or whatever +// the wait status was. The main executor, builder.do, knows not to +// print this error. +var errPrintedOutput = errors.New("already printed output - no need to show error") + +var cgoLine = regexp.MustCompile(`\[[^\[\]]+\.(cgo1|cover)\.go:[0-9]+(:[0-9]+)?\]`) +var cgoTypeSigRe = regexp.MustCompile(`\b_C2?(type|func|var|macro)_\B`) + +// run runs the command given by cmdline in the directory dir. +// If the command fails, run prints information about the failure +// and returns a non-nil error. +func (b *Builder) run(a *Action, dir string, desc string, env []string, cmdargs ...interface{}) error { + out, err := b.runOut(dir, desc, env, cmdargs...) + if len(out) > 0 { + if desc == "" { + desc = b.fmtcmd(dir, "%s", strings.Join(str.StringList(cmdargs...), " ")) + } + b.showOutput(a, dir, desc, b.processOutput(out)) + if err != nil { + err = errPrintedOutput + } + } + return err +} + +// processOutput prepares the output of runOut to be output to the console. +func (b *Builder) processOutput(out []byte) string { + if out[len(out)-1] != '\n' { + out = append(out, '\n') + } + messages := string(out) + // Fix up output referring to cgo-generated code to be more readable. + // Replace x.go:19[/tmp/.../x.cgo1.go:18] with x.go:19. + // Replace *[100]_Ctype_foo with *[100]C.foo. + // If we're using -x, assume we're debugging and want the full dump, so disable the rewrite. + if !cfg.BuildX && cgoLine.MatchString(messages) { + messages = cgoLine.ReplaceAllString(messages, "") + messages = cgoTypeSigRe.ReplaceAllString(messages, "C.") + } + return messages +} + +// runOut runs the command given by cmdline in the directory dir. +// It returns the command output and any errors that occurred. +func (b *Builder) runOut(dir string, desc string, env []string, cmdargs ...interface{}) ([]byte, error) { + cmdline := str.StringList(cmdargs...) + + for _, arg := range cmdline { + // GNU binutils commands, including gcc and gccgo, interpret an argument + // @foo anywhere in the command line (even following --) as meaning + // "read and insert arguments from the file named foo." + // Don't say anything that might be misinterpreted that way. + if strings.HasPrefix(arg, "@") { + return nil, fmt.Errorf("invalid command-line argument %s in command: %s", arg, joinUnambiguously(cmdline)) + } + } + + if cfg.BuildN || cfg.BuildX { + var envcmdline string + for _, e := range env { + if j := strings.IndexByte(e, '='); j != -1 { + if strings.ContainsRune(e[j+1:], '\'') { + envcmdline += fmt.Sprintf("%s=%q", e[:j], e[j+1:]) + } else { + envcmdline += fmt.Sprintf("%s='%s'", e[:j], e[j+1:]) + } + envcmdline += " " + } + } + envcmdline += joinUnambiguously(cmdline) + b.Showcmd(dir, "%s", envcmdline) + if cfg.BuildN { + return nil, nil + } + } + + var buf bytes.Buffer + cmd := exec.Command(cmdline[0], cmdline[1:]...) + cmd.Stdout = &buf + cmd.Stderr = &buf + cmd.Dir = dir + cmd.Env = base.MergeEnvLists(env, base.EnvForDir(cmd.Dir, os.Environ())) + err := cmd.Run() + + // err can be something like 'exit status 1'. + // Add information about what program was running. + // Note that if buf.Bytes() is non-empty, the caller usually + // shows buf.Bytes() and does not print err at all, so the + // prefix here does not make most output any more verbose. + if err != nil { + err = errors.New(cmdline[0] + ": " + err.Error()) + } + return buf.Bytes(), err +} + +// joinUnambiguously prints the slice, quoting where necessary to make the +// output unambiguous. +// TODO: See issue 5279. The printing of commands needs a complete redo. +func joinUnambiguously(a []string) string { + var buf bytes.Buffer + for i, s := range a { + if i > 0 { + buf.WriteByte(' ') + } + q := strconv.Quote(s) + if s == "" || strings.Contains(s, " ") || len(q) > len(s)+2 { + buf.WriteString(q) + } else { + buf.WriteString(s) + } + } + return buf.String() +} + +// mkdir makes the named directory. +func (b *Builder) Mkdir(dir string) error { + // Make Mkdir(a.Objdir) a no-op instead of an error when a.Objdir == "". + if dir == "" { + return nil + } + + b.exec.Lock() + defer b.exec.Unlock() + // We can be a little aggressive about being + // sure directories exist. Skip repeated calls. + if b.mkdirCache[dir] { + return nil + } + b.mkdirCache[dir] = true + + if cfg.BuildN || cfg.BuildX { + b.Showcmd("", "mkdir -p %s", dir) + if cfg.BuildN { + return nil + } + } + + if err := os.MkdirAll(dir, 0777); err != nil { + return err + } + return nil +} + +// symlink creates a symlink newname -> oldname. +func (b *Builder) Symlink(oldname, newname string) error { + if cfg.BuildN || cfg.BuildX { + b.Showcmd("", "ln -s %s %s", oldname, newname) + if cfg.BuildN { + return nil + } + } + return os.Symlink(oldname, newname) +} + +// mkAbs returns an absolute path corresponding to +// evaluating f in the directory dir. +// We always pass absolute paths of source files so that +// the error messages will include the full path to a file +// in need of attention. +func mkAbs(dir, f string) string { + // Leave absolute paths alone. + // Also, during -n mode we use the pseudo-directory $WORK + // instead of creating an actual work directory that won't be used. + // Leave paths beginning with $WORK alone too. + if filepath.IsAbs(f) || strings.HasPrefix(f, "$WORK") { + return f + } + return filepath.Join(dir, f) +} + +type toolchain interface { + // gc runs the compiler in a specific directory on a set of files + // and returns the name of the generated output file. + gc(b *Builder, a *Action, archive string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, out []byte, err error) + // cc runs the toolchain's C compiler in a directory on a C file + // to produce an output file. + cc(b *Builder, a *Action, ofile, cfile string) error + // asm runs the assembler in a specific directory on specific files + // and returns a list of named output files. + asm(b *Builder, a *Action, sfiles []string) ([]string, error) + // pack runs the archive packer in a specific directory to create + // an archive from a set of object files. + // typically it is run in the object directory. + pack(b *Builder, a *Action, afile string, ofiles []string) error + // ld runs the linker to create an executable starting at mainpkg. + ld(b *Builder, root *Action, out, importcfg, mainpkg string) error + // ldShared runs the linker to create a shared library containing the pkgs built by toplevelactions + ldShared(b *Builder, root *Action, toplevelactions []*Action, out, importcfg string, allactions []*Action) error + + compiler() string + linker() string +} + +type noToolchain struct{} + +func noCompiler() error { + log.Fatalf("unknown compiler %q", cfg.BuildContext.Compiler) + return nil +} + +func (noToolchain) compiler() string { + noCompiler() + return "" +} + +func (noToolchain) linker() string { + noCompiler() + return "" +} + +func (noToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, out []byte, err error) { + return "", nil, noCompiler() +} + +func (noToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error) { + return nil, noCompiler() +} + +func (noToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) error { + return noCompiler() +} + +func (noToolchain) ld(b *Builder, root *Action, out, importcfg, mainpkg string) error { + return noCompiler() +} + +func (noToolchain) ldShared(b *Builder, root *Action, toplevelactions []*Action, out, importcfg string, allactions []*Action) error { + return noCompiler() +} + +func (noToolchain) cc(b *Builder, a *Action, ofile, cfile string) error { + return noCompiler() +} + +// gcc runs the gcc C compiler to create an object from a single C file. +func (b *Builder) gcc(a *Action, p *load.Package, workdir, out string, flags []string, cfile string) error { + return b.ccompile(a, p, out, flags, cfile, b.GccCmd(p.Dir, workdir)) +} + +// gxx runs the g++ C++ compiler to create an object from a single C++ file. +func (b *Builder) gxx(a *Action, p *load.Package, workdir, out string, flags []string, cxxfile string) error { + return b.ccompile(a, p, out, flags, cxxfile, b.GxxCmd(p.Dir, workdir)) +} + +// gfortran runs the gfortran Fortran compiler to create an object from a single Fortran file. +func (b *Builder) gfortran(a *Action, p *load.Package, workdir, out string, flags []string, ffile string) error { + return b.ccompile(a, p, out, flags, ffile, b.gfortranCmd(p.Dir, workdir)) +} + +// ccompile runs the given C or C++ compiler and creates an object from a single source file. +func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []string, file string, compiler []string) error { + file = mkAbs(p.Dir, file) + desc := p.ImportPath + if !filepath.IsAbs(outfile) { + outfile = filepath.Join(p.Dir, outfile) + } + output, err := b.runOut(filepath.Dir(file), desc, nil, compiler, flags, "-o", outfile, "-c", filepath.Base(file)) + if len(output) > 0 { + // On FreeBSD 11, when we pass -g to clang 3.8 it + // invokes its internal assembler with -dwarf-version=2. + // When it sees .section .note.GNU-stack, it warns + // "DWARF2 only supports one section per compilation unit". + // This warning makes no sense, since the section is empty, + // but it confuses people. + // We work around the problem by detecting the warning + // and dropping -g and trying again. + if bytes.Contains(output, []byte("DWARF2 only supports one section per compilation unit")) { + newFlags := make([]string, 0, len(flags)) + for _, f := range flags { + if !strings.HasPrefix(f, "-g") { + newFlags = append(newFlags, f) + } + } + if len(newFlags) < len(flags) { + return b.ccompile(a, p, outfile, newFlags, file, compiler) + } + } + + b.showOutput(a, p.Dir, desc, b.processOutput(output)) + if err != nil { + err = errPrintedOutput + } else if os.Getenv("GO_BUILDER_NAME") != "" { + return errors.New("C compiler warning promoted to error on Go builders") + } + } + return err +} + +// gccld runs the gcc linker to create an executable from a set of object files. +func (b *Builder) gccld(p *load.Package, objdir, out string, flags []string, objs []string) error { + var cmd []string + if len(p.CXXFiles) > 0 || len(p.SwigCXXFiles) > 0 { + cmd = b.GxxCmd(p.Dir, objdir) + } else { + cmd = b.GccCmd(p.Dir, objdir) + } + return b.run(nil, p.Dir, p.ImportPath, nil, cmd, "-o", out, objs, flags) +} + +// Grab these before main helpfully overwrites them. +var ( + origCC = os.Getenv("CC") + origCXX = os.Getenv("CXX") +) + +// gccCmd returns a gcc command line prefix +// defaultCC is defined in zdefaultcc.go, written by cmd/dist. +func (b *Builder) GccCmd(incdir, workdir string) []string { + return b.compilerCmd(b.ccExe(), incdir, workdir) +} + +// gxxCmd returns a g++ command line prefix +// defaultCXX is defined in zdefaultcc.go, written by cmd/dist. +func (b *Builder) GxxCmd(incdir, workdir string) []string { + return b.compilerCmd(b.cxxExe(), incdir, workdir) +} + +// gfortranCmd returns a gfortran command line prefix. +func (b *Builder) gfortranCmd(incdir, workdir string) []string { + return b.compilerCmd(b.fcExe(), incdir, workdir) +} + +// ccExe returns the CC compiler setting without all the extra flags we add implicitly. +func (b *Builder) ccExe() []string { + return b.compilerExe(origCC, cfg.DefaultCC(cfg.Goos, cfg.Goarch)) +} + +// cxxExe returns the CXX compiler setting without all the extra flags we add implicitly. +func (b *Builder) cxxExe() []string { + return b.compilerExe(origCXX, cfg.DefaultCXX(cfg.Goos, cfg.Goarch)) +} + +// fcExe returns the FC compiler setting without all the extra flags we add implicitly. +func (b *Builder) fcExe() []string { + return b.compilerExe(os.Getenv("FC"), "gfortran") +} + +// compilerExe returns the compiler to use given an +// environment variable setting (the value not the name) +// and a default. The resulting slice is usually just the name +// of the compiler but can have additional arguments if they +// were present in the environment value. +// For example if CC="gcc -DGOPHER" then the result is ["gcc", "-DGOPHER"]. +func (b *Builder) compilerExe(envValue string, def string) []string { + compiler := strings.Fields(envValue) + if len(compiler) == 0 { + compiler = []string{def} + } + return compiler +} + +// compilerCmd returns a command line prefix for the given environment +// variable and using the default command when the variable is empty. +func (b *Builder) compilerCmd(compiler []string, incdir, workdir string) []string { + // NOTE: env.go's mkEnv knows that the first three + // strings returned are "gcc", "-I", incdir (and cuts them off). + a := []string{compiler[0], "-I", incdir} + a = append(a, compiler[1:]...) + + // Definitely want -fPIC but on Windows gcc complains + // "-fPIC ignored for target (all code is position independent)" + if cfg.Goos != "windows" { + a = append(a, "-fPIC") + } + a = append(a, b.gccArchArgs()...) + // gcc-4.5 and beyond require explicit "-pthread" flag + // for multithreading with pthread library. + if cfg.BuildContext.CgoEnabled { + switch cfg.Goos { + case "windows": + a = append(a, "-mthreads") + default: + a = append(a, "-pthread") + } + } + + // disable ASCII art in clang errors, if possible + if b.gccSupportsFlag(compiler, "-fno-caret-diagnostics") { + a = append(a, "-fno-caret-diagnostics") + } + // clang is too smart about command-line arguments + if b.gccSupportsFlag(compiler, "-Qunused-arguments") { + a = append(a, "-Qunused-arguments") + } + + // disable word wrapping in error messages + a = append(a, "-fmessage-length=0") + + // Tell gcc not to include the work directory in object files. + if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") { + if workdir == "" { + workdir = b.WorkDir + } + workdir = strings.TrimSuffix(workdir, string(filepath.Separator)) + a = append(a, "-fdebug-prefix-map="+workdir+"=/tmp/go-build") + } + + // Tell gcc not to include flags in object files, which defeats the + // point of -fdebug-prefix-map above. + if b.gccSupportsFlag(compiler, "-gno-record-gcc-switches") { + a = append(a, "-gno-record-gcc-switches") + } + + // On OS X, some of the compilers behave as if -fno-common + // is always set, and the Mach-O linker in 6l/8l assumes this. + // See https://golang.org/issue/3253. + if cfg.Goos == "darwin" { + a = append(a, "-fno-common") + } + + return a +} + +// gccNoPie returns the flag to use to request non-PIE. On systems +// with PIE (position independent executables) enabled by default, +// -no-pie must be passed when doing a partial link with -Wl,-r. +// But -no-pie is not supported by all compilers, and clang spells it -nopie. +func (b *Builder) gccNoPie(linker []string) string { + if b.gccSupportsFlag(linker, "-no-pie") { + return "-no-pie" + } + if b.gccSupportsFlag(linker, "-nopie") { + return "-nopie" + } + return "" +} + +// gccSupportsFlag checks to see if the compiler supports a flag. +func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool { + key := [2]string{compiler[0], flag} + + b.exec.Lock() + defer b.exec.Unlock() + if b, ok := b.flagCache[key]; ok { + return b + } + if b.flagCache == nil { + b.flagCache = make(map[[2]string]bool) + } + // We used to write an empty C file, but that gets complicated with + // go build -n. We tried using a file that does not exist, but that + // fails on systems with GCC version 4.2.1; that is the last GPLv2 + // version of GCC, so some systems have frozen on it. + // Now we pass an empty file on stdin, which should work at least for + // GCC and clang. + cmdArgs := str.StringList(compiler, flag, "-c", "-x", "c", "-") + if cfg.BuildN || cfg.BuildX { + b.Showcmd(b.WorkDir, "%s || true", joinUnambiguously(cmdArgs)) + if cfg.BuildN { + return false + } + } + cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) + cmd.Dir = b.WorkDir + cmd.Env = base.MergeEnvLists([]string{"LC_ALL=C"}, base.EnvForDir(cmd.Dir, os.Environ())) + out, _ := cmd.CombinedOutput() + // GCC says "unrecognized command line option". + // clang says "unknown argument". + // Older versions of GCC say "unrecognised debug output level". + // For -fsplit-stack GCC says "'-fsplit-stack' is not supported". + supported := !bytes.Contains(out, []byte("unrecognized")) && + !bytes.Contains(out, []byte("unknown")) && + !bytes.Contains(out, []byte("unrecognised")) && + !bytes.Contains(out, []byte("is not supported")) + b.flagCache[key] = supported + return supported +} + +// gccArchArgs returns arguments to pass to gcc based on the architecture. +func (b *Builder) gccArchArgs() []string { + switch cfg.Goarch { + case "386": + return []string{"-m32"} + case "amd64", "amd64p32": + return []string{"-m64"} + case "arm": + return []string{"-marm"} // not thumb + case "s390x": + return []string{"-m64", "-march=z196"} + case "mips64", "mips64le": + return []string{"-mabi=64"} + case "mips", "mipsle": + return []string{"-mabi=32", "-march=mips32"} + } + return nil +} + +// envList returns the value of the given environment variable broken +// into fields, using the default value when the variable is empty. +func envList(key, def string) []string { + v := os.Getenv(key) + if v == "" { + v = def + } + return strings.Fields(v) +} + +// CFlags returns the flags to use when invoking the C, C++ or Fortran compilers, or cgo. +func (b *Builder) CFlags(p *load.Package) (cppflags, cflags, cxxflags, fflags, ldflags []string, err error) { + defaults := "-g -O2" + + if cppflags, err = buildFlags("CPPFLAGS", "", p.CgoCPPFLAGS, checkCompilerFlags); err != nil { + return + } + if cflags, err = buildFlags("CFLAGS", defaults, p.CgoCFLAGS, checkCompilerFlags); err != nil { + return + } + if cxxflags, err = buildFlags("CXXFLAGS", defaults, p.CgoCXXFLAGS, checkCompilerFlags); err != nil { + return + } + if fflags, err = buildFlags("FFLAGS", defaults, p.CgoFFLAGS, checkCompilerFlags); err != nil { + return + } + if ldflags, err = buildFlags("LDFLAGS", defaults, p.CgoLDFLAGS, checkLinkerFlags); err != nil { + return + } + + return +} + +func buildFlags(name, defaults string, fromPackage []string, check func(string, string, []string) error) ([]string, error) { + if err := check(name, "#cgo "+name, fromPackage); err != nil { + return nil, err + } + return str.StringList(envList("CGO_"+name, defaults), fromPackage), nil +} + +var cgoRe = regexp.MustCompile(`[/\\:]`) + +func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, gxxfiles, mfiles, ffiles []string) (outGo, outObj []string, err error) { + p := a.Package + cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS, cgoLDFLAGS, err := b.CFlags(p) + if err != nil { + return nil, nil, err + } + + cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...) + cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...) + // If we are compiling Objective-C code, then we need to link against libobjc + if len(mfiles) > 0 { + cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc") + } + + // Likewise for Fortran, except there are many Fortran compilers. + // Support gfortran out of the box and let others pass the correct link options + // via CGO_LDFLAGS + if len(ffiles) > 0 { + fc := os.Getenv("FC") + if fc == "" { + fc = "gfortran" + } + if strings.Contains(fc, "gfortran") { + cgoLDFLAGS = append(cgoLDFLAGS, "-lgfortran") + } + } + + if cfg.BuildMSan { + cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...) + cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...) + } + + // Allows including _cgo_export.h from .[ch] files in the package. + cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", objdir) + + // cgo + // TODO: CGO_FLAGS? + gofiles := []string{objdir + "_cgo_gotypes.go"} + cfiles := []string{"_cgo_export.c"} + for _, fn := range cgofiles { + f := strings.TrimSuffix(filepath.Base(fn), ".go") + gofiles = append(gofiles, objdir+f+".cgo1.go") + cfiles = append(cfiles, f+".cgo2.c") + } + + // TODO: make cgo not depend on $GOARCH? + + cgoflags := []string{} + if p.Standard && p.ImportPath == "runtime/cgo" { + cgoflags = append(cgoflags, "-import_runtime_cgo=false") + } + if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/msan" || p.ImportPath == "runtime/cgo") { + cgoflags = append(cgoflags, "-import_syscall=false") + } + + // Update $CGO_LDFLAGS with p.CgoLDFLAGS. + // These flags are recorded in the generated _cgo_gotypes.go file + // using //go:cgo_ldflag directives, the compiler records them in the + // object file for the package, and then the Go linker passes them + // along to the host linker. At this point in the code, cgoLDFLAGS + // consists of the original $CGO_LDFLAGS (unchecked) and all the + // flags put together from source code (checked). + var cgoenv []string + if len(cgoLDFLAGS) > 0 { + flags := make([]string, len(cgoLDFLAGS)) + for i, f := range cgoLDFLAGS { + flags[i] = strconv.Quote(f) + } + cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")} + } + + if cfg.BuildToolchainName == "gccgo" { + switch cfg.Goarch { + case "386", "amd64": + cgoCFLAGS = append(cgoCFLAGS, "-fsplit-stack") + } + cgoflags = append(cgoflags, "-gccgo") + if pkgpath := gccgoPkgpath(p); pkgpath != "" { + cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath) + } + } + + switch cfg.BuildBuildmode { + case "c-archive", "c-shared": + // Tell cgo that if there are any exported functions + // it should generate a header file that C code can + // #include. + cgoflags = append(cgoflags, "-exportheader="+objdir+"_cgo_install.h") + } + + if err := b.run(a, p.Dir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil { + return nil, nil, err + } + outGo = append(outGo, gofiles...) + + // Use sequential object file names to keep them distinct + // and short enough to fit in the .a header file name slots. + // We no longer collect them all into _all.o, and we'd like + // tools to see both the .o suffix and unique names, so + // we need to make them short enough not to be truncated + // in the final archive. + oseq := 0 + nextOfile := func() string { + oseq++ + return objdir + fmt.Sprintf("_x%03d.o", oseq) + } + + // gcc + cflags := str.StringList(cgoCPPFLAGS, cgoCFLAGS) + for _, cfile := range cfiles { + ofile := nextOfile() + if err := b.gcc(a, p, a.Objdir, ofile, cflags, objdir+cfile); err != nil { + return nil, nil, err + } + outObj = append(outObj, ofile) + } + + for _, file := range gccfiles { + ofile := nextOfile() + if err := b.gcc(a, p, a.Objdir, ofile, cflags, file); err != nil { + return nil, nil, err + } + outObj = append(outObj, ofile) + } + + cxxflags := str.StringList(cgoCPPFLAGS, cgoCXXFLAGS) + for _, file := range gxxfiles { + ofile := nextOfile() + if err := b.gxx(a, p, a.Objdir, ofile, cxxflags, file); err != nil { + return nil, nil, err + } + outObj = append(outObj, ofile) + } + + for _, file := range mfiles { + ofile := nextOfile() + if err := b.gcc(a, p, a.Objdir, ofile, cflags, file); err != nil { + return nil, nil, err + } + outObj = append(outObj, ofile) + } + + fflags := str.StringList(cgoCPPFLAGS, cgoFFLAGS) + for _, file := range ffiles { + ofile := nextOfile() + if err := b.gfortran(a, p, a.Objdir, ofile, fflags, file); err != nil { + return nil, nil, err + } + outObj = append(outObj, ofile) + } + + switch cfg.BuildToolchainName { + case "gc": + importGo := objdir + "_cgo_import.go" + if err := b.dynimport(a, p, objdir, importGo, cgoExe, cflags, cgoLDFLAGS, outObj); err != nil { + return nil, nil, err + } + outGo = append(outGo, importGo) + + case "gccgo": + defunC := objdir + "_cgo_defun.c" + defunObj := objdir + "_cgo_defun.o" + if err := BuildToolchain.cc(b, a, defunObj, defunC); err != nil { + return nil, nil, err + } + outObj = append(outObj, defunObj) + + default: + noCompiler() + } + + return outGo, outObj, nil +} + +// dynimport creates a Go source file named importGo containing +// //go:cgo_import_dynamic directives for each symbol or library +// dynamically imported by the object files outObj. +func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) error { + cfile := objdir + "_cgo_main.c" + ofile := objdir + "_cgo_main.o" + if err := b.gcc(a, p, objdir, ofile, cflags, cfile); err != nil { + return err + } + + linkobj := str.StringList(ofile, outObj, p.SysoFiles) + dynobj := objdir + "_cgo_.o" + + // we need to use -pie for Linux/ARM to get accurate imported sym + ldflags := cgoLDFLAGS + if (cfg.Goarch == "arm" && cfg.Goos == "linux") || cfg.Goos == "android" { + ldflags = append(ldflags, "-pie") + } + if err := b.gccld(p, objdir, dynobj, ldflags, linkobj); err != nil { + return err + } + + // cgo -dynimport + var cgoflags []string + if p.Standard && p.ImportPath == "runtime/cgo" { + cgoflags = []string{"-dynlinker"} // record path to dynamic linker + } + return b.run(a, p.Dir, p.ImportPath, nil, cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) +} + +// Run SWIG on all SWIG input files. +// TODO: Don't build a shared library, once SWIG emits the necessary +// pragmas for external linking. +func (b *Builder) swig(a *Action, p *load.Package, objdir string, pcCFLAGS []string) (outGo, outC, outCXX []string, err error) { + if err := b.swigVersionCheck(); err != nil { + return nil, nil, nil, err + } + + intgosize, err := b.swigIntSize(objdir) + if err != nil { + return nil, nil, nil, err + } + + for _, f := range p.SwigFiles { + goFile, cFile, err := b.swigOne(a, p, f, objdir, pcCFLAGS, false, intgosize) + if err != nil { + return nil, nil, nil, err + } + if goFile != "" { + outGo = append(outGo, goFile) + } + if cFile != "" { + outC = append(outC, cFile) + } + } + for _, f := range p.SwigCXXFiles { + goFile, cxxFile, err := b.swigOne(a, p, f, objdir, pcCFLAGS, true, intgosize) + if err != nil { + return nil, nil, nil, err + } + if goFile != "" { + outGo = append(outGo, goFile) + } + if cxxFile != "" { + outCXX = append(outCXX, cxxFile) + } + } + return outGo, outC, outCXX, nil +} + +// Make sure SWIG is new enough. +var ( + swigCheckOnce sync.Once + swigCheck error +) + +func (b *Builder) swigDoVersionCheck() error { + out, err := b.runOut("", "", nil, "swig", "-version") + if err != nil { + return err + } + re := regexp.MustCompile(`[vV]ersion +([\d]+)([.][\d]+)?([.][\d]+)?`) + matches := re.FindSubmatch(out) + if matches == nil { + // Can't find version number; hope for the best. + return nil + } + + major, err := strconv.Atoi(string(matches[1])) + if err != nil { + // Can't find version number; hope for the best. + return nil + } + const errmsg = "must have SWIG version >= 3.0.6" + if major < 3 { + return errors.New(errmsg) + } + if major > 3 { + // 4.0 or later + return nil + } + + // We have SWIG version 3.x. + if len(matches[2]) > 0 { + minor, err := strconv.Atoi(string(matches[2][1:])) + if err != nil { + return nil + } + if minor > 0 { + // 3.1 or later + return nil + } + } + + // We have SWIG version 3.0.x. + if len(matches[3]) > 0 { + patch, err := strconv.Atoi(string(matches[3][1:])) + if err != nil { + return nil + } + if patch < 6 { + // Before 3.0.6. + return errors.New(errmsg) + } + } + + return nil +} + +func (b *Builder) swigVersionCheck() error { + swigCheckOnce.Do(func() { + swigCheck = b.swigDoVersionCheck() + }) + return swigCheck +} + +// Find the value to pass for the -intgosize option to swig. +var ( + swigIntSizeOnce sync.Once + swigIntSize string + swigIntSizeError error +) + +// This code fails to build if sizeof(int) <= 32 +const swigIntSizeCode = ` +package main +const i int = 1 << 32 +` + +// Determine the size of int on the target system for the -intgosize option +// of swig >= 2.0.9. Run only once. +func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) { + if cfg.BuildN { + return "$INTBITS", nil + } + src := filepath.Join(b.WorkDir, "swig_intsize.go") + if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0666); err != nil { + return + } + srcs := []string{src} + + p := load.GoFilesPackage(srcs) + + if _, _, e := BuildToolchain.gc(b, &Action{Mode: "swigDoIntSize", Package: p, Objdir: objdir}, "", nil, false, srcs); e != nil { + return "32", nil + } + return "64", nil +} + +// Determine the size of int on the target system for the -intgosize option +// of swig >= 2.0.9. +func (b *Builder) swigIntSize(objdir string) (intsize string, err error) { + swigIntSizeOnce.Do(func() { + swigIntSize, swigIntSizeError = b.swigDoIntSize(objdir) + }) + return swigIntSize, swigIntSizeError +} + +// Run SWIG on one SWIG input file. +func (b *Builder) swigOne(a *Action, p *load.Package, file, objdir string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outC string, err error) { + cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _, err := b.CFlags(p) + if err != nil { + return "", "", err + } + + var cflags []string + if cxx { + cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS) + } else { + cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS) + } + + n := 5 // length of ".swig" + if cxx { + n = 8 // length of ".swigcxx" + } + base := file[:len(file)-n] + goFile := base + ".go" + gccBase := base + "_wrap." + gccExt := "c" + if cxx { + gccExt = "cxx" + } + + gccgo := cfg.BuildToolchainName == "gccgo" + + // swig + args := []string{ + "-go", + "-cgo", + "-intgosize", intgosize, + "-module", base, + "-o", objdir + gccBase + gccExt, + "-outdir", objdir, + } + + for _, f := range cflags { + if len(f) > 3 && f[:2] == "-I" { + args = append(args, f) + } + } + + if gccgo { + args = append(args, "-gccgo") + if pkgpath := gccgoPkgpath(p); pkgpath != "" { + args = append(args, "-go-pkgpath", pkgpath) + } + } + if cxx { + args = append(args, "-c++") + } + + out, err := b.runOut(p.Dir, p.ImportPath, nil, "swig", args, file) + if err != nil { + if len(out) > 0 { + if bytes.Contains(out, []byte("-intgosize")) || bytes.Contains(out, []byte("-cgo")) { + return "", "", errors.New("must have SWIG version >= 3.0.6") + } + b.showOutput(a, p.Dir, p.ImportPath, b.processOutput(out)) // swig error + return "", "", errPrintedOutput + } + return "", "", err + } + if len(out) > 0 { + b.showOutput(a, p.Dir, p.ImportPath, b.processOutput(out)) // swig warning + } + + // If the input was x.swig, the output is x.go in the objdir. + // But there might be an x.go in the original dir too, and if it + // uses cgo as well, cgo will be processing both and will + // translate both into x.cgo1.go in the objdir, overwriting one. + // Rename x.go to _x_swig.go to avoid this problem. + // We ignore files in the original dir that begin with underscore + // so _x_swig.go cannot conflict with an original file we were + // going to compile. + goFile = objdir + goFile + newGoFile := objdir + "_" + base + "_swig.go" + if err := os.Rename(goFile, newGoFile); err != nil { + return "", "", err + } + return newGoFile, objdir + gccBase + gccExt, nil +} + +// disableBuildID adjusts a linker command line to avoid creating a +// build ID when creating an object file rather than an executable or +// shared library. Some systems, such as Ubuntu, always add +// --build-id to every link, but we don't want a build ID when we are +// producing an object file. On some of those system a plain -r (not +// -Wl,-r) will turn off --build-id, but clang 3.0 doesn't support a +// plain -r. I don't know how to turn off --build-id when using clang +// other than passing a trailing --build-id=none. So that is what we +// do, but only on systems likely to support it, which is to say, +// systems that normally use gold or the GNU linker. +func (b *Builder) disableBuildID(ldflags []string) []string { + switch cfg.Goos { + case "android", "dragonfly", "linux", "netbsd": + ldflags = append(ldflags, "-Wl,--build-id=none") + } + return ldflags +} + +// mkAbsFiles converts files into a list of absolute files, +// assuming they were originally relative to dir, +// and returns that new list. +func mkAbsFiles(dir string, files []string) []string { + abs := make([]string, len(files)) + for i, f := range files { + if !filepath.IsAbs(f) { + f = filepath.Join(dir, f) + } + abs[i] = f + } + return abs +}
diff --git a/vendor/cmd/go/internal/work/gc.go b/vendor/cmd/go/internal/work/gc.go new file mode 100644 index 0000000..9faa25a --- /dev/null +++ b/vendor/cmd/go/internal/work/gc.go
@@ -0,0 +1,489 @@ +// Copyright 2011 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 work + +import ( + "bufio" + "bytes" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "path/filepath" + "runtime" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/go/internal/str" + "crypto/sha1" +) + +// The Go toolchain. + +type gcToolchain struct{} + +func (gcToolchain) compiler() string { + return base.Tool("compile") +} + +func (gcToolchain) linker() string { + return base.Tool("link") +} + +func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) { + p := a.Package + objdir := a.Objdir + if archive != "" { + ofile = archive + } else { + out := "_go_.o" + ofile = objdir + out + } + + pkgpath := p.ImportPath + if cfg.BuildBuildmode == "plugin" { + pkgpath = pluginPath(a) + } else if p.Name == "main" && !p.Internal.ForceLibrary { + pkgpath = "main" + } + gcargs := []string{"-p", pkgpath} + if p.Standard { + gcargs = append(gcargs, "-std") + } + compilingRuntime := p.Standard && (p.ImportPath == "runtime" || strings.HasPrefix(p.ImportPath, "runtime/internal")) + if compilingRuntime { + // runtime compiles with a special gc flag to emit + // additional reflect type data. + gcargs = append(gcargs, "-+") + } + + // If we're giving the compiler the entire package (no C etc files), tell it that, + // so that it can give good error messages about forward declarations. + // Exceptions: a few standard packages have forward declarations for + // pieces supplied behind-the-scenes by package runtime. + extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.MFiles) + len(p.FFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles) + if p.Standard { + switch p.ImportPath { + case "bytes", "internal/poll", "net", "os", "runtime/pprof", "runtime/trace", "sync", "syscall", "time": + extFiles++ + } + } + if extFiles == 0 { + gcargs = append(gcargs, "-complete") + } + if cfg.BuildContext.InstallSuffix != "" { + gcargs = append(gcargs, "-installsuffix", cfg.BuildContext.InstallSuffix) + } + if a.buildID != "" { + gcargs = append(gcargs, "-buildid", a.buildID) + } + platform := cfg.Goos + "/" + cfg.Goarch + if p.Internal.OmitDebug || platform == "nacl/amd64p32" || platform == "darwin/arm" || platform == "darwin/arm64" || cfg.Goos == "plan9" { + gcargs = append(gcargs, "-dwarf=false") + } + if strings.HasPrefix(runtimeVersion, "go1") && !strings.Contains(os.Args[0], "go_bootstrap") { + gcargs = append(gcargs, "-goversion", runtimeVersion) + } + + gcflags := str.StringList(forcedGcflags, p.Internal.Gcflags) + if compilingRuntime { + // Remove -N, if present. + // It is not possible to build the runtime with no optimizations, + // because the compiler cannot eliminate enough write barriers. + for i := 0; i < len(gcflags); i++ { + if gcflags[i] == "-N" { + copy(gcflags[i:], gcflags[i+1:]) + gcflags = gcflags[:len(gcflags)-1] + i-- + } + } + } + + args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", trimDir(a.Objdir), gcflags, gcargs, "-D", p.Internal.LocalPrefix} + if importcfg != nil { + if err := b.writeFile(objdir+"importcfg", importcfg); err != nil { + return "", nil, err + } + args = append(args, "-importcfg", objdir+"importcfg") + } + if ofile == archive { + args = append(args, "-pack") + } + if asmhdr { + args = append(args, "-asmhdr", objdir+"go_asm.h") + } + + // Add -c=N to use concurrent backend compilation, if possible. + if c := gcBackendConcurrency(gcflags); c > 1 { + args = append(args, fmt.Sprintf("-c=%d", c)) + } + + for _, f := range gofiles { + args = append(args, mkAbs(p.Dir, f)) + } + + output, err = b.runOut(p.Dir, p.ImportPath, nil, args...) + return ofile, output, err +} + +// gcBackendConcurrency returns the backend compiler concurrency level for a package compilation. +func gcBackendConcurrency(gcflags []string) int { + // First, check whether we can use -c at all for this compilation. + canDashC := concurrentGCBackendCompilationEnabledByDefault + + switch e := os.Getenv("GO19CONCURRENTCOMPILATION"); e { + case "0": + canDashC = false + case "1": + canDashC = true + case "": + // Not set. Use default. + default: + log.Fatalf("GO19CONCURRENTCOMPILATION must be 0, 1, or unset, got %q", e) + } + +CheckFlags: + for _, flag := range gcflags { + // Concurrent compilation is presumed incompatible with any gcflags, + // except for a small whitelist of commonly used flags. + // If the user knows better, they can manually add their own -c to the gcflags. + switch flag { + case "-N", "-l", "-S", "-B", "-C", "-I": + // OK + default: + canDashC = false + break CheckFlags + } + } + + if !canDashC { + return 1 + } + + // Decide how many concurrent backend compilations to allow. + // + // If we allow too many, in theory we might end up with p concurrent processes, + // each with c concurrent backend compiles, all fighting over the same resources. + // However, in practice, that seems not to happen too much. + // Most build graphs are surprisingly serial, so p==1 for much of the build. + // Furthermore, concurrent backend compilation is only enabled for a part + // of the overall compiler execution, so c==1 for much of the build. + // So don't worry too much about that interaction for now. + // + // However, in practice, setting c above 4 tends not to help very much. + // See the analysis in CL 41192. + // + // TODO(josharian): attempt to detect whether this particular compilation + // is likely to be a bottleneck, e.g. when: + // - it has no successor packages to compile (usually package main) + // - all paths through the build graph pass through it + // - critical path scheduling says it is high priority + // and in such a case, set c to runtime.NumCPU. + // We do this now when p==1. + if cfg.BuildP == 1 { + // No process parallelism. Max out c. + return runtime.NumCPU() + } + // Some process parallelism. Set c to min(4, numcpu). + c := 4 + if ncpu := runtime.NumCPU(); ncpu < c { + c = ncpu + } + return c +} + +func trimDir(dir string) string { + if len(dir) > 1 && dir[len(dir)-1] == filepath.Separator { + dir = dir[:len(dir)-1] + } + return dir +} + +func (gcToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error) { + p := a.Package + // Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files. + inc := filepath.Join(cfg.GOROOT, "pkg", "include") + args := []interface{}{cfg.BuildToolexec, base.Tool("asm"), "-trimpath", trimDir(a.Objdir), "-I", a.Objdir, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, forcedAsmflags, p.Internal.Asmflags} + if p.ImportPath == "runtime" && cfg.Goarch == "386" { + for _, arg := range forcedAsmflags { + if arg == "-dynlink" { + args = append(args, "-D=GOBUILDMODE_shared=1") + } + } + } + + if cfg.Goarch == "mips" || cfg.Goarch == "mipsle" { + // Define GOMIPS_value from cfg.GOMIPS. + args = append(args, "-D", "GOMIPS_"+cfg.GOMIPS) + } + + var ofiles []string + for _, sfile := range sfiles { + ofile := a.Objdir + sfile[:len(sfile)-len(".s")] + ".o" + ofiles = append(ofiles, ofile) + args1 := append(args, "-o", ofile, mkAbs(p.Dir, sfile)) + if err := b.run(a, p.Dir, p.ImportPath, nil, args1...); err != nil { + return nil, err + } + } + return ofiles, nil +} + +// toolVerify checks that the command line args writes the same output file +// if run using newTool instead. +// Unused now but kept around for future use. +func toolVerify(a *Action, b *Builder, p *load.Package, newTool string, ofile string, args []interface{}) error { + newArgs := make([]interface{}, len(args)) + copy(newArgs, args) + newArgs[1] = base.Tool(newTool) + newArgs[3] = ofile + ".new" // x.6 becomes x.6.new + if err := b.run(a, p.Dir, p.ImportPath, nil, newArgs...); err != nil { + return err + } + data1, err := ioutil.ReadFile(ofile) + if err != nil { + return err + } + data2, err := ioutil.ReadFile(ofile + ".new") + if err != nil { + return err + } + if !bytes.Equal(data1, data2) { + return fmt.Errorf("%s and %s produced different output files:\n%s\n%s", filepath.Base(args[1].(string)), newTool, strings.Join(str.StringList(args...), " "), strings.Join(str.StringList(newArgs...), " ")) + } + os.Remove(ofile + ".new") + return nil +} + +func (gcToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) error { + var absOfiles []string + for _, f := range ofiles { + absOfiles = append(absOfiles, mkAbs(a.Objdir, f)) + } + absAfile := mkAbs(a.Objdir, afile) + + // The archive file should have been created by the compiler. + // Since it used to not work that way, verify. + if !cfg.BuildN { + if _, err := os.Stat(absAfile); err != nil { + base.Fatalf("os.Stat of archive file failed: %v", err) + } + } + + p := a.Package + if cfg.BuildN || cfg.BuildX { + cmdline := str.StringList(base.Tool("pack"), "r", absAfile, absOfiles) + b.Showcmd(p.Dir, "%s # internal", joinUnambiguously(cmdline)) + } + if cfg.BuildN { + return nil + } + if err := packInternal(b, absAfile, absOfiles); err != nil { + b.showOutput(a, p.Dir, p.ImportPath, err.Error()+"\n") + return errPrintedOutput + } + return nil +} + +func packInternal(b *Builder, afile string, ofiles []string) error { + dst, err := os.OpenFile(afile, os.O_WRONLY|os.O_APPEND, 0) + if err != nil { + return err + } + defer dst.Close() // only for error returns or panics + w := bufio.NewWriter(dst) + + for _, ofile := range ofiles { + src, err := os.Open(ofile) + if err != nil { + return err + } + fi, err := src.Stat() + if err != nil { + src.Close() + return err + } + // Note: Not using %-16.16s format because we care + // about bytes, not runes. + name := fi.Name() + if len(name) > 16 { + name = name[:16] + } else { + name += strings.Repeat(" ", 16-len(name)) + } + size := fi.Size() + fmt.Fprintf(w, "%s%-12d%-6d%-6d%-8o%-10d`\n", + name, 0, 0, 0, 0644, size) + n, err := io.Copy(w, src) + src.Close() + if err == nil && n < size { + err = io.ErrUnexpectedEOF + } else if err == nil && n > size { + err = fmt.Errorf("file larger than size reported by stat") + } + if err != nil { + return fmt.Errorf("copying %s to %s: %v", ofile, afile, err) + } + if size&1 != 0 { + w.WriteByte(0) + } + } + + if err := w.Flush(); err != nil { + return err + } + return dst.Close() +} + +// setextld sets the appropriate linker flags for the specified compiler. +func setextld(ldflags []string, compiler []string) []string { + for _, f := range ldflags { + if f == "-extld" || strings.HasPrefix(f, "-extld=") { + // don't override -extld if supplied + return ldflags + } + } + ldflags = append(ldflags, "-extld="+compiler[0]) + if len(compiler) > 1 { + extldflags := false + add := strings.Join(compiler[1:], " ") + for i, f := range ldflags { + if f == "-extldflags" && i+1 < len(ldflags) { + ldflags[i+1] = add + " " + ldflags[i+1] + extldflags = true + break + } else if strings.HasPrefix(f, "-extldflags=") { + ldflags[i] = "-extldflags=" + add + " " + ldflags[i][len("-extldflags="):] + extldflags = true + break + } + } + if !extldflags { + ldflags = append(ldflags, "-extldflags="+add) + } + } + return ldflags +} + +// pluginPath computes the package path for a plugin main package. +// +// This is typically the import path of the main package p, unless the +// plugin is being built directly from source files. In that case we +// combine the package build ID with the contents of the main package +// source files. This allows us to identify two different plugins +// built from two source files with the same name. +func pluginPath(a *Action) string { + p := a.Package + if p.ImportPath != "command-line-arguments" { + return p.ImportPath + } + h := sha1.New() + fmt.Fprintf(h, "build ID: %s\n", a.buildID) + for _, file := range str.StringList(p.GoFiles, p.CgoFiles, p.SFiles) { + data, err := ioutil.ReadFile(filepath.Join(p.Dir, file)) + if err != nil { + base.Fatalf("go: %s", err) + } + h.Write(data) + } + return fmt.Sprintf("plugin/unnamed-%x", h.Sum(nil)) +} + +func (gcToolchain) ld(b *Builder, root *Action, out, importcfg, mainpkg string) error { + cxx := len(root.Package.CXXFiles) > 0 || len(root.Package.SwigCXXFiles) > 0 + for _, a := range root.Deps { + if a.Package != nil && (len(a.Package.CXXFiles) > 0 || len(a.Package.SwigCXXFiles) > 0) { + cxx = true + } + } + var ldflags []string + if cfg.BuildContext.InstallSuffix != "" { + ldflags = append(ldflags, "-installsuffix", cfg.BuildContext.InstallSuffix) + } + if root.Package.Internal.OmitDebug { + ldflags = append(ldflags, "-s", "-w") + } + if cfg.BuildBuildmode == "plugin" { + ldflags = append(ldflags, "-pluginpath", pluginPath(root)) + } + + // Store BuildID inside toolchain binaries as a unique identifier of the + // tool being run, for use by content-based staleness determination. + if root.Package.Goroot && strings.HasPrefix(root.Package.ImportPath, "cmd/") { + ldflags = append(ldflags, "-X=cmd/internal/objabi.buildID="+root.buildID) + } + + // If the user has not specified the -extld option, then specify the + // appropriate linker. In case of C++ code, use the compiler named + // by the CXX environment variable or defaultCXX if CXX is not set. + // Else, use the CC environment variable and defaultCC as fallback. + var compiler []string + if cxx { + compiler = envList("CXX", cfg.DefaultCXX(cfg.Goos, cfg.Goarch)) + } else { + compiler = envList("CC", cfg.DefaultCC(cfg.Goos, cfg.Goarch)) + } + ldflags = append(ldflags, "-buildmode="+ldBuildmode) + if root.buildID != "" { + ldflags = append(ldflags, "-buildid="+root.buildID) + } + ldflags = append(ldflags, forcedLdflags...) + ldflags = append(ldflags, root.Package.Internal.Ldflags...) + ldflags = setextld(ldflags, compiler) + + // On OS X when using external linking to build a shared library, + // the argument passed here to -o ends up recorded in the final + // shared library in the LC_ID_DYLIB load command. + // To avoid putting the temporary output directory name there + // (and making the resulting shared library useless), + // run the link in the output directory so that -o can name + // just the final path element. + // On Windows, DLL file name is recorded in PE file + // export section, so do like on OS X. + dir := "." + if (cfg.Goos == "darwin" || cfg.Goos == "windows") && cfg.BuildBuildmode == "c-shared" { + dir, out = filepath.Split(out) + } + + return b.run(root, dir, root.Package.ImportPath, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, "-importcfg", importcfg, ldflags, mainpkg) +} + +func (gcToolchain) ldShared(b *Builder, root *Action, toplevelactions []*Action, out, importcfg string, allactions []*Action) error { + ldflags := []string{"-installsuffix", cfg.BuildContext.InstallSuffix} + ldflags = append(ldflags, "-buildmode=shared") + ldflags = append(ldflags, forcedLdflags...) + ldflags = append(ldflags, root.Package.Internal.Ldflags...) + cxx := false + for _, a := range allactions { + if a.Package != nil && (len(a.Package.CXXFiles) > 0 || len(a.Package.SwigCXXFiles) > 0) { + cxx = true + } + } + // If the user has not specified the -extld option, then specify the + // appropriate linker. In case of C++ code, use the compiler named + // by the CXX environment variable or defaultCXX if CXX is not set. + // Else, use the CC environment variable and defaultCC as fallback. + var compiler []string + if cxx { + compiler = envList("CXX", cfg.DefaultCXX(cfg.Goos, cfg.Goarch)) + } else { + compiler = envList("CC", cfg.DefaultCC(cfg.Goos, cfg.Goarch)) + } + ldflags = setextld(ldflags, compiler) + for _, d := range toplevelactions { + if !strings.HasSuffix(d.Target, ".a") { // omit unsafe etc and actions for other shared libraries + continue + } + ldflags = append(ldflags, d.Package.ImportPath+"="+d.Target) + } + return b.run(root, ".", out, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, "-importcfg", importcfg, ldflags) +} + +func (gcToolchain) cc(b *Builder, a *Action, ofile, cfile string) error { + return fmt.Errorf("%s: C source files not supported without cgo", mkAbs(a.Package.Dir, cfile)) +}
diff --git a/vendor/cmd/go/internal/work/gccgo.go b/vendor/cmd/go/internal/work/gccgo.go new file mode 100644 index 0000000..2512ffe --- /dev/null +++ b/vendor/cmd/go/internal/work/gccgo.go
@@ -0,0 +1,507 @@ +// Copyright 2011 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 work + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/go/internal/str" +) + +// The Gccgo toolchain. + +type gccgoToolchain struct{} + +var GccgoName, GccgoBin string +var gccgoErr error + +func init() { + GccgoName = os.Getenv("GCCGO") + if GccgoName == "" { + GccgoName = "gccgo" + } + GccgoBin, gccgoErr = exec.LookPath(GccgoName) +} + +func (gccgoToolchain) compiler() string { + checkGccgoBin() + return GccgoBin +} + +func (gccgoToolchain) linker() string { + checkGccgoBin() + return GccgoBin +} + +func checkGccgoBin() { + if gccgoErr == nil { + return + } + fmt.Fprintf(os.Stderr, "cmd/go: gccgo: %s\n", gccgoErr) + os.Exit(2) +} + +func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) { + p := a.Package + objdir := a.Objdir + out := "_go_.o" + ofile = objdir + out + gcargs := []string{"-g"} + gcargs = append(gcargs, b.gccArchArgs()...) + if pkgpath := gccgoPkgpath(p); pkgpath != "" { + gcargs = append(gcargs, "-fgo-pkgpath="+pkgpath) + } + if p.Internal.LocalPrefix != "" { + gcargs = append(gcargs, "-fgo-relative-import-path="+p.Internal.LocalPrefix) + } + + args := str.StringList(tools.compiler(), "-c", gcargs, "-o", ofile, forcedGccgoflags) + if importcfg != nil { + if b.gccSupportsFlag(args[:1], "-fgo-importcfg=/dev/null") { + if err := b.writeFile(objdir+"importcfg", importcfg); err != nil { + return "", nil, err + } + args = append(args, "-fgo-importcfg="+objdir+"importcfg") + } else { + root := objdir + "_importcfgroot_" + if err := buildImportcfgSymlinks(b, root, importcfg); err != nil { + return "", nil, err + } + args = append(args, "-I", root) + } + } + args = append(args, a.Package.Internal.Gccgoflags...) + for _, f := range gofiles { + args = append(args, mkAbs(p.Dir, f)) + } + + output, err = b.runOut(p.Dir, p.ImportPath, nil, args) + return ofile, output, err +} + +// buildImportcfgSymlinks builds in root a tree of symlinks +// implementing the directives from importcfg. +// This serves as a temporary transition mechanism until +// we can depend on gccgo reading an importcfg directly. +// (The Go 1.9 and later gc compilers already do.) +func buildImportcfgSymlinks(b *Builder, root string, importcfg []byte) error { + for lineNum, line := range strings.Split(string(importcfg), "\n") { + lineNum++ // 1-based + line = strings.TrimSpace(line) + if line == "" { + continue + } + if line == "" || strings.HasPrefix(line, "#") { + continue + } + var verb, args string + if i := strings.Index(line, " "); i < 0 { + verb = line + } else { + verb, args = line[:i], strings.TrimSpace(line[i+1:]) + } + var before, after string + if i := strings.Index(args, "="); i >= 0 { + before, after = args[:i], args[i+1:] + } + switch verb { + default: + base.Fatalf("importcfg:%d: unknown directive %q", lineNum, verb) + case "packagefile": + if before == "" || after == "" { + return fmt.Errorf(`importcfg:%d: invalid packagefile: syntax is "packagefile path=filename": %s`, lineNum, line) + } + archive := gccgoArchive(root, before) + if err := b.Mkdir(filepath.Dir(archive)); err != nil { + return err + } + if err := b.Symlink(after, archive); err != nil { + return err + } + case "importmap": + if before == "" || after == "" { + return fmt.Errorf(`importcfg:%d: invalid importmap: syntax is "importmap old=new": %s`, lineNum, line) + } + beforeA := gccgoArchive(root, before) + afterA := gccgoArchive(root, after) + if err := b.Mkdir(filepath.Dir(beforeA)); err != nil { + return err + } + if err := b.Mkdir(filepath.Dir(afterA)); err != nil { + return err + } + if err := b.Symlink(afterA, beforeA); err != nil { + return err + } + case "packageshlib": + return fmt.Errorf("gccgo -importcfg does not support shared libraries") + } + } + return nil +} + +func (tools gccgoToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error) { + p := a.Package + var ofiles []string + for _, sfile := range sfiles { + base := filepath.Base(sfile) + ofile := a.Objdir + base[:len(base)-len(".s")] + ".o" + ofiles = append(ofiles, ofile) + sfile = mkAbs(p.Dir, sfile) + defs := []string{"-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch} + if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { + defs = append(defs, `-D`, `GOPKGPATH=`+pkgpath) + } + defs = tools.maybePIC(defs) + defs = append(defs, b.gccArchArgs()...) + err := b.run(a, p.Dir, p.ImportPath, nil, tools.compiler(), "-xassembler-with-cpp", "-I", a.Objdir, "-c", "-o", ofile, defs, sfile) + if err != nil { + return nil, err + } + } + return ofiles, nil +} + +func gccgoArchive(basedir, imp string) string { + end := filepath.FromSlash(imp + ".a") + afile := filepath.Join(basedir, end) + // add "lib" to the final element + return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile)) +} + +func (gccgoToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) error { + p := a.Package + objdir := a.Objdir + var absOfiles []string + for _, f := range ofiles { + absOfiles = append(absOfiles, mkAbs(objdir, f)) + } + return b.run(a, p.Dir, p.ImportPath, nil, "ar", "rc", mkAbs(objdir, afile), absOfiles) +} + +func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string, allactions []*Action, buildmode, desc string) error { + // gccgo needs explicit linking with all package dependencies, + // and all LDFLAGS from cgo dependencies. + afiles := []string{} + shlibs := []string{} + ldflags := b.gccArchArgs() + cgoldflags := []string{} + usesCgo := false + cxx := false + objc := false + fortran := false + if root.Package != nil { + cxx = len(root.Package.CXXFiles) > 0 || len(root.Package.SwigCXXFiles) > 0 + objc = len(root.Package.MFiles) > 0 + fortran = len(root.Package.FFiles) > 0 + } + + readCgoFlags := func(flagsFile string) error { + flags, err := ioutil.ReadFile(flagsFile) + if err != nil { + return err + } + const ldflagsPrefix = "_CGO_LDFLAGS=" + for _, line := range strings.Split(string(flags), "\n") { + if strings.HasPrefix(line, ldflagsPrefix) { + newFlags := strings.Fields(line[len(ldflagsPrefix):]) + for _, flag := range newFlags { + // Every _cgo_flags file has -g and -O2 in _CGO_LDFLAGS + // but they don't mean anything to the linker so filter + // them out. + if flag != "-g" && !strings.HasPrefix(flag, "-O") { + cgoldflags = append(cgoldflags, flag) + } + } + } + } + return nil + } + + newID := 0 + readAndRemoveCgoFlags := func(archive string) (string, error) { + newID++ + newArchive := root.Objdir + fmt.Sprintf("_pkg%d_.a", newID) + if err := b.copyFile(root, newArchive, archive, 0666, false); err != nil { + return "", err + } + if cfg.BuildN || cfg.BuildX { + b.Showcmd("", "ar d %s _cgo_flags", newArchive) + if cfg.BuildN { + // TODO(rsc): We could do better about showing the right _cgo_flags even in -n mode. + // Either the archive is already built and we can read them out, + // or we're printing commands to build the archive and can + // forward the _cgo_flags directly to this step. + return "", nil + } + } + err := b.run(root, root.Objdir, desc, nil, "ar", "x", newArchive, "_cgo_flags") + if err != nil { + return "", err + } + err = b.run(root, ".", desc, nil, "ar", "d", newArchive, "_cgo_flags") + if err != nil { + return "", err + } + err = readCgoFlags(filepath.Join(root.Objdir, "_cgo_flags")) + if err != nil { + return "", err + } + return newArchive, nil + } + + // If using -linkshared, find the shared library deps. + haveShlib := make(map[string]bool) + targetBase := filepath.Base(root.Target) + if cfg.BuildLinkshared { + for _, a := range root.Deps { + p := a.Package + if p == nil || p.Shlib == "" { + continue + } + + // The .a we are linking into this .so + // will have its Shlib set to this .so. + // Don't start thinking we want to link + // this .so into itself. + base := filepath.Base(p.Shlib) + if base != targetBase { + haveShlib[base] = true + } + } + } + + // Arrange the deps into afiles and shlibs. + addedShlib := make(map[string]bool) + for _, a := range root.Deps { + p := a.Package + if p != nil && p.Shlib != "" && haveShlib[filepath.Base(p.Shlib)] { + // This is a package linked into a shared + // library that we will put into shlibs. + continue + } + + if haveShlib[filepath.Base(a.Target)] { + // This is a shared library we want to link againt. + if !addedShlib[a.Target] { + shlibs = append(shlibs, a.Target) + addedShlib[a.Target] = true + } + continue + } + + if p != nil { + target := a.built + if p.UsesCgo() || p.UsesSwig() { + var err error + target, err = readAndRemoveCgoFlags(target) + if err != nil { + continue + } + } + + afiles = append(afiles, target) + } + } + + for _, a := range allactions { + // Gather CgoLDFLAGS, but not from standard packages. + // The go tool can dig up runtime/cgo from GOROOT and + // think that it should use its CgoLDFLAGS, but gccgo + // doesn't use runtime/cgo. + if a.Package == nil { + continue + } + if !a.Package.Standard { + cgoldflags = append(cgoldflags, a.Package.CgoLDFLAGS...) + } + if len(a.Package.CgoFiles) > 0 { + usesCgo = true + } + if a.Package.UsesSwig() { + usesCgo = true + } + if len(a.Package.CXXFiles) > 0 || len(a.Package.SwigCXXFiles) > 0 { + cxx = true + } + if len(a.Package.MFiles) > 0 { + objc = true + } + if len(a.Package.FFiles) > 0 { + fortran = true + } + } + + ldflags = append(ldflags, "-Wl,--whole-archive") + ldflags = append(ldflags, afiles...) + ldflags = append(ldflags, "-Wl,--no-whole-archive") + + ldflags = append(ldflags, cgoldflags...) + ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...) + if root.Package != nil { + ldflags = append(ldflags, root.Package.CgoLDFLAGS...) + } + + ldflags = str.StringList("-Wl,-(", ldflags, "-Wl,-)") + + if root.buildID != "" { + // On systems that normally use gold or the GNU linker, + // use the --build-id option to write a GNU build ID note. + switch cfg.Goos { + case "android", "dragonfly", "linux", "netbsd": + ldflags = append(ldflags, fmt.Sprintf("-Wl,--build-id=0x%x", root.buildID)) + } + } + + for _, shlib := range shlibs { + ldflags = append( + ldflags, + "-L"+filepath.Dir(shlib), + "-Wl,-rpath="+filepath.Dir(shlib), + "-l"+strings.TrimSuffix( + strings.TrimPrefix(filepath.Base(shlib), "lib"), + ".so")) + } + + var realOut string + switch buildmode { + case "exe": + if usesCgo && cfg.Goos == "linux" { + ldflags = append(ldflags, "-Wl,-E") + } + + case "c-archive": + // Link the Go files into a single .o, and also link + // in -lgolibbegin. + // + // We need to use --whole-archive with -lgolibbegin + // because it doesn't define any symbols that will + // cause the contents to be pulled in; it's just + // initialization code. + // + // The user remains responsible for linking against + // -lgo -lpthread -lm in the final link. We can't use + // -r to pick them up because we can't combine + // split-stack and non-split-stack code in a single -r + // link, and libgo picks up non-split-stack code from + // libffi. + ldflags = append(ldflags, "-Wl,-r", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive") + + if nopie := b.gccNoPie([]string{tools.linker()}); nopie != "" { + ldflags = append(ldflags, nopie) + } + + // We are creating an object file, so we don't want a build ID. + if root.buildID == "" { + ldflags = b.disableBuildID(ldflags) + } + + realOut = out + out = out + ".o" + + case "c-shared": + ldflags = append(ldflags, "-shared", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive", "-lgo", "-lgcc_s", "-lgcc", "-lc", "-lgcc") + case "shared": + ldflags = append(ldflags, "-zdefs", "-shared", "-nostdlib", "-lgo", "-lgcc_s", "-lgcc", "-lc") + + default: + base.Fatalf("-buildmode=%s not supported for gccgo", buildmode) + } + + switch buildmode { + case "exe", "c-shared": + if cxx { + ldflags = append(ldflags, "-lstdc++") + } + if objc { + ldflags = append(ldflags, "-lobjc") + } + if fortran { + fc := os.Getenv("FC") + if fc == "" { + fc = "gfortran" + } + // support gfortran out of the box and let others pass the correct link options + // via CGO_LDFLAGS + if strings.Contains(fc, "gfortran") { + ldflags = append(ldflags, "-lgfortran") + } + } + } + + if err := b.run(root, ".", desc, nil, tools.linker(), "-o", out, ldflags, forcedGccgoflags, root.Package.Internal.Gccgoflags); err != nil { + return err + } + + switch buildmode { + case "c-archive": + if err := b.run(root, ".", desc, nil, "ar", "rc", realOut, out); err != nil { + return err + } + } + return nil +} + +func (tools gccgoToolchain) ld(b *Builder, root *Action, out, importcfg, mainpkg string) error { + return tools.link(b, root, out, importcfg, root.Deps, ldBuildmode, root.Package.ImportPath) +} + +func (tools gccgoToolchain) ldShared(b *Builder, root *Action, toplevelactions []*Action, out, importcfg string, allactions []*Action) error { + return tools.link(b, root, out, importcfg, allactions, "shared", out) +} + +func (tools gccgoToolchain) cc(b *Builder, a *Action, ofile, cfile string) error { + p := a.Package + inc := filepath.Join(cfg.GOROOT, "pkg", "include") + cfile = mkAbs(p.Dir, cfile) + defs := []string{"-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch} + defs = append(defs, b.gccArchArgs()...) + if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { + defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) + } + switch cfg.Goarch { + case "386", "amd64": + defs = append(defs, "-fsplit-stack") + } + defs = tools.maybePIC(defs) + return b.run(a, p.Dir, p.ImportPath, nil, envList("CC", cfg.DefaultCC(cfg.Goos, cfg.Goarch)), "-Wall", "-g", + "-I", a.Objdir, "-I", inc, "-o", ofile, defs, "-c", cfile) +} + +// maybePIC adds -fPIC to the list of arguments if needed. +func (tools gccgoToolchain) maybePIC(args []string) []string { + switch cfg.BuildBuildmode { + case "c-shared", "shared", "plugin": + args = append(args, "-fPIC") + } + return args +} + +func gccgoPkgpath(p *load.Package) string { + if p.Internal.Build.IsCommand() && !p.Internal.ForceLibrary { + return "" + } + return p.ImportPath +} + +func gccgoCleanPkgpath(p *load.Package) string { + clean := func(r rune) rune { + switch { + case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z', + '0' <= r && r <= '9': + return r + } + return '_' + } + return strings.Map(clean, gccgoPkgpath(p)) +}
diff --git a/vendor/cmd/go/internal/work/init.go b/vendor/cmd/go/internal/work/init.go new file mode 100644 index 0000000..7f894f5 --- /dev/null +++ b/vendor/cmd/go/internal/work/init.go
@@ -0,0 +1,217 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Build initialization (after flag parsing). + +package work + +import ( + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "flag" + "fmt" + "os" + "path/filepath" +) + +func BuildInit() { + instrumentInit() + buildModeInit() + + // Make sure -pkgdir is absolute, because we run commands + // in different directories. + if cfg.BuildPkgdir != "" && !filepath.IsAbs(cfg.BuildPkgdir) { + p, err := filepath.Abs(cfg.BuildPkgdir) + if err != nil { + fmt.Fprintf(os.Stderr, "go %s: evaluating -pkgdir: %v\n", flag.Args()[0], err) + os.Exit(2) + } + cfg.BuildPkgdir = p + } +} + +func instrumentInit() { + if !cfg.BuildRace && !cfg.BuildMSan { + return + } + if cfg.BuildRace && cfg.BuildMSan { + fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0]) + os.Exit(2) + } + if cfg.BuildMSan && (cfg.Goos != "linux" || cfg.Goarch != "amd64") { + fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch) + os.Exit(2) + } + if cfg.Goarch != "amd64" || cfg.Goos != "linux" && cfg.Goos != "freebsd" && cfg.Goos != "darwin" && cfg.Goos != "windows" { + fmt.Fprintf(os.Stderr, "go %s: -race and -msan are only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0]) + os.Exit(2) + } + + mode := "race" + if cfg.BuildMSan { + mode = "msan" + } + modeFlag := "-" + mode + + if !cfg.BuildContext.CgoEnabled { + fmt.Fprintf(os.Stderr, "go %s: %s requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0], modeFlag) + os.Exit(2) + } + forcedGcflags = append(forcedGcflags, modeFlag) + forcedLdflags = append(forcedLdflags, modeFlag) + + if cfg.BuildContext.InstallSuffix != "" { + cfg.BuildContext.InstallSuffix += "_" + } + cfg.BuildContext.InstallSuffix += mode + cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, mode) +} + +func buildModeInit() { + gccgo := cfg.BuildToolchainName == "gccgo" + var codegenArg string + platform := cfg.Goos + "/" + cfg.Goarch + switch cfg.BuildBuildmode { + case "archive": + pkgsFilter = pkgsNotMain + case "c-archive": + pkgsFilter = oneMainPkg + switch platform { + case "darwin/arm", "darwin/arm64": + codegenArg = "-shared" + default: + switch cfg.Goos { + case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris": + // Use -shared so that the result is + // suitable for inclusion in a PIE or + // shared library. + codegenArg = "-shared" + } + } + cfg.ExeSuffix = ".a" + ldBuildmode = "c-archive" + case "c-shared": + pkgsFilter = oneMainPkg + if gccgo { + codegenArg = "-fPIC" + } else { + switch platform { + case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/ppc64le", "linux/s390x", + "android/amd64", "android/arm", "android/arm64", "android/386": + codegenArg = "-shared" + case "darwin/amd64", "darwin/386": + case "windows/amd64", "windows/386": + // Do not add usual .exe suffix to the .dll file. + cfg.ExeSuffix = "" + default: + base.Fatalf("-buildmode=c-shared not supported on %s\n", platform) + } + } + ldBuildmode = "c-shared" + case "default": + switch platform { + case "android/arm", "android/arm64", "android/amd64", "android/386": + codegenArg = "-shared" + ldBuildmode = "pie" + case "darwin/arm", "darwin/arm64": + codegenArg = "-shared" + fallthrough + default: + ldBuildmode = "exe" + } + case "exe": + pkgsFilter = pkgsMain + ldBuildmode = "exe" + // Set the pkgsFilter to oneMainPkg if the user passed a specific binary output + // and is using buildmode=exe for a better error message. + // See issue #20017. + if cfg.BuildO != "" { + pkgsFilter = oneMainPkg + } + case "pie": + if cfg.BuildRace { + base.Fatalf("-buildmode=pie not supported when -race is enabled") + } + if gccgo { + base.Fatalf("-buildmode=pie not supported by gccgo") + } else { + switch platform { + case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x", + "android/amd64", "android/arm", "android/arm64", "android/386": + codegenArg = "-shared" + case "darwin/amd64": + codegenArg = "-shared" + default: + base.Fatalf("-buildmode=pie not supported on %s\n", platform) + } + } + ldBuildmode = "pie" + case "shared": + pkgsFilter = pkgsNotMain + if gccgo { + codegenArg = "-fPIC" + } else { + switch platform { + case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x": + default: + base.Fatalf("-buildmode=shared not supported on %s\n", platform) + } + codegenArg = "-dynlink" + } + if cfg.BuildO != "" { + base.Fatalf("-buildmode=shared and -o not supported together") + } + ldBuildmode = "shared" + case "plugin": + pkgsFilter = oneMainPkg + if gccgo { + codegenArg = "-fPIC" + } else { + switch platform { + case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/s390x", "linux/ppc64le", + "android/amd64", "android/arm", "android/arm64", "android/386": + case "darwin/amd64": + // Skip DWARF generation due to #21647 + forcedLdflags = append(forcedLdflags, "-w") + default: + base.Fatalf("-buildmode=plugin not supported on %s\n", platform) + } + codegenArg = "-dynlink" + } + cfg.ExeSuffix = ".so" + ldBuildmode = "plugin" + default: + base.Fatalf("buildmode=%s not supported", cfg.BuildBuildmode) + } + if cfg.BuildLinkshared { + if gccgo { + codegenArg = "-fPIC" + } else { + switch platform { + case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x": + forcedAsmflags = append(forcedAsmflags, "-D=GOBUILDMODE_shared=1") + default: + base.Fatalf("-linkshared not supported on %s\n", platform) + } + codegenArg = "-dynlink" + // TODO(mwhudson): remove -w when that gets fixed in linker. + forcedLdflags = append(forcedLdflags, "-linkshared", "-w") + } + } + if codegenArg != "" { + if gccgo { + forcedGccgoflags = append([]string{codegenArg}, forcedGccgoflags...) + } else { + forcedAsmflags = append([]string{codegenArg}, forcedAsmflags...) + forcedGcflags = append([]string{codegenArg}, forcedGcflags...) + } + // Don't alter InstallSuffix when modifying default codegen args. + if cfg.BuildBuildmode != "default" || cfg.BuildLinkshared { + if cfg.BuildContext.InstallSuffix != "" { + cfg.BuildContext.InstallSuffix += "_" + } + cfg.BuildContext.InstallSuffix += codegenArg[1:] + } + } +}
diff --git a/vendor/cmd/go/internal/work/security.go b/vendor/cmd/go/internal/work/security.go new file mode 100644 index 0000000..54fd6b9 --- /dev/null +++ b/vendor/cmd/go/internal/work/security.go
@@ -0,0 +1,202 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Checking of compiler and linker flags. +// We must avoid flags like -fplugin=, which can allow +// arbitrary code execution during the build. +// Do not make changes here without carefully +// considering the implications. +// (That's why the code is isolated in a file named security.go.) +// +// Note that -Wl,foo means split foo on commas and pass to +// the linker, so that -Wl,-foo,bar means pass -foo bar to +// the linker. Similarly -Wa,foo for the assembler and so on. +// If any of these are permitted, the wildcard portion must +// disallow commas. +// +// Note also that GNU binutils accept any argument @foo +// as meaning "read more flags from the file foo", so we must +// guard against any command-line argument beginning with @, +// even things like "-I @foo". +// We use load.SafeArg (which is even more conservative) +// to reject these. +// +// Even worse, gcc -I@foo (one arg) turns into cc1 -I @foo (two args), +// so although gcc doesn't expand the @foo, cc1 will. +// So out of paranoia, we reject @ at the beginning of every +// flag argument that might be split into its own argument. + +package work + +import ( + "cmd/go/internal/load" + "fmt" + "os" + "regexp" + "strings" +) + +var re = regexp.MustCompile + +var validCompilerFlags = []*regexp.Regexp{ + re(`-D([A-Za-z_].*)`), + re(`-I([^@\-].*)`), + re(`-O`), + re(`-O([^@\-].*)`), + re(`-W`), + re(`-W([^@,]+)`), // -Wall but not -Wa,-foo. + re(`-f(no-)?blocks`), + re(`-f(no-)?common`), + re(`-f(no-)?constant-cfstrings`), + re(`-f(no-)?exceptions`), + re(`-finput-charset=([^@\-].*)`), + re(`-f(no-)?lto`), + re(`-f(no-)?modules`), + re(`-f(no-)?objc-arc`), + re(`-f(no-)?omit-frame-pointer`), + re(`-f(no-)?openmp(-simd)?`), + re(`-f(no-)?permissive`), + re(`-f(no-)?(pic|PIC|pie|PIE)`), + re(`-f(no-)?rtti`), + re(`-f(no-)?split-stack`), + re(`-f(no-)?stack-(.+)`), + re(`-f(no-)?strict-aliasing`), + re(`-fsanitize=(.+)`), + re(`-g([^@\-].*)?`), + re(`-m(arch|cpu|fpu|tune)=([^@\-].*)`), + re(`-m(no-)?avx[0-9a-z.]*`), + re(`-m(no-)?ms-bitfields`), + re(`-m(no-)?stack-(.+)`), + re(`-mmacosx-(.+)`), + re(`-mnop-fun-dllimport`), + re(`-m(no-)?sse[0-9.]*`), + re(`-pedantic(-errors)?`), + re(`-pipe`), + re(`-pthread`), + re(`-?-std=([^@\-].*)`), + re(`-x([^@\-].*)`), +} + +var validCompilerFlagsWithNextArg = []string{ + "-D", + "-I", + "-isystem", + "-framework", + "-x", +} + +var validLinkerFlags = []*regexp.Regexp{ + re(`-F([^@\-].*)`), + re(`-l([^@\-].*)`), + re(`-L([^@\-].*)`), + re(`-f(no-)?(pic|PIC|pie|PIE)`), + re(`-fsanitize=([^@\-].*)`), + re(`-g([^@\-].*)?`), + re(`-m(arch|cpu|fpu|tune)=([^@\-].*)`), + re(`-(pic|PIC|pie|PIE)`), + re(`-pthread`), + re(`-?-static([-a-z0-9+]*)`), + + // Note that any wildcards in -Wl need to exclude comma, + // since -Wl splits its argument at commas and passes + // them all to the linker uninterpreted. Allowing comma + // in a wildcard would allow tunnelling arbitrary additional + // linker arguments through one of these. + re(`-Wl,--(no-)?as-needed`), + re(`-Wl,-Bdynamic`), + re(`-Wl,-Bstatic`), + re(`-Wl,--disable-new-dtags`), + re(`-Wl,--enable-new-dtags`), + re(`-Wl,--end-group`), + re(`-Wl,-framework,[^,@\-][^,]+`), + re(`-Wl,-headerpad_max_install_names`), + re(`-Wl,--no-undefined`), + re(`-Wl,-rpath,([^,@\-][^,]+)`), + re(`-Wl,-search_paths_first`), + re(`-Wl,--start-group`), + re(`-Wl,-?-unresolved-symbols=[^,]+`), + re(`-Wl,--(no-)?warn-([^,]+)`), + + re(`[a-zA-Z0-9_/].*\.(a|o|obj|dll|dylib|so)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o) +} + +var validLinkerFlagsWithNextArg = []string{ + "-F", + "-l", + "-L", + "-framework", + "-Wl,-framework", +} + +func checkCompilerFlags(name, source string, list []string) error { + return checkFlags(name, source, list, validCompilerFlags, validCompilerFlagsWithNextArg) +} + +func checkLinkerFlags(name, source string, list []string) error { + return checkFlags(name, source, list, validLinkerFlags, validLinkerFlagsWithNextArg) +} + +func checkFlags(name, source string, list []string, valid []*regexp.Regexp, validNext []string) error { + // Let users override rules with $CGO_CFLAGS_ALLOW, $CGO_CFLAGS_DISALLOW, etc. + var ( + allow *regexp.Regexp + disallow *regexp.Regexp + ) + if env := os.Getenv("CGO_" + name + "_ALLOW"); env != "" { + r, err := regexp.Compile(env) + if err != nil { + return fmt.Errorf("parsing $CGO_%s_ALLOW: %v", name, err) + } + allow = r + } + if env := os.Getenv("CGO_" + name + "_DISALLOW"); env != "" { + r, err := regexp.Compile(env) + if err != nil { + return fmt.Errorf("parsing $CGO_%s_DISALLOW: %v", name, err) + } + disallow = r + } + +Args: + for i := 0; i < len(list); i++ { + arg := list[i] + if disallow != nil && disallow.FindString(arg) == arg { + goto Bad + } + if allow != nil && allow.FindString(arg) == arg { + continue Args + } + for _, re := range valid { + if re.FindString(arg) == arg { // must be complete match + continue Args + } + } + for _, x := range validNext { + if arg == x { + if i+1 < len(list) && load.SafeArg(list[i+1]) { + i++ + continue Args + } + + // Permit -Wl,-framework -Wl,name. + if i+1 < len(list) && + strings.HasPrefix(arg, "-Wl,") && + strings.HasPrefix(list[i+1], "-Wl,") && + load.SafeArg(list[i+1][4:]) && + !strings.Contains(list[i+1][4:], ",") { + i++ + continue Args + } + + if i+1 < len(list) { + return fmt.Errorf("invalid flag in %s: %s %s (see https://golang.org/s/invalidflag)", source, arg, list[i+1]) + } + return fmt.Errorf("invalid flag in %s: %s without argument (see https://golang.org/s/invalidflag)", source, arg) + } + } + Bad: + return fmt.Errorf("invalid flag in %s: %s", source, arg) + } + return nil +}
diff --git a/vendor/cmd/go/internal/work/security_test.go b/vendor/cmd/go/internal/work/security_test.go new file mode 100644 index 0000000..976501b --- /dev/null +++ b/vendor/cmd/go/internal/work/security_test.go
@@ -0,0 +1,247 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package work + +import ( + "os" + "testing" +) + +var goodCompilerFlags = [][]string{ + {"-DFOO"}, + {"-Dfoo=bar"}, + {"-I/"}, + {"-I/etc/passwd"}, + {"-I."}, + {"-O"}, + {"-O2"}, + {"-Osmall"}, + {"-W"}, + {"-Wall"}, + {"-fobjc-arc"}, + {"-fno-objc-arc"}, + {"-fomit-frame-pointer"}, + {"-fno-omit-frame-pointer"}, + {"-fpic"}, + {"-fno-pic"}, + {"-fPIC"}, + {"-fno-PIC"}, + {"-fpie"}, + {"-fno-pie"}, + {"-fPIE"}, + {"-fno-PIE"}, + {"-fsplit-stack"}, + {"-fno-split-stack"}, + {"-fstack-xxx"}, + {"-fno-stack-xxx"}, + {"-fsanitize=hands"}, + {"-g"}, + {"-ggdb"}, + {"-march=souza"}, + {"-mcpu=123"}, + {"-mfpu=123"}, + {"-mtune=happybirthday"}, + {"-mstack-overflow"}, + {"-mno-stack-overflow"}, + {"-mmacosx-version"}, + {"-mnop-fun-dllimport"}, + {"-pthread"}, + {"-std=c99"}, + {"-xc"}, + {"-D", "FOO"}, + {"-D", "foo=bar"}, + {"-I", "."}, + {"-I", "/etc/passwd"}, + {"-I", "世界"}, + {"-framework", "Chocolate"}, + {"-x", "c"}, +} + +var badCompilerFlags = [][]string{ + {"-D@X"}, + {"-D-X"}, + {"-I@dir"}, + {"-I-dir"}, + {"-O@1"}, + {"-Wa,-foo"}, + {"-W@foo"}, + {"-g@gdb"}, + {"-g-gdb"}, + {"-march=@dawn"}, + {"-march=-dawn"}, + {"-std=@c99"}, + {"-std=-c99"}, + {"-x@c"}, + {"-x-c"}, + {"-D", "@foo"}, + {"-D", "-foo"}, + {"-I", "@foo"}, + {"-I", "-foo"}, + {"-framework", "-Caffeine"}, + {"-framework", "@Home"}, + {"-x", "--c"}, + {"-x", "@obj"}, +} + +func TestCheckCompilerFlags(t *testing.T) { + for _, f := range goodCompilerFlags { + if err := checkCompilerFlags("test", "test", f); err != nil { + t.Errorf("unexpected error for %q: %v", f, err) + } + } + for _, f := range badCompilerFlags { + if err := checkCompilerFlags("test", "test", f); err == nil { + t.Errorf("missing error for %q", f) + } + } +} + +var goodLinkerFlags = [][]string{ + {"-Fbar"}, + {"-lbar"}, + {"-Lbar"}, + {"-fpic"}, + {"-fno-pic"}, + {"-fPIC"}, + {"-fno-PIC"}, + {"-fpie"}, + {"-fno-pie"}, + {"-fPIE"}, + {"-fno-PIE"}, + {"-fsanitize=hands"}, + {"-g"}, + {"-ggdb"}, + {"-march=souza"}, + {"-mcpu=123"}, + {"-mfpu=123"}, + {"-mtune=happybirthday"}, + {"-pic"}, + {"-pthread"}, + {"-Wl,-rpath,foo"}, + {"-Wl,-rpath,$ORIGIN/foo"}, + {"-Wl,--warn-error"}, + {"-Wl,--no-warn-error"}, + {"foo.so"}, + {"_世界.dll"}, + {"libcgosotest.dylib"}, + {"-F", "framework"}, + {"-l", "."}, + {"-l", "/etc/passwd"}, + {"-l", "世界"}, + {"-L", "framework"}, + {"-framework", "Chocolate"}, + {"-Wl,-framework", "-Wl,Chocolate"}, + {"-Wl,-framework,Chocolate"}, + {"-Wl,-unresolved-symbols=ignore-all"}, +} + +var badLinkerFlags = [][]string{ + {"-DFOO"}, + {"-Dfoo=bar"}, + {"-O"}, + {"-O2"}, + {"-Osmall"}, + {"-W"}, + {"-Wall"}, + {"-fobjc-arc"}, + {"-fno-objc-arc"}, + {"-fomit-frame-pointer"}, + {"-fno-omit-frame-pointer"}, + {"-fsplit-stack"}, + {"-fno-split-stack"}, + {"-fstack-xxx"}, + {"-fno-stack-xxx"}, + {"-mstack-overflow"}, + {"-mno-stack-overflow"}, + {"-mmacosx-version"}, + {"-mnop-fun-dllimport"}, + {"-std=c99"}, + {"-xc"}, + {"-D", "FOO"}, + {"-D", "foo=bar"}, + {"-I", "FOO"}, + {"-L", "@foo"}, + {"-L", "-foo"}, + {"-x", "c"}, + {"-D@X"}, + {"-D-X"}, + {"-I@dir"}, + {"-I-dir"}, + {"-O@1"}, + {"-Wa,-foo"}, + {"-W@foo"}, + {"-g@gdb"}, + {"-g-gdb"}, + {"-march=@dawn"}, + {"-march=-dawn"}, + {"-std=@c99"}, + {"-std=-c99"}, + {"-x@c"}, + {"-x-c"}, + {"-D", "@foo"}, + {"-D", "-foo"}, + {"-I", "@foo"}, + {"-I", "-foo"}, + {"-l", "@foo"}, + {"-l", "-foo"}, + {"-framework", "-Caffeine"}, + {"-framework", "@Home"}, + {"-Wl,-framework,-Caffeine"}, + {"-Wl,-framework", "-Wl,@Home"}, + {"-Wl,-framework", "@Home"}, + {"-Wl,-framework,Chocolate,@Home"}, + {"-x", "--c"}, + {"-x", "@obj"}, + {"-Wl,-rpath,@foo"}, +} + +func TestCheckLinkerFlags(t *testing.T) { + for _, f := range goodLinkerFlags { + if err := checkLinkerFlags("test", "test", f); err != nil { + t.Errorf("unexpected error for %q: %v", f, err) + } + } + for _, f := range badLinkerFlags { + if err := checkLinkerFlags("test", "test", f); err == nil { + t.Errorf("missing error for %q", f) + } + } +} + +func TestCheckFlagAllowDisallow(t *testing.T) { + if err := checkCompilerFlags("TEST", "test", []string{"-disallow"}); err == nil { + t.Fatalf("missing error for -disallow") + } + os.Setenv("CGO_TEST_ALLOW", "-disallo") + if err := checkCompilerFlags("TEST", "test", []string{"-disallow"}); err == nil { + t.Fatalf("missing error for -disallow with CGO_TEST_ALLOW=-disallo") + } + os.Setenv("CGO_TEST_ALLOW", "-disallow") + if err := checkCompilerFlags("TEST", "test", []string{"-disallow"}); err != nil { + t.Fatalf("unexpected error for -disallow with CGO_TEST_ALLOW=-disallow: %v", err) + } + os.Unsetenv("CGO_TEST_ALLOW") + + if err := checkCompilerFlags("TEST", "test", []string{"-Wall"}); err != nil { + t.Fatalf("unexpected error for -Wall: %v", err) + } + os.Setenv("CGO_TEST_DISALLOW", "-Wall") + if err := checkCompilerFlags("TEST", "test", []string{"-Wall"}); err == nil { + t.Fatalf("missing error for -Wall with CGO_TEST_DISALLOW=-Wall") + } + os.Setenv("CGO_TEST_ALLOW", "-Wall") // disallow wins + if err := checkCompilerFlags("TEST", "test", []string{"-Wall"}); err == nil { + t.Fatalf("missing error for -Wall with CGO_TEST_DISALLOW=-Wall and CGO_TEST_ALLOW=-Wall") + } + + os.Setenv("CGO_TEST_ALLOW", "-fplugin.*") + os.Setenv("CGO_TEST_DISALLOW", "-fplugin=lint.so") + if err := checkCompilerFlags("TEST", "test", []string{"-fplugin=faster.so"}); err != nil { + t.Fatalf("unexpected error for -fplugin=faster.so: %v", err) + } + if err := checkCompilerFlags("TEST", "test", []string{"-fplugin=lint.so"}); err == nil { + t.Fatalf("missing error for -fplugin=lint.so: %v", err) + } +}
diff --git a/vendor/cmd/go/internal/work/testgo.go b/vendor/cmd/go/internal/work/testgo.go new file mode 100644 index 0000000..3e623c6 --- /dev/null +++ b/vendor/cmd/go/internal/work/testgo.go
@@ -0,0 +1,17 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains extra hooks for testing the go command. + +// +build testgo + +package work + +import "os" + +func init() { + if v := os.Getenv("TESTGO_VERSION"); v != "" { + runtimeVersion = v + } +}
diff --git a/vendor/cmd/go/main.go b/vendor/cmd/go/main.go new file mode 100644 index 0000000..dbe6b78 --- /dev/null +++ b/vendor/cmd/go/main.go
@@ -0,0 +1,162 @@ +// Copyright 2011 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. + +//go:generate ./mkalldocs.sh + +package Main + +import ( + "flag" + "fmt" + "log" + "os" + "path/filepath" + "runtime" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/bug" + "cmd/go/internal/cfg" + "cmd/go/internal/clean" + "cmd/go/internal/doc" + "cmd/go/internal/envcmd" + "cmd/go/internal/fix" + "cmd/go/internal/fmtcmd" + "cmd/go/internal/generate" + "cmd/go/internal/get" + "cmd/go/internal/help" + "cmd/go/internal/list" + "cmd/go/internal/run" + "cmd/go/internal/test" + "cmd/go/internal/tool" + "cmd/go/internal/version" + "cmd/go/internal/vet" + "cmd/go/internal/work" +) + +func init() { + base.Commands = []*base.Command{ + bug.CmdBug, + work.CmdBuild, + clean.CmdClean, + doc.CmdDoc, + envcmd.CmdEnv, + fix.CmdFix, + fmtcmd.CmdFmt, + generate.CmdGenerate, + get.CmdGet, + work.CmdInstall, + list.CmdList, + run.CmdRun, + test.CmdTest, + tool.CmdTool, + version.CmdVersion, + vet.CmdVet, + + help.HelpBuildmode, + help.HelpC, + help.HelpCache, + help.HelpEnvironment, + help.HelpFileType, + help.HelpGopath, + help.HelpImportPath, + help.HelpPackages, + test.HelpTestflag, + test.HelpTestfunc, + } +} + +func Main() { + _ = go11tag + flag.Usage = base.Usage + flag.Parse() + log.SetFlags(0) + + args := flag.Args() + if len(args) < 1 { + base.Usage() + } + + cfg.CmdName = args[0] // for error messages + if args[0] == "help" { + help.Help(args[1:]) + return + } + + // Diagnose common mistake: GOPATH==GOROOT. + // This setting is equivalent to not setting GOPATH at all, + // which is not what most people want when they do it. + if gopath := cfg.BuildContext.GOPATH; filepath.Clean(gopath) == filepath.Clean(runtime.GOROOT()) { + fmt.Fprintf(os.Stderr, "warning: GOPATH set to GOROOT (%s) has no effect\n", gopath) + } else { + for _, p := range filepath.SplitList(gopath) { + // Some GOPATHs have empty directory elements - ignore them. + // See issue 21928 for details. + if p == "" { + continue + } + // Note: using HasPrefix instead of Contains because a ~ can appear + // in the middle of directory elements, such as /tmp/git-1.8.2~rc3 + // or C:\PROGRA~1. Only ~ as a path prefix has meaning to the shell. + if strings.HasPrefix(p, "~") { + fmt.Fprintf(os.Stderr, "go: GOPATH entry cannot start with shell metacharacter '~': %q\n", p) + os.Exit(2) + } + if !filepath.IsAbs(p) { + fmt.Fprintf(os.Stderr, "go: GOPATH entry is relative; must be absolute path: %q.\nFor more details see: 'go help gopath'\n", p) + os.Exit(2) + } + } + } + + if fi, err := os.Stat(cfg.GOROOT); err != nil || !fi.IsDir() { + fmt.Fprintf(os.Stderr, "go: cannot find GOROOT directory: %v\n", cfg.GOROOT) + os.Exit(2) + } + + // Set environment (GOOS, GOARCH, etc) explicitly. + // In theory all the commands we invoke should have + // the same default computation of these as we do, + // but in practice there might be skew + // This makes sure we all agree. + cfg.OrigEnv = os.Environ() + cfg.CmdEnv = envcmd.MkEnv() + for _, env := range cfg.CmdEnv { + if os.Getenv(env.Name) != env.Value { + os.Setenv(env.Name, env.Value) + } + } + + for _, cmd := range base.Commands { + if cmd.Name() == args[0] && cmd.Runnable() { + cmd.Flag.Usage = func() { cmd.Usage() } + if cmd.CustomFlags { + args = args[1:] + } else { + cmd.Flag.Parse(args[1:]) + args = cmd.Flag.Args() + } + cmd.Run(cmd, args) + base.Exit() + return + } + } + + fmt.Fprintf(os.Stderr, "go: unknown subcommand %q\nRun 'go help' for usage.\n", args[0]) + base.SetExitStatus(2) + base.Exit() +} + +func init() { + base.Usage = mainUsage +} + +func mainUsage() { + // special case "go test -h" + if len(os.Args) > 1 && os.Args[1] == "test" { + test.Usage() + } + help.PrintUsage(os.Stderr) + os.Exit(2) +}
diff --git a/vendor/cmd/go/mkalldocs.sh b/vendor/cmd/go/mkalldocs.sh new file mode 100755 index 0000000..bc5009d --- /dev/null +++ b/vendor/cmd/go/mkalldocs.sh
@@ -0,0 +1,11 @@ +#!/bin/bash +# Copyright 2012 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +set -e + +go build -o go.latest +./go.latest help documentation | sed 's/^package main/&_/' >alldocs.go +gofmt -w alldocs.go +rm go.latest
diff --git a/vendor/cmd/go/note_test.go b/vendor/cmd/go/note_test.go new file mode 100644 index 0000000..0c161c4 --- /dev/null +++ b/vendor/cmd/go/note_test.go
@@ -0,0 +1,72 @@ +// Copyright 2015 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 Main_test + +import ( + "go/build" + "runtime" + "testing" + + "cmd/internal/buildid" +) + +func TestNoteReading(t *testing.T) { + // cmd/internal/buildid already has tests that the basic reading works. + // This test is essentially checking that -ldflags=-buildid=XXX works, + // both in internal and external linking mode. + tg := testgo(t) + defer tg.cleanup() + tg.tempFile("hello.go", `package main; func main() { print("hello, world\n") }`) + const buildID = "TestNoteReading-Build-ID" + tg.run("build", "-ldflags", "-buildid="+buildID, "-o", tg.path("hello.exe"), tg.path("hello.go")) + id, err := buildid.ReadFile(tg.path("hello.exe")) + if err != nil { + t.Fatalf("reading build ID from hello binary: %v", err) + } + if id != buildID { + t.Fatalf("buildID in hello binary = %q, want %q", id, buildID) + } + + switch { + case !build.Default.CgoEnabled: + t.Skipf("skipping - no cgo, so assuming external linking not available") + case runtime.GOOS == "openbsd" && runtime.GOARCH == "arm": + t.Skipf("skipping - external linking not supported, golang.org/issue/10619") + case runtime.GOOS == "plan9": + t.Skipf("skipping - external linking not supported") + } + + tg.run("build", "-ldflags", "-buildid="+buildID+" -linkmode=external", "-o", tg.path("hello2.exe"), tg.path("hello.go")) + id, err = buildid.ReadFile(tg.path("hello2.exe")) + if err != nil { + t.Fatalf("reading build ID from hello binary (linkmode=external): %v", err) + } + if id != buildID { + t.Fatalf("buildID in hello binary = %q, want %q (linkmode=external)", id, buildID) + } + + switch runtime.GOOS { + case "dragonfly", "freebsd", "linux", "netbsd", "openbsd": + // Test while forcing use of the gold linker, since in the past + // we've had trouble reading the notes generated by gold. + err := tg.doRun([]string{"build", "-ldflags", "-buildid=" + buildID + " -linkmode=external -extldflags=-fuse-ld=gold", "-o", tg.path("hello3.exe"), tg.path("hello.go")}) + if err != nil { + if tg.grepCountBoth("(invalid linker|gold|cannot find 'ld')") > 0 { + // It's not an error if gold isn't there. gcc claims it "cannot find 'ld'" if + // ld.gold is missing, see issue #22340. + t.Log("skipping gold test") + break + } + t.Fatalf("building hello binary: %v", err) + } + id, err = buildid.ReadFile(tg.path("hello3.exe")) + if err != nil { + t.Fatalf("reading build ID from hello binary (linkmode=external -extldflags=-fuse-ld=gold): %v", err) + } + if id != buildID { + t.Fatalf("buildID in hello binary = %q, want %q (linkmode=external -extldflags=-fuse-ld=gold)", id, buildID) + } + } +}
diff --git a/vendor/cmd/go/testdata/dep_test.go b/vendor/cmd/go/testdata/dep_test.go new file mode 100644 index 0000000..ac39a5b --- /dev/null +++ b/vendor/cmd/go/testdata/dep_test.go
@@ -0,0 +1,7 @@ +// Copyright 2014 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 deps + +import _ "testing"
diff --git a/vendor/cmd/go/testdata/example1_test.go b/vendor/cmd/go/testdata/example1_test.go new file mode 100644 index 0000000..87e6c0a --- /dev/null +++ b/vendor/cmd/go/testdata/example1_test.go
@@ -0,0 +1,23 @@ +// Copyright 2013 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. + +// Make sure that go test runs Example_Z before Example_A, preserving source order. + +package p + +import "fmt" + +var n int + +func Example_Z() { + n++ + fmt.Println(n) + // Output: 1 +} + +func Example_A() { + n++ + fmt.Println(n) + // Output: 2 +}
diff --git a/vendor/cmd/go/testdata/example2_test.go b/vendor/cmd/go/testdata/example2_test.go new file mode 100644 index 0000000..5d13426 --- /dev/null +++ b/vendor/cmd/go/testdata/example2_test.go
@@ -0,0 +1,21 @@ +// Copyright 2013 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. + +// Make sure that go test runs Example_Y before Example_B, preserving source order. + +package p + +import "fmt" + +func Example_Y() { + n++ + fmt.Println(n) + // Output: 3 +} + +func Example_B() { + n++ + fmt.Println(n) + // Output: 4 +}
diff --git a/vendor/cmd/go/testdata/failssh/ssh b/vendor/cmd/go/testdata/failssh/ssh new file mode 100755 index 0000000..ecdbef9 --- /dev/null +++ b/vendor/cmd/go/testdata/failssh/ssh
@@ -0,0 +1,2 @@ +#!/bin/sh +exit 1
diff --git a/vendor/cmd/go/testdata/flag_test.go b/vendor/cmd/go/testdata/flag_test.go new file mode 100644 index 0000000..ddf613d --- /dev/null +++ b/vendor/cmd/go/testdata/flag_test.go
@@ -0,0 +1,16 @@ +package flag_test + +import ( + "flag" + "log" + "testing" +) + +var v = flag.Int("v", 0, "v flag") + +// Run this as go test pkg -v=7 +func TestVFlagIsSet(t *testing.T) { + if *v != 7 { + log.Fatal("v flag not set") + } +}
diff --git a/vendor/cmd/go/testdata/generate/test1.go b/vendor/cmd/go/testdata/generate/test1.go new file mode 100644 index 0000000..168cfb7 --- /dev/null +++ b/vendor/cmd/go/testdata/generate/test1.go
@@ -0,0 +1,13 @@ +// Copyright 2014 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. + +// Simple test for go generate. + +// We include a build tag that go generate should ignore. + +// +build ignore + +//go:generate echo Success + +package p
diff --git a/vendor/cmd/go/testdata/generate/test2.go b/vendor/cmd/go/testdata/generate/test2.go new file mode 100644 index 0000000..829244a --- /dev/null +++ b/vendor/cmd/go/testdata/generate/test2.go
@@ -0,0 +1,10 @@ +// Copyright 2014 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. + +// Test that go generate handles command aliases. + +//go:generate -command run echo Now is the time +//go:generate run for all good men + +package p
diff --git a/vendor/cmd/go/testdata/generate/test3.go b/vendor/cmd/go/testdata/generate/test3.go new file mode 100644 index 0000000..e950da5 --- /dev/null +++ b/vendor/cmd/go/testdata/generate/test3.go
@@ -0,0 +1,9 @@ +// Copyright 2014 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. + +// Test go generate variable substitution. + +//go:generate echo $GOARCH $GOFILE:$GOLINE ${GOPACKAGE}abc xyz$GOPACKAGE/$GOFILE/123 + +package p
diff --git a/vendor/cmd/go/testdata/generate/test4.go b/vendor/cmd/go/testdata/generate/test4.go new file mode 100644 index 0000000..6dae048 --- /dev/null +++ b/vendor/cmd/go/testdata/generate/test4.go
@@ -0,0 +1,10 @@ +// Copyright 2015 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. + +// Test -run flag + +//go:generate echo oh yes my man +//go:generate echo no, no, a thousand times no + +package p
diff --git a/vendor/cmd/go/testdata/importcom/bad.go b/vendor/cmd/go/testdata/importcom/bad.go new file mode 100644 index 0000000..e104c2e --- /dev/null +++ b/vendor/cmd/go/testdata/importcom/bad.go
@@ -0,0 +1,3 @@ +package p + +import "bad"
diff --git a/vendor/cmd/go/testdata/importcom/conflict.go b/vendor/cmd/go/testdata/importcom/conflict.go new file mode 100644 index 0000000..995556c --- /dev/null +++ b/vendor/cmd/go/testdata/importcom/conflict.go
@@ -0,0 +1,3 @@ +package p + +import "conflict"
diff --git a/vendor/cmd/go/testdata/importcom/src/bad/bad.go b/vendor/cmd/go/testdata/importcom/src/bad/bad.go new file mode 100644 index 0000000..bc51fd3 --- /dev/null +++ b/vendor/cmd/go/testdata/importcom/src/bad/bad.go
@@ -0,0 +1 @@ +package bad // import
diff --git a/vendor/cmd/go/testdata/importcom/src/conflict/a.go b/vendor/cmd/go/testdata/importcom/src/conflict/a.go new file mode 100644 index 0000000..2d67703 --- /dev/null +++ b/vendor/cmd/go/testdata/importcom/src/conflict/a.go
@@ -0,0 +1 @@ +package conflict // import "a"
diff --git a/vendor/cmd/go/testdata/importcom/src/conflict/b.go b/vendor/cmd/go/testdata/importcom/src/conflict/b.go new file mode 100644 index 0000000..8fcfb3c --- /dev/null +++ b/vendor/cmd/go/testdata/importcom/src/conflict/b.go
@@ -0,0 +1 @@ +package conflict /* import "b" */
diff --git a/vendor/cmd/go/testdata/importcom/src/works/x/x.go b/vendor/cmd/go/testdata/importcom/src/works/x/x.go new file mode 100644 index 0000000..044c6ec --- /dev/null +++ b/vendor/cmd/go/testdata/importcom/src/works/x/x.go
@@ -0,0 +1 @@ +package x // import "works/x"
diff --git a/vendor/cmd/go/testdata/importcom/src/works/x/x1.go b/vendor/cmd/go/testdata/importcom/src/works/x/x1.go new file mode 100644 index 0000000..2449b29 --- /dev/null +++ b/vendor/cmd/go/testdata/importcom/src/works/x/x1.go
@@ -0,0 +1 @@ +package x // important! not an import comment
diff --git a/vendor/cmd/go/testdata/importcom/src/wrongplace/x.go b/vendor/cmd/go/testdata/importcom/src/wrongplace/x.go new file mode 100644 index 0000000..b89849d --- /dev/null +++ b/vendor/cmd/go/testdata/importcom/src/wrongplace/x.go
@@ -0,0 +1 @@ +package x // import "my/x"
diff --git a/vendor/cmd/go/testdata/importcom/works.go b/vendor/cmd/go/testdata/importcom/works.go new file mode 100644 index 0000000..31b55d0 --- /dev/null +++ b/vendor/cmd/go/testdata/importcom/works.go
@@ -0,0 +1,3 @@ +package p + +import _ "works/x"
diff --git a/vendor/cmd/go/testdata/importcom/wrongplace.go b/vendor/cmd/go/testdata/importcom/wrongplace.go new file mode 100644 index 0000000..e2535e0 --- /dev/null +++ b/vendor/cmd/go/testdata/importcom/wrongplace.go
@@ -0,0 +1,3 @@ +package p + +import "wrongplace"
diff --git a/vendor/cmd/go/testdata/local/easy.go b/vendor/cmd/go/testdata/local/easy.go new file mode 100644 index 0000000..4eeb517 --- /dev/null +++ b/vendor/cmd/go/testdata/local/easy.go
@@ -0,0 +1,7 @@ +package main + +import "./easysub" + +func main() { + easysub.Hello() +}
diff --git a/vendor/cmd/go/testdata/local/easysub/easysub.go b/vendor/cmd/go/testdata/local/easysub/easysub.go new file mode 100644 index 0000000..07040da --- /dev/null +++ b/vendor/cmd/go/testdata/local/easysub/easysub.go
@@ -0,0 +1,7 @@ +package easysub + +import "fmt" + +func Hello() { + fmt.Println("easysub.Hello") +}
diff --git a/vendor/cmd/go/testdata/local/easysub/main.go b/vendor/cmd/go/testdata/local/easysub/main.go new file mode 100644 index 0000000..6c30b52 --- /dev/null +++ b/vendor/cmd/go/testdata/local/easysub/main.go
@@ -0,0 +1,9 @@ +// +build ignore + +package main + +import "." + +func main() { + easysub.Hello() +}
diff --git a/vendor/cmd/go/testdata/local/hard.go b/vendor/cmd/go/testdata/local/hard.go new file mode 100644 index 0000000..2ffac3f --- /dev/null +++ b/vendor/cmd/go/testdata/local/hard.go
@@ -0,0 +1,7 @@ +package main + +import "./sub" + +func main() { + sub.Hello() +}
diff --git a/vendor/cmd/go/testdata/local/sub/sub.go b/vendor/cmd/go/testdata/local/sub/sub.go new file mode 100644 index 0000000..d5dbf6d --- /dev/null +++ b/vendor/cmd/go/testdata/local/sub/sub.go
@@ -0,0 +1,12 @@ +package sub + +import ( + "fmt" + + subsub "./sub" +) + +func Hello() { + fmt.Println("sub.Hello") + subsub.Hello() +}
diff --git a/vendor/cmd/go/testdata/local/sub/sub/subsub.go b/vendor/cmd/go/testdata/local/sub/sub/subsub.go new file mode 100644 index 0000000..4cc7223 --- /dev/null +++ b/vendor/cmd/go/testdata/local/sub/sub/subsub.go
@@ -0,0 +1,7 @@ +package subsub + +import "fmt" + +func Hello() { + fmt.Println("subsub.Hello") +}
diff --git a/vendor/cmd/go/testdata/norunexample/example_test.go b/vendor/cmd/go/testdata/norunexample/example_test.go new file mode 100644 index 0000000..e158305 --- /dev/null +++ b/vendor/cmd/go/testdata/norunexample/example_test.go
@@ -0,0 +1,11 @@ +package pkg_test + +import "os" + +func init() { + os.Stdout.Write([]byte("File with non-runnable example was built.\n")) +} + +func Example_test() { + // This test will not be run, it has no "Output:" comment. +}
diff --git a/vendor/cmd/go/testdata/norunexample/test_test.go b/vendor/cmd/go/testdata/norunexample/test_test.go new file mode 100644 index 0000000..d2e9198 --- /dev/null +++ b/vendor/cmd/go/testdata/norunexample/test_test.go
@@ -0,0 +1,10 @@ +package pkg + +import ( + "os" + "testing" +) + +func TestBuilt(t *testing.T) { + os.Stdout.Write([]byte("A normal test was executed.\n")) +}
diff --git a/vendor/cmd/go/testdata/print_goroot.go b/vendor/cmd/go/testdata/print_goroot.go new file mode 100644 index 0000000..5477291 --- /dev/null +++ b/vendor/cmd/go/testdata/print_goroot.go
@@ -0,0 +1,11 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "runtime" + +func main() { + println(runtime.GOROOT()) +}
diff --git a/vendor/cmd/go/testdata/rundir/sub/sub.go b/vendor/cmd/go/testdata/rundir/sub/sub.go new file mode 100644 index 0000000..06ab7d0 --- /dev/null +++ b/vendor/cmd/go/testdata/rundir/sub/sub.go
@@ -0,0 +1 @@ +package main
diff --git a/vendor/cmd/go/testdata/rundir/x.go b/vendor/cmd/go/testdata/rundir/x.go new file mode 100644 index 0000000..06ab7d0 --- /dev/null +++ b/vendor/cmd/go/testdata/rundir/x.go
@@ -0,0 +1 @@ +package main
diff --git a/vendor/cmd/go/testdata/shadow/root1/src/foo/foo.go b/vendor/cmd/go/testdata/shadow/root1/src/foo/foo.go new file mode 100644 index 0000000..f52652b --- /dev/null +++ b/vendor/cmd/go/testdata/shadow/root1/src/foo/foo.go
@@ -0,0 +1 @@ +package foo
diff --git a/vendor/cmd/go/testdata/shadow/root1/src/math/math.go b/vendor/cmd/go/testdata/shadow/root1/src/math/math.go new file mode 100644 index 0000000..c91c24e --- /dev/null +++ b/vendor/cmd/go/testdata/shadow/root1/src/math/math.go
@@ -0,0 +1 @@ +package math
diff --git a/vendor/cmd/go/testdata/shadow/root2/src/foo/foo.go b/vendor/cmd/go/testdata/shadow/root2/src/foo/foo.go new file mode 100644 index 0000000..f52652b --- /dev/null +++ b/vendor/cmd/go/testdata/shadow/root2/src/foo/foo.go
@@ -0,0 +1 @@ +package foo
diff --git a/vendor/cmd/go/testdata/src/badc/x.c b/vendor/cmd/go/testdata/src/badc/x.c new file mode 100644 index 0000000..f6cbf69 --- /dev/null +++ b/vendor/cmd/go/testdata/src/badc/x.c
@@ -0,0 +1 @@ +// C code!
diff --git a/vendor/cmd/go/testdata/src/badc/x.go b/vendor/cmd/go/testdata/src/badc/x.go new file mode 100644 index 0000000..bfa1de2 --- /dev/null +++ b/vendor/cmd/go/testdata/src/badc/x.go
@@ -0,0 +1 @@ +package badc
diff --git a/vendor/cmd/go/testdata/src/badpkg/x.go b/vendor/cmd/go/testdata/src/badpkg/x.go new file mode 100644 index 0000000..dda35e8 --- /dev/null +++ b/vendor/cmd/go/testdata/src/badpkg/x.go
@@ -0,0 +1 @@ +pkg badpkg
diff --git a/vendor/cmd/go/testdata/src/badtest/badexec/x_test.go b/vendor/cmd/go/testdata/src/badtest/badexec/x_test.go new file mode 100644 index 0000000..12f5051 --- /dev/null +++ b/vendor/cmd/go/testdata/src/badtest/badexec/x_test.go
@@ -0,0 +1,5 @@ +package badexec + +func init() { + panic("badexec") +}
diff --git a/vendor/cmd/go/testdata/src/badtest/badsyntax/x.go b/vendor/cmd/go/testdata/src/badtest/badsyntax/x.go new file mode 100644 index 0000000..c8a5407 --- /dev/null +++ b/vendor/cmd/go/testdata/src/badtest/badsyntax/x.go
@@ -0,0 +1 @@ +package badsyntax
diff --git a/vendor/cmd/go/testdata/src/badtest/badsyntax/x_test.go b/vendor/cmd/go/testdata/src/badtest/badsyntax/x_test.go new file mode 100644 index 0000000..5be1074 --- /dev/null +++ b/vendor/cmd/go/testdata/src/badtest/badsyntax/x_test.go
@@ -0,0 +1,3 @@ +package badsyntax + +func func func func func!
diff --git a/vendor/cmd/go/testdata/src/badtest/badvar/x.go b/vendor/cmd/go/testdata/src/badtest/badvar/x.go new file mode 100644 index 0000000..fdd46c4 --- /dev/null +++ b/vendor/cmd/go/testdata/src/badtest/badvar/x.go
@@ -0,0 +1 @@ +package badvar
diff --git a/vendor/cmd/go/testdata/src/badtest/badvar/x_test.go b/vendor/cmd/go/testdata/src/badtest/badvar/x_test.go new file mode 100644 index 0000000..c67df01 --- /dev/null +++ b/vendor/cmd/go/testdata/src/badtest/badvar/x_test.go
@@ -0,0 +1,5 @@ +package badvar_test + +func f() { + _ = notdefined +}
diff --git a/vendor/cmd/go/testdata/src/bench/x_test.go b/vendor/cmd/go/testdata/src/bench/x_test.go new file mode 100644 index 0000000..32cabf8 --- /dev/null +++ b/vendor/cmd/go/testdata/src/bench/x_test.go
@@ -0,0 +1,6 @@ +package bench + +import "testing" + +func Benchmark(b *testing.B) { +}
diff --git a/vendor/cmd/go/testdata/src/benchfatal/x_test.go b/vendor/cmd/go/testdata/src/benchfatal/x_test.go new file mode 100644 index 0000000..8d3a5de --- /dev/null +++ b/vendor/cmd/go/testdata/src/benchfatal/x_test.go
@@ -0,0 +1,7 @@ +package benchfatal + +import "testing" + +func BenchmarkThatCallsFatal(b *testing.B) { + b.Fatal("called by benchmark") +}
diff --git a/vendor/cmd/go/testdata/src/canonical/a/a.go b/vendor/cmd/go/testdata/src/canonical/a/a.go new file mode 100644 index 0000000..486cc48 --- /dev/null +++ b/vendor/cmd/go/testdata/src/canonical/a/a.go
@@ -0,0 +1,3 @@ +package a + +import _ "c"
diff --git a/vendor/cmd/go/testdata/src/canonical/a/vendor/c/c.go b/vendor/cmd/go/testdata/src/canonical/a/vendor/c/c.go new file mode 100644 index 0000000..7f96c22 --- /dev/null +++ b/vendor/cmd/go/testdata/src/canonical/a/vendor/c/c.go
@@ -0,0 +1 @@ +package c
diff --git a/vendor/cmd/go/testdata/src/canonical/b/b.go b/vendor/cmd/go/testdata/src/canonical/b/b.go new file mode 100644 index 0000000..ce0f4ce --- /dev/null +++ b/vendor/cmd/go/testdata/src/canonical/b/b.go
@@ -0,0 +1,3 @@ +package b + +import _ "canonical/a/"
diff --git a/vendor/cmd/go/testdata/src/canonical/d/d.go b/vendor/cmd/go/testdata/src/canonical/d/d.go new file mode 100644 index 0000000..ef7dd7d --- /dev/null +++ b/vendor/cmd/go/testdata/src/canonical/d/d.go
@@ -0,0 +1,3 @@ +package d + +import _ "canonical/b"
diff --git a/vendor/cmd/go/testdata/src/cgoasm/p.go b/vendor/cmd/go/testdata/src/cgoasm/p.go new file mode 100644 index 0000000..148b47f --- /dev/null +++ b/vendor/cmd/go/testdata/src/cgoasm/p.go
@@ -0,0 +1,8 @@ +package p + +/* +// hi +*/ +import "C" + +func F() {}
diff --git a/vendor/cmd/go/testdata/src/cgoasm/p.s b/vendor/cmd/go/testdata/src/cgoasm/p.s new file mode 100644 index 0000000..aaade03 --- /dev/null +++ b/vendor/cmd/go/testdata/src/cgoasm/p.s
@@ -0,0 +1,2 @@ +TEXT asm(SB),$0 + RET
diff --git a/vendor/cmd/go/testdata/src/cgocover/p.go b/vendor/cmd/go/testdata/src/cgocover/p.go new file mode 100644 index 0000000..a6a3891 --- /dev/null +++ b/vendor/cmd/go/testdata/src/cgocover/p.go
@@ -0,0 +1,19 @@ +package p + +/* +void +f(void) +{ +} +*/ +import "C" + +var b bool + +func F() { + if b { + for { + } + } + C.f() +}
diff --git a/vendor/cmd/go/testdata/src/cgocover/p_test.go b/vendor/cmd/go/testdata/src/cgocover/p_test.go new file mode 100644 index 0000000..a8f057e --- /dev/null +++ b/vendor/cmd/go/testdata/src/cgocover/p_test.go
@@ -0,0 +1,7 @@ +package p + +import "testing" + +func TestF(t *testing.T) { + F() +}
diff --git a/vendor/cmd/go/testdata/src/cgocover2/p.go b/vendor/cmd/go/testdata/src/cgocover2/p.go new file mode 100644 index 0000000..a6a3891 --- /dev/null +++ b/vendor/cmd/go/testdata/src/cgocover2/p.go
@@ -0,0 +1,19 @@ +package p + +/* +void +f(void) +{ +} +*/ +import "C" + +var b bool + +func F() { + if b { + for { + } + } + C.f() +}
diff --git a/vendor/cmd/go/testdata/src/cgocover2/x_test.go b/vendor/cmd/go/testdata/src/cgocover2/x_test.go new file mode 100644 index 0000000..f4790d2 --- /dev/null +++ b/vendor/cmd/go/testdata/src/cgocover2/x_test.go
@@ -0,0 +1,10 @@ +package p_test + +import ( + . "cgocover2" + "testing" +) + +func TestF(t *testing.T) { + F() +}
diff --git a/vendor/cmd/go/testdata/src/cgocover3/p.go b/vendor/cmd/go/testdata/src/cgocover3/p.go new file mode 100644 index 0000000..a6a3891 --- /dev/null +++ b/vendor/cmd/go/testdata/src/cgocover3/p.go
@@ -0,0 +1,19 @@ +package p + +/* +void +f(void) +{ +} +*/ +import "C" + +var b bool + +func F() { + if b { + for { + } + } + C.f() +}
diff --git a/vendor/cmd/go/testdata/src/cgocover3/p_test.go b/vendor/cmd/go/testdata/src/cgocover3/p_test.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/cgocover3/p_test.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/cgocover3/x_test.go b/vendor/cmd/go/testdata/src/cgocover3/x_test.go new file mode 100644 index 0000000..97d0e0f --- /dev/null +++ b/vendor/cmd/go/testdata/src/cgocover3/x_test.go
@@ -0,0 +1,10 @@ +package p_test + +import ( + . "cgocover3" + "testing" +) + +func TestF(t *testing.T) { + F() +}
diff --git a/vendor/cmd/go/testdata/src/cgocover4/notcgo.go b/vendor/cmd/go/testdata/src/cgocover4/notcgo.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/cgocover4/notcgo.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/cgocover4/p.go b/vendor/cmd/go/testdata/src/cgocover4/p.go new file mode 100644 index 0000000..a6a3891 --- /dev/null +++ b/vendor/cmd/go/testdata/src/cgocover4/p.go
@@ -0,0 +1,19 @@ +package p + +/* +void +f(void) +{ +} +*/ +import "C" + +var b bool + +func F() { + if b { + for { + } + } + C.f() +}
diff --git a/vendor/cmd/go/testdata/src/cgocover4/x_test.go b/vendor/cmd/go/testdata/src/cgocover4/x_test.go new file mode 100644 index 0000000..fd9bae7 --- /dev/null +++ b/vendor/cmd/go/testdata/src/cgocover4/x_test.go
@@ -0,0 +1,10 @@ +package p_test + +import ( + . "cgocover4" + "testing" +) + +func TestF(t *testing.T) { + F() +}
diff --git a/vendor/cmd/go/testdata/src/cgotest/m.go b/vendor/cmd/go/testdata/src/cgotest/m.go new file mode 100644 index 0000000..4d68307 --- /dev/null +++ b/vendor/cmd/go/testdata/src/cgotest/m.go
@@ -0,0 +1,5 @@ +package cgotest + +import "C" + +var _ C.int
diff --git a/vendor/cmd/go/testdata/src/complex/main.go b/vendor/cmd/go/testdata/src/complex/main.go new file mode 100644 index 0000000..c38df01 --- /dev/null +++ b/vendor/cmd/go/testdata/src/complex/main.go
@@ -0,0 +1,12 @@ +package main + +import ( + _ "complex/nest/sub/test12" + _ "complex/nest/sub/test23" + "complex/w" + "v" +) + +func main() { + println(v.Hello + " " + w.World) +}
diff --git a/vendor/cmd/go/testdata/src/complex/nest/sub/test12/p.go b/vendor/cmd/go/testdata/src/complex/nest/sub/test12/p.go new file mode 100644 index 0000000..94943ec --- /dev/null +++ b/vendor/cmd/go/testdata/src/complex/nest/sub/test12/p.go
@@ -0,0 +1,11 @@ +package test12 + +// Check that vendor/v1 is used but vendor/v2 is NOT used (sub/vendor/v2 wins). + +import ( + "v1" + "v2" +) + +const x = v1.ComplexNestVendorV1 +const y = v2.ComplexNestSubVendorV2
diff --git a/vendor/cmd/go/testdata/src/complex/nest/sub/test23/p.go b/vendor/cmd/go/testdata/src/complex/nest/sub/test23/p.go new file mode 100644 index 0000000..8801a48 --- /dev/null +++ b/vendor/cmd/go/testdata/src/complex/nest/sub/test23/p.go
@@ -0,0 +1,11 @@ +package test23 + +// Check that vendor/v3 is used but vendor/v2 is NOT used (sub/vendor/v2 wins). + +import ( + "v2" + "v3" +) + +const x = v3.ComplexNestVendorV3 +const y = v2.ComplexNestSubVendorV2
diff --git a/vendor/cmd/go/testdata/src/complex/nest/sub/vendor/v2/v2.go b/vendor/cmd/go/testdata/src/complex/nest/sub/vendor/v2/v2.go new file mode 100644 index 0000000..2991871 --- /dev/null +++ b/vendor/cmd/go/testdata/src/complex/nest/sub/vendor/v2/v2.go
@@ -0,0 +1,3 @@ +package v2 + +const ComplexNestSubVendorV2 = true
diff --git a/vendor/cmd/go/testdata/src/complex/nest/vendor/v1/v1.go b/vendor/cmd/go/testdata/src/complex/nest/vendor/v1/v1.go new file mode 100644 index 0000000..a55f529 --- /dev/null +++ b/vendor/cmd/go/testdata/src/complex/nest/vendor/v1/v1.go
@@ -0,0 +1,3 @@ +package v1 + +const ComplexNestVendorV1 = true
diff --git a/vendor/cmd/go/testdata/src/complex/nest/vendor/v2/v2.go b/vendor/cmd/go/testdata/src/complex/nest/vendor/v2/v2.go new file mode 100644 index 0000000..ac94def --- /dev/null +++ b/vendor/cmd/go/testdata/src/complex/nest/vendor/v2/v2.go
@@ -0,0 +1,3 @@ +package v2 + +const ComplexNestVendorV2 = true
diff --git a/vendor/cmd/go/testdata/src/complex/nest/vendor/v3/v3.go b/vendor/cmd/go/testdata/src/complex/nest/vendor/v3/v3.go new file mode 100644 index 0000000..abf99b9 --- /dev/null +++ b/vendor/cmd/go/testdata/src/complex/nest/vendor/v3/v3.go
@@ -0,0 +1,3 @@ +package v3 + +const ComplexNestVendorV3 = true
diff --git a/vendor/cmd/go/testdata/src/complex/vendor/v/v.go b/vendor/cmd/go/testdata/src/complex/vendor/v/v.go new file mode 100644 index 0000000..bb20d86 --- /dev/null +++ b/vendor/cmd/go/testdata/src/complex/vendor/v/v.go
@@ -0,0 +1,3 @@ +package v + +const Hello = "hello"
diff --git a/vendor/cmd/go/testdata/src/complex/w/w.go b/vendor/cmd/go/testdata/src/complex/w/w.go new file mode 100644 index 0000000..a9c7fbb --- /dev/null +++ b/vendor/cmd/go/testdata/src/complex/w/w.go
@@ -0,0 +1,3 @@ +package w + +const World = "world"
diff --git a/vendor/cmd/go/testdata/src/coverasm/p.go b/vendor/cmd/go/testdata/src/coverasm/p.go new file mode 100644 index 0000000..ab0c300 --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverasm/p.go
@@ -0,0 +1,7 @@ +package p + +func f() + +func g() { + println("g") +}
diff --git a/vendor/cmd/go/testdata/src/coverasm/p.s b/vendor/cmd/go/testdata/src/coverasm/p.s new file mode 100644 index 0000000..5e728f9 --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverasm/p.s
@@ -0,0 +1,2 @@ +// empty asm file, +// so go test doesn't complain about declaration of f in p.go.
diff --git a/vendor/cmd/go/testdata/src/coverasm/p_test.go b/vendor/cmd/go/testdata/src/coverasm/p_test.go new file mode 100644 index 0000000..3cb3bd5 --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverasm/p_test.go
@@ -0,0 +1,7 @@ +package p + +import "testing" + +func Test(t *testing.T) { + g() +}
diff --git a/vendor/cmd/go/testdata/src/coverbad/p.go b/vendor/cmd/go/testdata/src/coverbad/p.go new file mode 100644 index 0000000..16504a4 --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverbad/p.go
@@ -0,0 +1,5 @@ +package p + +func f() { + g() +}
diff --git a/vendor/cmd/go/testdata/src/coverbad/p1.go b/vendor/cmd/go/testdata/src/coverbad/p1.go new file mode 100644 index 0000000..2d25c8e --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverbad/p1.go
@@ -0,0 +1,7 @@ +package p + +import "C" + +func h() { + j() +}
diff --git a/vendor/cmd/go/testdata/src/coverbad/p_test.go b/vendor/cmd/go/testdata/src/coverbad/p_test.go new file mode 100644 index 0000000..3a876d6 --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverbad/p_test.go
@@ -0,0 +1,5 @@ +package p + +import "testing" + +func Test(t *testing.T) {}
diff --git a/vendor/cmd/go/testdata/src/coverdep/p.go b/vendor/cmd/go/testdata/src/coverdep/p.go new file mode 100644 index 0000000..6baf6d5 --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverdep/p.go
@@ -0,0 +1,6 @@ +package p + +import _ "coverdep/p1" + +func F() { +}
diff --git a/vendor/cmd/go/testdata/src/coverdep/p1/p1.go b/vendor/cmd/go/testdata/src/coverdep/p1/p1.go new file mode 100644 index 0000000..8ae793d --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverdep/p1/p1.go
@@ -0,0 +1,3 @@ +package p1 + +import _ "errors"
diff --git a/vendor/cmd/go/testdata/src/coverdep/p_test.go b/vendor/cmd/go/testdata/src/coverdep/p_test.go new file mode 100644 index 0000000..11a1434 --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverdep/p_test.go
@@ -0,0 +1,7 @@ +package p + +import "testing" + +func Test(t *testing.T) { + F() +}
diff --git a/vendor/cmd/go/testdata/src/coverdep2/p1/p.go b/vendor/cmd/go/testdata/src/coverdep2/p1/p.go new file mode 100644 index 0000000..fd31527 --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverdep2/p1/p.go
@@ -0,0 +1,3 @@ +package p1 + +func F() int { return 1 }
diff --git a/vendor/cmd/go/testdata/src/coverdep2/p1/p_test.go b/vendor/cmd/go/testdata/src/coverdep2/p1/p_test.go new file mode 100644 index 0000000..c402568 --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverdep2/p1/p_test.go
@@ -0,0 +1,10 @@ +package p1_test + +import ( + "coverdep2/p2" + "testing" +) + +func Test(t *testing.T) { + p2.F() +}
diff --git a/vendor/cmd/go/testdata/src/coverdep2/p2/p2.go b/vendor/cmd/go/testdata/src/coverdep2/p2/p2.go new file mode 100644 index 0000000..33561bb --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverdep2/p2/p2.go
@@ -0,0 +1,7 @@ +package p2 + +import "coverdep2/p1" + +func F() { + p1.F() +}
diff --git a/vendor/cmd/go/testdata/src/coverdot1/p.go b/vendor/cmd/go/testdata/src/coverdot1/p.go new file mode 100644 index 0000000..cda364f --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverdot1/p.go
@@ -0,0 +1,3 @@ +package coverdot1 + +func F() {}
diff --git a/vendor/cmd/go/testdata/src/coverdot2/p.go b/vendor/cmd/go/testdata/src/coverdot2/p.go new file mode 100644 index 0000000..80f79ae --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverdot2/p.go
@@ -0,0 +1,5 @@ +package coverdot2 + +import . "coverdot1" + +func G() { F() }
diff --git a/vendor/cmd/go/testdata/src/coverdot2/p_test.go b/vendor/cmd/go/testdata/src/coverdot2/p_test.go new file mode 100644 index 0000000..da66e3e --- /dev/null +++ b/vendor/cmd/go/testdata/src/coverdot2/p_test.go
@@ -0,0 +1,7 @@ +package coverdot2 + +import "testing" + +func TestG(t *testing.T) { + G() +}
diff --git a/vendor/cmd/go/testdata/src/dupload/dupload.go b/vendor/cmd/go/testdata/src/dupload/dupload.go new file mode 100644 index 0000000..2f07852 --- /dev/null +++ b/vendor/cmd/go/testdata/src/dupload/dupload.go
@@ -0,0 +1,8 @@ +package main + +import ( + _ "dupload/p2" + _ "p" +) + +func main() {}
diff --git a/vendor/cmd/go/testdata/src/dupload/p/p.go b/vendor/cmd/go/testdata/src/dupload/p/p.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/dupload/p/p.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/dupload/p2/p2.go b/vendor/cmd/go/testdata/src/dupload/p2/p2.go new file mode 100644 index 0000000..40f5a5b --- /dev/null +++ b/vendor/cmd/go/testdata/src/dupload/p2/p2.go
@@ -0,0 +1,2 @@ +package p2 +import _ "dupload/vendor/p"
diff --git a/vendor/cmd/go/testdata/src/dupload/vendor/p/p.go b/vendor/cmd/go/testdata/src/dupload/vendor/p/p.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/dupload/vendor/p/p.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/empty/pkg/pkg.go b/vendor/cmd/go/testdata/src/empty/pkg/pkg.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/empty/pkg/pkg.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/empty/pkgtest/pkg.go b/vendor/cmd/go/testdata/src/empty/pkgtest/pkg.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/empty/pkgtest/pkg.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/empty/pkgtest/test_test.go b/vendor/cmd/go/testdata/src/empty/pkgtest/test_test.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/empty/pkgtest/test_test.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/empty/pkgtestxtest/pkg.go b/vendor/cmd/go/testdata/src/empty/pkgtestxtest/pkg.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/empty/pkgtestxtest/pkg.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/empty/pkgtestxtest/test_test.go b/vendor/cmd/go/testdata/src/empty/pkgtestxtest/test_test.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/empty/pkgtestxtest/test_test.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/empty/pkgtestxtest/xtest_test.go b/vendor/cmd/go/testdata/src/empty/pkgtestxtest/xtest_test.go new file mode 100644 index 0000000..9b64e8e --- /dev/null +++ b/vendor/cmd/go/testdata/src/empty/pkgtestxtest/xtest_test.go
@@ -0,0 +1 @@ +package p_test
diff --git a/vendor/cmd/go/testdata/src/empty/pkgxtest/pkg.go b/vendor/cmd/go/testdata/src/empty/pkgxtest/pkg.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/empty/pkgxtest/pkg.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/empty/pkgxtest/xtest_test.go b/vendor/cmd/go/testdata/src/empty/pkgxtest/xtest_test.go new file mode 100644 index 0000000..9b64e8e --- /dev/null +++ b/vendor/cmd/go/testdata/src/empty/pkgxtest/xtest_test.go
@@ -0,0 +1 @@ +package p_test
diff --git a/vendor/cmd/go/testdata/src/empty/test/test_test.go b/vendor/cmd/go/testdata/src/empty/test/test_test.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/empty/test/test_test.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/empty/testxtest/test_test.go b/vendor/cmd/go/testdata/src/empty/testxtest/test_test.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/empty/testxtest/test_test.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/empty/testxtest/xtest_test.go b/vendor/cmd/go/testdata/src/empty/testxtest/xtest_test.go new file mode 100644 index 0000000..9b64e8e --- /dev/null +++ b/vendor/cmd/go/testdata/src/empty/testxtest/xtest_test.go
@@ -0,0 +1 @@ +package p_test
diff --git a/vendor/cmd/go/testdata/src/empty/xtest/xtest_test.go b/vendor/cmd/go/testdata/src/empty/xtest/xtest_test.go new file mode 100644 index 0000000..9b64e8e --- /dev/null +++ b/vendor/cmd/go/testdata/src/empty/xtest/xtest_test.go
@@ -0,0 +1 @@ +package p_test
diff --git a/vendor/cmd/go/testdata/src/exclude/empty/x.txt b/vendor/cmd/go/testdata/src/exclude/empty/x.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/vendor/cmd/go/testdata/src/exclude/empty/x.txt
diff --git a/vendor/cmd/go/testdata/src/exclude/ignore/_x.go b/vendor/cmd/go/testdata/src/exclude/ignore/_x.go new file mode 100644 index 0000000..823aafd --- /dev/null +++ b/vendor/cmd/go/testdata/src/exclude/ignore/_x.go
@@ -0,0 +1 @@ +package x
diff --git a/vendor/cmd/go/testdata/src/exclude/x.go b/vendor/cmd/go/testdata/src/exclude/x.go new file mode 100644 index 0000000..9affd21 --- /dev/null +++ b/vendor/cmd/go/testdata/src/exclude/x.go
@@ -0,0 +1,3 @@ +// +build linux,!linux + +package x
diff --git a/vendor/cmd/go/testdata/src/exclude/x_linux.go b/vendor/cmd/go/testdata/src/exclude/x_linux.go new file mode 100644 index 0000000..a5bbb61 --- /dev/null +++ b/vendor/cmd/go/testdata/src/exclude/x_linux.go
@@ -0,0 +1,4 @@ +// +build windows + +package x +
diff --git a/vendor/cmd/go/testdata/src/failfast_test.go b/vendor/cmd/go/testdata/src/failfast_test.go new file mode 100644 index 0000000..fef4d2a --- /dev/null +++ b/vendor/cmd/go/testdata/src/failfast_test.go
@@ -0,0 +1,54 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package failfast + +import "testing" + +func TestA(t *testing.T) { + // Edge-case testing, mixing unparallel tests too + t.Logf("LOG: %s", t.Name()) +} + +func TestFailingA(t *testing.T) { + t.Errorf("FAIL - %s", t.Name()) +} + +func TestB(t *testing.T) { + // Edge-case testing, mixing unparallel tests too + t.Logf("LOG: %s", t.Name()) +} + +func TestParallelFailingA(t *testing.T) { + t.Parallel() + t.Errorf("FAIL - %s", t.Name()) +} + +func TestParallelFailingB(t *testing.T) { + t.Parallel() + t.Errorf("FAIL - %s", t.Name()) +} + +func TestParallelFailingSubtestsA(t *testing.T) { + t.Parallel() + t.Run("TestFailingSubtestsA1", func(t *testing.T) { + t.Errorf("FAIL - %s", t.Name()) + }) + t.Run("TestFailingSubtestsA2", func(t *testing.T) { + t.Errorf("FAIL - %s", t.Name()) + }) +} + +func TestFailingSubtestsA(t *testing.T) { + t.Run("TestFailingSubtestsA1", func(t *testing.T) { + t.Errorf("FAIL - %s", t.Name()) + }) + t.Run("TestFailingSubtestsA2", func(t *testing.T) { + t.Errorf("FAIL - %s", t.Name()) + }) +} + +func TestFailingB(t *testing.T) { + t.Errorf("FAIL - %s", t.Name()) +}
diff --git a/vendor/cmd/go/testdata/src/gencycle/gencycle.go b/vendor/cmd/go/testdata/src/gencycle/gencycle.go new file mode 100644 index 0000000..600afd9 --- /dev/null +++ b/vendor/cmd/go/testdata/src/gencycle/gencycle.go
@@ -0,0 +1,5 @@ +//go:generate echo hello world + +package gencycle + +import _ "gencycle"
diff --git a/vendor/cmd/go/testdata/src/go-cmd-test/helloworld.go b/vendor/cmd/go/testdata/src/go-cmd-test/helloworld.go new file mode 100644 index 0000000..002a5c7 --- /dev/null +++ b/vendor/cmd/go/testdata/src/go-cmd-test/helloworld.go
@@ -0,0 +1,5 @@ +package main + +func main() { + println("hello world") +}
diff --git a/vendor/cmd/go/testdata/src/importmain/ismain/main.go b/vendor/cmd/go/testdata/src/importmain/ismain/main.go new file mode 100644 index 0000000..bf01907 --- /dev/null +++ b/vendor/cmd/go/testdata/src/importmain/ismain/main.go
@@ -0,0 +1,5 @@ +package main + +import _ "importmain/test" + +func main() {}
diff --git a/vendor/cmd/go/testdata/src/importmain/test/test.go b/vendor/cmd/go/testdata/src/importmain/test/test.go new file mode 100644 index 0000000..56e5404 --- /dev/null +++ b/vendor/cmd/go/testdata/src/importmain/test/test.go
@@ -0,0 +1 @@ +package test
diff --git a/vendor/cmd/go/testdata/src/importmain/test/test_test.go b/vendor/cmd/go/testdata/src/importmain/test/test_test.go new file mode 100644 index 0000000..2268a82 --- /dev/null +++ b/vendor/cmd/go/testdata/src/importmain/test/test_test.go
@@ -0,0 +1,6 @@ +package test_test + +import "testing" +import _ "importmain/ismain" + +func TestCase(t *testing.T) {}
diff --git a/vendor/cmd/go/testdata/src/main_test/m.go b/vendor/cmd/go/testdata/src/main_test/m.go new file mode 100644 index 0000000..c682f03 --- /dev/null +++ b/vendor/cmd/go/testdata/src/main_test/m.go
@@ -0,0 +1,4 @@ +package main + +func F() {} +func main() {}
diff --git a/vendor/cmd/go/testdata/src/main_test/m_test.go b/vendor/cmd/go/testdata/src/main_test/m_test.go new file mode 100644 index 0000000..f865b77 --- /dev/null +++ b/vendor/cmd/go/testdata/src/main_test/m_test.go
@@ -0,0 +1,10 @@ +package main_test + +import ( + . "main_test" + "testing" +) + +func Test1(t *testing.T) { + F() +}
diff --git a/vendor/cmd/go/testdata/src/multimain/multimain_test.go b/vendor/cmd/go/testdata/src/multimain/multimain_test.go new file mode 100644 index 0000000..007a86a --- /dev/null +++ b/vendor/cmd/go/testdata/src/multimain/multimain_test.go
@@ -0,0 +1,16 @@ +package multimain_test + +import "testing" + +func TestMain(m *testing.M) { + // Some users run m.Run multiple times, changing + // some kind of global state between runs. + // This used to work so I guess now it has to keep working. + // See golang.org/issue/23129. + m.Run() + m.Run() +} + +func Test(t *testing.T) { + t.Log("notwithstanding") +}
diff --git a/vendor/cmd/go/testdata/src/my.pkg/main/main.go b/vendor/cmd/go/testdata/src/my.pkg/main/main.go new file mode 100644 index 0000000..397e8b6 --- /dev/null +++ b/vendor/cmd/go/testdata/src/my.pkg/main/main.go
@@ -0,0 +1,5 @@ +package main +import "my.pkg" +func main() { + println(pkg.Text) +}
diff --git a/vendor/cmd/go/testdata/src/my.pkg/pkg.go b/vendor/cmd/go/testdata/src/my.pkg/pkg.go new file mode 100644 index 0000000..17702a6 --- /dev/null +++ b/vendor/cmd/go/testdata/src/my.pkg/pkg.go
@@ -0,0 +1,3 @@ +package pkg + +var Text = "unset"
diff --git a/vendor/cmd/go/testdata/src/not_main/not_main.go b/vendor/cmd/go/testdata/src/not_main/not_main.go new file mode 100644 index 0000000..75a397c --- /dev/null +++ b/vendor/cmd/go/testdata/src/not_main/not_main.go
@@ -0,0 +1,3 @@ +package not_main + +func F() {}
diff --git a/vendor/cmd/go/testdata/src/notest/hello.go b/vendor/cmd/go/testdata/src/notest/hello.go new file mode 100644 index 0000000..7c42c32 --- /dev/null +++ b/vendor/cmd/go/testdata/src/notest/hello.go
@@ -0,0 +1,6 @@ +package notest + +func hello() { + println("hello world") +} +Hello world
diff --git a/vendor/cmd/go/testdata/src/run/bad.go b/vendor/cmd/go/testdata/src/run/bad.go new file mode 100644 index 0000000..c1cc3ac --- /dev/null +++ b/vendor/cmd/go/testdata/src/run/bad.go
@@ -0,0 +1,5 @@ +package main + +import _ "run/subdir/internal/private" + +func main() {}
diff --git a/vendor/cmd/go/testdata/src/run/good.go b/vendor/cmd/go/testdata/src/run/good.go new file mode 100644 index 0000000..0b67dce --- /dev/null +++ b/vendor/cmd/go/testdata/src/run/good.go
@@ -0,0 +1,5 @@ +package main + +import _ "run/internal" + +func main() {}
diff --git a/vendor/cmd/go/testdata/src/run/internal/internal.go b/vendor/cmd/go/testdata/src/run/internal/internal.go new file mode 100644 index 0000000..5bf0569 --- /dev/null +++ b/vendor/cmd/go/testdata/src/run/internal/internal.go
@@ -0,0 +1 @@ +package internal
diff --git a/vendor/cmd/go/testdata/src/run/subdir/internal/private/private.go b/vendor/cmd/go/testdata/src/run/subdir/internal/private/private.go new file mode 100644 index 0000000..735e4dc --- /dev/null +++ b/vendor/cmd/go/testdata/src/run/subdir/internal/private/private.go
@@ -0,0 +1 @@ +package private
diff --git a/vendor/cmd/go/testdata/src/skipper/skip_test.go b/vendor/cmd/go/testdata/src/skipper/skip_test.go new file mode 100644 index 0000000..58e6dc5 --- /dev/null +++ b/vendor/cmd/go/testdata/src/skipper/skip_test.go
@@ -0,0 +1,7 @@ +package skipper + +import "testing" + +func Test(t *testing.T) { + t.Skip("skipping") +}
diff --git a/vendor/cmd/go/testdata/src/sleepy1/p_test.go b/vendor/cmd/go/testdata/src/sleepy1/p_test.go new file mode 100644 index 0000000..333be7d --- /dev/null +++ b/vendor/cmd/go/testdata/src/sleepy1/p_test.go
@@ -0,0 +1,10 @@ +package p + +import ( + "testing" + "time" +) + +func Test1(t *testing.T) { + time.Sleep(200 * time.Millisecond) +}
diff --git a/vendor/cmd/go/testdata/src/sleepy2/p_test.go b/vendor/cmd/go/testdata/src/sleepy2/p_test.go new file mode 100644 index 0000000..333be7d --- /dev/null +++ b/vendor/cmd/go/testdata/src/sleepy2/p_test.go
@@ -0,0 +1,10 @@ +package p + +import ( + "testing" + "time" +) + +func Test1(t *testing.T) { + time.Sleep(200 * time.Millisecond) +}
diff --git a/vendor/cmd/go/testdata/src/sleepybad/p.go b/vendor/cmd/go/testdata/src/sleepybad/p.go new file mode 100644 index 0000000..e05b403 --- /dev/null +++ b/vendor/cmd/go/testdata/src/sleepybad/p.go
@@ -0,0 +1,5 @@ +package p + +// missing import + +var _ = io.DoesNotExist
diff --git a/vendor/cmd/go/testdata/src/syntaxerror/x.go b/vendor/cmd/go/testdata/src/syntaxerror/x.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/syntaxerror/x.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/syntaxerror/x_test.go b/vendor/cmd/go/testdata/src/syntaxerror/x_test.go new file mode 100644 index 0000000..2460743 --- /dev/null +++ b/vendor/cmd/go/testdata/src/syntaxerror/x_test.go
@@ -0,0 +1,4 @@ +package p + +func f() (x.y, z int) { +}
diff --git a/vendor/cmd/go/testdata/src/testcache/testcache_test.go b/vendor/cmd/go/testdata/src/testcache/testcache_test.go new file mode 100644 index 0000000..9b2d1ea --- /dev/null +++ b/vendor/cmd/go/testdata/src/testcache/testcache_test.go
@@ -0,0 +1,91 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testcache + +import ( + "io/ioutil" + "os" + "runtime" + "testing" +) + +func TestChdir(t *testing.T) { + os.Chdir("..") + defer os.Chdir("testcache") + info, err := os.Stat("testcache/file.txt") + if err != nil { + t.Fatal(err) + } + if info.Size()%2 != 1 { + t.Fatal("even file") + } +} + +func TestOddFileContent(t *testing.T) { + f, err := os.Open("file.txt") + if err != nil { + t.Fatal(err) + } + data, err := ioutil.ReadAll(f) + f.Close() + if err != nil { + t.Fatal(err) + } + if len(data)%2 != 1 { + t.Fatal("even file") + } +} + +func TestOddFileSize(t *testing.T) { + info, err := os.Stat("file.txt") + if err != nil { + t.Fatal(err) + } + if info.Size()%2 != 1 { + t.Fatal("even file") + } +} + +func TestOddGetenv(t *testing.T) { + val := os.Getenv("TESTKEY") + if len(val)%2 != 1 { + t.Fatal("even env value") + } +} + +func TestLookupEnv(t *testing.T) { + _, ok := os.LookupEnv("TESTKEY") + if !ok { + t.Fatal("env missing") + } +} + +func TestDirList(t *testing.T) { + f, err := os.Open(".") + if err != nil { + t.Fatal(err) + } + f.Readdirnames(-1) + f.Close() +} + +func TestExec(t *testing.T) { + if runtime.GOOS == "plan9" || runtime.GOOS == "windows" || runtime.GOOS == "nacl" { + t.Skip("non-unix") + } + + // Note: not using os/exec to make sure there is no unexpected stat. + p, err := os.StartProcess("./script.sh", []string{"script"}, new(os.ProcAttr)) + if err != nil { + t.Fatal(err) + } + ps, err := p.Wait() + if err != nil { + t.Fatal(err) + } + if !ps.Success() { + t.Fatalf("script failed: %v", err) + } +}
diff --git a/vendor/cmd/go/testdata/src/testcycle/p1/p1.go b/vendor/cmd/go/testdata/src/testcycle/p1/p1.go new file mode 100644 index 0000000..65ab76d --- /dev/null +++ b/vendor/cmd/go/testdata/src/testcycle/p1/p1.go
@@ -0,0 +1,7 @@ +package p1 + +import _ "testcycle/p2" + +func init() { + println("p1 init") +}
diff --git a/vendor/cmd/go/testdata/src/testcycle/p1/p1_test.go b/vendor/cmd/go/testdata/src/testcycle/p1/p1_test.go new file mode 100644 index 0000000..75abb13 --- /dev/null +++ b/vendor/cmd/go/testdata/src/testcycle/p1/p1_test.go
@@ -0,0 +1,6 @@ +package p1 + +import "testing" + +func Test(t *testing.T) { +}
diff --git a/vendor/cmd/go/testdata/src/testcycle/p2/p2.go b/vendor/cmd/go/testdata/src/testcycle/p2/p2.go new file mode 100644 index 0000000..7e26cdf --- /dev/null +++ b/vendor/cmd/go/testdata/src/testcycle/p2/p2.go
@@ -0,0 +1,7 @@ +package p2 + +import _ "testcycle/p3" + +func init() { + println("p2 init") +}
diff --git a/vendor/cmd/go/testdata/src/testcycle/p3/p3.go b/vendor/cmd/go/testdata/src/testcycle/p3/p3.go new file mode 100644 index 0000000..bb0a2f4 --- /dev/null +++ b/vendor/cmd/go/testdata/src/testcycle/p3/p3.go
@@ -0,0 +1,5 @@ +package p3 + +func init() { + println("p3 init") +}
diff --git a/vendor/cmd/go/testdata/src/testcycle/p3/p3_test.go b/vendor/cmd/go/testdata/src/testcycle/p3/p3_test.go new file mode 100644 index 0000000..9b4b075 --- /dev/null +++ b/vendor/cmd/go/testdata/src/testcycle/p3/p3_test.go
@@ -0,0 +1,10 @@ +package p3 + +import ( + "testing" + + _ "testcycle/p1" +) + +func Test(t *testing.T) { +}
diff --git a/vendor/cmd/go/testdata/src/testcycle/q1/q1.go b/vendor/cmd/go/testdata/src/testcycle/q1/q1.go new file mode 100644 index 0000000..7a471f0 --- /dev/null +++ b/vendor/cmd/go/testdata/src/testcycle/q1/q1.go
@@ -0,0 +1 @@ +package q1
diff --git a/vendor/cmd/go/testdata/src/testcycle/q1/q1_test.go b/vendor/cmd/go/testdata/src/testcycle/q1/q1_test.go new file mode 100644 index 0000000..ca81bd2 --- /dev/null +++ b/vendor/cmd/go/testdata/src/testcycle/q1/q1_test.go
@@ -0,0 +1,6 @@ +package q1 + +import "testing" +import _ "testcycle/q1" + +func Test(t *testing.T) {}
diff --git a/vendor/cmd/go/testdata/src/testdep/p1/p1.go b/vendor/cmd/go/testdata/src/testdep/p1/p1.go new file mode 100644 index 0000000..a457035 --- /dev/null +++ b/vendor/cmd/go/testdata/src/testdep/p1/p1.go
@@ -0,0 +1 @@ +package p1
diff --git a/vendor/cmd/go/testdata/src/testdep/p1/p1_test.go b/vendor/cmd/go/testdata/src/testdep/p1/p1_test.go new file mode 100644 index 0000000..8be7533 --- /dev/null +++ b/vendor/cmd/go/testdata/src/testdep/p1/p1_test.go
@@ -0,0 +1,3 @@ +package p1 + +import _ "testdep/p2"
diff --git a/vendor/cmd/go/testdata/src/testdep/p2/p2.go b/vendor/cmd/go/testdata/src/testdep/p2/p2.go new file mode 100644 index 0000000..15ba2ea --- /dev/null +++ b/vendor/cmd/go/testdata/src/testdep/p2/p2.go
@@ -0,0 +1,3 @@ +package p2 + +import _ "testdep/p3"
diff --git a/vendor/cmd/go/testdata/src/testdep/p3/p3.go b/vendor/cmd/go/testdata/src/testdep/p3/p3.go new file mode 100644 index 0000000..0219e7f --- /dev/null +++ b/vendor/cmd/go/testdata/src/testdep/p3/p3.go
@@ -0,0 +1,3 @@ +// +build ignore + +package ignored
diff --git a/vendor/cmd/go/testdata/src/testlist/bench_test.go b/vendor/cmd/go/testdata/src/testlist/bench_test.go new file mode 100644 index 0000000..22f147b --- /dev/null +++ b/vendor/cmd/go/testdata/src/testlist/bench_test.go
@@ -0,0 +1,14 @@ +package testlist + +import ( + "fmt" + "testing" +) + +func BenchmarkSimplefunc(b *testing.B) { + b.StopTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + _ = fmt.Sprint("Test for bench") + } +}
diff --git a/vendor/cmd/go/testdata/src/testlist/example_test.go b/vendor/cmd/go/testdata/src/testlist/example_test.go new file mode 100644 index 0000000..0298dfd --- /dev/null +++ b/vendor/cmd/go/testdata/src/testlist/example_test.go
@@ -0,0 +1,21 @@ +package testlist + +import ( + "fmt" +) + +func ExampleSimple() { + fmt.Println("Test with Output.") + + // Output: Test with Output. +} + +func ExampleWithEmptyOutput() { + fmt.Println("") + + // Output: +} + +func ExampleNoOutput() { + _ = fmt.Sprint("Test with no output") +}
diff --git a/vendor/cmd/go/testdata/src/testlist/test_test.go b/vendor/cmd/go/testdata/src/testlist/test_test.go new file mode 100644 index 0000000..bdc09f2 --- /dev/null +++ b/vendor/cmd/go/testdata/src/testlist/test_test.go
@@ -0,0 +1,10 @@ +package testlist + +import ( + "fmt" + "testing" +) + +func TestSimple(t *testing.T) { + _ = fmt.Sprint("Test simple") +}
diff --git a/vendor/cmd/go/testdata/src/testrace/race_test.go b/vendor/cmd/go/testdata/src/testrace/race_test.go new file mode 100644 index 0000000..7ec0c6d --- /dev/null +++ b/vendor/cmd/go/testdata/src/testrace/race_test.go
@@ -0,0 +1,31 @@ +package testrace + +import "testing" + +func TestRace(t *testing.T) { + for i := 0; i < 10; i++ { + c := make(chan int) + x := 1 + go func() { + x = 2 + c <- 1 + }() + x = 3 + <-c + _ = x + } +} + +func BenchmarkRace(b *testing.B) { + for i := 0; i < b.N; i++ { + c := make(chan int) + x := 1 + go func() { + x = 2 + c <- 1 + }() + x = 3 + <-c + _ = x + } +}
diff --git a/vendor/cmd/go/testdata/src/testregexp/x_test.go b/vendor/cmd/go/testdata/src/testregexp/x_test.go new file mode 100644 index 0000000..7573e79 --- /dev/null +++ b/vendor/cmd/go/testdata/src/testregexp/x_test.go
@@ -0,0 +1,17 @@ +package x + +import "testing" + +func TestX(t *testing.T) { + t.Logf("LOG: X running") + t.Run("Y", func(t *testing.T) { + t.Logf("LOG: Y running") + }) +} + +func BenchmarkX(b *testing.B) { + b.Logf("LOG: X running N=%d", b.N) + b.Run("Y", func(b *testing.B) { + b.Logf("LOG: Y running N=%d", b.N) + }) +}
diff --git a/vendor/cmd/go/testdata/src/testregexp/z_test.go b/vendor/cmd/go/testdata/src/testregexp/z_test.go new file mode 100644 index 0000000..4fd1979 --- /dev/null +++ b/vendor/cmd/go/testdata/src/testregexp/z_test.go
@@ -0,0 +1,19 @@ +package x + +import "testing" + +func TestZ(t *testing.T) { + t.Logf("LOG: Z running") +} + +func TestXX(t *testing.T) { + t.Logf("LOG: XX running") +} + +func BenchmarkZ(b *testing.B) { + b.Logf("LOG: Z running N=%d", b.N) +} + +func BenchmarkXX(b *testing.B) { + b.Logf("LOG: XX running N=%d", b.N) +}
diff --git a/vendor/cmd/go/testdata/src/vend/bad.go b/vendor/cmd/go/testdata/src/vend/bad.go new file mode 100644 index 0000000..57cc595 --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/bad.go
@@ -0,0 +1,3 @@ +package vend + +import _ "r"
diff --git a/vendor/cmd/go/testdata/src/vend/dir1/dir1.go b/vendor/cmd/go/testdata/src/vend/dir1/dir1.go new file mode 100644 index 0000000..b719ead --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/dir1/dir1.go
@@ -0,0 +1 @@ +package dir1
diff --git a/vendor/cmd/go/testdata/src/vend/good.go b/vendor/cmd/go/testdata/src/vend/good.go new file mode 100644 index 0000000..952ada3 --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/good.go
@@ -0,0 +1,3 @@ +package vend + +import _ "p"
diff --git a/vendor/cmd/go/testdata/src/vend/hello/hello.go b/vendor/cmd/go/testdata/src/vend/hello/hello.go new file mode 100644 index 0000000..41dc03e --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/hello/hello.go
@@ -0,0 +1,10 @@ +package main + +import ( + "fmt" + "strings" // really ../vendor/strings +) + +func main() { + fmt.Printf("%s\n", strings.Msg) +}
diff --git a/vendor/cmd/go/testdata/src/vend/hello/hello_test.go b/vendor/cmd/go/testdata/src/vend/hello/hello_test.go new file mode 100644 index 0000000..7190f59 --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/hello/hello_test.go
@@ -0,0 +1,12 @@ +package main + +import ( + "strings" // really ../vendor/strings + "testing" +) + +func TestMsgInternal(t *testing.T) { + if strings.Msg != "hello, world" { + t.Fatalf("unexpected msg: %v", strings.Msg) + } +}
diff --git a/vendor/cmd/go/testdata/src/vend/hello/hellox_test.go b/vendor/cmd/go/testdata/src/vend/hello/hellox_test.go new file mode 100644 index 0000000..3f2165b --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/hello/hellox_test.go
@@ -0,0 +1,12 @@ +package main_test + +import ( + "strings" // really ../vendor/strings + "testing" +) + +func TestMsgExternal(t *testing.T) { + if strings.Msg != "hello, world" { + t.Fatalf("unexpected msg: %v", strings.Msg) + } +}
diff --git a/vendor/cmd/go/testdata/src/vend/subdir/bad.go b/vendor/cmd/go/testdata/src/vend/subdir/bad.go new file mode 100644 index 0000000..d0ddaac --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/subdir/bad.go
@@ -0,0 +1,3 @@ +package subdir + +import _ "r"
diff --git a/vendor/cmd/go/testdata/src/vend/subdir/good.go b/vendor/cmd/go/testdata/src/vend/subdir/good.go new file mode 100644 index 0000000..edd0454 --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/subdir/good.go
@@ -0,0 +1,3 @@ +package subdir + +import _ "p"
diff --git a/vendor/cmd/go/testdata/src/vend/vendor/p/p.go b/vendor/cmd/go/testdata/src/vend/vendor/p/p.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/vendor/p/p.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/vend/vendor/q/q.go b/vendor/cmd/go/testdata/src/vend/vendor/q/q.go new file mode 100644 index 0000000..946e6d9 --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/vendor/q/q.go
@@ -0,0 +1 @@ +package q
diff --git a/vendor/cmd/go/testdata/src/vend/vendor/strings/msg.go b/vendor/cmd/go/testdata/src/vend/vendor/strings/msg.go new file mode 100644 index 0000000..438126b --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/vendor/strings/msg.go
@@ -0,0 +1,3 @@ +package strings + +var Msg = "hello, world"
diff --git a/vendor/cmd/go/testdata/src/vend/vendor/vend/dir1/dir2/dir2.go b/vendor/cmd/go/testdata/src/vend/vendor/vend/dir1/dir2/dir2.go new file mode 100644 index 0000000..6fe35e9 --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/vendor/vend/dir1/dir2/dir2.go
@@ -0,0 +1 @@ +package dir2
diff --git a/vendor/cmd/go/testdata/src/vend/x/invalid/invalid.go b/vendor/cmd/go/testdata/src/vend/x/invalid/invalid.go new file mode 100644 index 0000000..e250d5b --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/x/invalid/invalid.go
@@ -0,0 +1,3 @@ +package invalid + +import "vend/x/invalid/vendor/foo"
diff --git a/vendor/cmd/go/testdata/src/vend/x/vendor/p/p.go b/vendor/cmd/go/testdata/src/vend/x/vendor/p/p.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/x/vendor/p/p.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/src/vend/x/vendor/p/p/p.go b/vendor/cmd/go/testdata/src/vend/x/vendor/p/p/p.go new file mode 100644 index 0000000..e12e12c --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/x/vendor/p/p/p.go
@@ -0,0 +1,3 @@ +package p + +import _ "notfound"
diff --git a/vendor/cmd/go/testdata/src/vend/x/vendor/r/r.go b/vendor/cmd/go/testdata/src/vend/x/vendor/r/r.go new file mode 100644 index 0000000..838c177 --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/x/vendor/r/r.go
@@ -0,0 +1 @@ +package r
diff --git a/vendor/cmd/go/testdata/src/vend/x/x.go b/vendor/cmd/go/testdata/src/vend/x/x.go new file mode 100644 index 0000000..bdcde57 --- /dev/null +++ b/vendor/cmd/go/testdata/src/vend/x/x.go
@@ -0,0 +1,7 @@ +package x + +import _ "p" +import _ "q" +import _ "r" +import _ "vend/dir1" // not vendored +import _ "vend/dir1/dir2" // vendored
diff --git a/vendor/cmd/go/testdata/src/vetcycle/p.go b/vendor/cmd/go/testdata/src/vetcycle/p.go new file mode 100644 index 0000000..857c3a6 --- /dev/null +++ b/vendor/cmd/go/testdata/src/vetcycle/p.go
@@ -0,0 +1,12 @@ +package p + + +type ( + _ interface{ m(B1) } + A1 interface{ a(D1) } + B1 interface{ A1 } + C1 interface{ B1 /* ERROR issue #18395 */ } + D1 interface{ C1 } +) + +var _ A1 = C1 /* ERROR cannot use C1 */ (nil)
diff --git a/vendor/cmd/go/testdata/src/vetfail/p1/p1.go b/vendor/cmd/go/testdata/src/vetfail/p1/p1.go new file mode 100644 index 0000000..248317b --- /dev/null +++ b/vendor/cmd/go/testdata/src/vetfail/p1/p1.go
@@ -0,0 +1,7 @@ +package p1 + +import "fmt" + +func F() { + fmt.Printf("%d", "hello") // causes vet error +}
diff --git a/vendor/cmd/go/testdata/src/vetfail/p2/p2.go b/vendor/cmd/go/testdata/src/vetfail/p2/p2.go new file mode 100644 index 0000000..88b1cc2 --- /dev/null +++ b/vendor/cmd/go/testdata/src/vetfail/p2/p2.go
@@ -0,0 +1,6 @@ +package p2 + +import _ "vetfail/p1" + +func F() { +}
diff --git a/vendor/cmd/go/testdata/src/vetfail/p2/p2_test.go b/vendor/cmd/go/testdata/src/vetfail/p2/p2_test.go new file mode 100644 index 0000000..fde0d1a --- /dev/null +++ b/vendor/cmd/go/testdata/src/vetfail/p2/p2_test.go
@@ -0,0 +1,7 @@ +package p2 + +import "testing" + +func TestF(t *testing.T) { + F() +}
diff --git a/vendor/cmd/go/testdata/src/vetpkg/a_test.go b/vendor/cmd/go/testdata/src/vetpkg/a_test.go new file mode 100644 index 0000000..9b64e8e --- /dev/null +++ b/vendor/cmd/go/testdata/src/vetpkg/a_test.go
@@ -0,0 +1 @@ +package p_test
diff --git a/vendor/cmd/go/testdata/src/vetpkg/b.go b/vendor/cmd/go/testdata/src/vetpkg/b.go new file mode 100644 index 0000000..99e18f6 --- /dev/null +++ b/vendor/cmd/go/testdata/src/vetpkg/b.go
@@ -0,0 +1,7 @@ +package p + +import "fmt" + +func f() { + fmt.Printf("%d") +}
diff --git a/vendor/cmd/go/testdata/src/vetpkg/c.go b/vendor/cmd/go/testdata/src/vetpkg/c.go new file mode 100644 index 0000000..ef5648f --- /dev/null +++ b/vendor/cmd/go/testdata/src/vetpkg/c.go
@@ -0,0 +1,9 @@ +// +build tagtest + +package p + +import "fmt" + +func g() { + fmt.Printf("%d", 3, 4) +}
diff --git a/vendor/cmd/go/testdata/src/xtestonly/f.go b/vendor/cmd/go/testdata/src/xtestonly/f.go new file mode 100644 index 0000000..dac039e --- /dev/null +++ b/vendor/cmd/go/testdata/src/xtestonly/f.go
@@ -0,0 +1,3 @@ +package xtestonly + +func F() int { return 42 }
diff --git a/vendor/cmd/go/testdata/src/xtestonly/f_test.go b/vendor/cmd/go/testdata/src/xtestonly/f_test.go new file mode 100644 index 0000000..01f6e83 --- /dev/null +++ b/vendor/cmd/go/testdata/src/xtestonly/f_test.go
@@ -0,0 +1,12 @@ +package xtestonly_test + +import ( + "testing" + "xtestonly" +) + +func TestF(t *testing.T) { + if x := xtestonly.F(); x != 42 { + t.Errorf("f.F() = %d, want 42", x) + } +}
diff --git a/vendor/cmd/go/testdata/standalone_benchmark_test.go b/vendor/cmd/go/testdata/standalone_benchmark_test.go new file mode 100644 index 0000000..4850f98 --- /dev/null +++ b/vendor/cmd/go/testdata/standalone_benchmark_test.go
@@ -0,0 +1,6 @@ +package standalone_benchmark + +import "testing" + +func Benchmark(b *testing.B) { +}
diff --git a/vendor/cmd/go/testdata/standalone_fail_sub_test.go b/vendor/cmd/go/testdata/standalone_fail_sub_test.go new file mode 100644 index 0000000..ac483f9 --- /dev/null +++ b/vendor/cmd/go/testdata/standalone_fail_sub_test.go
@@ -0,0 +1,8 @@ +package standalone_fail_sub_test + +import "testing" + +func TestThatFails(t *testing.T) { + t.Run("Sub", func(t *testing.T) {}) + t.Fail() +}
diff --git a/vendor/cmd/go/testdata/standalone_main_normal_test.go b/vendor/cmd/go/testdata/standalone_main_normal_test.go new file mode 100644 index 0000000..018ce75 --- /dev/null +++ b/vendor/cmd/go/testdata/standalone_main_normal_test.go
@@ -0,0 +1,10 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package standalone_main_normal_test + +import "testing" + +func TestMain(t *testing.T) { +}
diff --git a/vendor/cmd/go/testdata/standalone_main_wrong_test.go b/vendor/cmd/go/testdata/standalone_main_wrong_test.go new file mode 100644 index 0000000..5999887 --- /dev/null +++ b/vendor/cmd/go/testdata/standalone_main_wrong_test.go
@@ -0,0 +1,10 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package standalone_main_wrong_test + +import "testing" + +func TestMain(m *testing.Main) { +}
diff --git a/vendor/cmd/go/testdata/standalone_parallel_sub_test.go b/vendor/cmd/go/testdata/standalone_parallel_sub_test.go new file mode 100644 index 0000000..d326de0 --- /dev/null +++ b/vendor/cmd/go/testdata/standalone_parallel_sub_test.go
@@ -0,0 +1,14 @@ +package standalone_parallel_sub_test + +import "testing" + +func Test(t *testing.T) { + ch := make(chan bool, 1) + t.Run("Sub", func(t *testing.T) { + t.Parallel() + <-ch + t.Run("Nested", func(t *testing.T) {}) + }) + // Ensures that Sub will finish after its t.Run call already returned. + ch <- true +}
diff --git a/vendor/cmd/go/testdata/standalone_sub_test.go b/vendor/cmd/go/testdata/standalone_sub_test.go new file mode 100644 index 0000000..f6c31db --- /dev/null +++ b/vendor/cmd/go/testdata/standalone_sub_test.go
@@ -0,0 +1,7 @@ +package standalone_sub_test + +import "testing" + +func Test(t *testing.T) { + t.Run("Sub", func(t *testing.T) {}) +}
diff --git a/vendor/cmd/go/testdata/standalone_test.go b/vendor/cmd/go/testdata/standalone_test.go new file mode 100644 index 0000000..59cf918 --- /dev/null +++ b/vendor/cmd/go/testdata/standalone_test.go
@@ -0,0 +1,6 @@ +package standalone_test + +import "testing" + +func Test(t *testing.T) { +}
diff --git a/vendor/cmd/go/testdata/testimport/p.go b/vendor/cmd/go/testdata/testimport/p.go new file mode 100644 index 0000000..f94d2cd --- /dev/null +++ b/vendor/cmd/go/testdata/testimport/p.go
@@ -0,0 +1,3 @@ +package p + +func F() int { return 1 }
diff --git a/vendor/cmd/go/testdata/testimport/p1/p1.go b/vendor/cmd/go/testdata/testimport/p1/p1.go new file mode 100644 index 0000000..fd31527 --- /dev/null +++ b/vendor/cmd/go/testdata/testimport/p1/p1.go
@@ -0,0 +1,3 @@ +package p1 + +func F() int { return 1 }
diff --git a/vendor/cmd/go/testdata/testimport/p2/p2.go b/vendor/cmd/go/testdata/testimport/p2/p2.go new file mode 100644 index 0000000..d488886 --- /dev/null +++ b/vendor/cmd/go/testdata/testimport/p2/p2.go
@@ -0,0 +1,3 @@ +package p2 + +func F() int { return 1 }
diff --git a/vendor/cmd/go/testdata/testimport/p_test.go b/vendor/cmd/go/testdata/testimport/p_test.go new file mode 100644 index 0000000..a3fb4a9 --- /dev/null +++ b/vendor/cmd/go/testdata/testimport/p_test.go
@@ -0,0 +1,13 @@ +package p + +import ( + "./p1" + + "testing" +) + +func TestF(t *testing.T) { + if F() != p1.F() { + t.Fatal(F()) + } +}
diff --git a/vendor/cmd/go/testdata/testimport/x_test.go b/vendor/cmd/go/testdata/testimport/x_test.go new file mode 100644 index 0000000..b253e3f --- /dev/null +++ b/vendor/cmd/go/testdata/testimport/x_test.go
@@ -0,0 +1,15 @@ +package p_test + +import ( + . "../testimport" + + "./p2" + + "testing" +) + +func TestF1(t *testing.T) { + if F() != p2.F() { + t.Fatal(F()) + } +}
diff --git a/vendor/cmd/go/testdata/testinternal/p.go b/vendor/cmd/go/testdata/testinternal/p.go new file mode 100644 index 0000000..e3558a5 --- /dev/null +++ b/vendor/cmd/go/testdata/testinternal/p.go
@@ -0,0 +1,3 @@ +package p + +import _ "net/http/internal"
diff --git a/vendor/cmd/go/testdata/testinternal2/p.go b/vendor/cmd/go/testdata/testinternal2/p.go new file mode 100644 index 0000000..c594f5c --- /dev/null +++ b/vendor/cmd/go/testdata/testinternal2/p.go
@@ -0,0 +1,3 @@ +package p + +import _ "./x/y/z/internal/w"
diff --git a/vendor/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go b/vendor/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go new file mode 100644 index 0000000..a796c0b --- /dev/null +++ b/vendor/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go
@@ -0,0 +1 @@ +package w
diff --git a/vendor/cmd/go/testdata/testinternal3/t.go b/vendor/cmd/go/testdata/testinternal3/t.go new file mode 100644 index 0000000..8576a4b --- /dev/null +++ b/vendor/cmd/go/testdata/testinternal3/t.go
@@ -0,0 +1,3 @@ +package t + +import _ "internal/does-not-exist"
diff --git a/vendor/cmd/go/testdata/testinternal4/src/p/p.go b/vendor/cmd/go/testdata/testinternal4/src/p/p.go new file mode 100644 index 0000000..6bdee27 --- /dev/null +++ b/vendor/cmd/go/testdata/testinternal4/src/p/p.go
@@ -0,0 +1,6 @@ +package p + +import ( + _ "q/internal/x" + _ "q/j" +)
diff --git a/vendor/cmd/go/testdata/testinternal4/src/q/internal/x/x.go b/vendor/cmd/go/testdata/testinternal4/src/q/internal/x/x.go new file mode 100644 index 0000000..823aafd --- /dev/null +++ b/vendor/cmd/go/testdata/testinternal4/src/q/internal/x/x.go
@@ -0,0 +1 @@ +package x
diff --git a/vendor/cmd/go/testdata/testinternal4/src/q/j/j.go b/vendor/cmd/go/testdata/testinternal4/src/q/j/j.go new file mode 100644 index 0000000..9f07543 --- /dev/null +++ b/vendor/cmd/go/testdata/testinternal4/src/q/j/j.go
@@ -0,0 +1,3 @@ +package j + +import _ "q/internal/x"
diff --git a/vendor/cmd/go/testdata/testonly/p_test.go b/vendor/cmd/go/testdata/testonly/p_test.go new file mode 100644 index 0000000..c89cd18 --- /dev/null +++ b/vendor/cmd/go/testdata/testonly/p_test.go
@@ -0,0 +1 @@ +package p
diff --git a/vendor/cmd/go/testdata/testterminal18153/terminal_test.go b/vendor/cmd/go/testdata/testterminal18153/terminal_test.go new file mode 100644 index 0000000..d662e55 --- /dev/null +++ b/vendor/cmd/go/testdata/testterminal18153/terminal_test.go
@@ -0,0 +1,39 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build linux + +// This test is run by src/cmd/dist/test.go (cmd_go_test_terminal), +// and not by cmd/go's tests. This is because this test requires that +// that it be called with its stdout and stderr being a terminal. +// dist doesn't run `cmd/go test` against this test directory if +// dist's stdout/stderr aren't terminals. +// +// See issue 18153. + +package p + +import ( + "syscall" + "testing" + "unsafe" +) + +const ioctlReadTermios = syscall.TCGETS + +// isTerminal reports whether fd is a terminal. +func isTerminal(fd uintptr) bool { + var termios syscall.Termios + _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) + return err == 0 +} + +func TestIsTerminal(t *testing.T) { + if !isTerminal(1) { + t.Errorf("stdout is not a terminal") + } + if !isTerminal(2) { + t.Errorf("stderr is not a terminal") + } +}
diff --git a/vendor/cmd/go/testdata/testvendor/src/p/p.go b/vendor/cmd/go/testdata/testvendor/src/p/p.go new file mode 100644 index 0000000..e740715 --- /dev/null +++ b/vendor/cmd/go/testdata/testvendor/src/p/p.go
@@ -0,0 +1,6 @@ +package p + +import ( + _ "q/y" + _ "q/z" +)
diff --git a/vendor/cmd/go/testdata/testvendor/src/q/vendor/x/x.go b/vendor/cmd/go/testdata/testvendor/src/q/vendor/x/x.go new file mode 100644 index 0000000..823aafd --- /dev/null +++ b/vendor/cmd/go/testdata/testvendor/src/q/vendor/x/x.go
@@ -0,0 +1 @@ +package x
diff --git a/vendor/cmd/go/testdata/testvendor/src/q/y/y.go b/vendor/cmd/go/testdata/testvendor/src/q/y/y.go new file mode 100644 index 0000000..4f84223 --- /dev/null +++ b/vendor/cmd/go/testdata/testvendor/src/q/y/y.go
@@ -0,0 +1,3 @@ +package y + +import _ "x"
diff --git a/vendor/cmd/go/testdata/testvendor/src/q/z/z.go b/vendor/cmd/go/testdata/testvendor/src/q/z/z.go new file mode 100644 index 0000000..a8d4924 --- /dev/null +++ b/vendor/cmd/go/testdata/testvendor/src/q/z/z.go
@@ -0,0 +1,3 @@ +package z + +import _ "q/vendor/x"
diff --git a/vendor/cmd/go/testdata/testvendor2/src/p/p.go b/vendor/cmd/go/testdata/testvendor2/src/p/p.go new file mode 100644 index 0000000..220b2b2 --- /dev/null +++ b/vendor/cmd/go/testdata/testvendor2/src/p/p.go
@@ -0,0 +1,3 @@ +package p + +import "x"
diff --git a/vendor/cmd/go/testdata/testvendor2/vendor/x/x.go b/vendor/cmd/go/testdata/testvendor2/vendor/x/x.go new file mode 100644 index 0000000..823aafd --- /dev/null +++ b/vendor/cmd/go/testdata/testvendor2/vendor/x/x.go
@@ -0,0 +1 @@ +package x
diff --git a/vendor/cmd/go/testdata/timeoutbench_test.go b/vendor/cmd/go/testdata/timeoutbench_test.go new file mode 100644 index 0000000..57a8888 --- /dev/null +++ b/vendor/cmd/go/testdata/timeoutbench_test.go
@@ -0,0 +1,10 @@ +package timeoutbench_test + +import ( + "testing" + "time" +) + +func BenchmarkSleep1s(b *testing.B) { + time.Sleep(1 * time.Second) +}
diff --git a/vendor/cmd/go/vendor_test.go b/vendor/cmd/go/vendor_test.go new file mode 100644 index 0000000..e276828 --- /dev/null +++ b/vendor/cmd/go/vendor_test.go
@@ -0,0 +1,330 @@ +// Copyright 2015 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. + +// Tests for vendoring semantics. + +package Main_test + +import ( + "bytes" + "fmt" + "internal/testenv" + "path/filepath" + "regexp" + "strings" + "testing" +) + +func TestVendorImports(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("list", "-f", "{{.ImportPath}} {{.Imports}}", "vend/...", "vend/vendor/...", "vend/x/vendor/...") + want := ` + vend [vend/vendor/p r] + vend/dir1 [] + vend/hello [fmt vend/vendor/strings] + vend/subdir [vend/vendor/p r] + vend/x [vend/x/vendor/p vend/vendor/q vend/x/vendor/r vend/dir1 vend/vendor/vend/dir1/dir2] + vend/x/invalid [vend/x/invalid/vendor/foo] + vend/vendor/p [] + vend/vendor/q [] + vend/vendor/strings [] + vend/vendor/vend/dir1/dir2 [] + vend/x/vendor/p [] + vend/x/vendor/p/p [notfound] + vend/x/vendor/r [] + ` + want = strings.Replace(want+"\t", "\n\t\t", "\n", -1) + want = strings.TrimPrefix(want, "\n") + + have := tg.stdout.String() + + if have != want { + t.Errorf("incorrect go list output:\n%s", diffSortedOutputs(have, want)) + } +} + +func TestVendorBuild(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("build", "vend/x") +} + +func TestVendorRun(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.cd(filepath.Join(tg.pwd(), "testdata/src/vend/hello")) + tg.run("run", "hello.go") + tg.grepStdout("hello, world", "missing hello world output") +} + +func TestVendorGOPATH(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + changeVolume := func(s string, f func(s string) string) string { + vol := filepath.VolumeName(s) + return f(vol) + s[len(vol):] + } + gopath := changeVolume(filepath.Join(tg.pwd(), "testdata"), strings.ToLower) + tg.setenv("GOPATH", gopath) + cd := changeVolume(filepath.Join(tg.pwd(), "testdata/src/vend/hello"), strings.ToUpper) + tg.cd(cd) + tg.run("run", "hello.go") + tg.grepStdout("hello, world", "missing hello world output") +} + +func TestVendorTest(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.cd(filepath.Join(tg.pwd(), "testdata/src/vend/hello")) + tg.run("test", "-v") + tg.grepStdout("TestMsgInternal", "missing use in internal test") + tg.grepStdout("TestMsgExternal", "missing use in external test") +} + +func TestVendorInvalid(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + + tg.runFail("build", "vend/x/invalid") + tg.grepStderr("must be imported as foo", "missing vendor import error") +} + +func TestVendorImportError(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + + tg.runFail("build", "vend/x/vendor/p/p") + + re := regexp.MustCompile(`cannot find package "notfound" in any of: + .*[\\/]testdata[\\/]src[\\/]vend[\\/]x[\\/]vendor[\\/]notfound \(vendor tree\) + .*[\\/]testdata[\\/]src[\\/]vend[\\/]vendor[\\/]notfound + .*[\\/]src[\\/]notfound \(from \$GOROOT\) + .*[\\/]testdata[\\/]src[\\/]notfound \(from \$GOPATH\)`) + + if !re.MatchString(tg.stderr.String()) { + t.Errorf("did not find expected search list in error text") + } +} + +// diffSortedOutput prepares a diff of the already sorted outputs haveText and wantText. +// The diff shows common lines prefixed by a tab, lines present only in haveText +// prefixed by "unexpected: ", and lines present only in wantText prefixed by "missing: ". +func diffSortedOutputs(haveText, wantText string) string { + var diff bytes.Buffer + have := splitLines(haveText) + want := splitLines(wantText) + for len(have) > 0 || len(want) > 0 { + if len(want) == 0 || len(have) > 0 && have[0] < want[0] { + fmt.Fprintf(&diff, "unexpected: %s\n", have[0]) + have = have[1:] + continue + } + if len(have) == 0 || len(want) > 0 && want[0] < have[0] { + fmt.Fprintf(&diff, "missing: %s\n", want[0]) + want = want[1:] + continue + } + fmt.Fprintf(&diff, "\t%s\n", want[0]) + want = want[1:] + have = have[1:] + } + return diff.String() +} + +func splitLines(s string) []string { + x := strings.Split(s, "\n") + if x[len(x)-1] == "" { + x = x[:len(x)-1] + } + return x +} + +func TestVendorGet(t *testing.T) { + tooSlow(t) + tg := testgo(t) + defer tg.cleanup() + tg.tempFile("src/v/m.go", ` + package main + import ("fmt"; "vendor.org/p") + func main() { + fmt.Println(p.C) + }`) + tg.tempFile("src/v/m_test.go", ` + package main + import ("fmt"; "testing"; "vendor.org/p") + func TestNothing(t *testing.T) { + fmt.Println(p.C) + }`) + tg.tempFile("src/v/vendor/vendor.org/p/p.go", ` + package p + const C = 1`) + tg.setenv("GOPATH", tg.path(".")) + tg.cd(tg.path("src/v")) + tg.run("run", "m.go") + tg.run("test") + tg.run("list", "-f", "{{.Imports}}") + tg.grepStdout("v/vendor/vendor.org/p", "import not in vendor directory") + tg.run("list", "-f", "{{.TestImports}}") + tg.grepStdout("v/vendor/vendor.org/p", "test import not in vendor directory") + tg.run("get", "-d") + tg.run("get", "-t", "-d") +} + +func TestVendorGetUpdate(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.run("get", "github.com/rsc/go-get-issue-11864") + tg.run("get", "-u", "github.com/rsc/go-get-issue-11864") +} + +func TestVendorGetU(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.run("get", "-u", "github.com/rsc/go-get-issue-11864") +} + +func TestVendorGetTU(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.run("get", "-t", "-u", "github.com/rsc/go-get-issue-11864/...") +} + +func TestVendorGetBadVendor(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + for _, suffix := range []string{"bad/imp", "bad/imp2", "bad/imp3", "..."} { + t.Run(suffix, func(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.runFail("get", "-t", "-u", "github.com/rsc/go-get-issue-18219/"+suffix) + tg.grepStderr("must be imported as", "did not find error about vendor import") + tg.mustNotExist(tg.path("src/github.com/rsc/vendor")) + }) + } +} + +func TestGetSubmodules(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.run("get", "-d", "github.com/rsc/go-get-issue-12612") + tg.run("get", "-u", "-d", "github.com/rsc/go-get-issue-12612") + tg.mustExist(tg.path("src/github.com/rsc/go-get-issue-12612/vendor/golang.org/x/crypto/.git")) +} + +func TestVendorCache(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor")) + tg.runFail("build", "p") + tg.grepStderr("must be imported as x", "did not fail to build p") +} + +func TestVendorTest2(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.run("get", "github.com/rsc/go-get-issue-11864") + + // build -i should work + tg.run("build", "-i", "github.com/rsc/go-get-issue-11864") + tg.run("build", "-i", "github.com/rsc/go-get-issue-11864/t") + + // test -i should work like build -i (golang.org/issue/11988) + tg.run("test", "-i", "github.com/rsc/go-get-issue-11864") + tg.run("test", "-i", "github.com/rsc/go-get-issue-11864/t") + + // test should work too + tg.run("test", "github.com/rsc/go-get-issue-11864") + tg.run("test", "github.com/rsc/go-get-issue-11864/t") + + // external tests should observe internal test exports (golang.org/issue/11977) + tg.run("test", "github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2") +} + +func TestVendorTest3(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.run("get", "github.com/clsung/go-vendor-issue-14613") + + tg.run("build", "-o", tg.path("a.out"), "-i", "github.com/clsung/go-vendor-issue-14613") + + // test folder should work + tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613") + tg.run("test", "github.com/clsung/go-vendor-issue-14613") + + // test with specified _test.go should work too + tg.cd(filepath.Join(tg.path("."), "src")) + tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613/vendor_test.go") + tg.run("test", "github.com/clsung/go-vendor-issue-14613/vendor_test.go") + + // test with imported and not used + tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go") + tg.runFail("test", "github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go") + tg.grepStderr("imported and not used:", `should say "imported and not used"`) +} + +func TestVendorList(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.run("get", "github.com/rsc/go-get-issue-11864") + + tg.run("list", "-f", `{{join .TestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/t") + tg.grepStdout("go-get-issue-11864/vendor/vendor.org/p", "did not find vendor-expanded p") + + tg.run("list", "-f", `{{join .XTestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/tx") + tg.grepStdout("go-get-issue-11864/vendor/vendor.org/p", "did not find vendor-expanded p") + + tg.run("list", "-f", `{{join .XTestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2") + tg.grepStdout("go-get-issue-11864/vendor/vendor.org/tx2", "did not find vendor-expanded tx2") + + tg.run("list", "-f", `{{join .XTestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3") + tg.grepStdout("go-get-issue-11864/vendor/vendor.org/tx3", "did not find vendor-expanded tx3") +} + +func TestVendor12156(t *testing.T) { + // Former index out of range panic. + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor2")) + tg.cd(filepath.Join(tg.pwd(), "testdata/testvendor2/src/p")) + tg.runFail("build", "p.go") + tg.grepStderrNot("panic", "panicked") + tg.grepStderr(`cannot find package "x"`, "wrong error") +}
diff --git a/vendor/cmd/internal/browser/browser.go b/vendor/cmd/internal/browser/browser.go new file mode 100644 index 0000000..6867c85 --- /dev/null +++ b/vendor/cmd/internal/browser/browser.go
@@ -0,0 +1,67 @@ +// Copyright 2016 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 browser provides utilities for interacting with users' browsers. +package browser + +import ( + "os" + "os/exec" + "runtime" + "time" +) + +// Commands returns a list of possible commands to use to open a url. +func Commands() [][]string { + var cmds [][]string + if exe := os.Getenv("BROWSER"); exe != "" { + cmds = append(cmds, []string{exe}) + } + switch runtime.GOOS { + case "darwin": + cmds = append(cmds, []string{"/usr/bin/open"}) + case "windows": + cmds = append(cmds, []string{"cmd", "/c", "start"}) + default: + if os.Getenv("DISPLAY") != "" { + // xdg-open is only for use in a desktop environment. + cmds = append(cmds, []string{"xdg-open"}) + } + } + cmds = append(cmds, + []string{"chrome"}, + []string{"google-chrome"}, + []string{"chromium"}, + []string{"firefox"}, + ) + return cmds +} + +// Open tries to open url in a browser and reports whether it succeeded. +func Open(url string) bool { + for _, args := range Commands() { + cmd := exec.Command(args[0], append(args[1:], url)...) + if cmd.Start() == nil && appearsSuccessful(cmd, 3*time.Second) { + return true + } + } + return false +} + +// appearsSuccessful reports whether the command appears to have run successfully. +// If the command runs longer than the timeout, it's deemed successful. +// If the command runs within the timeout, it's deemed successful if it exited cleanly. +func appearsSuccessful(cmd *exec.Cmd, timeout time.Duration) bool { + errc := make(chan error, 1) + go func() { + errc <- cmd.Wait() + }() + + select { + case <-time.After(timeout): + return true + case err := <-errc: + return err == nil + } +}
diff --git a/vendor/cmd/internal/buildid/buildid.go b/vendor/cmd/internal/buildid/buildid.go new file mode 100644 index 0000000..fa3d7f3 --- /dev/null +++ b/vendor/cmd/internal/buildid/buildid.go
@@ -0,0 +1,238 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package buildid + +import ( + "bytes" + "debug/elf" + "fmt" + "io" + "os" + "strconv" + "strings" +) + +var ( + errBuildIDToolchain = fmt.Errorf("build ID only supported in gc toolchain") + errBuildIDMalformed = fmt.Errorf("malformed object file") + errBuildIDUnknown = fmt.Errorf("lost build ID") +) + +var ( + bangArch = []byte("!<arch>") + pkgdef = []byte("__.PKGDEF") + goobject = []byte("go object ") + buildid = []byte("build id ") +) + +// ReadFile reads the build ID from an archive or executable file. +func ReadFile(name string) (id string, err error) { + f, err := os.Open(name) + if err != nil { + return "", err + } + defer f.Close() + + buf := make([]byte, 8) + if _, err := f.ReadAt(buf, 0); err != nil { + return "", err + } + if string(buf) != "!<arch>\n" { + return readBinary(name, f) + } + + // Read just enough of the target to fetch the build ID. + // The archive is expected to look like: + // + // !<arch> + // __.PKGDEF 0 0 0 644 7955 ` + // go object darwin amd64 devel X:none + // build id "b41e5c45250e25c9fd5e9f9a1de7857ea0d41224" + // + // The variable-sized strings are GOOS, GOARCH, and the experiment list (X:none). + // Reading the first 1024 bytes should be plenty. + data := make([]byte, 1024) + n, err := io.ReadFull(f, data) + if err != nil && n == 0 { + return "", err + } + + tryGccgo := func() (string, error) { + return readGccgoArchive(name, f) + } + + // Archive header. + for i := 0; ; i++ { // returns during i==3 + j := bytes.IndexByte(data, '\n') + if j < 0 { + return tryGccgo() + } + line := data[:j] + data = data[j+1:] + switch i { + case 0: + if !bytes.Equal(line, bangArch) { + return tryGccgo() + } + case 1: + if !bytes.HasPrefix(line, pkgdef) { + return tryGccgo() + } + case 2: + if !bytes.HasPrefix(line, goobject) { + return tryGccgo() + } + case 3: + if !bytes.HasPrefix(line, buildid) { + // Found the object header, just doesn't have a build id line. + // Treat as successful, with empty build id. + return "", nil + } + id, err := strconv.Unquote(string(line[len(buildid):])) + if err != nil { + return tryGccgo() + } + return id, nil + } + } +} + +// readGccgoArchive tries to parse the archive as a standard Unix +// archive file, and fetch the build ID from the _buildid.o entry. +// The _buildid.o entry is written by (*Builder).gccgoBuildIDELFFile +// in cmd/go/internal/work/exec.go. +func readGccgoArchive(name string, f *os.File) (string, error) { + bad := func() (string, error) { + return "", &os.PathError{Op: "parse", Path: name, Err: errBuildIDMalformed} + } + + off := int64(8) + for { + if _, err := f.Seek(off, io.SeekStart); err != nil { + return "", err + } + + // TODO(iant): Make a debug/ar package, and use it + // here and in cmd/link. + var hdr [60]byte + if _, err := io.ReadFull(f, hdr[:]); err != nil { + if err == io.EOF { + // No more entries, no build ID. + return "", nil + } + return "", err + } + off += 60 + + sizeStr := strings.TrimSpace(string(hdr[48:58])) + size, err := strconv.ParseInt(sizeStr, 0, 64) + if err != nil { + return bad() + } + + name := strings.TrimSpace(string(hdr[:16])) + if name == "_buildid.o/" { + sr := io.NewSectionReader(f, off, size) + e, err := elf.NewFile(sr) + if err != nil { + return bad() + } + s := e.Section(".go.buildid") + if s == nil { + return bad() + } + data, err := s.Data() + if err != nil { + return bad() + } + return string(data), nil + } + + off += size + if off&1 != 0 { + off++ + } + } +} + +var ( + goBuildPrefix = []byte("\xff Go build ID: \"") + goBuildEnd = []byte("\"\n \xff") + + elfPrefix = []byte("\x7fELF") + + machoPrefixes = [][]byte{ + {0xfe, 0xed, 0xfa, 0xce}, + {0xfe, 0xed, 0xfa, 0xcf}, + {0xce, 0xfa, 0xed, 0xfe}, + {0xcf, 0xfa, 0xed, 0xfe}, + } +) + +var readSize = 32 * 1024 // changed for testing + +// readBinary reads the build ID from a binary. +// +// ELF binaries store the build ID in a proper PT_NOTE section. +// +// Other binary formats are not so flexible. For those, the linker +// stores the build ID as non-instruction bytes at the very beginning +// of the text segment, which should appear near the beginning +// of the file. This is clumsy but fairly portable. Custom locations +// can be added for other binary types as needed, like we did for ELF. +func readBinary(name string, f *os.File) (id string, err error) { + // Read the first 32 kB of the binary file. + // That should be enough to find the build ID. + // In ELF files, the build ID is in the leading headers, + // which are typically less than 4 kB, not to mention 32 kB. + // In Mach-O files, there's no limit, so we have to parse the file. + // On other systems, we're trying to read enough that + // we get the beginning of the text segment in the read. + // The offset where the text segment begins in a hello + // world compiled for each different object format today: + // + // Plan 9: 0x20 + // Windows: 0x600 + // + data := make([]byte, readSize) + _, err = io.ReadFull(f, data) + if err == io.ErrUnexpectedEOF { + err = nil + } + if err != nil { + return "", err + } + + if bytes.HasPrefix(data, elfPrefix) { + return readELF(name, f, data) + } + for _, m := range machoPrefixes { + if bytes.HasPrefix(data, m) { + return readMacho(name, f, data) + } + } + return readRaw(name, data) +} + +// readRaw finds the raw build ID stored in text segment data. +func readRaw(name string, data []byte) (id string, err error) { + i := bytes.Index(data, goBuildPrefix) + if i < 0 { + // Missing. Treat as successful but build ID empty. + return "", nil + } + + j := bytes.Index(data[i+len(goBuildPrefix):], goBuildEnd) + if j < 0 { + return "", &os.PathError{Op: "parse", Path: name, Err: errBuildIDMalformed} + } + + quoted := data[i+len(goBuildPrefix)-1 : i+len(goBuildPrefix)+j+1] + id, err = strconv.Unquote(string(quoted)) + if err != nil { + return "", &os.PathError{Op: "parse", Path: name, Err: errBuildIDMalformed} + } + return id, nil +}
diff --git a/vendor/cmd/internal/buildid/buildid_test.go b/vendor/cmd/internal/buildid/buildid_test.go new file mode 100644 index 0000000..15481dd --- /dev/null +++ b/vendor/cmd/internal/buildid/buildid_test.go
@@ -0,0 +1,137 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package buildid + +import ( + "bytes" + "crypto/sha256" + "io/ioutil" + "os" + "reflect" + "testing" +) + +const ( + expectedID = "abcdefghijklmnopqrstuvwxyz.1234567890123456789012345678901234567890123456789012345678901234" + newID = "bcdefghijklmnopqrstuvwxyza.2345678901234567890123456789012345678901234567890123456789012341" +) + +func TestReadFile(t *testing.T) { + var files = []string{ + "p.a", + "a.elf", + "a.macho", + "a.pe", + } + + f, err := ioutil.TempFile("", "buildid-test-") + if err != nil { + t.Fatal(err) + } + tmp := f.Name() + defer os.Remove(tmp) + f.Close() + + for _, f := range files { + id, err := ReadFile("testdata/" + f) + if id != expectedID || err != nil { + t.Errorf("ReadFile(testdata/%s) = %q, %v, want %q, nil", f, id, err, expectedID) + } + old := readSize + readSize = 2048 + id, err = ReadFile("testdata/" + f) + readSize = old + if id != expectedID || err != nil { + t.Errorf("ReadFile(testdata/%s) [readSize=2k] = %q, %v, want %q, nil", f, id, err, expectedID) + } + + data, err := ioutil.ReadFile("testdata/" + f) + if err != nil { + t.Fatal(err) + } + m, _, err := FindAndHash(bytes.NewReader(data), expectedID, 1024) + if err != nil { + t.Errorf("FindAndHash(testdata/%s): %v", f, err) + continue + } + if err := ioutil.WriteFile(tmp, data, 0666); err != nil { + t.Error(err) + continue + } + tf, err := os.OpenFile(tmp, os.O_WRONLY, 0) + if err != nil { + t.Error(err) + continue + } + err = Rewrite(tf, m, newID) + err2 := tf.Close() + if err != nil { + t.Errorf("Rewrite(testdata/%s): %v", f, err) + continue + } + if err2 != nil { + t.Fatal(err2) + } + + id, err = ReadFile(tmp) + if id != newID || err != nil { + t.Errorf("ReadFile(testdata/%s after Rewrite) = %q, %v, want %q, nil", f, id, err, newID) + } + } +} + +func TestFindAndHash(t *testing.T) { + buf := make([]byte, 64) + buf2 := make([]byte, 64) + id := make([]byte, 8) + zero := make([]byte, 8) + for i := range id { + id[i] = byte(i) + } + numError := 0 + errorf := func(msg string, args ...interface{}) { + t.Errorf(msg, args...) + if numError++; numError > 20 { + t.Logf("stopping after too many errors") + t.FailNow() + } + } + for bufSize := len(id); bufSize <= len(buf); bufSize++ { + for j := range buf { + for k := 0; k < 2*len(id) && j+k < len(buf); k++ { + for i := range buf { + buf[i] = 1 + } + copy(buf[j:], id) + copy(buf[j+k:], id) + var m []int64 + if j+len(id) <= j+k { + m = append(m, int64(j)) + } + if j+k+len(id) <= len(buf) { + m = append(m, int64(j+k)) + } + copy(buf2, buf) + for _, p := range m { + copy(buf2[p:], zero) + } + h := sha256.Sum256(buf2) + + matches, hash, err := FindAndHash(bytes.NewReader(buf), string(id), bufSize) + if err != nil { + errorf("bufSize=%d j=%d k=%d: findAndHash: %v", bufSize, j, k, err) + continue + } + if !reflect.DeepEqual(matches, m) { + errorf("bufSize=%d j=%d k=%d: findAndHash: matches=%v, want %v", bufSize, j, k, matches, m) + continue + } + if hash != h { + errorf("bufSize=%d j=%d k=%d: findAndHash: matches correct, but hash=%x, want %x", bufSize, j, k, hash, h) + } + } + } + } +}
diff --git a/vendor/cmd/internal/buildid/note.go b/vendor/cmd/internal/buildid/note.go new file mode 100644 index 0000000..f0439fb --- /dev/null +++ b/vendor/cmd/internal/buildid/note.go
@@ -0,0 +1,206 @@ +// Copyright 2015 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 buildid + +import ( + "bytes" + "debug/elf" + "debug/macho" + "encoding/binary" + "fmt" + "io" + "os" +) + +func readAligned4(r io.Reader, sz int32) ([]byte, error) { + full := (sz + 3) &^ 3 + data := make([]byte, full) + _, err := io.ReadFull(r, data) + if err != nil { + return nil, err + } + data = data[:sz] + return data, nil +} + +func ReadELFNote(filename, name string, typ int32) ([]byte, error) { + f, err := elf.Open(filename) + if err != nil { + return nil, err + } + for _, sect := range f.Sections { + if sect.Type != elf.SHT_NOTE { + continue + } + r := sect.Open() + for { + var namesize, descsize, noteType int32 + err = binary.Read(r, f.ByteOrder, &namesize) + if err != nil { + if err == io.EOF { + break + } + return nil, fmt.Errorf("read namesize failed: %v", err) + } + err = binary.Read(r, f.ByteOrder, &descsize) + if err != nil { + return nil, fmt.Errorf("read descsize failed: %v", err) + } + err = binary.Read(r, f.ByteOrder, ¬eType) + if err != nil { + return nil, fmt.Errorf("read type failed: %v", err) + } + noteName, err := readAligned4(r, namesize) + if err != nil { + return nil, fmt.Errorf("read name failed: %v", err) + } + desc, err := readAligned4(r, descsize) + if err != nil { + return nil, fmt.Errorf("read desc failed: %v", err) + } + if name == string(noteName) && typ == noteType { + return desc, nil + } + } + } + return nil, nil +} + +var elfGoNote = []byte("Go\x00\x00") +var elfGNUNote = []byte("GNU\x00") + +// The Go build ID is stored in a note described by an ELF PT_NOTE prog +// header. The caller has already opened filename, to get f, and read +// at least 4 kB out, in data. +func readELF(name string, f *os.File, data []byte) (buildid string, err error) { + // Assume the note content is in the data, already read. + // Rewrite the ELF header to set shnum to 0, so that we can pass + // the data to elf.NewFile and it will decode the Prog list but not + // try to read the section headers and the string table from disk. + // That's a waste of I/O when all we care about is the Prog list + // and the one ELF note. + switch elf.Class(data[elf.EI_CLASS]) { + case elf.ELFCLASS32: + data[48] = 0 + data[49] = 0 + case elf.ELFCLASS64: + data[60] = 0 + data[61] = 0 + } + + const elfGoBuildIDTag = 4 + const gnuBuildIDTag = 3 + + ef, err := elf.NewFile(bytes.NewReader(data)) + if err != nil { + return "", &os.PathError{Path: name, Op: "parse", Err: err} + } + var gnu string + for _, p := range ef.Progs { + if p.Type != elf.PT_NOTE || p.Filesz < 16 { + continue + } + + var note []byte + if p.Off+p.Filesz < uint64(len(data)) { + note = data[p.Off : p.Off+p.Filesz] + } else { + // For some linkers, such as the Solaris linker, + // the buildid may not be found in data (which + // likely contains the first 16kB of the file) + // or even the first few megabytes of the file + // due to differences in note segment placement; + // in that case, extract the note data manually. + _, err = f.Seek(int64(p.Off), io.SeekStart) + if err != nil { + return "", err + } + + note = make([]byte, p.Filesz) + _, err = io.ReadFull(f, note) + if err != nil { + return "", err + } + } + + filesz := p.Filesz + off := p.Off + for filesz >= 16 { + nameSize := ef.ByteOrder.Uint32(note) + valSize := ef.ByteOrder.Uint32(note[4:]) + tag := ef.ByteOrder.Uint32(note[8:]) + nname := note[12:16] + if nameSize == 4 && 16+valSize <= uint32(len(note)) && tag == elfGoBuildIDTag && bytes.Equal(nname, elfGoNote) { + return string(note[16 : 16+valSize]), nil + } + + if nameSize == 4 && 16+valSize <= uint32(len(note)) && tag == gnuBuildIDTag && bytes.Equal(nname, elfGNUNote) { + gnu = string(note[16 : 16+valSize]) + } + + nameSize = (nameSize + 3) &^ 3 + valSize = (valSize + 3) &^ 3 + notesz := uint64(12 + nameSize + valSize) + if filesz <= notesz { + break + } + off += notesz + align := uint64(p.Align) + alignedOff := (off + align - 1) &^ (align - 1) + notesz += alignedOff - off + off = alignedOff + filesz -= notesz + note = note[notesz:] + } + } + + // If we didn't find a Go note, use a GNU note if available. + // This is what gccgo uses. + if gnu != "" { + return gnu, nil + } + + // No note. Treat as successful but build ID empty. + return "", nil +} + +// The Go build ID is stored at the beginning of the Mach-O __text segment. +// The caller has already opened filename, to get f, and read a few kB out, in data. +// Sadly, that's not guaranteed to hold the note, because there is an arbitrary amount +// of other junk placed in the file ahead of the main text. +func readMacho(name string, f *os.File, data []byte) (buildid string, err error) { + // If the data we want has already been read, don't worry about Mach-O parsing. + // This is both an optimization and a hedge against the Mach-O parsing failing + // in the future due to, for example, the name of the __text section changing. + if b, err := readRaw(name, data); b != "" && err == nil { + return b, err + } + + mf, err := macho.NewFile(f) + if err != nil { + return "", &os.PathError{Path: name, Op: "parse", Err: err} + } + + sect := mf.Section("__text") + if sect == nil { + // Every binary has a __text section. Something is wrong. + return "", &os.PathError{Path: name, Op: "parse", Err: fmt.Errorf("cannot find __text section")} + } + + // It should be in the first few bytes, but read a lot just in case, + // especially given our past problems on OS X with the build ID moving. + // There shouldn't be much difference between reading 4kB and 32kB: + // the hard part is getting to the data, not transferring it. + n := sect.Size + if n > uint64(readSize) { + n = uint64(readSize) + } + buf := make([]byte, n) + if _, err := f.ReadAt(buf, int64(sect.Offset)); err != nil { + return "", err + } + + return readRaw(name, buf) +}
diff --git a/vendor/cmd/internal/buildid/rewrite.go b/vendor/cmd/internal/buildid/rewrite.go new file mode 100644 index 0000000..5be5455 --- /dev/null +++ b/vendor/cmd/internal/buildid/rewrite.go
@@ -0,0 +1,91 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package buildid + +import ( + "bytes" + "crypto/sha256" + "fmt" + "io" +) + +// FindAndHash reads all of r and returns the offsets of occurrences of id. +// While reading, findAndHash also computes and returns +// a hash of the content of r, but with occurrences of id replaced by zeros. +// FindAndHash reads bufSize bytes from r at a time. +// If bufSize == 0, FindAndHash uses a reasonable default. +func FindAndHash(r io.Reader, id string, bufSize int) (matches []int64, hash [32]byte, err error) { + if bufSize == 0 { + bufSize = 31 * 1024 // bufSize+little will likely fit in 32 kB + } + if len(id) > bufSize { + return nil, [32]byte{}, fmt.Errorf("buildid.FindAndHash: buffer too small") + } + zeros := make([]byte, len(id)) + idBytes := []byte(id) + + // The strategy is to read the file through buf, looking for id, + // but we need to worry about what happens if id is broken up + // and returned in parts by two different reads. + // We allocate a tiny buffer (at least len(id)) and a big buffer (bufSize bytes) + // next to each other in memory and then copy the tail of + // one read into the tiny buffer before reading new data into the big buffer. + // The search for id is over the entire tiny+big buffer. + tiny := (len(id) + 127) &^ 127 // round up to 128-aligned + buf := make([]byte, tiny+bufSize) + h := sha256.New() + start := tiny + for offset := int64(0); ; { + // The file offset maintained by the loop corresponds to &buf[tiny]. + // buf[start:tiny] is left over from previous iteration. + // After reading n bytes into buf[tiny:], we process buf[start:tiny+n]. + n, err := io.ReadFull(r, buf[tiny:]) + if err != io.ErrUnexpectedEOF && err != io.EOF && err != nil { + return nil, [32]byte{}, err + } + + // Process any matches. + for { + i := bytes.Index(buf[start:tiny+n], idBytes) + if i < 0 { + break + } + matches = append(matches, offset+int64(start+i-tiny)) + h.Write(buf[start : start+i]) + h.Write(zeros) + start += i + len(id) + } + if n < bufSize { + // Did not fill buffer, must be at end of file. + h.Write(buf[start : tiny+n]) + break + } + + // Process all but final tiny bytes of buf (bufSize = len(buf)-tiny). + // Note that start > len(buf)-tiny is possible, if the search above + // found an id ending in the final tiny fringe. That's OK. + if start < len(buf)-tiny { + h.Write(buf[start : len(buf)-tiny]) + start = len(buf) - tiny + } + + // Slide ending tiny-sized fringe to beginning of buffer. + copy(buf[0:], buf[bufSize:]) + start -= bufSize + offset += int64(bufSize) + } + h.Sum(hash[:0]) + return matches, hash, nil +} + +func Rewrite(w io.WriterAt, pos []int64, id string) error { + b := []byte(id) + for _, p := range pos { + if _, err := w.WriteAt(b, p); err != nil { + return err + } + } + return nil +}
diff --git a/vendor/cmd/internal/buildid/testdata/a.elf b/vendor/cmd/internal/buildid/testdata/a.elf new file mode 100755 index 0000000..f631289 --- /dev/null +++ b/vendor/cmd/internal/buildid/testdata/a.elf Binary files differ
diff --git a/vendor/cmd/internal/buildid/testdata/a.macho b/vendor/cmd/internal/buildid/testdata/a.macho new file mode 100755 index 0000000..fbbd57c --- /dev/null +++ b/vendor/cmd/internal/buildid/testdata/a.macho Binary files differ
diff --git a/vendor/cmd/internal/buildid/testdata/a.pe b/vendor/cmd/internal/buildid/testdata/a.pe new file mode 100755 index 0000000..9120272 --- /dev/null +++ b/vendor/cmd/internal/buildid/testdata/a.pe Binary files differ
diff --git a/vendor/cmd/internal/buildid/testdata/p.a b/vendor/cmd/internal/buildid/testdata/p.a new file mode 100644 index 0000000..dcc3e76 --- /dev/null +++ b/vendor/cmd/internal/buildid/testdata/p.a Binary files differ
diff --git a/vendor/cmd/internal/test2json/test2json.go b/vendor/cmd/internal/test2json/test2json.go new file mode 100644 index 0000000..483fb1d --- /dev/null +++ b/vendor/cmd/internal/test2json/test2json.go
@@ -0,0 +1,445 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package test2json implements conversion of test binary output to JSON. +// It is used by cmd/test2json and cmd/go. +// +// See the cmd/test2json documentation for details of the JSON encoding. +package test2json + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "strconv" + "strings" + "time" + "unicode" + "unicode/utf8" +) + +// Mode controls details of the conversion. +type Mode int + +const ( + Timestamp Mode = 1 << iota // include Time in events +) + +// event is the JSON struct we emit. +type event struct { + Time *time.Time `json:",omitempty"` + Action string + Package string `json:",omitempty"` + Test string `json:",omitempty"` + Elapsed *float64 `json:",omitempty"` + Output *textBytes `json:",omitempty"` +} + +// textBytes is a hack to get JSON to emit a []byte as a string +// without actually copying it to a string. +// It implements encoding.TextMarshaler, which returns its text form as a []byte, +// and then json encodes that text form as a string (which was our goal). +type textBytes []byte + +func (b textBytes) MarshalText() ([]byte, error) { return b, nil } + +// A converter holds the state of a test-to-JSON conversion. +// It implements io.WriteCloser; the caller writes test output in, +// and the converter writes JSON output to w. +type converter struct { + w io.Writer // JSON output stream + pkg string // package to name in events + mode Mode // mode bits + start time.Time // time converter started + testName string // name of current test, for output attribution + report []*event // pending test result reports (nested for subtests) + result string // overall test result if seen + input lineBuffer // input buffer + output lineBuffer // output buffer +} + +// inBuffer and outBuffer are the input and output buffer sizes. +// They're variables so that they can be reduced during testing. +// +// The input buffer needs to be able to hold any single test +// directive line we want to recognize, like: +// +// <many spaces> --- PASS: very/nested/s/u/b/t/e/s/t +// +// If anyone reports a test directive line > 4k not working, it will +// be defensible to suggest they restructure their test or test names. +// +// The output buffer must be >= utf8.UTFMax, so that it can +// accumulate any single UTF8 sequence. Lines that fit entirely +// within the output buffer are emitted in single output events. +// Otherwise they are split into multiple events. +// The output buffer size therefore limits the size of the encoding +// of a single JSON output event. 1k seems like a reasonable balance +// between wanting to avoid splitting an output line and not wanting to +// generate enormous output events. +var ( + inBuffer = 4096 + outBuffer = 1024 +) + +// NewConverter returns a "test to json" converter. +// Writes on the returned writer are written as JSON to w, +// with minimal delay. +// +// The writes to w are whole JSON events ending in \n, +// so that it is safe to run multiple tests writing to multiple converters +// writing to a single underlying output stream w. +// As long as the underlying output w can handle concurrent writes +// from multiple goroutines, the result will be a JSON stream +// describing the relative ordering of execution in all the concurrent tests. +// +// The mode flag adjusts the behavior of the converter. +// Passing ModeTime includes event timestamps and elapsed times. +// +// The pkg string, if present, specifies the import path to +// report in the JSON stream. +func NewConverter(w io.Writer, pkg string, mode Mode) io.WriteCloser { + c := new(converter) + *c = converter{ + w: w, + pkg: pkg, + mode: mode, + start: time.Now(), + input: lineBuffer{ + b: make([]byte, 0, inBuffer), + line: c.handleInputLine, + part: c.output.write, + }, + output: lineBuffer{ + b: make([]byte, 0, outBuffer), + line: c.writeOutputEvent, + part: c.writeOutputEvent, + }, + } + return c +} + +// Write writes the test input to the converter. +func (c *converter) Write(b []byte) (int, error) { + c.input.write(b) + return len(b), nil +} + +var ( + bigPass = []byte("PASS\n") + bigFail = []byte("FAIL\n") + + updates = [][]byte{ + []byte("=== RUN "), + []byte("=== PAUSE "), + []byte("=== CONT "), + } + + reports = [][]byte{ + []byte("--- PASS: "), + []byte("--- FAIL: "), + []byte("--- SKIP: "), + []byte("--- BENCH: "), + } + + fourSpace = []byte(" ") + + skipLinePrefix = []byte("? \t") + skipLineSuffix = []byte("\t[no test files]\n") +) + +// handleInputLine handles a single whole test output line. +// It must write the line to c.output but may choose to do so +// before or after emitting other events. +func (c *converter) handleInputLine(line []byte) { + // Final PASS or FAIL. + if bytes.Equal(line, bigPass) || bytes.Equal(line, bigFail) { + c.flushReport(0) + c.output.write(line) + if bytes.Equal(line, bigPass) { + c.result = "pass" + } else { + c.result = "fail" + } + return + } + + // Special case for entirely skipped test binary: "? \tpkgname\t[no test files]\n" is only line. + // Report it as plain output but remember to say skip in the final summary. + if bytes.HasPrefix(line, skipLinePrefix) && bytes.HasSuffix(line, skipLineSuffix) && len(c.report) == 0 { + c.result = "skip" + } + + // "=== RUN " + // "=== PAUSE " + // "=== CONT " + origLine := line + ok := false + indent := 0 + for _, magic := range updates { + if bytes.HasPrefix(line, magic) { + ok = true + break + } + } + if !ok { + // "--- PASS: " + // "--- FAIL: " + // "--- SKIP: " + // "--- BENCH: " + // but possibly indented. + for bytes.HasPrefix(line, fourSpace) { + line = line[4:] + indent++ + } + for _, magic := range reports { + if bytes.HasPrefix(line, magic) { + ok = true + break + } + } + } + + if !ok { + // Not a special test output line. + c.output.write(origLine) + return + } + + // Parse out action and test name. + i := bytes.IndexByte(line, ':') + 1 + if i == 0 { + i = len(updates[0]) + } + action := strings.ToLower(strings.TrimSuffix(strings.TrimSpace(string(line[4:i])), ":")) + name := strings.TrimSpace(string(line[i:])) + + e := &event{Action: action} + if line[0] == '-' { // PASS or FAIL report + // Parse out elapsed time. + if i := strings.Index(name, " ("); i >= 0 { + if strings.HasSuffix(name, "s)") { + t, err := strconv.ParseFloat(name[i+2:len(name)-2], 64) + if err == nil { + if c.mode&Timestamp != 0 { + e.Elapsed = &t + } + } + } + name = name[:i] + } + if len(c.report) < indent { + // Nested deeper than expected. + // Treat this line as plain output. + c.output.write(origLine) + return + } + // Flush reports at this indentation level or deeper. + c.flushReport(indent) + e.Test = name + c.testName = name + c.report = append(c.report, e) + c.output.write(origLine) + return + } + // === update. + // Finish any pending PASS/FAIL reports. + c.flushReport(0) + c.testName = name + + if action == "pause" { + // For a pause, we want to write the pause notification before + // delivering the pause event, just so it doesn't look like the test + // is generating output immediately after being paused. + c.output.write(origLine) + } + c.writeEvent(e) + if action != "pause" { + c.output.write(origLine) + } + + return +} + +// flushReport flushes all pending PASS/FAIL reports at levels >= depth. +func (c *converter) flushReport(depth int) { + c.testName = "" + for len(c.report) > depth { + e := c.report[len(c.report)-1] + c.report = c.report[:len(c.report)-1] + c.writeEvent(e) + } +} + +// Close marks the end of the go test output. +// It flushes any pending input and then output (only partial lines at this point) +// and then emits the final overall package-level pass/fail event. +func (c *converter) Close() error { + c.input.flush() + c.output.flush() + e := &event{Action: "fail"} + if c.result != "" { + e.Action = c.result + } + if c.mode&Timestamp != 0 { + dt := time.Since(c.start).Round(1 * time.Millisecond).Seconds() + e.Elapsed = &dt + } + c.writeEvent(e) + return nil +} + +// writeOutputEvent writes a single output event with the given bytes. +func (c *converter) writeOutputEvent(out []byte) { + c.writeEvent(&event{ + Action: "output", + Output: (*textBytes)(&out), + }) +} + +// writeEvent writes a single event. +// It adds the package, time (if requested), and test name (if needed). +func (c *converter) writeEvent(e *event) { + e.Package = c.pkg + if c.mode&Timestamp != 0 { + t := time.Now() + e.Time = &t + } + if e.Test == "" { + e.Test = c.testName + } + js, err := json.Marshal(e) + if err != nil { + // Should not happen - event is valid for json.Marshal. + c.w.Write([]byte(fmt.Sprintf("testjson internal error: %v\n", err))) + return + } + js = append(js, '\n') + c.w.Write(js) +} + +// A lineBuffer is an I/O buffer that reacts to writes by invoking +// input-processing callbacks on whole lines or (for long lines that +// have been split) line fragments. +// +// It should be initialized with b set to a buffer of length 0 but non-zero capacity, +// and line and part set to the desired input processors. +// The lineBuffer will call line(x) for any whole line x (including the final newline) +// that fits entirely in cap(b). It will handle input lines longer than cap(b) by +// calling part(x) for sections of the line. The line will be split at UTF8 boundaries, +// and the final call to part for a long line includes the final newline. +type lineBuffer struct { + b []byte // buffer + mid bool // whether we're in the middle of a long line + line func([]byte) // line callback + part func([]byte) // partial line callback +} + +// write writes b to the buffer. +func (l *lineBuffer) write(b []byte) { + for len(b) > 0 { + // Copy what we can into b. + m := copy(l.b[len(l.b):cap(l.b)], b) + l.b = l.b[:len(l.b)+m] + b = b[m:] + + // Process lines in b. + i := 0 + for i < len(l.b) { + j := bytes.IndexByte(l.b[i:], '\n') + if j < 0 { + if !l.mid { + if j := bytes.IndexByte(l.b[i:], '\t'); j >= 0 { + if isBenchmarkName(bytes.TrimRight(l.b[i:i+j], " ")) { + l.part(l.b[i : i+j+1]) + l.mid = true + i += j + 1 + } + } + } + break + } + e := i + j + 1 + if l.mid { + // Found the end of a partial line. + l.part(l.b[i:e]) + l.mid = false + } else { + // Found a whole line. + l.line(l.b[i:e]) + } + i = e + } + + // Whatever's left in l.b is a line fragment. + if i == 0 && len(l.b) == cap(l.b) { + // The whole buffer is a fragment. + // Emit it as the beginning (or continuation) of a partial line. + t := trimUTF8(l.b) + l.part(l.b[:t]) + l.b = l.b[:copy(l.b, l.b[t:])] + l.mid = true + } + + // There's room for more input. + // Slide it down in hope of completing the line. + if i > 0 { + l.b = l.b[:copy(l.b, l.b[i:])] + } + } +} + +// flush flushes the line buffer. +func (l *lineBuffer) flush() { + if len(l.b) > 0 { + // Must be a line without a \n, so a partial line. + l.part(l.b) + l.b = l.b[:0] + } +} + +var benchmark = []byte("Benchmark") + +// isBenchmarkName reports whether b is a valid benchmark name +// that might appear as the first field in a benchmark result line. +func isBenchmarkName(b []byte) bool { + if !bytes.HasPrefix(b, benchmark) { + return false + } + if len(b) == len(benchmark) { // just "Benchmark" + return true + } + r, _ := utf8.DecodeRune(b[len(benchmark):]) + return !unicode.IsLower(r) +} + +// trimUTF8 returns a length t as close to len(b) as possible such that b[:t] +// does not end in the middle of a possibly-valid UTF-8 sequence. +// +// If a large text buffer must be split before position i at the latest, +// splitting at position trimUTF(b[:i]) avoids splitting a UTF-8 sequence. +func trimUTF8(b []byte) int { + // Scan backward to find non-continuation byte. + for i := 1; i < utf8.UTFMax && i <= len(b); i++ { + if c := b[len(b)-i]; c&0xc0 != 0x80 { + switch { + case c&0xe0 == 0xc0: + if i < 2 { + return len(b) - i + } + case c&0xf0 == 0xe0: + if i < 3 { + return len(b) - i + } + case c&0xf8 == 0xf0: + if i < 4 { + return len(b) - i + } + } + break + } + } + return len(b) +}
diff --git a/vendor/cmd/internal/test2json/test2json_test.go b/vendor/cmd/internal/test2json/test2json_test.go new file mode 100644 index 0000000..4683907 --- /dev/null +++ b/vendor/cmd/internal/test2json/test2json_test.go
@@ -0,0 +1,277 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package test2json + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "io" + "io/ioutil" + "path/filepath" + "reflect" + "strings" + "testing" + "unicode/utf8" +) + +var update = flag.Bool("update", false, "rewrite testdata/*.json files") + +func TestGolden(t *testing.T) { + files, err := filepath.Glob("testdata/*.test") + if err != nil { + t.Fatal(err) + } + for _, file := range files { + name := strings.TrimSuffix(filepath.Base(file), ".test") + t.Run(name, func(t *testing.T) { + orig, err := ioutil.ReadFile(file) + if err != nil { + t.Fatal(err) + } + + // Test one line written to c at a time. + // Assume that's the most likely to be handled correctly. + var buf bytes.Buffer + c := NewConverter(&buf, "", 0) + in := append([]byte{}, orig...) + for _, line := range bytes.SplitAfter(in, []byte("\n")) { + writeAndKill(c, line) + } + c.Close() + + if *update { + js := strings.TrimSuffix(file, ".test") + ".json" + t.Logf("rewriting %s", js) + if err := ioutil.WriteFile(js, buf.Bytes(), 0666); err != nil { + t.Fatal(err) + } + return + } + + want, err := ioutil.ReadFile(strings.TrimSuffix(file, ".test") + ".json") + if err != nil { + t.Fatal(err) + } + diffJSON(t, buf.Bytes(), want) + if t.Failed() { + // If the line-at-a-time conversion fails, no point testing boundary conditions. + return + } + + // Write entire input in bulk. + t.Run("bulk", func(t *testing.T) { + buf.Reset() + c = NewConverter(&buf, "", 0) + in = append([]byte{}, orig...) + writeAndKill(c, in) + c.Close() + diffJSON(t, buf.Bytes(), want) + }) + + // Write 2 bytes at a time on even boundaries. + t.Run("even2", func(t *testing.T) { + buf.Reset() + c = NewConverter(&buf, "", 0) + in = append([]byte{}, orig...) + for i := 0; i < len(in); i += 2 { + if i+2 <= len(in) { + writeAndKill(c, in[i:i+2]) + } else { + writeAndKill(c, in[i:]) + } + } + c.Close() + diffJSON(t, buf.Bytes(), want) + }) + + // Write 2 bytes at a time on odd boundaries. + t.Run("odd2", func(t *testing.T) { + buf.Reset() + c = NewConverter(&buf, "", 0) + in = append([]byte{}, orig...) + if len(in) > 0 { + writeAndKill(c, in[:1]) + } + for i := 1; i < len(in); i += 2 { + if i+2 <= len(in) { + writeAndKill(c, in[i:i+2]) + } else { + writeAndKill(c, in[i:]) + } + } + c.Close() + diffJSON(t, buf.Bytes(), want) + }) + + // Test with very small output buffers, to check that + // UTF8 sequences are not broken up. + for b := 5; b <= 8; b++ { + t.Run(fmt.Sprintf("tiny%d", b), func(t *testing.T) { + oldIn := inBuffer + oldOut := outBuffer + defer func() { + inBuffer = oldIn + outBuffer = oldOut + }() + inBuffer = 64 + outBuffer = b + buf.Reset() + c = NewConverter(&buf, "", 0) + in = append([]byte{}, orig...) + writeAndKill(c, in) + c.Close() + diffJSON(t, buf.Bytes(), want) + }) + } + }) + } +} + +// writeAndKill writes b to w and then fills b with Zs. +// The filling makes sure that if w is holding onto b for +// future use, that future use will have obviously wrong data. +func writeAndKill(w io.Writer, b []byte) { + w.Write(b) + for i := range b { + b[i] = 'Z' + } +} + +// diffJSON diffs the stream we have against the stream we want +// and fails the test with a useful message if they don't match. +func diffJSON(t *testing.T, have, want []byte) { + t.Helper() + type event map[string]interface{} + + // Parse into events, one per line. + parseEvents := func(b []byte) ([]event, []string) { + t.Helper() + var events []event + var lines []string + for _, line := range bytes.SplitAfter(b, []byte("\n")) { + if len(line) > 0 { + line = bytes.TrimSpace(line) + var e event + err := json.Unmarshal(line, &e) + if err != nil { + t.Errorf("unmarshal %s: %v", b, err) + continue + } + events = append(events, e) + lines = append(lines, string(line)) + } + } + return events, lines + } + haveEvents, haveLines := parseEvents(have) + wantEvents, wantLines := parseEvents(want) + if t.Failed() { + return + } + + // Make sure the events we have match the events we want. + // At each step we're matching haveEvents[i] against wantEvents[j]. + // i and j can move independently due to choices about exactly + // how to break up text in "output" events. + i := 0 + j := 0 + + // Fail reports a failure at the current i,j and stops the test. + // It shows the events around the current positions, + // with the current positions marked. + fail := func() { + var buf bytes.Buffer + show := func(i int, lines []string) { + for k := -2; k < 5; k++ { + marker := "" + if k == 0 { + marker = "» " + } + if 0 <= i+k && i+k < len(lines) { + fmt.Fprintf(&buf, "\t%s%s\n", marker, lines[i+k]) + } + } + if i >= len(lines) { + // show marker after end of input + fmt.Fprintf(&buf, "\t» \n") + } + } + fmt.Fprintf(&buf, "have:\n") + show(i, haveLines) + fmt.Fprintf(&buf, "want:\n") + show(j, wantLines) + t.Fatal(buf.String()) + } + + var outputTest string // current "Test" key in "output" events + var wantOutput, haveOutput string // collected "Output" of those events + + // getTest returns the "Test" setting, or "" if it is missing. + getTest := func(e event) string { + s, _ := e["Test"].(string) + return s + } + + // checkOutput collects output from the haveEvents for the current outputTest + // and then checks that the collected output matches the wanted output. + checkOutput := func() { + for i < len(haveEvents) && haveEvents[i]["Action"] == "output" && getTest(haveEvents[i]) == outputTest { + haveOutput += haveEvents[i]["Output"].(string) + i++ + } + if haveOutput != wantOutput { + t.Errorf("output mismatch for Test=%q:\nhave %q\nwant %q", outputTest, haveOutput, wantOutput) + fail() + } + haveOutput = "" + wantOutput = "" + } + + // Walk through wantEvents matching against haveEvents. + for j = range wantEvents { + e := wantEvents[j] + if e["Action"] == "output" && getTest(e) == outputTest { + wantOutput += e["Output"].(string) + continue + } + checkOutput() + if e["Action"] == "output" { + outputTest = getTest(e) + wantOutput += e["Output"].(string) + continue + } + if i >= len(haveEvents) { + t.Errorf("early end of event stream: missing event") + fail() + } + if !reflect.DeepEqual(haveEvents[i], e) { + t.Errorf("events out of sync") + fail() + } + i++ + } + checkOutput() + if i < len(haveEvents) { + t.Errorf("extra events in stream") + fail() + } +} + +func TestTrimUTF8(t *testing.T) { + s := "hello α ☺ 😂 world" // α is 2-byte, ☺ is 3-byte, 😂 is 4-byte + b := []byte(s) + for i := 0; i < len(s); i++ { + j := trimUTF8(b[:i]) + u := string([]rune(s[:j])) + string([]rune(s[j:])) + if u != s { + t.Errorf("trimUTF8(%q) = %d (-%d), not at boundary (split: %q %q)", s[:i], j, i-j, s[:j], s[j:]) + } + if utf8.FullRune(b[j:i]) { + t.Errorf("trimUTF8(%q) = %d (-%d), too early (missed: %q)", s[:j], j, i-j, s[j:i]) + } + } +}
diff --git a/vendor/cmd/internal/test2json/testdata/ascii.json b/vendor/cmd/internal/test2json/testdata/ascii.json new file mode 100644 index 0000000..67fccfc --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/ascii.json
@@ -0,0 +1,10 @@ +{"Action":"run","Test":"TestAscii"} +{"Action":"output","Test":"TestAscii","Output":"=== RUN TestAscii\n"} +{"Action":"output","Test":"TestAscii","Output":"I can eat glass, and it doesn't hurt me. I can eat glass, and it doesn't hurt me.\n"} +{"Action":"output","Test":"TestAscii","Output":"I CAN EAT GLASS, AND IT DOESN'T HURT ME. I CAN EAT GLASS, AND IT DOESN'T HURT ME.\n"} +{"Action":"output","Test":"TestAscii","Output":"--- PASS: TestAscii\n"} +{"Action":"output","Test":"TestAscii","Output":" i can eat glass, and it doesn't hurt me. i can eat glass, and it doesn't hurt me.\n"} +{"Action":"output","Test":"TestAscii","Output":" V PNA RNG TYNFF, NAQ VG QBRFA'G UHEG ZR. V PNA RNG TYNFF, NAQ VG QBRFA'G UHEG ZR.\n"} +{"Action":"pass","Test":"TestAscii"} +{"Action":"output","Output":"PASS\n"} +{"Action":"pass"}
diff --git a/vendor/cmd/internal/test2json/testdata/ascii.test b/vendor/cmd/internal/test2json/testdata/ascii.test new file mode 100644 index 0000000..4ff7453 --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/ascii.test
@@ -0,0 +1,7 @@ +=== RUN TestAscii +I can eat glass, and it doesn't hurt me. I can eat glass, and it doesn't hurt me. +I CAN EAT GLASS, AND IT DOESN'T HURT ME. I CAN EAT GLASS, AND IT DOESN'T HURT ME. +--- PASS: TestAscii + i can eat glass, and it doesn't hurt me. i can eat glass, and it doesn't hurt me. + V PNA RNG TYNFF, NAQ VG QBRFA'G UHEG ZR. V PNA RNG TYNFF, NAQ VG QBRFA'G UHEG ZR. +PASS
diff --git a/vendor/cmd/internal/test2json/testdata/bench.json b/vendor/cmd/internal/test2json/testdata/bench.json new file mode 100644 index 0000000..69e417e --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/bench.json
@@ -0,0 +1,14 @@ +{"Action":"output","Output":"goos: darwin\n"} +{"Action":"output","Output":"goarch: 386\n"} +{"Action":"output","Output":"BenchmarkFoo-8 \t2000000000\t 0.00 ns/op\n"} +{"Action":"output","Test":"BenchmarkFoo-8","Output":"--- BENCH: BenchmarkFoo-8\n"} +{"Action":"output","Test":"BenchmarkFoo-8","Output":"\tx_test.go:8: My benchmark\n"} +{"Action":"output","Test":"BenchmarkFoo-8","Output":"\tx_test.go:8: My benchmark\n"} +{"Action":"output","Test":"BenchmarkFoo-8","Output":"\tx_test.go:8: My benchmark\n"} +{"Action":"output","Test":"BenchmarkFoo-8","Output":"\tx_test.go:8: My benchmark\n"} +{"Action":"output","Test":"BenchmarkFoo-8","Output":"\tx_test.go:8: My benchmark\n"} +{"Action":"output","Test":"BenchmarkFoo-8","Output":"\tx_test.go:8: My benchmark\n"} +{"Action":"bench","Test":"BenchmarkFoo-8"} +{"Action":"output","Output":"PASS\n"} +{"Action":"output","Output":"ok \tcommand-line-arguments\t0.009s\n"} +{"Action":"pass"}
diff --git a/vendor/cmd/internal/test2json/testdata/bench.test b/vendor/cmd/internal/test2json/testdata/bench.test new file mode 100644 index 0000000..453bd59 --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/bench.test
@@ -0,0 +1,12 @@ +goos: darwin +goarch: 386 +BenchmarkFoo-8 2000000000 0.00 ns/op +--- BENCH: BenchmarkFoo-8 + x_test.go:8: My benchmark + x_test.go:8: My benchmark + x_test.go:8: My benchmark + x_test.go:8: My benchmark + x_test.go:8: My benchmark + x_test.go:8: My benchmark +PASS +ok command-line-arguments 0.009s
diff --git a/vendor/cmd/internal/test2json/testdata/benchfail.json b/vendor/cmd/internal/test2json/testdata/benchfail.json new file mode 100644 index 0000000..ad3ac9e --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/benchfail.json
@@ -0,0 +1,6 @@ +{"Action":"output","Test":"BenchmarkFoo","Output":"--- FAIL: BenchmarkFoo\n"} +{"Action":"output","Test":"BenchmarkFoo","Output":"\tx_test.go:8: My benchmark\n"} +{"Action":"fail","Test":"BenchmarkFoo"} +{"Action":"output","Output":"FAIL\n"} +{"Action":"output","Output":"FAIL\tcommand-line-arguments\t0.008s\n"} +{"Action":"fail"}
diff --git a/vendor/cmd/internal/test2json/testdata/benchfail.test b/vendor/cmd/internal/test2json/testdata/benchfail.test new file mode 100644 index 0000000..538d957 --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/benchfail.test
@@ -0,0 +1,4 @@ +--- FAIL: BenchmarkFoo + x_test.go:8: My benchmark +FAIL +FAIL command-line-arguments 0.008s
diff --git a/vendor/cmd/internal/test2json/testdata/benchshort.json b/vendor/cmd/internal/test2json/testdata/benchshort.json new file mode 100644 index 0000000..8c61d95 --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/benchshort.json
@@ -0,0 +1,7 @@ +{"Action":"output","Output":"# This file ends in an early EOF to trigger the Benchmark prefix test,\n"} +{"Action":"output","Output":"# which only happens when a benchmark prefix is seen ahead of the \\n.\n"} +{"Action":"output","Output":"# Normally that's due to the benchmark running and the \\n coming later,\n"} +{"Action":"output","Output":"# but to avoid questions of timing, we just use a file with no \\n at all.\n"} +{"Action":"output","Output":"BenchmarkFoo \t"} +{"Action":"output","Output":"10000 early EOF"} +{"Action":"fail"}
diff --git a/vendor/cmd/internal/test2json/testdata/benchshort.test b/vendor/cmd/internal/test2json/testdata/benchshort.test new file mode 100644 index 0000000..0b173ab --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/benchshort.test
@@ -0,0 +1,5 @@ +# This file ends in an early EOF to trigger the Benchmark prefix test, +# which only happens when a benchmark prefix is seen ahead of the \n. +# Normally that's due to the benchmark running and the \n coming later, +# but to avoid questions of timing, we just use a file with no \n at all. +BenchmarkFoo 10000 early EOF \ No newline at end of file
diff --git a/vendor/cmd/internal/test2json/testdata/issue23036.json b/vendor/cmd/internal/test2json/testdata/issue23036.json new file mode 100644 index 0000000..935c0c5 --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/issue23036.json
@@ -0,0 +1,12 @@ +{"Action":"run","Test":"TestActualCase"} +{"Action":"output","Test":"TestActualCase","Output":"=== RUN TestActualCase\n"} +{"Action":"output","Test":"TestActualCase","Output":"--- FAIL: TestActualCase (0.00s)\n"} +{"Action":"output","Test":"TestActualCase","Output":" foo_test.go:14: Differed.\n"} +{"Action":"output","Test":"TestActualCase","Output":" Expected: MyTest:\n"} +{"Action":"output","Test":"TestActualCase","Output":" --- FAIL: Test output from other tool\n"} +{"Action":"output","Test":"TestActualCase","Output":" Actual: not expected\n"} +{"Action":"fail","Test":"TestActualCase"} +{"Action":"output","Output":"FAIL\n"} +{"Action":"output","Output":"exit status 1\n"} +{"Action":"output","Output":"FAIL github.com/org/project/badtest 0.049s\n"} +{"Action":"fail"}
diff --git a/vendor/cmd/internal/test2json/testdata/issue23036.test b/vendor/cmd/internal/test2json/testdata/issue23036.test new file mode 100644 index 0000000..fd4774f --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/issue23036.test
@@ -0,0 +1,9 @@ +=== RUN TestActualCase +--- FAIL: TestActualCase (0.00s) + foo_test.go:14: Differed. + Expected: MyTest: + --- FAIL: Test output from other tool + Actual: not expected +FAIL +exit status 1 +FAIL github.com/org/project/badtest 0.049s
diff --git a/vendor/cmd/internal/test2json/testdata/smiley.json b/vendor/cmd/internal/test2json/testdata/smiley.json new file mode 100644 index 0000000..afa990d --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/smiley.json
@@ -0,0 +1,182 @@ +{"Action":"run","Test":"Test☺☹"} +{"Action":"output","Test":"Test☺☹","Output":"=== RUN Test☺☹\n"} +{"Action":"output","Test":"Test☺☹","Output":"=== PAUSE Test☺☹\n"} +{"Action":"pause","Test":"Test☺☹"} +{"Action":"run","Test":"Test☺☹Asm"} +{"Action":"output","Test":"Test☺☹Asm","Output":"=== RUN Test☺☹Asm\n"} +{"Action":"output","Test":"Test☺☹Asm","Output":"=== PAUSE Test☺☹Asm\n"} +{"Action":"pause","Test":"Test☺☹Asm"} +{"Action":"run","Test":"Test☺☹Dirs"} +{"Action":"output","Test":"Test☺☹Dirs","Output":"=== RUN Test☺☹Dirs\n"} +{"Action":"output","Test":"Test☺☹Dirs","Output":"=== PAUSE Test☺☹Dirs\n"} +{"Action":"pause","Test":"Test☺☹Dirs"} +{"Action":"run","Test":"TestTags"} +{"Action":"output","Test":"TestTags","Output":"=== RUN TestTags\n"} +{"Action":"output","Test":"TestTags","Output":"=== PAUSE TestTags\n"} +{"Action":"pause","Test":"TestTags"} +{"Action":"run","Test":"Test☺☹Verbose"} +{"Action":"output","Test":"Test☺☹Verbose","Output":"=== RUN Test☺☹Verbose\n"} +{"Action":"output","Test":"Test☺☹Verbose","Output":"=== PAUSE Test☺☹Verbose\n"} +{"Action":"pause","Test":"Test☺☹Verbose"} +{"Action":"cont","Test":"Test☺☹"} +{"Action":"output","Test":"Test☺☹","Output":"=== CONT Test☺☹\n"} +{"Action":"cont","Test":"TestTags"} +{"Action":"output","Test":"TestTags","Output":"=== CONT TestTags\n"} +{"Action":"cont","Test":"Test☺☹Verbose"} +{"Action":"output","Test":"Test☺☹Verbose","Output":"=== CONT Test☺☹Verbose\n"} +{"Action":"run","Test":"TestTags/testtag"} +{"Action":"output","Test":"TestTags/testtag","Output":"=== RUN TestTags/testtag\n"} +{"Action":"output","Test":"TestTags/testtag","Output":"=== PAUSE TestTags/testtag\n"} +{"Action":"pause","Test":"TestTags/testtag"} +{"Action":"cont","Test":"Test☺☹Dirs"} +{"Action":"output","Test":"Test☺☹Dirs","Output":"=== CONT Test☺☹Dirs\n"} +{"Action":"cont","Test":"Test☺☹Asm"} +{"Action":"output","Test":"Test☺☹Asm","Output":"=== CONT Test☺☹Asm\n"} +{"Action":"run","Test":"Test☺☹/0"} +{"Action":"output","Test":"Test☺☹/0","Output":"=== RUN Test☺☹/0\n"} +{"Action":"output","Test":"Test☺☹/0","Output":"=== PAUSE Test☺☹/0\n"} +{"Action":"pause","Test":"Test☺☹/0"} +{"Action":"run","Test":"Test☺☹/1"} +{"Action":"output","Test":"Test☺☹/1","Output":"=== RUN Test☺☹/1\n"} +{"Action":"output","Test":"Test☺☹/1","Output":"=== PAUSE Test☺☹/1\n"} +{"Action":"pause","Test":"Test☺☹/1"} +{"Action":"run","Test":"Test☺☹/2"} +{"Action":"output","Test":"Test☺☹/2","Output":"=== RUN Test☺☹/2\n"} +{"Action":"output","Test":"Test☺☹/2","Output":"=== PAUSE Test☺☹/2\n"} +{"Action":"pause","Test":"Test☺☹/2"} +{"Action":"run","Test":"Test☺☹/3"} +{"Action":"output","Test":"Test☺☹/3","Output":"=== RUN Test☺☹/3\n"} +{"Action":"output","Test":"Test☺☹/3","Output":"=== PAUSE Test☺☹/3\n"} +{"Action":"pause","Test":"Test☺☹/3"} +{"Action":"run","Test":"Test☺☹/4"} +{"Action":"output","Test":"Test☺☹/4","Output":"=== RUN Test☺☹/4\n"} +{"Action":"run","Test":"TestTags/x_testtag_y"} +{"Action":"output","Test":"TestTags/x_testtag_y","Output":"=== RUN TestTags/x_testtag_y\n"} +{"Action":"output","Test":"Test☺☹/4","Output":"=== PAUSE Test☺☹/4\n"} +{"Action":"pause","Test":"Test☺☹/4"} +{"Action":"run","Test":"Test☺☹/5"} +{"Action":"output","Test":"Test☺☹/5","Output":"=== RUN Test☺☹/5\n"} +{"Action":"output","Test":"Test☺☹/5","Output":"=== PAUSE Test☺☹/5\n"} +{"Action":"pause","Test":"Test☺☹/5"} +{"Action":"output","Test":"TestTags/x_testtag_y","Output":"=== PAUSE TestTags/x_testtag_y\n"} +{"Action":"pause","Test":"TestTags/x_testtag_y"} +{"Action":"run","Test":"Test☺☹/6"} +{"Action":"output","Test":"Test☺☹/6","Output":"=== RUN Test☺☹/6\n"} +{"Action":"run","Test":"TestTags/x,testtag,y"} +{"Action":"output","Test":"TestTags/x,testtag,y","Output":"=== RUN TestTags/x,testtag,y\n"} +{"Action":"output","Test":"TestTags/x,testtag,y","Output":"=== PAUSE TestTags/x,testtag,y\n"} +{"Action":"pause","Test":"TestTags/x,testtag,y"} +{"Action":"run","Test":"Test☺☹Dirs/testingpkg"} +{"Action":"output","Test":"Test☺☹Dirs/testingpkg","Output":"=== RUN Test☺☹Dirs/testingpkg\n"} +{"Action":"output","Test":"Test☺☹/6","Output":"=== PAUSE Test☺☹/6\n"} +{"Action":"pause","Test":"Test☺☹/6"} +{"Action":"cont","Test":"TestTags/x,testtag,y"} +{"Action":"output","Test":"TestTags/x,testtag,y","Output":"=== CONT TestTags/x,testtag,y\n"} +{"Action":"output","Test":"Test☺☹Dirs/testingpkg","Output":"=== PAUSE Test☺☹Dirs/testingpkg\n"} +{"Action":"pause","Test":"Test☺☹Dirs/testingpkg"} +{"Action":"run","Test":"Test☺☹Dirs/divergent"} +{"Action":"output","Test":"Test☺☹Dirs/divergent","Output":"=== RUN Test☺☹Dirs/divergent\n"} +{"Action":"run","Test":"Test☺☹/7"} +{"Action":"output","Test":"Test☺☹/7","Output":"=== RUN Test☺☹/7\n"} +{"Action":"output","Test":"Test☺☹/7","Output":"=== PAUSE Test☺☹/7\n"} +{"Action":"pause","Test":"Test☺☹/7"} +{"Action":"output","Test":"Test☺☹Dirs/divergent","Output":"=== PAUSE Test☺☹Dirs/divergent\n"} +{"Action":"pause","Test":"Test☺☹Dirs/divergent"} +{"Action":"cont","Test":"TestTags/x_testtag_y"} +{"Action":"output","Test":"TestTags/x_testtag_y","Output":"=== CONT TestTags/x_testtag_y\n"} +{"Action":"cont","Test":"TestTags/testtag"} +{"Action":"output","Test":"TestTags/testtag","Output":"=== CONT TestTags/testtag\n"} +{"Action":"run","Test":"Test☺☹Dirs/buildtag"} +{"Action":"output","Test":"Test☺☹Dirs/buildtag","Output":"=== RUN Test☺☹Dirs/buildtag\n"} +{"Action":"output","Test":"Test☺☹Dirs/buildtag","Output":"=== PAUSE Test☺☹Dirs/buildtag\n"} +{"Action":"pause","Test":"Test☺☹Dirs/buildtag"} +{"Action":"cont","Test":"Test☺☹/0"} +{"Action":"output","Test":"Test☺☹/0","Output":"=== CONT Test☺☹/0\n"} +{"Action":"cont","Test":"Test☺☹/4"} +{"Action":"output","Test":"Test☺☹/4","Output":"=== CONT Test☺☹/4\n"} +{"Action":"run","Test":"Test☺☹Dirs/incomplete"} +{"Action":"output","Test":"Test☺☹Dirs/incomplete","Output":"=== RUN Test☺☹Dirs/incomplete\n"} +{"Action":"output","Test":"Test☺☹Dirs/incomplete","Output":"=== PAUSE Test☺☹Dirs/incomplete\n"} +{"Action":"pause","Test":"Test☺☹Dirs/incomplete"} +{"Action":"run","Test":"Test☺☹Dirs/cgo"} +{"Action":"output","Test":"Test☺☹Dirs/cgo","Output":"=== RUN Test☺☹Dirs/cgo\n"} +{"Action":"output","Test":"Test☺☹Dirs/cgo","Output":"=== PAUSE Test☺☹Dirs/cgo\n"} +{"Action":"pause","Test":"Test☺☹Dirs/cgo"} +{"Action":"cont","Test":"Test☺☹/7"} +{"Action":"output","Test":"Test☺☹/7","Output":"=== CONT Test☺☹/7\n"} +{"Action":"cont","Test":"Test☺☹/6"} +{"Action":"output","Test":"Test☺☹/6","Output":"=== CONT Test☺☹/6\n"} +{"Action":"output","Test":"Test☺☹Verbose","Output":"--- PASS: Test☺☹Verbose (0.04s)\n"} +{"Action":"pass","Test":"Test☺☹Verbose"} +{"Action":"cont","Test":"Test☺☹/5"} +{"Action":"output","Test":"Test☺☹/5","Output":"=== CONT Test☺☹/5\n"} +{"Action":"cont","Test":"Test☺☹/3"} +{"Action":"output","Test":"Test☺☹/3","Output":"=== CONT Test☺☹/3\n"} +{"Action":"cont","Test":"Test☺☹/2"} +{"Action":"output","Test":"Test☺☹/2","Output":"=== CONT Test☺☹/2\n"} +{"Action":"output","Test":"TestTags","Output":"--- PASS: TestTags (0.00s)\n"} +{"Action":"output","Test":"TestTags/x_testtag_y","Output":" --- PASS: TestTags/x_testtag_y (0.04s)\n"} +{"Action":"output","Test":"TestTags/x_testtag_y","Output":" \tvet_test.go:187: -tags=x testtag y\n"} +{"Action":"pass","Test":"TestTags/x_testtag_y"} +{"Action":"output","Test":"TestTags/x,testtag,y","Output":" --- PASS: TestTags/x,testtag,y (0.04s)\n"} +{"Action":"output","Test":"TestTags/x,testtag,y","Output":" \tvet_test.go:187: -tags=x,testtag,y\n"} +{"Action":"pass","Test":"TestTags/x,testtag,y"} +{"Action":"output","Test":"TestTags/testtag","Output":" --- PASS: TestTags/testtag (0.04s)\n"} +{"Action":"output","Test":"TestTags/testtag","Output":" \tvet_test.go:187: -tags=testtag\n"} +{"Action":"pass","Test":"TestTags/testtag"} +{"Action":"pass","Test":"TestTags"} +{"Action":"cont","Test":"Test☺☹/1"} +{"Action":"output","Test":"Test☺☹/1","Output":"=== CONT Test☺☹/1\n"} +{"Action":"cont","Test":"Test☺☹Dirs/testingpkg"} +{"Action":"output","Test":"Test☺☹Dirs/testingpkg","Output":"=== CONT Test☺☹Dirs/testingpkg\n"} +{"Action":"cont","Test":"Test☺☹Dirs/buildtag"} +{"Action":"output","Test":"Test☺☹Dirs/buildtag","Output":"=== CONT Test☺☹Dirs/buildtag\n"} +{"Action":"cont","Test":"Test☺☹Dirs/divergent"} +{"Action":"output","Test":"Test☺☹Dirs/divergent","Output":"=== CONT Test☺☹Dirs/divergent\n"} +{"Action":"cont","Test":"Test☺☹Dirs/incomplete"} +{"Action":"output","Test":"Test☺☹Dirs/incomplete","Output":"=== CONT Test☺☹Dirs/incomplete\n"} +{"Action":"cont","Test":"Test☺☹Dirs/cgo"} +{"Action":"output","Test":"Test☺☹Dirs/cgo","Output":"=== CONT Test☺☹Dirs/cgo\n"} +{"Action":"output","Test":"Test☺☹","Output":"--- PASS: Test☺☹ (0.39s)\n"} +{"Action":"output","Test":"Test☺☹/5","Output":" --- PASS: Test☺☹/5 (0.07s)\n"} +{"Action":"output","Test":"Test☺☹/5","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/copylock_func.go\" \"testdata/rangeloop.go\"]\n"} +{"Action":"pass","Test":"Test☺☹/5"} +{"Action":"output","Test":"Test☺☹/3","Output":" --- PASS: Test☺☹/3 (0.07s)\n"} +{"Action":"output","Test":"Test☺☹/3","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/composite.go\" \"testdata/nilfunc.go\"]\n"} +{"Action":"pass","Test":"Test☺☹/3"} +{"Action":"output","Test":"Test☺☹/6","Output":" --- PASS: Test☺☹/6 (0.07s)\n"} +{"Action":"output","Test":"Test☺☹/6","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/copylock_range.go\" \"testdata/shadow.go\"]\n"} +{"Action":"pass","Test":"Test☺☹/6"} +{"Action":"output","Test":"Test☺☹/2","Output":" --- PASS: Test☺☹/2 (0.07s)\n"} +{"Action":"output","Test":"Test☺☹/2","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/bool.go\" \"testdata/method.go\" \"testdata/unused.go\"]\n"} +{"Action":"pass","Test":"Test☺☹/2"} +{"Action":"output","Test":"Test☺☹/0","Output":" --- PASS: Test☺☹/0 (0.13s)\n"} +{"Action":"output","Test":"Test☺☹/0","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/assign.go\" \"testdata/httpresponse.go\" \"testdata/structtag.go\"]\n"} +{"Action":"pass","Test":"Test☺☹/0"} +{"Action":"output","Test":"Test☺☹/4","Output":" --- PASS: Test☺☹/4 (0.16s)\n"} +{"Action":"output","Test":"Test☺☹/4","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/copylock.go\" \"testdata/print.go\"]\n"} +{"Action":"pass","Test":"Test☺☹/4"} +{"Action":"output","Test":"Test☺☹/1","Output":" --- PASS: Test☺☹/1 (0.07s)\n"} +{"Action":"output","Test":"Test☺☹/1","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/atomic.go\" \"testdata/lostcancel.go\" \"testdata/unsafeptr.go\"]\n"} +{"Action":"pass","Test":"Test☺☹/1"} +{"Action":"output","Test":"Test☺☹/7","Output":" --- PASS: Test☺☹/7 (0.19s)\n"} +{"Action":"output","Test":"Test☺☹/7","Output":" \tvet_test.go:114: φιλεσ: [\"testdata/deadcode.go\" \"testdata/shift.go\"]\n"} +{"Action":"pass","Test":"Test☺☹/7"} +{"Action":"pass","Test":"Test☺☹"} +{"Action":"output","Test":"Test☺☹Dirs","Output":"--- PASS: Test☺☹Dirs (0.01s)\n"} +{"Action":"output","Test":"Test☺☹Dirs/testingpkg","Output":" --- PASS: Test☺☹Dirs/testingpkg (0.06s)\n"} +{"Action":"pass","Test":"Test☺☹Dirs/testingpkg"} +{"Action":"output","Test":"Test☺☹Dirs/divergent","Output":" --- PASS: Test☺☹Dirs/divergent (0.05s)\n"} +{"Action":"pass","Test":"Test☺☹Dirs/divergent"} +{"Action":"output","Test":"Test☺☹Dirs/buildtag","Output":" --- PASS: Test☺☹Dirs/buildtag (0.06s)\n"} +{"Action":"pass","Test":"Test☺☹Dirs/buildtag"} +{"Action":"output","Test":"Test☺☹Dirs/incomplete","Output":" --- PASS: Test☺☹Dirs/incomplete (0.05s)\n"} +{"Action":"pass","Test":"Test☺☹Dirs/incomplete"} +{"Action":"output","Test":"Test☺☹Dirs/cgo","Output":" --- PASS: Test☺☹Dirs/cgo (0.04s)\n"} +{"Action":"pass","Test":"Test☺☹Dirs/cgo"} +{"Action":"pass","Test":"Test☺☹Dirs"} +{"Action":"output","Test":"Test☺☹Asm","Output":"--- PASS: Test☺☹Asm (0.75s)\n"} +{"Action":"pass","Test":"Test☺☹Asm"} +{"Action":"output","Output":"PASS\n"} +{"Action":"output","Output":"ok \tcmd/vet\t(cached)\n"} +{"Action":"pass"}
diff --git a/vendor/cmd/internal/test2json/testdata/smiley.test b/vendor/cmd/internal/test2json/testdata/smiley.test new file mode 100644 index 0000000..05edf5a --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/smiley.test
@@ -0,0 +1,97 @@ +=== RUN Test☺☹ +=== PAUSE Test☺☹ +=== RUN Test☺☹Asm +=== PAUSE Test☺☹Asm +=== RUN Test☺☹Dirs +=== PAUSE Test☺☹Dirs +=== RUN TestTags +=== PAUSE TestTags +=== RUN Test☺☹Verbose +=== PAUSE Test☺☹Verbose +=== CONT Test☺☹ +=== CONT TestTags +=== CONT Test☺☹Verbose +=== RUN TestTags/testtag +=== PAUSE TestTags/testtag +=== CONT Test☺☹Dirs +=== CONT Test☺☹Asm +=== RUN Test☺☹/0 +=== PAUSE Test☺☹/0 +=== RUN Test☺☹/1 +=== PAUSE Test☺☹/1 +=== RUN Test☺☹/2 +=== PAUSE Test☺☹/2 +=== RUN Test☺☹/3 +=== PAUSE Test☺☹/3 +=== RUN Test☺☹/4 +=== RUN TestTags/x_testtag_y +=== PAUSE Test☺☹/4 +=== RUN Test☺☹/5 +=== PAUSE Test☺☹/5 +=== PAUSE TestTags/x_testtag_y +=== RUN Test☺☹/6 +=== RUN TestTags/x,testtag,y +=== PAUSE TestTags/x,testtag,y +=== RUN Test☺☹Dirs/testingpkg +=== PAUSE Test☺☹/6 +=== CONT TestTags/x,testtag,y +=== PAUSE Test☺☹Dirs/testingpkg +=== RUN Test☺☹Dirs/divergent +=== RUN Test☺☹/7 +=== PAUSE Test☺☹/7 +=== PAUSE Test☺☹Dirs/divergent +=== CONT TestTags/x_testtag_y +=== CONT TestTags/testtag +=== RUN Test☺☹Dirs/buildtag +=== PAUSE Test☺☹Dirs/buildtag +=== CONT Test☺☹/0 +=== CONT Test☺☹/4 +=== RUN Test☺☹Dirs/incomplete +=== PAUSE Test☺☹Dirs/incomplete +=== RUN Test☺☹Dirs/cgo +=== PAUSE Test☺☹Dirs/cgo +=== CONT Test☺☹/7 +=== CONT Test☺☹/6 +--- PASS: Test☺☹Verbose (0.04s) +=== CONT Test☺☹/5 +=== CONT Test☺☹/3 +=== CONT Test☺☹/2 +--- PASS: TestTags (0.00s) + --- PASS: TestTags/x_testtag_y (0.04s) + vet_test.go:187: -tags=x testtag y + --- PASS: TestTags/x,testtag,y (0.04s) + vet_test.go:187: -tags=x,testtag,y + --- PASS: TestTags/testtag (0.04s) + vet_test.go:187: -tags=testtag +=== CONT Test☺☹/1 +=== CONT Test☺☹Dirs/testingpkg +=== CONT Test☺☹Dirs/buildtag +=== CONT Test☺☹Dirs/divergent +=== CONT Test☺☹Dirs/incomplete +=== CONT Test☺☹Dirs/cgo +--- PASS: Test☺☹ (0.39s) + --- PASS: Test☺☹/5 (0.07s) + vet_test.go:114: φιλεσ: ["testdata/copylock_func.go" "testdata/rangeloop.go"] + --- PASS: Test☺☹/3 (0.07s) + vet_test.go:114: φιλεσ: ["testdata/composite.go" "testdata/nilfunc.go"] + --- PASS: Test☺☹/6 (0.07s) + vet_test.go:114: φιλεσ: ["testdata/copylock_range.go" "testdata/shadow.go"] + --- PASS: Test☺☹/2 (0.07s) + vet_test.go:114: φιλεσ: ["testdata/bool.go" "testdata/method.go" "testdata/unused.go"] + --- PASS: Test☺☹/0 (0.13s) + vet_test.go:114: φιλεσ: ["testdata/assign.go" "testdata/httpresponse.go" "testdata/structtag.go"] + --- PASS: Test☺☹/4 (0.16s) + vet_test.go:114: φιλεσ: ["testdata/copylock.go" "testdata/print.go"] + --- PASS: Test☺☹/1 (0.07s) + vet_test.go:114: φιλεσ: ["testdata/atomic.go" "testdata/lostcancel.go" "testdata/unsafeptr.go"] + --- PASS: Test☺☹/7 (0.19s) + vet_test.go:114: φιλεσ: ["testdata/deadcode.go" "testdata/shift.go"] +--- PASS: Test☺☹Dirs (0.01s) + --- PASS: Test☺☹Dirs/testingpkg (0.06s) + --- PASS: Test☺☹Dirs/divergent (0.05s) + --- PASS: Test☺☹Dirs/buildtag (0.06s) + --- PASS: Test☺☹Dirs/incomplete (0.05s) + --- PASS: Test☺☹Dirs/cgo (0.04s) +--- PASS: Test☺☹Asm (0.75s) +PASS +ok cmd/vet (cached)
diff --git a/vendor/cmd/internal/test2json/testdata/unicode.json b/vendor/cmd/internal/test2json/testdata/unicode.json new file mode 100644 index 0000000..9cfb5f2 --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/unicode.json
@@ -0,0 +1,10 @@ +{"Action":"run","Test":"TestUnicode"} +{"Action":"output","Test":"TestUnicode","Output":"=== RUN TestUnicode\n"} +{"Action":"output","Test":"TestUnicode","Output":"Μπορώ να φάω σπασμένα γυαλιά χωρίς να πάθω τίποτα. Μπορώ να φάω σπασμένα γυαλιά χωρίς να πάθω τίποτα.\n"} +{"Action":"output","Test":"TestUnicode","Output":"私はガラスを食べられます。それは私を傷つけません。私はガラスを食べられます。それは私を傷つけません。\n"} +{"Action":"output","Test":"TestUnicode","Output":"--- PASS: TestUnicode\n"} +{"Action":"output","Test":"TestUnicode","Output":" ฉันกินกระจกได้ แต่มันไม่ทำให้ฉันเจ็บ ฉันกินกระจกได้ แต่มันไม่ทำให้ฉันเจ็บ\n"} +{"Action":"output","Test":"TestUnicode","Output":" אני יכול לאכול זכוכית וזה לא מזיק לי. אני יכול לאכול זכוכית וזה לא מזיק לי.\n"} +{"Action":"pass","Test":"TestUnicode"} +{"Action":"output","Output":"PASS\n"} +{"Action":"pass"}
diff --git a/vendor/cmd/internal/test2json/testdata/unicode.test b/vendor/cmd/internal/test2json/testdata/unicode.test new file mode 100644 index 0000000..58c620d --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/unicode.test
@@ -0,0 +1,7 @@ +=== RUN TestUnicode +Μπορώ να φάω σπασμένα γυαλιά χωρίς να πάθω τίποτα. Μπορώ να φάω σπασμένα γυαλιά χωρίς να πάθω τίποτα. +私はガラスを食べられます。それは私を傷つけません。私はガラスを食べられます。それは私を傷つけません。 +--- PASS: TestUnicode + ฉันกินกระจกได้ แต่มันไม่ทำให้ฉันเจ็บ ฉันกินกระจกได้ แต่มันไม่ทำให้ฉันเจ็บ + אני יכול לאכול זכוכית וזה לא מזיק לי. אני יכול לאכול זכוכית וזה לא מזיק לי. +PASS
diff --git a/vendor/cmd/internal/test2json/testdata/vet.json b/vendor/cmd/internal/test2json/testdata/vet.json new file mode 100644 index 0000000..8c5921d --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/vet.json
@@ -0,0 +1,182 @@ +{"Action":"run","Test":"TestVet"} +{"Action":"output","Test":"TestVet","Output":"=== RUN TestVet\n"} +{"Action":"output","Test":"TestVet","Output":"=== PAUSE TestVet\n"} +{"Action":"pause","Test":"TestVet"} +{"Action":"run","Test":"TestVetAsm"} +{"Action":"output","Test":"TestVetAsm","Output":"=== RUN TestVetAsm\n"} +{"Action":"output","Test":"TestVetAsm","Output":"=== PAUSE TestVetAsm\n"} +{"Action":"pause","Test":"TestVetAsm"} +{"Action":"run","Test":"TestVetDirs"} +{"Action":"output","Test":"TestVetDirs","Output":"=== RUN TestVetDirs\n"} +{"Action":"output","Test":"TestVetDirs","Output":"=== PAUSE TestVetDirs\n"} +{"Action":"pause","Test":"TestVetDirs"} +{"Action":"run","Test":"TestTags"} +{"Action":"output","Test":"TestTags","Output":"=== RUN TestTags\n"} +{"Action":"output","Test":"TestTags","Output":"=== PAUSE TestTags\n"} +{"Action":"pause","Test":"TestTags"} +{"Action":"run","Test":"TestVetVerbose"} +{"Action":"output","Test":"TestVetVerbose","Output":"=== RUN TestVetVerbose\n"} +{"Action":"output","Test":"TestVetVerbose","Output":"=== PAUSE TestVetVerbose\n"} +{"Action":"pause","Test":"TestVetVerbose"} +{"Action":"cont","Test":"TestVet"} +{"Action":"output","Test":"TestVet","Output":"=== CONT TestVet\n"} +{"Action":"cont","Test":"TestTags"} +{"Action":"output","Test":"TestTags","Output":"=== CONT TestTags\n"} +{"Action":"cont","Test":"TestVetVerbose"} +{"Action":"output","Test":"TestVetVerbose","Output":"=== CONT TestVetVerbose\n"} +{"Action":"run","Test":"TestTags/testtag"} +{"Action":"output","Test":"TestTags/testtag","Output":"=== RUN TestTags/testtag\n"} +{"Action":"output","Test":"TestTags/testtag","Output":"=== PAUSE TestTags/testtag\n"} +{"Action":"pause","Test":"TestTags/testtag"} +{"Action":"cont","Test":"TestVetDirs"} +{"Action":"output","Test":"TestVetDirs","Output":"=== CONT TestVetDirs\n"} +{"Action":"cont","Test":"TestVetAsm"} +{"Action":"output","Test":"TestVetAsm","Output":"=== CONT TestVetAsm\n"} +{"Action":"run","Test":"TestVet/0"} +{"Action":"output","Test":"TestVet/0","Output":"=== RUN TestVet/0\n"} +{"Action":"output","Test":"TestVet/0","Output":"=== PAUSE TestVet/0\n"} +{"Action":"pause","Test":"TestVet/0"} +{"Action":"run","Test":"TestVet/1"} +{"Action":"output","Test":"TestVet/1","Output":"=== RUN TestVet/1\n"} +{"Action":"output","Test":"TestVet/1","Output":"=== PAUSE TestVet/1\n"} +{"Action":"pause","Test":"TestVet/1"} +{"Action":"run","Test":"TestVet/2"} +{"Action":"output","Test":"TestVet/2","Output":"=== RUN TestVet/2\n"} +{"Action":"output","Test":"TestVet/2","Output":"=== PAUSE TestVet/2\n"} +{"Action":"pause","Test":"TestVet/2"} +{"Action":"run","Test":"TestVet/3"} +{"Action":"output","Test":"TestVet/3","Output":"=== RUN TestVet/3\n"} +{"Action":"output","Test":"TestVet/3","Output":"=== PAUSE TestVet/3\n"} +{"Action":"pause","Test":"TestVet/3"} +{"Action":"run","Test":"TestVet/4"} +{"Action":"output","Test":"TestVet/4","Output":"=== RUN TestVet/4\n"} +{"Action":"run","Test":"TestTags/x_testtag_y"} +{"Action":"output","Test":"TestTags/x_testtag_y","Output":"=== RUN TestTags/x_testtag_y\n"} +{"Action":"output","Test":"TestVet/4","Output":"=== PAUSE TestVet/4\n"} +{"Action":"pause","Test":"TestVet/4"} +{"Action":"run","Test":"TestVet/5"} +{"Action":"output","Test":"TestVet/5","Output":"=== RUN TestVet/5\n"} +{"Action":"output","Test":"TestVet/5","Output":"=== PAUSE TestVet/5\n"} +{"Action":"pause","Test":"TestVet/5"} +{"Action":"output","Test":"TestTags/x_testtag_y","Output":"=== PAUSE TestTags/x_testtag_y\n"} +{"Action":"pause","Test":"TestTags/x_testtag_y"} +{"Action":"run","Test":"TestVet/6"} +{"Action":"output","Test":"TestVet/6","Output":"=== RUN TestVet/6\n"} +{"Action":"run","Test":"TestTags/x,testtag,y"} +{"Action":"output","Test":"TestTags/x,testtag,y","Output":"=== RUN TestTags/x,testtag,y\n"} +{"Action":"output","Test":"TestTags/x,testtag,y","Output":"=== PAUSE TestTags/x,testtag,y\n"} +{"Action":"pause","Test":"TestTags/x,testtag,y"} +{"Action":"run","Test":"TestVetDirs/testingpkg"} +{"Action":"output","Test":"TestVetDirs/testingpkg","Output":"=== RUN TestVetDirs/testingpkg\n"} +{"Action":"output","Test":"TestVet/6","Output":"=== PAUSE TestVet/6\n"} +{"Action":"pause","Test":"TestVet/6"} +{"Action":"cont","Test":"TestTags/x,testtag,y"} +{"Action":"output","Test":"TestTags/x,testtag,y","Output":"=== CONT TestTags/x,testtag,y\n"} +{"Action":"output","Test":"TestVetDirs/testingpkg","Output":"=== PAUSE TestVetDirs/testingpkg\n"} +{"Action":"pause","Test":"TestVetDirs/testingpkg"} +{"Action":"run","Test":"TestVetDirs/divergent"} +{"Action":"output","Test":"TestVetDirs/divergent","Output":"=== RUN TestVetDirs/divergent\n"} +{"Action":"run","Test":"TestVet/7"} +{"Action":"output","Test":"TestVet/7","Output":"=== RUN TestVet/7\n"} +{"Action":"output","Test":"TestVet/7","Output":"=== PAUSE TestVet/7\n"} +{"Action":"pause","Test":"TestVet/7"} +{"Action":"output","Test":"TestVetDirs/divergent","Output":"=== PAUSE TestVetDirs/divergent\n"} +{"Action":"pause","Test":"TestVetDirs/divergent"} +{"Action":"cont","Test":"TestTags/x_testtag_y"} +{"Action":"output","Test":"TestTags/x_testtag_y","Output":"=== CONT TestTags/x_testtag_y\n"} +{"Action":"cont","Test":"TestTags/testtag"} +{"Action":"output","Test":"TestTags/testtag","Output":"=== CONT TestTags/testtag\n"} +{"Action":"run","Test":"TestVetDirs/buildtag"} +{"Action":"output","Test":"TestVetDirs/buildtag","Output":"=== RUN TestVetDirs/buildtag\n"} +{"Action":"output","Test":"TestVetDirs/buildtag","Output":"=== PAUSE TestVetDirs/buildtag\n"} +{"Action":"pause","Test":"TestVetDirs/buildtag"} +{"Action":"cont","Test":"TestVet/0"} +{"Action":"output","Test":"TestVet/0","Output":"=== CONT TestVet/0\n"} +{"Action":"cont","Test":"TestVet/4"} +{"Action":"output","Test":"TestVet/4","Output":"=== CONT TestVet/4\n"} +{"Action":"run","Test":"TestVetDirs/incomplete"} +{"Action":"output","Test":"TestVetDirs/incomplete","Output":"=== RUN TestVetDirs/incomplete\n"} +{"Action":"output","Test":"TestVetDirs/incomplete","Output":"=== PAUSE TestVetDirs/incomplete\n"} +{"Action":"pause","Test":"TestVetDirs/incomplete"} +{"Action":"run","Test":"TestVetDirs/cgo"} +{"Action":"output","Test":"TestVetDirs/cgo","Output":"=== RUN TestVetDirs/cgo\n"} +{"Action":"output","Test":"TestVetDirs/cgo","Output":"=== PAUSE TestVetDirs/cgo\n"} +{"Action":"pause","Test":"TestVetDirs/cgo"} +{"Action":"cont","Test":"TestVet/7"} +{"Action":"output","Test":"TestVet/7","Output":"=== CONT TestVet/7\n"} +{"Action":"cont","Test":"TestVet/6"} +{"Action":"output","Test":"TestVet/6","Output":"=== CONT TestVet/6\n"} +{"Action":"output","Test":"TestVetVerbose","Output":"--- PASS: TestVetVerbose (0.04s)\n"} +{"Action":"pass","Test":"TestVetVerbose"} +{"Action":"cont","Test":"TestVet/5"} +{"Action":"output","Test":"TestVet/5","Output":"=== CONT TestVet/5\n"} +{"Action":"cont","Test":"TestVet/3"} +{"Action":"output","Test":"TestVet/3","Output":"=== CONT TestVet/3\n"} +{"Action":"cont","Test":"TestVet/2"} +{"Action":"output","Test":"TestVet/2","Output":"=== CONT TestVet/2\n"} +{"Action":"output","Test":"TestTags","Output":"--- PASS: TestTags (0.00s)\n"} +{"Action":"output","Test":"TestTags/x_testtag_y","Output":" --- PASS: TestTags/x_testtag_y (0.04s)\n"} +{"Action":"output","Test":"TestTags/x_testtag_y","Output":" \tvet_test.go:187: -tags=x testtag y\n"} +{"Action":"pass","Test":"TestTags/x_testtag_y"} +{"Action":"output","Test":"TestTags/x,testtag,y","Output":" --- PASS: TestTags/x,testtag,y (0.04s)\n"} +{"Action":"output","Test":"TestTags/x,testtag,y","Output":" \tvet_test.go:187: -tags=x,testtag,y\n"} +{"Action":"pass","Test":"TestTags/x,testtag,y"} +{"Action":"output","Test":"TestTags/testtag","Output":" --- PASS: TestTags/testtag (0.04s)\n"} +{"Action":"output","Test":"TestTags/testtag","Output":" \tvet_test.go:187: -tags=testtag\n"} +{"Action":"pass","Test":"TestTags/testtag"} +{"Action":"pass","Test":"TestTags"} +{"Action":"cont","Test":"TestVet/1"} +{"Action":"output","Test":"TestVet/1","Output":"=== CONT TestVet/1\n"} +{"Action":"cont","Test":"TestVetDirs/testingpkg"} +{"Action":"output","Test":"TestVetDirs/testingpkg","Output":"=== CONT TestVetDirs/testingpkg\n"} +{"Action":"cont","Test":"TestVetDirs/buildtag"} +{"Action":"output","Test":"TestVetDirs/buildtag","Output":"=== CONT TestVetDirs/buildtag\n"} +{"Action":"cont","Test":"TestVetDirs/divergent"} +{"Action":"output","Test":"TestVetDirs/divergent","Output":"=== CONT TestVetDirs/divergent\n"} +{"Action":"cont","Test":"TestVetDirs/incomplete"} +{"Action":"output","Test":"TestVetDirs/incomplete","Output":"=== CONT TestVetDirs/incomplete\n"} +{"Action":"cont","Test":"TestVetDirs/cgo"} +{"Action":"output","Test":"TestVetDirs/cgo","Output":"=== CONT TestVetDirs/cgo\n"} +{"Action":"output","Test":"TestVet","Output":"--- PASS: TestVet (0.39s)\n"} +{"Action":"output","Test":"TestVet/5","Output":" --- PASS: TestVet/5 (0.07s)\n"} +{"Action":"output","Test":"TestVet/5","Output":" \tvet_test.go:114: files: [\"testdata/copylock_func.go\" \"testdata/rangeloop.go\"]\n"} +{"Action":"pass","Test":"TestVet/5"} +{"Action":"output","Test":"TestVet/3","Output":" --- PASS: TestVet/3 (0.07s)\n"} +{"Action":"output","Test":"TestVet/3","Output":" \tvet_test.go:114: files: [\"testdata/composite.go\" \"testdata/nilfunc.go\"]\n"} +{"Action":"pass","Test":"TestVet/3"} +{"Action":"output","Test":"TestVet/6","Output":" --- PASS: TestVet/6 (0.07s)\n"} +{"Action":"output","Test":"TestVet/6","Output":" \tvet_test.go:114: files: [\"testdata/copylock_range.go\" \"testdata/shadow.go\"]\n"} +{"Action":"pass","Test":"TestVet/6"} +{"Action":"output","Test":"TestVet/2","Output":" --- PASS: TestVet/2 (0.07s)\n"} +{"Action":"output","Test":"TestVet/2","Output":" \tvet_test.go:114: files: [\"testdata/bool.go\" \"testdata/method.go\" \"testdata/unused.go\"]\n"} +{"Action":"pass","Test":"TestVet/2"} +{"Action":"output","Test":"TestVet/0","Output":" --- PASS: TestVet/0 (0.13s)\n"} +{"Action":"output","Test":"TestVet/0","Output":" \tvet_test.go:114: files: [\"testdata/assign.go\" \"testdata/httpresponse.go\" \"testdata/structtag.go\"]\n"} +{"Action":"pass","Test":"TestVet/0"} +{"Action":"output","Test":"TestVet/4","Output":" --- PASS: TestVet/4 (0.16s)\n"} +{"Action":"output","Test":"TestVet/4","Output":" \tvet_test.go:114: files: [\"testdata/copylock.go\" \"testdata/print.go\"]\n"} +{"Action":"pass","Test":"TestVet/4"} +{"Action":"output","Test":"TestVet/1","Output":" --- PASS: TestVet/1 (0.07s)\n"} +{"Action":"output","Test":"TestVet/1","Output":" \tvet_test.go:114: files: [\"testdata/atomic.go\" \"testdata/lostcancel.go\" \"testdata/unsafeptr.go\"]\n"} +{"Action":"pass","Test":"TestVet/1"} +{"Action":"output","Test":"TestVet/7","Output":" --- PASS: TestVet/7 (0.19s)\n"} +{"Action":"output","Test":"TestVet/7","Output":" \tvet_test.go:114: files: [\"testdata/deadcode.go\" \"testdata/shift.go\"]\n"} +{"Action":"pass","Test":"TestVet/7"} +{"Action":"pass","Test":"TestVet"} +{"Action":"output","Test":"TestVetDirs","Output":"--- PASS: TestVetDirs (0.01s)\n"} +{"Action":"output","Test":"TestVetDirs/testingpkg","Output":" --- PASS: TestVetDirs/testingpkg (0.06s)\n"} +{"Action":"pass","Test":"TestVetDirs/testingpkg"} +{"Action":"output","Test":"TestVetDirs/divergent","Output":" --- PASS: TestVetDirs/divergent (0.05s)\n"} +{"Action":"pass","Test":"TestVetDirs/divergent"} +{"Action":"output","Test":"TestVetDirs/buildtag","Output":" --- PASS: TestVetDirs/buildtag (0.06s)\n"} +{"Action":"pass","Test":"TestVetDirs/buildtag"} +{"Action":"output","Test":"TestVetDirs/incomplete","Output":" --- PASS: TestVetDirs/incomplete (0.05s)\n"} +{"Action":"pass","Test":"TestVetDirs/incomplete"} +{"Action":"output","Test":"TestVetDirs/cgo","Output":" --- PASS: TestVetDirs/cgo (0.04s)\n"} +{"Action":"pass","Test":"TestVetDirs/cgo"} +{"Action":"pass","Test":"TestVetDirs"} +{"Action":"output","Test":"TestVetAsm","Output":"--- PASS: TestVetAsm (0.75s)\n"} +{"Action":"pass","Test":"TestVetAsm"} +{"Action":"output","Output":"PASS\n"} +{"Action":"output","Output":"ok \tcmd/vet\t(cached)\n"} +{"Action":"pass"}
diff --git a/vendor/cmd/internal/test2json/testdata/vet.test b/vendor/cmd/internal/test2json/testdata/vet.test new file mode 100644 index 0000000..3389559 --- /dev/null +++ b/vendor/cmd/internal/test2json/testdata/vet.test
@@ -0,0 +1,97 @@ +=== RUN TestVet +=== PAUSE TestVet +=== RUN TestVetAsm +=== PAUSE TestVetAsm +=== RUN TestVetDirs +=== PAUSE TestVetDirs +=== RUN TestTags +=== PAUSE TestTags +=== RUN TestVetVerbose +=== PAUSE TestVetVerbose +=== CONT TestVet +=== CONT TestTags +=== CONT TestVetVerbose +=== RUN TestTags/testtag +=== PAUSE TestTags/testtag +=== CONT TestVetDirs +=== CONT TestVetAsm +=== RUN TestVet/0 +=== PAUSE TestVet/0 +=== RUN TestVet/1 +=== PAUSE TestVet/1 +=== RUN TestVet/2 +=== PAUSE TestVet/2 +=== RUN TestVet/3 +=== PAUSE TestVet/3 +=== RUN TestVet/4 +=== RUN TestTags/x_testtag_y +=== PAUSE TestVet/4 +=== RUN TestVet/5 +=== PAUSE TestVet/5 +=== PAUSE TestTags/x_testtag_y +=== RUN TestVet/6 +=== RUN TestTags/x,testtag,y +=== PAUSE TestTags/x,testtag,y +=== RUN TestVetDirs/testingpkg +=== PAUSE TestVet/6 +=== CONT TestTags/x,testtag,y +=== PAUSE TestVetDirs/testingpkg +=== RUN TestVetDirs/divergent +=== RUN TestVet/7 +=== PAUSE TestVet/7 +=== PAUSE TestVetDirs/divergent +=== CONT TestTags/x_testtag_y +=== CONT TestTags/testtag +=== RUN TestVetDirs/buildtag +=== PAUSE TestVetDirs/buildtag +=== CONT TestVet/0 +=== CONT TestVet/4 +=== RUN TestVetDirs/incomplete +=== PAUSE TestVetDirs/incomplete +=== RUN TestVetDirs/cgo +=== PAUSE TestVetDirs/cgo +=== CONT TestVet/7 +=== CONT TestVet/6 +--- PASS: TestVetVerbose (0.04s) +=== CONT TestVet/5 +=== CONT TestVet/3 +=== CONT TestVet/2 +--- PASS: TestTags (0.00s) + --- PASS: TestTags/x_testtag_y (0.04s) + vet_test.go:187: -tags=x testtag y + --- PASS: TestTags/x,testtag,y (0.04s) + vet_test.go:187: -tags=x,testtag,y + --- PASS: TestTags/testtag (0.04s) + vet_test.go:187: -tags=testtag +=== CONT TestVet/1 +=== CONT TestVetDirs/testingpkg +=== CONT TestVetDirs/buildtag +=== CONT TestVetDirs/divergent +=== CONT TestVetDirs/incomplete +=== CONT TestVetDirs/cgo +--- PASS: TestVet (0.39s) + --- PASS: TestVet/5 (0.07s) + vet_test.go:114: files: ["testdata/copylock_func.go" "testdata/rangeloop.go"] + --- PASS: TestVet/3 (0.07s) + vet_test.go:114: files: ["testdata/composite.go" "testdata/nilfunc.go"] + --- PASS: TestVet/6 (0.07s) + vet_test.go:114: files: ["testdata/copylock_range.go" "testdata/shadow.go"] + --- PASS: TestVet/2 (0.07s) + vet_test.go:114: files: ["testdata/bool.go" "testdata/method.go" "testdata/unused.go"] + --- PASS: TestVet/0 (0.13s) + vet_test.go:114: files: ["testdata/assign.go" "testdata/httpresponse.go" "testdata/structtag.go"] + --- PASS: TestVet/4 (0.16s) + vet_test.go:114: files: ["testdata/copylock.go" "testdata/print.go"] + --- PASS: TestVet/1 (0.07s) + vet_test.go:114: files: ["testdata/atomic.go" "testdata/lostcancel.go" "testdata/unsafeptr.go"] + --- PASS: TestVet/7 (0.19s) + vet_test.go:114: files: ["testdata/deadcode.go" "testdata/shift.go"] +--- PASS: TestVetDirs (0.01s) + --- PASS: TestVetDirs/testingpkg (0.06s) + --- PASS: TestVetDirs/divergent (0.05s) + --- PASS: TestVetDirs/buildtag (0.06s) + --- PASS: TestVetDirs/incomplete (0.05s) + --- PASS: TestVetDirs/cgo (0.04s) +--- PASS: TestVetAsm (0.75s) +PASS +ok cmd/vet (cached)
diff --git a/vendor/internal/singleflight/singleflight.go b/vendor/internal/singleflight/singleflight.go new file mode 100644 index 0000000..1e9960d --- /dev/null +++ b/vendor/internal/singleflight/singleflight.go
@@ -0,0 +1,113 @@ +// Copyright 2013 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 singleflight provides a duplicate function call suppression +// mechanism. +package singleflight + +import "sync" + +// call is an in-flight or completed singleflight.Do call +type call struct { + wg sync.WaitGroup + + // These fields are written once before the WaitGroup is done + // and are only read after the WaitGroup is done. + val interface{} + err error + + // These fields are read and written with the singleflight + // mutex held before the WaitGroup is done, and are read but + // not written after the WaitGroup is done. + dups int + chans []chan<- Result +} + +// Group represents a class of work and forms a namespace in +// which units of work can be executed with duplicate suppression. +type Group struct { + mu sync.Mutex // protects m + m map[string]*call // lazily initialized +} + +// Result holds the results of Do, so they can be passed +// on a channel. +type Result struct { + Val interface{} + Err error + Shared bool +} + +// Do executes and returns the results of the given function, making +// sure that only one execution is in-flight for a given key at a +// time. If a duplicate comes in, the duplicate caller waits for the +// original to complete and receives the same results. +// The return value shared indicates whether v was given to multiple callers. +func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) { + g.mu.Lock() + if g.m == nil { + g.m = make(map[string]*call) + } + if c, ok := g.m[key]; ok { + c.dups++ + g.mu.Unlock() + c.wg.Wait() + return c.val, c.err, true + } + c := new(call) + c.wg.Add(1) + g.m[key] = c + g.mu.Unlock() + + g.doCall(c, key, fn) + return c.val, c.err, c.dups > 0 +} + +// DoChan is like Do but returns a channel that will receive the +// results when they are ready. The second result is true if the function +// will eventually be called, false if it will not (because there is +// a pending request with this key). +func (g *Group) DoChan(key string, fn func() (interface{}, error)) (<-chan Result, bool) { + ch := make(chan Result, 1) + g.mu.Lock() + if g.m == nil { + g.m = make(map[string]*call) + } + if c, ok := g.m[key]; ok { + c.dups++ + c.chans = append(c.chans, ch) + g.mu.Unlock() + return ch, false + } + c := &call{chans: []chan<- Result{ch}} + c.wg.Add(1) + g.m[key] = c + g.mu.Unlock() + + go g.doCall(c, key, fn) + + return ch, true +} + +// doCall handles the single call for a key. +func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) { + c.val, c.err = fn() + c.wg.Done() + + g.mu.Lock() + delete(g.m, key) + for _, ch := range c.chans { + ch <- Result{c.val, c.err, c.dups > 0} + } + g.mu.Unlock() +} + +// Forget tells the singleflight to forget about a key. Future calls +// to Do for this key will call the function rather than waiting for +// an earlier call to complete. +func (g *Group) Forget(key string) { + g.mu.Lock() + delete(g.m, key) + g.mu.Unlock() +}
diff --git a/vendor/internal/singleflight/singleflight_test.go b/vendor/internal/singleflight/singleflight_test.go new file mode 100644 index 0000000..5e6f1b3 --- /dev/null +++ b/vendor/internal/singleflight/singleflight_test.go
@@ -0,0 +1,87 @@ +// Copyright 2013 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 singleflight + +import ( + "errors" + "fmt" + "sync" + "sync/atomic" + "testing" + "time" +) + +func TestDo(t *testing.T) { + var g Group + v, err, _ := g.Do("key", func() (interface{}, error) { + return "bar", nil + }) + if got, want := fmt.Sprintf("%v (%T)", v, v), "bar (string)"; got != want { + t.Errorf("Do = %v; want %v", got, want) + } + if err != nil { + t.Errorf("Do error = %v", err) + } +} + +func TestDoErr(t *testing.T) { + var g Group + someErr := errors.New("Some error") + v, err, _ := g.Do("key", func() (interface{}, error) { + return nil, someErr + }) + if err != someErr { + t.Errorf("Do error = %v; want someErr %v", err, someErr) + } + if v != nil { + t.Errorf("unexpected non-nil value %#v", v) + } +} + +func TestDoDupSuppress(t *testing.T) { + var g Group + var wg1, wg2 sync.WaitGroup + c := make(chan string, 1) + var calls int32 + fn := func() (interface{}, error) { + if atomic.AddInt32(&calls, 1) == 1 { + // First invocation. + wg1.Done() + } + v := <-c + c <- v // pump; make available for any future calls + + time.Sleep(10 * time.Millisecond) // let more goroutines enter Do + + return v, nil + } + + const n = 10 + wg1.Add(1) + for i := 0; i < n; i++ { + wg1.Add(1) + wg2.Add(1) + go func() { + defer wg2.Done() + wg1.Done() + v, err, _ := g.Do("key", fn) + if err != nil { + t.Errorf("Do error: %v", err) + return + } + if s, _ := v.(string); s != "bar" { + t.Errorf("Do = %T %v; want %q", v, v, "bar") + } + }() + } + wg1.Wait() + // At least one goroutine is in fn now and all of them have at + // least reached the line before the Do. + c <- "bar" + wg2.Wait() + if got := atomic.LoadInt32(&calls); got <= 0 || got >= n { + t.Errorf("number of calls = %d; want over 0 and less than %d", got, n) + } +}
diff --git a/vendor/internal/testenv/testenv.go b/vendor/internal/testenv/testenv.go new file mode 100644 index 0000000..b3c16a8 --- /dev/null +++ b/vendor/internal/testenv/testenv.go
@@ -0,0 +1,245 @@ +// Copyright 2015 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 testenv provides information about what functionality +// is available in different testing environments run by the Go team. +// +// It is an internal package because these details are specific +// to the Go team's test setup (on build.golang.org) and not +// fundamental to tests in general. +package testenv + +import ( + "errors" + "flag" + "os" + "os/exec" + "path/filepath" + "runtime" + "strconv" + "strings" + "testing" +) + +// Builder reports the name of the builder running this test +// (for example, "linux-amd64" or "windows-386-gce"). +// If the test is not running on the build infrastructure, +// Builder returns the empty string. +func Builder() string { + return os.Getenv("GO_BUILDER_NAME") +} + +// HasGoBuild reports whether the current system can build programs with ``go build'' +// and then run them with os.StartProcess or exec.Command. +func HasGoBuild() bool { + if os.Getenv("GO_GCFLAGS") != "" { + // It's too much work to require every caller of the go command + // to pass along "-gcflags="+os.Getenv("GO_GCFLAGS"). + // For now, if $GO_GCFLAGS is set, report that we simply can't + // run go build. + return false + } + switch runtime.GOOS { + case "android", "nacl": + return false + case "darwin": + if strings.HasPrefix(runtime.GOARCH, "arm") { + return false + } + } + return true +} + +// MustHaveGoBuild checks that the current system can build programs with ``go build'' +// and then run them with os.StartProcess or exec.Command. +// If not, MustHaveGoBuild calls t.Skip with an explanation. +func MustHaveGoBuild(t testing.TB) { + if os.Getenv("GO_GCFLAGS") != "" { + t.Skipf("skipping test: 'go build' not compatible with setting $GO_GCFLAGS") + } + if !HasGoBuild() { + t.Skipf("skipping test: 'go build' not available on %s/%s", runtime.GOOS, runtime.GOARCH) + } +} + +// HasGoRun reports whether the current system can run programs with ``go run.'' +func HasGoRun() bool { + // For now, having go run and having go build are the same. + return HasGoBuild() +} + +// MustHaveGoRun checks that the current system can run programs with ``go run.'' +// If not, MustHaveGoRun calls t.Skip with an explanation. +func MustHaveGoRun(t testing.TB) { + if !HasGoRun() { + t.Skipf("skipping test: 'go run' not available on %s/%s", runtime.GOOS, runtime.GOARCH) + } +} + +// GoToolPath reports the path to the Go tool. +// It is a convenience wrapper around GoTool. +// If the tool is unavailable GoToolPath calls t.Skip. +// If the tool should be available and isn't, GoToolPath calls t.Fatal. +func GoToolPath(t testing.TB) string { + MustHaveGoBuild(t) + path, err := GoTool() + if err != nil { + t.Fatal(err) + } + return path +} + +// GoTool reports the path to the Go tool. +func GoTool() (string, error) { + if !HasGoBuild() { + return "", errors.New("platform cannot run go tool") + } + var exeSuffix string + if runtime.GOOS == "windows" { + exeSuffix = ".exe" + } + path := filepath.Join(runtime.GOROOT(), "bin", "go"+exeSuffix) + if _, err := os.Stat(path); err == nil { + return path, nil + } + goBin, err := exec.LookPath("go" + exeSuffix) + if err != nil { + return "", errors.New("cannot find go tool: " + err.Error()) + } + return goBin, nil +} + +// HasExec reports whether the current system can start new processes +// using os.StartProcess or (more commonly) exec.Command. +func HasExec() bool { + switch runtime.GOOS { + case "nacl": + return false + case "darwin": + if strings.HasPrefix(runtime.GOARCH, "arm") { + return false + } + } + return true +} + +// HasSrc reports whether the entire source tree is available under GOROOT. +func HasSrc() bool { + switch runtime.GOOS { + case "nacl": + return false + case "darwin": + if strings.HasPrefix(runtime.GOARCH, "arm") { + return false + } + } + return true +} + +// MustHaveExec checks that the current system can start new processes +// using os.StartProcess or (more commonly) exec.Command. +// If not, MustHaveExec calls t.Skip with an explanation. +func MustHaveExec(t testing.TB) { + if !HasExec() { + t.Skipf("skipping test: cannot exec subprocess on %s/%s", runtime.GOOS, runtime.GOARCH) + } +} + +// HasExternalNetwork reports whether the current system can use +// external (non-localhost) networks. +func HasExternalNetwork() bool { + return !testing.Short() +} + +// MustHaveExternalNetwork checks that the current system can use +// external (non-localhost) networks. +// If not, MustHaveExternalNetwork calls t.Skip with an explanation. +func MustHaveExternalNetwork(t testing.TB) { + if testing.Short() { + t.Skipf("skipping test: no external network in -short mode") + } +} + +var haveCGO bool + +// HasCGO reports whether the current system can use cgo. +func HasCGO() bool { + return haveCGO +} + +// MustHaveCGO calls t.Skip if cgo is not available. +func MustHaveCGO(t testing.TB) { + if !haveCGO { + t.Skipf("skipping test: no cgo") + } +} + +// HasSymlink reports whether the current system can use os.Symlink. +func HasSymlink() bool { + ok, _ := hasSymlink() + return ok +} + +// MustHaveSymlink reports whether the current system can use os.Symlink. +// If not, MustHaveSymlink calls t.Skip with an explanation. +func MustHaveSymlink(t testing.TB) { + ok, reason := hasSymlink() + if !ok { + t.Skipf("skipping test: cannot make symlinks on %s/%s%s", runtime.GOOS, runtime.GOARCH, reason) + } +} + +// HasLink reports whether the current system can use os.Link. +func HasLink() bool { + // From Android release M (Marshmallow), hard linking files is blocked + // and an attempt to call link() on a file will return EACCES. + // - https://code.google.com/p/android-developer-preview/issues/detail?id=3150 + return runtime.GOOS != "plan9" && runtime.GOOS != "android" +} + +// MustHaveLink reports whether the current system can use os.Link. +// If not, MustHaveLink calls t.Skip with an explanation. +func MustHaveLink(t testing.TB) { + if !HasLink() { + t.Skipf("skipping test: hardlinks are not supported on %s/%s", runtime.GOOS, runtime.GOARCH) + } +} + +var flaky = flag.Bool("flaky", false, "run known-flaky tests too") + +func SkipFlaky(t testing.TB, issue int) { + t.Helper() + if !*flaky { + t.Skipf("skipping known flaky test without the -flaky flag; see golang.org/issue/%d", issue) + } +} + +func SkipFlakyNet(t testing.TB) { + t.Helper() + if v, _ := strconv.ParseBool(os.Getenv("GO_BUILDER_FLAKY_NET")); v { + t.Skip("skipping test on builder known to have frequent network failures") + } +} + +// CleanCmdEnv will fill cmd.Env with the environment, excluding certain +// variables that could modify the behavior of the Go tools such as +// GODEBUG and GOTRACEBACK. +func CleanCmdEnv(cmd *exec.Cmd) *exec.Cmd { + if cmd.Env != nil { + panic("environment already set") + } + for _, env := range os.Environ() { + // Exclude GODEBUG from the environment to prevent its output + // from breaking tests that are trying to parse other command output. + if strings.HasPrefix(env, "GODEBUG=") { + continue + } + // Exclude GOTRACEBACK for the same reason. + if strings.HasPrefix(env, "GOTRACEBACK=") { + continue + } + cmd.Env = append(cmd.Env, env) + } + return cmd +}
diff --git a/vendor/internal/testenv/testenv_cgo.go b/vendor/internal/testenv/testenv_cgo.go new file mode 100644 index 0000000..e3d4d16 --- /dev/null +++ b/vendor/internal/testenv/testenv_cgo.go
@@ -0,0 +1,11 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build cgo + +package testenv + +func init() { + haveCGO = true +}
diff --git a/vendor/internal/testenv/testenv_notwin.go b/vendor/internal/testenv/testenv_notwin.go new file mode 100644 index 0000000..d8ce6cd --- /dev/null +++ b/vendor/internal/testenv/testenv_notwin.go
@@ -0,0 +1,20 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !windows + +package testenv + +import ( + "runtime" +) + +func hasSymlink() (ok bool, reason string) { + switch runtime.GOOS { + case "android", "nacl", "plan9": + return false, "" + } + + return true, "" +}
diff --git a/vendor/internal/testenv/testenv_windows.go b/vendor/internal/testenv/testenv_windows.go new file mode 100644 index 0000000..eb8d6ac --- /dev/null +++ b/vendor/internal/testenv/testenv_windows.go
@@ -0,0 +1,48 @@ +// Copyright 2016 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 testenv + +import ( + "io/ioutil" + "os" + "path/filepath" + "sync" + "syscall" +) + +var symlinkOnce sync.Once +var winSymlinkErr error + +func initWinHasSymlink() { + tmpdir, err := ioutil.TempDir("", "symtest") + if err != nil { + panic("failed to create temp directory: " + err.Error()) + } + defer os.RemoveAll(tmpdir) + + err = os.Symlink("target", filepath.Join(tmpdir, "symlink")) + if err != nil { + err = err.(*os.LinkError).Err + switch err { + case syscall.EWINDOWS, syscall.ERROR_PRIVILEGE_NOT_HELD: + winSymlinkErr = err + } + } +} + +func hasSymlink() (ok bool, reason string) { + symlinkOnce.Do(initWinHasSymlink) + + switch winSymlinkErr { + case nil: + return true, "" + case syscall.EWINDOWS: + return false, ": symlinks are not supported on your version of Windows" + case syscall.ERROR_PRIVILEGE_NOT_HELD: + return false, ": you don't have enough privileges to create symlinks" + } + + return false, "" +}