summaryrefslogtreecommitdiff
path: root/src/cmd/go
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2012-01-30 15:38:19 +0100
committerOndřej Surý <ondrej@sury.org>2012-01-30 15:38:19 +0100
commit4cecda6c347bd6902b960c6a35a967add7070b0d (patch)
treea462e224ff41ec9f3eb1a0b6e815806f9e8804ad /src/cmd/go
parent6c7ca6e4d4e26e4c8cbe0d183966011b3b088a0a (diff)
downloadgolang-4cecda6c347bd6902b960c6a35a967add7070b0d.tar.gz
Imported Upstream version 2012.01.27upstream-weekly/2012.01.27
Diffstat (limited to 'src/cmd/go')
-rw-r--r--src/cmd/go/Makefile25
-rw-r--r--src/cmd/go/bootstrap.go17
-rw-r--r--src/cmd/go/build.go1142
-rw-r--r--src/cmd/go/doc.go601
-rw-r--r--src/cmd/go/fix.go30
-rw-r--r--src/cmd/go/fmt.go54
-rw-r--r--src/cmd/go/get.go269
-rw-r--r--src/cmd/go/help.go185
-rw-r--r--src/cmd/go/http.go35
-rw-r--r--src/cmd/go/list.go114
-rw-r--r--src/cmd/go/main.go485
-rwxr-xr-xsrc/cmd/go/mkdoc.sh8
-rw-r--r--src/cmd/go/pkg.go445
-rw-r--r--src/cmd/go/run.go57
-rwxr-xr-xsrc/cmd/go/script23
-rw-r--r--src/cmd/go/script.txt352
-rw-r--r--src/cmd/go/test.go681
-rw-r--r--src/cmd/go/testflag.go215
-rw-r--r--src/cmd/go/vcs.go425
-rw-r--r--src/cmd/go/version.go25
-rw-r--r--src/cmd/go/vet.go30
21 files changed, 5218 insertions, 0 deletions
diff --git a/src/cmd/go/Makefile b/src/cmd/go/Makefile
new file mode 100644
index 000000000..295a14498
--- /dev/null
+++ b/src/cmd/go/Makefile
@@ -0,0 +1,25 @@
+# Copyright 2009 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.
+
+include ../../Make.inc
+
+TARG=go
+GOFILES=\
+ build.go\
+ fix.go\
+ get.go\
+ fmt.go\
+ help.go\
+ http.go\
+ list.go\
+ main.go\
+ pkg.go\
+ run.go\
+ test.go\
+ testflag.go\
+ version.go\
+ vet.go\
+ vcs.go\
+
+include ../../Make.cmd
diff --git a/src/cmd/go/bootstrap.go b/src/cmd/go/bootstrap.go
new file mode 100644
index 000000000..bc9a3dbbc
--- /dev/null
+++ b/src/cmd/go/bootstrap.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 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 main
+
+import "errors"
+
+func httpGET(url string) ([]byte, error) {
+ return nil, errors.New("no http in bootstrap go command")
+}
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
new file mode 100644
index 000000000..cbe36f52e
--- /dev/null
+++ b/src/cmd/go/build.go
@@ -0,0 +1,1142 @@
+// 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 main
+
+import (
+ "bytes"
+ "container/heap"
+ "errors"
+ "fmt"
+ "go/build"
+ "io"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "runtime"
+ "strings"
+ "sync"
+)
+
+var cmdBuild = &Command{
+ UsageLine: "build [-a] [-n] [-o output] [-p n] [-v] [-x] [importpath... | gofiles...]",
+ 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 are a list of .go files, build treats them as a list
+of source files specifying a single package.
+
+When the command line specifies a single main package,
+build writes the resulting executable to output (default a.out).
+Otherwise build compiles the packages but discards the results,
+serving only as a check that the packages can be built.
+
+The -a flag forces rebuilding of packages that are already up-to-date.
+The -n flag prints the commands but does not run them.
+The -v flag prints the names of packages as they are compiled.
+The -x flag prints the commands.
+
+The -o flag specifies the output file name.
+It is an error to use -o when the command line specifies multiple packages.
+
+The -p flag specifies the number of builds that can be run in parallel.
+The default is the number of CPUs available.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go install, go get, go clean.
+ `,
+}
+
+func init() {
+ // break init cycle
+ cmdBuild.Run = runBuild
+ cmdInstall.Run = runInstall
+
+ addBuildFlags(cmdBuild)
+ addBuildFlags(cmdInstall)
+}
+
+// Flags set by multiple commands.
+var buildA bool // -a flag
+var buildN bool // -n flag
+var buildP = runtime.NumCPU() // -p flag
+var buildV bool // -v flag
+var buildX bool // -x flag
+var buildO = cmdBuild.Flag.String("o", "", "output file")
+
+var buildContext = build.DefaultContext
+
+// addBuildFlags adds the flags common to the build and install commands.
+func addBuildFlags(cmd *Command) {
+ cmd.Flag.BoolVar(&buildA, "a", false, "")
+ cmd.Flag.BoolVar(&buildN, "n", false, "")
+ cmd.Flag.IntVar(&buildP, "p", buildP, "")
+ cmd.Flag.BoolVar(&buildV, "v", false, "")
+ cmd.Flag.BoolVar(&buildX, "x", false, "")
+
+ // TODO(rsc): This -t flag is used by buildscript.sh but
+ // not documented. Should be documented but the
+ // usage lines are getting too long. Probably need to say
+ // that these flags are applicable to every command and
+ // document them in one help message instead of on every
+ // command's help message.
+ cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "t", "")
+}
+
+type stringsFlag []string
+
+func (v *stringsFlag) Set(s string) error {
+ *v = append(*v, s)
+ return nil
+}
+
+func (v *stringsFlag) String() string {
+ return "<stringsFlag>"
+}
+
+func runBuild(cmd *Command, args []string) {
+ var b builder
+ b.init()
+
+ var pkgs []*Package
+ if len(args) > 0 && strings.HasSuffix(args[0], ".go") {
+ pkg := goFilesPackage(args, "")
+ pkgs = append(pkgs, pkg)
+ } else {
+ pkgs = packagesForBuild(args)
+ }
+
+ if len(pkgs) == 1 && pkgs[0].Name == "main" && *buildO == "" {
+ *buildO = "a.out"
+ }
+
+ if *buildO != "" {
+ if len(pkgs) > 1 {
+ fatalf("go build: cannot use -o with multiple packages")
+ }
+ p := pkgs[0]
+ p.target = "" // must build - not up to date
+ a := b.action(modeInstall, modeBuild, p)
+ a.target = *buildO
+ b.do(a)
+ return
+ }
+
+ a := &action{}
+ for _, p := range packages(args) {
+ a.deps = append(a.deps, b.action(modeBuild, modeBuild, p))
+ }
+ b.do(a)
+}
+
+var cmdInstall = &Command{
+ UsageLine: "install [-a] [-n] [-p n] [-v] [-x] [importpath...]",
+ Short: "compile and install packages and dependencies",
+ Long: `
+Install compiles and installs the packages named by the import paths,
+along with their dependencies.
+
+The -a flag forces reinstallation of packages that are already up-to-date.
+The -n flag prints the commands but does not run them.
+The -v flag prints the names of packages as they are compiled.
+The -x flag prints the commands.
+
+The -p flag specifies the number of builds that can be run in parallel.
+The default is the number of CPUs available.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go build, go get, go clean.
+ `,
+}
+
+func runInstall(cmd *Command, args []string) {
+ pkgs := packagesForBuild(args)
+
+ var b builder
+ b.init()
+ a := &action{}
+ for _, p := range pkgs {
+ a.deps = append(a.deps, b.action(modeInstall, modeInstall, p))
+ }
+ b.do(a)
+}
+
+// A builder holds global state about a build.
+// It does not hold per-package state, because eventually we will
+// build packages in parallel, and the builder will be shared.
+type builder struct {
+ work string // the temporary work directory (ends in filepath.Separator)
+ arch string // e.g., "6"
+ goroot string // the $GOROOT
+ goarch string // the $GOARCH
+ goos string // the $GOOS
+ gobin string // the $GOBIN
+ exe string // the executable suffix - "" or ".exe"
+ gcflags []string // additional flags for Go compiler
+ actionCache map[cacheKey]*action // a cache of already-constructed actions
+ mkdirCache map[string]bool // a cache of created directories
+
+ output sync.Mutex
+ scriptDir string // current directory in printed script
+
+ exec sync.Mutex
+ readySema chan bool
+ ready actionQueue
+}
+
+// An action represents a single action in the action graph.
+type action struct {
+ p *Package // the package this action works on
+ deps []*action // actions that must happen before this one
+ triggers []*action // inverse of deps
+ cgo *action // action for cgo binary if needed
+ args []string // additional args for runProgram
+ testOutput *bytes.Buffer // test output buffer
+
+ f func(*builder, *action) error // the action itself (nil = no-op)
+ ignoreFail bool // whether to run f even if dependencies fail
+
+ // Generated files, directories.
+ link bool // target is executable, not just package
+ pkgdir string // the -I or -L argument to use when importing this package
+ objdir string // directory for intermediate objects
+ objpkg string // the intermediate package .a file created during the action
+ target string // goal of the action: the created package or executable
+
+ // Execution state.
+ pending int // number of deps yet to complete
+ priority int // relative execution priority
+ failed bool // whether the action failed
+}
+
+// cacheKey is the key for the action cache.
+type cacheKey struct {
+ mode buildMode
+ p *Package
+}
+
+// buildMode specifies the build mode:
+// are we just building things or also installing the results?
+type buildMode int
+
+const (
+ modeBuild buildMode = iota
+ modeInstall
+)
+
+func (b *builder) init() {
+ var err error
+ b.actionCache = make(map[cacheKey]*action)
+ b.mkdirCache = make(map[string]bool)
+ b.goarch = buildContext.GOARCH
+ b.goos = buildContext.GOOS
+ b.goroot = build.Path[0].Path
+ b.gobin = build.Path[0].BinDir()
+ if b.goos == "windows" {
+ b.exe = ".exe"
+ }
+ b.gcflags = strings.Fields(os.Getenv("GCFLAGS"))
+
+ b.arch, err = build.ArchChar(b.goarch)
+ if err != nil {
+ fatalf("%s", err)
+ }
+
+ if buildN {
+ b.work = "$WORK"
+ } else {
+ b.work, err = ioutil.TempDir("", "go-build")
+ if err != nil {
+ fatalf("%s", err)
+ }
+ if buildX {
+ fmt.Printf("WORK=%s\n", b.work)
+ }
+ atexit(func() { os.RemoveAll(b.work) })
+ }
+}
+
+// goFilesPackage creates a package for building a collection of Go files
+// (typically named on the command line). If target is given, the package
+// target is target. Otherwise, the target is named p.a for
+// package p or named after the first Go file for package main.
+func goFilesPackage(gofiles []string, target string) *Package {
+ // TODO: Remove this restriction.
+ for _, f := range gofiles {
+ if !strings.HasSuffix(f, ".go") || strings.Contains(f, "/") || strings.Contains(f, string(filepath.Separator)) {
+ fatalf("named files must be in current directory and .go files")
+ }
+ }
+
+ // Synthesize fake "directory" that only shows those two files,
+ // to make it look like this is a standard package or
+ // command directory.
+ var dir []os.FileInfo
+ for _, file := range gofiles {
+ fi, err := os.Stat(file)
+ if err != nil {
+ fatalf("%s", err)
+ }
+ if fi.IsDir() {
+ fatalf("%s is a directory, should be a Go file", file)
+ }
+ dir = append(dir, fi)
+ }
+ ctxt := buildContext
+ ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dir, nil }
+ pwd, _ := os.Getwd()
+ var stk importStack
+ pkg := scanPackage(&ctxt, &build.Tree{Path: "."}, "<command line>", "<command line>", pwd+"/.", &stk)
+ if pkg.Error != nil {
+ fatalf("%s", pkg.Error)
+ }
+ if target != "" {
+ pkg.target = target
+ } else if pkg.Name == "main" {
+ pkg.target = gofiles[0][:len(gofiles[0])-len(".go")]
+ } else {
+ pkg.target = pkg.Name + ".a"
+ }
+ pkg.ImportPath = "_/" + pkg.target
+ return pkg
+}
+
+// action returns the action for applying the given operation (mode) to the package.
+// depMode is the action to use when building dependencies.
+func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action {
+ key := cacheKey{mode, p}
+ a := b.actionCache[key]
+ if a != nil {
+ return a
+ }
+
+ a = &action{p: p, pkgdir: p.t.PkgDir()}
+ if p.pkgdir != "" { // overrides p.t
+ a.pkgdir = p.pkgdir
+ }
+
+ b.actionCache[key] = a
+
+ for _, p1 := range p.imports {
+ a.deps = append(a.deps, b.action(depMode, depMode, p1))
+ }
+
+ if len(p.CgoFiles) > 0 {
+ var stk importStack
+ p1 := loadPackage("cmd/cgo", &stk)
+ if p1.Error != nil {
+ fatalf("load cmd/cgo: %v", p1.Error)
+ }
+ a.cgo = b.action(depMode, depMode, p1)
+ a.deps = append(a.deps, a.cgo)
+ }
+
+ if p.Standard {
+ switch p.ImportPath {
+ case "builtin", "unsafe":
+ // Fake packages - nothing to build.
+ return a
+ }
+ }
+
+ if !p.Stale && !buildA && p.target != "" {
+ // p.Stale==false implies that p.target is up-to-date.
+ // Record target name for use by actions depending on this one.
+ a.target = p.target
+ return a
+ }
+
+ a.objdir = filepath.Join(b.work, filepath.FromSlash(a.p.ImportPath+"/_obj")) + string(filepath.Separator)
+ a.objpkg = filepath.Join(b.work, filepath.FromSlash(a.p.ImportPath+".a"))
+ a.link = p.Name == "main"
+
+ switch mode {
+ case modeInstall:
+ a.f = (*builder).install
+ a.deps = []*action{b.action(modeBuild, depMode, p)}
+ a.target = a.p.target
+ case modeBuild:
+ a.f = (*builder).build
+ a.target = a.objpkg
+ if a.link {
+ // An executable file.
+ // Have to use something other than .a for the suffix.
+ // It is easier on Windows if we use .exe, so use .exe everywhere.
+ // (This is the name of a temporary file.)
+ a.target = a.objdir + "a.out" + b.exe
+ }
+ }
+
+ return a
+}
+
+// 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) {
+ // 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
+ }
+
+ b.readySema = make(chan bool, len(all))
+ done := make(chan bool)
+
+ // 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.f != nil && (!a.failed || a.ignoreFail) {
+ err = a.f(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 {
+ exitStatus = 2
+ } else {
+ 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)
+ done <- true
+ }
+ }
+
+ // 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 := buildP
+ if buildN {
+ par = 1
+ }
+ for i := 0; i < par; i++ {
+ go func() {
+ for _ = range b.readySema {
+ // Receiving a value from b.sema entitles
+ // us to take from the ready queue.
+ b.exec.Lock()
+ a := b.ready.pop()
+ b.exec.Unlock()
+ handle(a)
+ }
+ }()
+ }
+
+ <-done
+}
+
+// build is the action for building a single package or command.
+func (b *builder) build(a *action) error {
+ if 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.
+ fmt.Printf("\n#\n# %s\n#\n\n", a.p.ImportPath)
+ }
+
+ if buildV {
+ fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath)
+ }
+
+ // Make build directory.
+ obj := a.objdir
+ if err := b.mkdir(obj); err != nil {
+ return err
+ }
+
+ var gofiles, cfiles, sfiles, objects, cgoObjects []string
+ gofiles = append(gofiles, a.p.GoFiles...)
+ cfiles = append(cfiles, a.p.CFiles...)
+ sfiles = append(sfiles, a.p.SFiles...)
+
+ // Run cgo.
+ if len(a.p.CgoFiles) > 0 {
+ // In a package using cgo, cgo compiles the 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
+ if a.p.Standard && a.p.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
+ }
+ cfiles, gccfiles = filter(cfiles, cfiles[:0], gccfiles)
+ sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles)
+ } else {
+ gccfiles = append(cfiles, sfiles...)
+ cfiles = nil
+ sfiles = nil
+ }
+
+ outGo, outObj, err := b.cgo(a.p, a.cgo.target, obj, gccfiles)
+ if err != nil {
+ return err
+ }
+ cgoObjects = append(cgoObjects, outObj...)
+ gofiles = append(gofiles, outGo...)
+ }
+
+ // Prepare Go import path list.
+ inc := b.includeArgs("-I", a.deps)
+
+ // Compile Go.
+ if len(gofiles) > 0 {
+ out := "_go_." + b.arch
+ gcargs := []string{"-p", a.p.ImportPath}
+ if a.p.Standard && a.p.ImportPath == "runtime" {
+ // runtime compiles with a special 6g flag to emit
+ // additional reflect type data.
+ gcargs = append(gcargs, "-+")
+ }
+ if err := b.gc(a.p, obj+out, gcargs, inc, gofiles); err != nil {
+ return err
+ }
+ objects = append(objects, out)
+ }
+
+ // 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 := "_" + b.goos + "_" + b.goarch + ".h"
+ _goos := "_" + b.goos + ".h"
+ _goarch := "_" + b.goarch + ".h"
+ for _, file := range a.p.HFiles {
+ switch {
+ case strings.HasSuffix(file, _goos_goarch):
+ targ := file[:len(file)-len(_goos_goarch)] + "_GOOS_GOARCH.h"
+ if err := b.copyFile(obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
+ return err
+ }
+ case strings.HasSuffix(file, _goarch):
+ targ := file[:len(file)-len(_goarch)] + "_GOARCH.h"
+ if err := b.copyFile(obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
+ return err
+ }
+ case strings.HasSuffix(file, _goos):
+ targ := file[:len(file)-len(_goos)] + "_GOOS.h"
+ if err := b.copyFile(obj+targ, filepath.Join(a.p.Dir, file), 0666); err != nil {
+ return err
+ }
+ }
+ }
+
+ for _, file := range cfiles {
+ out := file[:len(file)-len(".c")] + "." + b.arch
+ if err := b.cc(a.p, obj, obj+out, file); err != nil {
+ return err
+ }
+ objects = append(objects, out)
+ }
+
+ // Assemble .s files.
+ for _, file := range sfiles {
+ out := file[:len(file)-len(".s")] + "." + b.arch
+ if err := b.asm(a.p, obj, obj+out, file); err != nil {
+ return err
+ }
+ objects = append(objects, out)
+ }
+
+ // 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.
+ // http://golang.org/issue/2601
+ objects = append(objects, cgoObjects...)
+
+ // Pack into archive in obj directory
+ if err := b.gopack(a.p, obj, a.objpkg, objects); err != nil {
+ return err
+ }
+
+ // Link if needed.
+ if a.link {
+ // The compiler only cares about direct imports, but the
+ // linker needs the whole dependency tree.
+ all := actionList(a)
+ all = all[:len(all)-1] // drop a
+ inc := b.includeArgs("-L", all)
+ if err := b.ld(a.p, a.target, inc, a.objpkg); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// install is the action for installing a single package or executable.
+func (b *builder) install(a *action) error {
+ a1 := a.deps[0]
+ perm := os.FileMode(0666)
+ if a1.link {
+ perm = 0777
+ }
+
+ // make target directory
+ dir, _ := filepath.Split(a.target)
+ if dir != "" {
+ if err := b.mkdir(dir); err != nil {
+ return err
+ }
+ }
+
+ return b.copyFile(a.target, a1.target, perm)
+}
+
+// includeArgs returns the -I or -L directory list for access
+// to the results of the list of actions.
+func (b *builder) includeArgs(flag string, all []*action) []string {
+ inc := []string{}
+ incMap := map[string]bool{
+ b.work: true, // handled later
+ build.Path[0].PkgDir(): true, // goroot
+ "": true, // ignore empty strings
+ }
+
+ // Look in the temporary space for results of test-specific actions.
+ // This is the $WORK/my/package/_test directory for the
+ // package being built, so there are few of these.
+ for _, a1 := range all {
+ if dir := a1.pkgdir; dir != a1.p.t.PkgDir() && !incMap[dir] {
+ incMap[dir] = true
+ inc = append(inc, flag, dir)
+ }
+ }
+
+ // Also look in $WORK for any non-test packages that have
+ // been built but not installed.
+ inc = append(inc, flag, b.work)
+
+ // Finally, look in the installed package directories for each action.
+ for _, a1 := range all {
+ if dir := a1.pkgdir; dir == a1.p.t.PkgDir() && !incMap[dir] {
+ incMap[dir] = true
+ inc = append(inc, flag, dir)
+ }
+ }
+
+ return inc
+}
+
+// removeByRenaming removes file name by moving it to a tmp
+// directory and deleting the target if possible.
+func removeByRenaming(name string) error {
+ f, err := ioutil.TempFile("", "")
+ if err != nil {
+ return err
+ }
+ tmpname := f.Name()
+ f.Close()
+ err = os.Remove(tmpname)
+ if err != nil {
+ return err
+ }
+ err = os.Rename(name, tmpname)
+ if err != nil {
+ // assume name file does not exists,
+ // otherwise later code will fail.
+ return nil
+ }
+ err = os.Remove(tmpname)
+ if err != nil {
+ // TODO(brainman): file is locked and can't be deleted.
+ // We need to come up with a better way of doing it.
+ }
+ return nil
+}
+
+// copyFile is like 'cp src dst'.
+func (b *builder) copyFile(dst, src string, perm os.FileMode) error {
+ if buildN || buildX {
+ b.showcmd("", "cp %s %s", src, dst)
+ if buildN {
+ return nil
+ }
+ }
+
+ sf, err := os.Open(src)
+ if err != nil {
+ return err
+ }
+ defer sf.Close()
+ os.Remove(dst)
+ df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
+ if err != nil {
+ if runtime.GOOS != "windows" {
+ return err
+ }
+ // Windows does not allow to replace binary file
+ // while it is executing. We will cheat.
+ err = removeByRenaming(dst)
+ if err != nil {
+ return err
+ }
+ 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 {
+ os.Remove(dst)
+ return err
+ }
+ return nil
+}
+
+// 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.work with $WORK.
+// fmtcmd replaces the value of b.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 != "" {
+ cmd = strings.Replace(" "+cmd, " "+dir, " .", -1)[1:]
+ if b.scriptDir != dir {
+ b.scriptDir = dir
+ cmd = "cd " + dir + "\n" + cmd
+ }
+ }
+ cmd = strings.Replace(cmd, b.work, "$WORK", -1)
+ cmd = strings.Replace(cmd, b.gobin, "$GOBIN", -1)
+ cmd = strings.Replace(cmd, b.goroot, "$GOROOT", -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()
+ fmt.Println(b.fmtcmd(dir, format, args...))
+}
+
+// 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/pkg/html,
+// the output is
+//
+// $ go build
+// # fmt
+// ../fmt/print.go:1090: undefined: asdf
+// $
+//
+// instead of
+//
+// $ go build
+// # fmt
+// /usr/gopher/go/src/pkg/fmt/print.go:1090: undefined: asdf
+// $
+//
+// showOutput also replaces references to the work directory with $WORK.
+//
+func (b *builder) showOutput(dir, desc, out string) {
+ prefix := "# " + desc
+ suffix := "\n" + out
+ pwd, _ := os.Getwd()
+ if reldir, err := filepath.Rel(pwd, dir); err == nil && len(reldir) < len(dir) {
+ suffix = strings.Replace(suffix, " "+dir, " "+reldir, -1)
+ suffix = strings.Replace(suffix, "\n"+dir, "\n"+reldir, -1)
+ }
+ suffix = strings.Replace(suffix, " "+b.work, " $WORK", -1)
+
+ b.output.Lock()
+ defer b.output.Unlock()
+ fmt.Print(prefix, suffix)
+}
+
+// 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
+ 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
+}
+
+// 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")
+
+// run runs the command given by cmdline in the directory dir.
+// If the commnd fails, run prints information about the failure
+// and returns a non-nil error.
+func (b *builder) run(dir string, desc string, cmdargs ...interface{}) error {
+ out, err := b.runOut(dir, desc, cmdargs...)
+ if len(out) > 0 {
+ if out[len(out)-1] != '\n' {
+ out = append(out, '\n')
+ }
+ if desc == "" {
+ desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdargs...), " "))
+ }
+ b.showOutput(dir, desc, string(out))
+ if err != nil {
+ err = errPrintedOutput
+ }
+ }
+ return err
+}
+
+// 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, cmdargs ...interface{}) ([]byte, error) {
+ cmdline := stringList(cmdargs...)
+ if buildN || buildX {
+ b.showcmd(dir, "%s", strings.Join(cmdline, " "))
+ if buildN {
+ return nil, nil
+ }
+ }
+
+ var buf bytes.Buffer
+ cmd := exec.Command(cmdline[0], cmdline[1:]...)
+ cmd.Stdout = &buf
+ cmd.Stderr = &buf
+ cmd.Dir = dir
+ // TODO: cmd.Env
+ err := cmd.Run()
+ return buf.Bytes(), err
+}
+
+// mkdir makes the named directory.
+func (b *builder) mkdir(dir string) error {
+ 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 buildN || buildX {
+ b.showcmd("", "mkdir -p %s", dir)
+ if buildN {
+ return nil
+ }
+ }
+
+ if err := os.MkdirAll(dir, 0777); err != nil {
+ return err
+ }
+ return nil
+}
+
+// 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)
+}
+
+// gc runs the Go compiler in a specific directory on a set of files
+// to generate the named output file.
+func (b *builder) gc(p *Package, ofile string, gcargs, importArgs []string, gofiles []string) error {
+ args := stringList(b.arch+"g", "-o", ofile, b.gcflags, gcargs, importArgs)
+ for _, f := range gofiles {
+ args = append(args, mkAbs(p.Dir, f))
+ }
+ return b.run(p.Dir, p.ImportPath, args)
+}
+
+// asm runs the assembler in a specific directory on a specific file
+// to generate the named output file.
+func (b *builder) asm(p *Package, obj, ofile, sfile string) error {
+ sfile = mkAbs(p.Dir, sfile)
+ return b.run(p.Dir, p.ImportPath, b.arch+"a", "-I", obj, "-o", ofile, "-DGOOS_"+b.goos, "-DGOARCH_"+b.goarch, sfile)
+}
+
+// gopack runs the assembler in a specific directory to create
+// an archive from a set of object files.
+// typically it is run in the object directory.
+func (b *builder) gopack(p *Package, objDir, afile string, ofiles []string) error {
+ var absOfiles []string
+ for _, f := range ofiles {
+ absOfiles = append(absOfiles, mkAbs(objDir, f))
+ }
+ return b.run(p.Dir, p.ImportPath, "gopack", "grc", mkAbs(objDir, afile), absOfiles)
+}
+
+// ld runs the linker to create a package starting at mainpkg.
+func (b *builder) ld(p *Package, out string, importArgs []string, mainpkg string) error {
+ return b.run(p.Dir, p.ImportPath, b.arch+"l", "-o", out, importArgs, mainpkg)
+}
+
+// cc runs the gc-toolchain C compiler in a directory on a C file
+// to produce an output file.
+func (b *builder) cc(p *Package, objdir, ofile, cfile string) error {
+ inc := filepath.Join(b.goroot, "pkg", fmt.Sprintf("%s_%s", b.goos, b.goarch))
+ cfile = mkAbs(p.Dir, cfile)
+ return b.run(p.Dir, p.ImportPath, b.arch+"c", "-FVw",
+ "-I", objdir, "-I", inc, "-o", ofile,
+ "-DGOOS_"+b.goos, "-DGOARCH_"+b.goarch, cfile)
+}
+
+// gcc runs the gcc C compiler to create an object from a single C file.
+func (b *builder) gcc(p *Package, out string, flags []string, cfile string) error {
+ cfile = mkAbs(p.Dir, cfile)
+ return b.run(p.Dir, p.ImportPath, b.gccCmd(p.Dir), flags, "-o", out, "-c", cfile)
+}
+
+// gccld runs the gcc linker to create an executable from a set of object files
+func (b *builder) gccld(p *Package, out string, flags []string, obj []string) error {
+ return b.run(p.Dir, p.ImportPath, b.gccCmd(p.Dir), "-o", out, obj, flags)
+}
+
+// gccCmd returns a gcc command line prefix
+func (b *builder) gccCmd(objdir string) []string {
+ // TODO: HOST_CC?
+ a := []string{"gcc", "-I", objdir, "-g", "-O2"}
+
+ // Definitely want -fPIC but on Windows gcc complains
+ // "-fPIC ignored for target (all code is position independent)"
+ if b.goos != "windows" {
+ a = append(a, "-fPIC")
+ }
+ switch b.arch {
+ case "8":
+ a = append(a, "-m32")
+ case "6":
+ a = append(a, "-m64")
+ }
+ // gcc-4.5 and beyond require explicit "-pthread" flag
+ // for multithreading with pthread library.
+ if buildContext.CgoEnabled {
+ switch b.goos {
+ case "windows":
+ a = append(a, "-mthreads")
+ default:
+ a = append(a, "-pthread")
+ }
+ }
+ return a
+}
+
+var cgoRe = regexp.MustCompile(`[/\\:]`)
+
+func (b *builder) cgo(p *Package, cgoExe, obj string, gccfiles []string) (outGo, outObj []string, err error) {
+ if b.goos != runtime.GOOS {
+ return nil, nil, errors.New("cannot use cgo when compiling for a different operating system")
+ }
+
+ outObj = append(outObj, "") // for importObj, at end of function
+
+ cgoCFLAGS := stringList(p.info.CgoCFLAGS)
+ cgoLDFLAGS := stringList(p.info.CgoLDFLAGS)
+ if pkgs := p.info.CgoPkgConfig; len(pkgs) > 0 {
+ out, err := b.runOut(p.Dir, p.ImportPath, "pkg-config", "--cflags", pkgs)
+ if err != nil {
+ return nil, nil, err
+ }
+ if len(out) > 0 {
+ cgoCFLAGS = append(cgoCFLAGS, strings.Fields(string(out))...)
+ }
+ out, err = b.runOut(p.Dir, p.ImportPath, "pkg-config", "--libs", pkgs)
+ if err != nil {
+ return nil, nil, err
+ }
+ if len(out) > 0 {
+ cgoLDFLAGS = append(cgoLDFLAGS, strings.Fields(string(out))...)
+ }
+ }
+
+ // cgo
+ // TODO: CGOPKGPATH, CGO_FLAGS?
+ gofiles := []string{obj + "_cgo_gotypes.go"}
+ cfiles := []string{"_cgo_main.c", "_cgo_export.c"}
+ for _, fn := range p.CgoFiles {
+ f := cgoRe.ReplaceAllString(fn[:len(fn)-2], "_")
+ gofiles = append(gofiles, obj+f+"cgo1.go")
+ cfiles = append(cfiles, f+"cgo2.c")
+ }
+ defunC := obj + "_cgo_defun.c"
+ // TODO: make cgo not depend on $GOARCH?
+ var runtimeFlag []string
+ if p.Standard && p.ImportPath == "runtime/cgo" {
+ runtimeFlag = []string{"-import_runtime_cgo=false"}
+ }
+ if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, runtimeFlag, "--", p.CgoFiles); err != nil {
+ return nil, nil, err
+ }
+ outGo = append(outGo, gofiles...)
+
+ // cc _cgo_defun.c
+ defunObj := obj + "_cgo_defun." + b.arch
+ if err := b.cc(p, obj, defunObj, defunC); err != nil {
+ return nil, nil, err
+ }
+ outObj = append(outObj, defunObj)
+
+ // gcc
+ var linkobj []string
+ for _, cfile := range cfiles {
+ ofile := obj + cfile[:len(cfile)-1] + "o"
+ if err := b.gcc(p, ofile, cgoCFLAGS, obj+cfile); err != nil {
+ return nil, nil, err
+ }
+ linkobj = append(linkobj, ofile)
+ if !strings.HasSuffix(ofile, "_cgo_main.o") {
+ outObj = append(outObj, ofile)
+ }
+ }
+ for _, file := range gccfiles {
+ ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o"
+ if err := b.gcc(p, ofile, cgoCFLAGS, file); err != nil {
+ return nil, nil, err
+ }
+ linkobj = append(linkobj, ofile)
+ outObj = append(outObj, ofile)
+ }
+ dynobj := obj + "_cgo_.o"
+ if err := b.gccld(p, dynobj, cgoLDFLAGS, linkobj); err != nil {
+ return nil, nil, err
+ }
+
+ // cgo -dynimport
+ importC := obj + "_cgo_import.c"
+ if err := b.run(p.Dir, p.ImportPath, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC); err != nil {
+ return nil, nil, err
+ }
+
+ // cc _cgo_import.ARCH
+ importObj := obj + "_cgo_import." + b.arch
+ if err := b.cc(p, obj, importObj, importC); err != nil {
+ return nil, nil, err
+ }
+
+ // NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows
+ // must be processed before the gcc-generated objects.
+ // Put it first. We left room above. http://golang.org/issue/2601
+ outObj[0] = importObj
+
+ return outGo, outObj, nil
+}
+
+// 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)
+}
diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go
new file mode 100644
index 000000000..27be32bf3
--- /dev/null
+++ b/src/cmd/go/doc.go
@@ -0,0 +1,601 @@
+// 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 is a tool for managing Go source code.
+
+Usage: go command [arguments]
+
+The commands are:
+
+ build compile packages and dependencies
+ doc run godoc on package sources
+ fix run gofix on packages
+ fmt run gofmt on package sources
+ 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
+ version print Go version
+ vet run govet on packages
+
+Use "go help [command]" for more information about a command.
+
+Additional help topics:
+
+ gopath GOPATH environment variable
+ importpath description of import paths
+ remote remote import path syntax
+ testflag description of testing flags
+ testfunc description of testing functions
+
+Use "go help [topic]" for more information about that topic.
+
+
+Compile packages and dependencies
+
+Usage:
+
+ go build [-a] [-n] [-o output] [-p n] [-v] [-x] [importpath... | gofiles...]
+
+Build compiles the packages named by the import paths,
+along with their dependencies, but it does not install the results.
+
+If the arguments are a list of .go files, build treats them as a list
+of source files specifying a single package.
+
+When the command line specifies a single main package,
+build writes the resulting executable to output (default a.out).
+Otherwise build compiles the packages but discards the results,
+serving only as a check that the packages can be built.
+
+The -a flag forces rebuilding of packages that are already up-to-date.
+The -n flag prints the commands but does not run them.
+The -v flag prints the names of packages as they are compiled.
+The -x flag prints the commands.
+
+The -o flag specifies the output file name.
+It is an error to use -o when the command line specifies multiple packages.
+
+The -p flag specifies the number of builds that can be run in parallel.
+The default is the number of CPUs available.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go install, go get, go clean.
+
+
+Run godoc on package sources
+
+Usage:
+
+ go doc [importpath...]
+
+Doc runs the godoc command on the packages named by the
+import paths.
+
+For more about godoc, see 'godoc godoc'.
+For more about import paths, see 'go help importpath'.
+
+To run godoc with specific options, run godoc itself.
+
+See also: go fix, go fmt, go vet.
+
+
+Run gofix on packages
+
+Usage:
+
+ go fix [importpath...]
+
+Fix runs the gofix command on the packages named by the import paths.
+
+For more about gofix, see 'godoc gofix'.
+For more about import paths, see 'go help importpath'.
+
+To run gofix with specific options, run gofix itself.
+
+See also: go fmt, go vet.
+
+
+Run gofmt on package sources
+
+Usage:
+
+ go fmt [importpath...]
+
+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 'godoc gofmt'.
+For more about import paths, see 'go help importpath'.
+
+To run gofmt with specific options, run gofmt itself.
+
+See also: go doc, go fix, go vet.
+
+
+Download and install packages and dependencies
+
+Usage:
+
+ go get [-a] [-d] [-fix] [-n] [-p n] [-u] [-v] [-x] [importpath...]
+
+Get downloads and installs the packages named by the import paths,
+along with their dependencies.
+
+The -a, -n, -v, -x, and -p flags have the same meaning as in 'go build'
+and 'go install'. See 'go help install'.
+
+The -d flag instructs get to stop after downloading the packages; that is,
+it instructs get not to install the packages.
+
+The -fix flag instructs get to run gofix on the downloaded packages
+before resolving dependencies or building the code.
+
+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.
+
+TODO: Explain versions better.
+
+For more about import paths, see 'go help importpath'.
+
+For more about how 'go get' finds source code to
+download, see 'go help remote'.
+
+See also: go build, go install, go clean.
+
+
+Compile and install packages and dependencies
+
+Usage:
+
+ go install [-a] [-n] [-p n] [-v] [-x] [importpath...]
+
+Install compiles and installs the packages named by the import paths,
+along with their dependencies.
+
+The -a flag forces reinstallation of packages that are already up-to-date.
+The -n flag prints the commands but does not run them.
+The -v flag prints the names of packages as they are compiled.
+The -x flag prints the commands.
+
+The -p flag specifies the number of builds that can be run in parallel.
+The default is the number of CPUs available.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go build, go get, go clean.
+
+
+List packages
+
+Usage:
+
+ go list [-e] [-f format] [-json] [importpath...]
+
+List lists the packages named by the import paths, one per line.
+
+The default output shows the package import path:
+
+ code.google.com/p/google-api-go-client/books/v1
+ code.google.com/p/goauth2/oauth
+ code.google.com/p/sqlite
+
+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 {
+ Name string // package name
+ Doc string // package documentation string
+ ImportPath string // import path of package in dir
+ Dir string // directory containing package sources
+ Version string // version of installed package (TODO)
+ Stale bool // would 'go install' do anything for this package?
+
+ // Source files
+ GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, and XTestGoFiles)
+ TestGoFiles []string // _test.go source files internal to the package they are testing
+ XTestGoFiles []string // _test.go source files external to the package they are testing
+ CFiles []string // .c source files
+ HFiles []string // .h source files
+ SFiles []string // .s source files
+ CgoFiles []string // .go sources files that import "C"
+
+ // Dependency information
+ Imports []string // import paths used by this package
+ Deps []string // all (recursively) imported dependencies
+
+ // Error information
+ Incomplete bool // this package or a dependency has an error
+ Error *PackageError // error loading package
+ DepsErrors []*PackageError // errors loading dependencies
+ }
+
+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 import paths, see 'go help importpath'.
+
+
+Compile and run Go program
+
+Usage:
+
+ go run [-a] [-n] [-x] gofiles... [arguments...]
+
+Run compiles and runs the main package comprising the named Go source files.
+
+The -a flag forces reinstallation of packages that are already up-to-date.
+The -n flag prints the commands but does not run them.
+The -x flag prints the commands.
+
+See also: go build.
+
+
+Test packages
+
+Usage:
+
+ go test [-c] [-file a.go -file b.go ...] [-p n] [-x] [importpath...] [flags for test binary]
+
+'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.
+
+By default, go test needs no arguments. It compiles and tests the package
+with source in the current directory, including tests, and runs the tests.
+If file names are given (with flag -file=test.go, one per extra test source file),
+only those test files are added to the package. (The non-test files are always
+compiled.)
+
+The package is built in a temporary directory so it does not interfere with the
+non-test installation.
+
+See 'go help testflag' for details about flags handled by 'go test'
+and the test binary.
+
+See 'go help importpath' for more about import paths.
+
+See also: go build, go vet.
+
+
+Print Go version
+
+Usage:
+
+ go version
+
+Version prints the Go version, as reported by runtime.Version.
+
+
+Run govet on packages
+
+Usage:
+
+ go vet [importpath...]
+
+Vet runs the govet command on the packages named by the import paths.
+
+For more about govet, see 'godoc govet'.
+For more about import paths, see 'go help importpath'.
+
+To run govet with specific options, run govet itself.
+
+See also: go fmt, go fix.
+
+
+GOPATH environment variable
+
+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.
+
+GOPATH must be set to build and install packages outside the
+standard Go tree.
+
+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/ is stripped
+so that you can add DIR/bin to your PATH to get at the
+installed commands.
+
+Here's an example directory layout:
+
+ GOPATH=/home/user/gocode
+
+ /home/user/gocode/
+ 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.
+
+
+Description of import paths
+
+Many commands apply to a set of packages named by import paths:
+
+ go action [importpath...]
+
+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 (see 'go help gopath').
+
+If no import paths are given, the action applies to the
+package in the current directory.
+
+The special import path "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.
+
+The special import path "std" is like all but expands to just the
+packages in the standard Go library.
+
+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. For example, encoding/... expands to all packages
+in the encoding tree.
+
+An import path can also name a package to be downloaded from
+a remote repository. Run 'go help remote' 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 'code.google.com/p/project'.
+
+
+Remote import path syntax
+
+An import path (see 'go help importpath') denotes a package
+stored in the local file system. 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 (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"
+
+ Google Code Project Hosting (Git, Mercurial, Subversion)
+
+ import "code.google.com/p/project"
+ import "code.google.com/p/project/sub/directory"
+
+ import "code.google.com/p/project.subrepository"
+ import "code.google.com/p/project.subrepository/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"
+
+For code hosted on other servers, 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.com/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 git://, then https://, then http://.
+
+New downloaded packages are written to the first directory
+listed in the GOPATH environment variable (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 install' for more.
+
+
+Description of testing flags
+
+The 'go test' command takes both flags that apply to 'go test' itself
+and flags that apply to the resulting test binary.
+
+The flags handled by 'go test' are:
+
+ -c Compile the test binary to test.out but do not run it.
+
+ -file a.go
+ Use only the tests in the source file a.go.
+ Multiple -file flags may be provided.
+
+ -p n
+ Compile and test up to n packages in parallel.
+ The default value is the number of CPUs available.
+
+ -x Print each subcommand go test executes.
+
+The resulting test binary, called test.out, has its own flags:
+
+ -test.v
+ Verbose output: log all tests as they are run.
+
+ -test.run pattern
+ Run only those tests matching the regular expression.
+
+ -test.bench pattern
+ Run benchmarks matching the regular expression.
+ By default, no benchmarks run.
+
+ -test.cpuprofile cpu.out
+ Write a CPU profile to the specified file before exiting.
+
+ -test.memprofile mem.out
+ Write a memory profile to the specified file when all tests
+ are complete.
+
+ -test.memprofilerate n
+ Enable more precise (and expensive) memory profiles by setting
+ runtime.MemProfileRate. See 'godoc runtime MemProfileRate'.
+ To profile all memory allocations, use -test.memprofilerate=1
+ and set the environment variable GOGC=off to disable the
+ garbage collector, provided the test can run in the available
+ memory without garbage collection.
+
+ -test.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.
+
+ -test.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.
+
+ -test.timeout t
+ If a test runs longer than t, panic.
+
+ -test.benchtime n
+ Run enough iterations of each benchmark to take n seconds.
+ The default is 1 second.
+
+ -test.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.
+
+For convenience, each of these -test.X flags of the test binary is
+also available as the flag -X in 'go test' itself. Flags not listed
+here are passed through unaltered. For instance, the command
+
+ go test -x -v -cpuprofile=prof.out -dir=testdata -update -file x_test.go
+
+will compile the test binary using x_test.go and then run it as
+
+ test.out -test.v -test.cpuprofile=prof.out -dir=testdata -update
+
+
+Description of 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 is any alphanumeric string
+not starting 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 and os.Stderr.
+That output is compared against the function's doc comment.
+An example without a doc comment is compiled but not executed.
+
+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:
+
+ // The output of this example function.
+ func ExamplePrintln() {
+ Println("The output of this example function.")
+ }
+
+See the documentation of the testing package for more information.
+
+
+*/
+package documentation
+
+// NOTE: cmdDoc is in fmt.go.
diff --git a/src/cmd/go/fix.go b/src/cmd/go/fix.go
new file mode 100644
index 000000000..bae9f5c98
--- /dev/null
+++ b/src/cmd/go/fix.go
@@ -0,0 +1,30 @@
+// 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 main
+
+var cmdFix = &Command{
+ Run: runFix,
+ UsageLine: "fix [importpath...]",
+ Short: "run gofix on packages",
+ Long: `
+Fix runs the gofix command on the packages named by the import paths.
+
+For more about gofix, see 'godoc gofix'.
+For more about import paths, see 'go help importpath'.
+
+To run gofix with specific options, run gofix itself.
+
+See also: go fmt, go vet.
+ `,
+}
+
+func runFix(cmd *Command, args []string) {
+ for _, pkg := range packages(args) {
+ // Use pkg.gofiles instead of pkg.Dir so that
+ // the command only applies to this package,
+ // not to packages in subdirectories.
+ run(stringList("gofix", relPaths(pkg.gofiles)))
+ }
+}
diff --git a/src/cmd/go/fmt.go b/src/cmd/go/fmt.go
new file mode 100644
index 000000000..4a47e2ea2
--- /dev/null
+++ b/src/cmd/go/fmt.go
@@ -0,0 +1,54 @@
+// 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 main
+
+var cmdFmt = &Command{
+ Run: runFmt,
+ UsageLine: "fmt [importpath...]",
+ Short: "run gofmt on 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 'godoc gofmt'.
+For more about import paths, see 'go help importpath'.
+
+To run gofmt with specific options, run gofmt itself.
+
+See also: go doc, go fix, go vet.
+ `,
+}
+
+func runFmt(cmd *Command, args []string) {
+ for _, pkg := range packages(args) {
+ // Use pkg.gofiles instead of pkg.Dir so that
+ // the command only applies to this package,
+ // not to packages in subdirectories.
+ run(stringList("gofmt", "-l", "-w", relPaths(pkg.gofiles)))
+ }
+}
+
+var cmdDoc = &Command{
+ Run: runDoc,
+ UsageLine: "doc [importpath...]",
+ Short: "run godoc on package sources",
+ Long: `
+Doc runs the godoc command on the packages named by the
+import paths.
+
+For more about godoc, see 'godoc godoc'.
+For more about import paths, see 'go help importpath'.
+
+To run godoc with specific options, run godoc itself.
+
+See also: go fix, go fmt, go vet.
+ `,
+}
+
+func runDoc(cmd *Command, args []string) {
+ for _, pkg := range packages(args) {
+ run("godoc", pkg.Dir)
+ }
+}
diff --git a/src/cmd/go/get.go b/src/cmd/go/get.go
new file mode 100644
index 000000000..cd57d3025
--- /dev/null
+++ b/src/cmd/go/get.go
@@ -0,0 +1,269 @@
+// 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.
+
+// TODO: Dashboard upload
+
+package main
+
+import (
+ "fmt"
+ "go/build"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strconv"
+ "strings"
+)
+
+var cmdGet = &Command{
+ UsageLine: "get [-a] [-d] [-fix] [-n] [-p n] [-u] [-v] [-x] [importpath...]",
+ Short: "download and install packages and dependencies",
+ Long: `
+Get downloads and installs the packages named by the import paths,
+along with their dependencies.
+
+The -a, -n, -v, -x, and -p flags have the same meaning as in 'go build'
+and 'go install'. See 'go help install'.
+
+The -d flag instructs get to stop after downloading the packages; that is,
+it instructs get not to install the packages.
+
+The -fix flag instructs get to run gofix on the downloaded packages
+before resolving dependencies or building the code.
+
+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.
+
+TODO: Explain versions better.
+
+For more about import paths, see 'go help importpath'.
+
+For more about how 'go get' finds source code to
+download, see 'go help remote'.
+
+See also: go build, go install, go clean.
+ `,
+}
+
+var getD = cmdGet.Flag.Bool("d", false, "")
+var getU = cmdGet.Flag.Bool("u", false, "")
+var getFix = cmdGet.Flag.Bool("fix", false, "")
+
+func init() {
+ addBuildFlags(cmdGet)
+ cmdGet.Run = runGet // break init loop
+}
+
+func runGet(cmd *Command, args []string) {
+ // Phase 1. Download/update.
+ args = importPaths(args)
+ var stk importStack
+ for _, arg := range args {
+ download(arg, &stk)
+ }
+ exitIfErrors()
+
+ if *getD {
+ // download only
+ return
+ }
+
+ // Phase 2. Install.
+
+ // 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.
+ for name := range packageCache {
+ delete(packageCache, name)
+ }
+
+ runInstall(cmd, args)
+}
+
+// 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 code.google.com/p/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, stk *importStack) {
+ p := loadPackage(arg, stk)
+
+ // There's nothing to do if this is a package in the standard library.
+ if p.Standard {
+ return
+ }
+
+ // Only process each package once.
+ if downloadCache[arg] {
+ return
+ }
+ downloadCache[arg] = true
+
+ // Download if the package is missing, or update if we're using -u.
+ if p.Dir == "" || *getU {
+ // The actual download.
+ stk.push(p.ImportPath)
+ defer stk.pop()
+ if err := downloadPackage(p); err != nil {
+ errorf("%s", &PackageError{stk.copy(), err.Error()})
+ return
+ }
+
+ // Reread the package information from the updated files.
+ p = reloadPackage(arg, stk)
+ if p.Error != nil {
+ errorf("%s", p.Error)
+ return
+ }
+ }
+
+ if *getFix {
+ run(stringList("gofix", relPaths(p.gofiles)))
+
+ // The imports might have changed, so reload again.
+ p = reloadPackage(arg, stk)
+ if p.Error != nil {
+ errorf("%s", p.Error)
+ return
+ }
+ }
+
+ // Process dependencies, now that we know what they are.
+ for _, dep := range p.deps {
+ download(dep.ImportPath, stk)
+ }
+}
+
+// downloadPackage runs the create or download command
+// to make the first copy of or update a copy of the given package.
+func downloadPackage(p *Package) error {
+ // Analyze the import path to determine the version control system,
+ // repository, and the import path for the root of the repository.
+ vcs, repo, rootPath, err := vcsForImportPath(p.ImportPath)
+ if err != nil {
+ return err
+ }
+ if p.t == nil {
+ // Package not found. Put in first directory of $GOPATH or else $GOROOT.
+ p.t = build.Path[0] // $GOROOT
+ if len(build.Path) > 1 {
+ p.t = build.Path[1] // first in $GOPATH
+ }
+ p.Dir = filepath.Join(p.t.SrcDir(), p.ImportPath)
+ }
+ root := filepath.Join(p.t.SrcDir(), rootPath)
+
+ // If we've considered this repository already, don't do it again.
+ if downloadRootCache[root] {
+ return nil
+ }
+ downloadRootCache[root] = true
+
+ if 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)
+ st, err := os.Stat(meta)
+ if err == nil && !st.IsDir() {
+ return fmt.Errorf("%s exists but is not a directory", meta)
+ }
+ if err != nil {
+ // Metadata 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)
+ }
+ // 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 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
+ }
+ }
+
+ // 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]
+ }
+ tag := selectTag(vers, tags)
+ if tag == "" {
+ tag = vcs.tagDefault
+ }
+ if err := vcs.tagSync(root, tag); 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 "release.rN" matches tags of the form "go.rN" (N being a decimal).
+// Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD".
+func selectTag(goVersion string, tags []string) (match string) {
+ const rPrefix = "release.r"
+ if strings.HasPrefix(goVersion, rPrefix) {
+ p := "go.r"
+ v, err := strconv.ParseFloat(goVersion[len(rPrefix):], 64)
+ if err != nil {
+ return ""
+ }
+ var matchf float64
+ for _, t := range tags {
+ if !strings.HasPrefix(t, p) {
+ continue
+ }
+ tf, err := strconv.ParseFloat(t[len(p):], 64)
+ if err != nil {
+ continue
+ }
+ if matchf < tf && tf <= v {
+ match, matchf = t, tf
+ }
+ }
+ }
+ const wPrefix = "weekly."
+ if strings.HasPrefix(goVersion, wPrefix) {
+ p := "go.weekly."
+ v := goVersion[len(wPrefix):]
+ for _, t := range tags {
+ if !strings.HasPrefix(t, p) {
+ continue
+ }
+ if match < t && t[len(p):] <= v {
+ match = t
+ }
+ }
+ }
+ return match
+}
diff --git a/src/cmd/go/help.go b/src/cmd/go/help.go
new file mode 100644
index 000000000..33716eff9
--- /dev/null
+++ b/src/cmd/go/help.go
@@ -0,0 +1,185 @@
+// 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 main
+
+var helpImportpath = &Command{
+ UsageLine: "importpath",
+ Short: "description of import paths",
+ Long: `
+Many commands apply to a set of packages named by import paths:
+
+ go action [importpath...]
+
+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 (see 'go help gopath').
+
+If no import paths are given, the action applies to the
+package in the current directory.
+
+The special import path "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.
+
+The special import path "std" is like all but expands to just the
+packages in the standard Go library.
+
+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. For example, encoding/... expands to all packages
+in the encoding tree.
+
+An import path can also name a package to be downloaded from
+a remote repository. Run 'go help remote' 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 'code.google.com/p/project'.
+ `,
+}
+
+var helpRemote = &Command{
+ UsageLine: "remote",
+ Short: "remote import path syntax",
+ Long: `
+
+An import path (see 'go help importpath') denotes a package
+stored in the local file system. 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 (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"
+
+ Google Code Project Hosting (Git, Mercurial, Subversion)
+
+ import "code.google.com/p/project"
+ import "code.google.com/p/project/sub/directory"
+
+ import "code.google.com/p/project.subrepository"
+ import "code.google.com/p/project.subrepository/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"
+
+For code hosted on other servers, 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.com/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 git://, then https://, then http://.
+
+New downloaded packages are written to the first directory
+listed in the GOPATH environment variable (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 install' for more.
+ `,
+}
+
+var helpGopath = &Command{
+ UsageLine: "gopath",
+ Short: "GOPATH environment variable",
+ Long: `
+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.
+
+GOPATH must be set to build and install packages outside the
+standard Go tree.
+
+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/ is stripped
+so that you can add DIR/bin to your PATH to get at the
+installed commands.
+
+Here's an example directory layout:
+
+ GOPATH=/home/user/gocode
+
+ /home/user/gocode/
+ 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.
+ `,
+}
diff --git a/src/cmd/go/http.go b/src/cmd/go/http.go
new file mode 100644
index 000000000..8d9b2a165
--- /dev/null
+++ b/src/cmd/go/http.go
@@ -0,0 +1,35 @@
+// 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 main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net/http"
+)
+
+// httpGET returns the data from an HTTP GET request for the given URL.
+func httpGET(url string) ([]byte, error) {
+ resp, err := http.Get(url)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != 200 {
+ return nil, fmt.Errorf("%s: %s", url, resp.Status)
+ }
+ b, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, fmt.Errorf("%s: %v", url, err)
+ }
+ return b, nil
+}
diff --git a/src/cmd/go/list.go b/src/cmd/go/list.go
new file mode 100644
index 000000000..af211f98d
--- /dev/null
+++ b/src/cmd/go/list.go
@@ -0,0 +1,114 @@
+// 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 main
+
+import (
+ "encoding/json"
+ "os"
+ "text/template"
+)
+
+var cmdList = &Command{
+ UsageLine: "list [-e] [-f format] [-json] [importpath...]",
+ Short: "list packages",
+ Long: `
+List lists the packages named by the import paths, one per line.
+
+The default output shows the package import path:
+
+ code.google.com/p/google-api-go-client/books/v1
+ code.google.com/p/goauth2/oauth
+ code.google.com/p/sqlite
+
+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 {
+ Name string // package name
+ Doc string // package documentation string
+ ImportPath string // import path of package in dir
+ Dir string // directory containing package sources
+ Version string // version of installed package (TODO)
+ Stale bool // would 'go install' do anything for this package?
+
+ // Source files
+ GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, and XTestGoFiles)
+ TestGoFiles []string // _test.go source files internal to the package they are testing
+ XTestGoFiles []string // _test.go source files external to the package they are testing
+ CFiles []string // .c source files
+ HFiles []string // .h source files
+ SFiles []string // .s source files
+ CgoFiles []string // .go sources files that import "C"
+
+ // Dependency information
+ Imports []string // import paths used by this package
+ Deps []string // all (recursively) imported dependencies
+
+ // Error information
+ Incomplete bool // this package or a dependency has an error
+ Error *PackageError // error loading package
+ DepsErrors []*PackageError // errors loading dependencies
+ }
+
+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 import paths, see 'go help importpath'.
+ `,
+}
+
+func init() {
+ cmdList.Run = runList // break init cycle
+}
+
+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 *Command, args []string) {
+ var do func(*Package)
+ if *listJson {
+ do = func(p *Package) {
+ b, err := json.MarshalIndent(p, "", "\t")
+ if err != nil {
+ fatalf("%s", err)
+ }
+ os.Stdout.Write(b)
+ os.Stdout.Write(nl)
+ }
+ } else {
+ tmpl, err := template.New("main").Parse(*listFmt + "\n")
+ if err != nil {
+ fatalf("%s", err)
+ }
+ do = func(p *Package) {
+ if err := tmpl.Execute(os.Stdout, p); err != nil {
+ fatalf("%s", err)
+ }
+ }
+ }
+
+ load := packages
+ if *listE {
+ load = packagesAndErrors
+ }
+
+ for _, pkg := range load(args) {
+ do(pkg)
+ }
+}
diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go
new file mode 100644
index 000000000..ca3b1188a
--- /dev/null
+++ b/src/cmd/go/main.go
@@ -0,0 +1,485 @@
+// 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 main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/build"
+ "io"
+ "log"
+ "os"
+ "os/exec"
+ "path"
+ "path/filepath"
+ "regexp"
+ "strings"
+ "text/template"
+ "unicode"
+ "unicode/utf8"
+)
+
+// 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
+}
+
+// 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\n", c.UsageLine)
+ fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long))
+ os.Exit(2)
+}
+
+// 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{
+ cmdBuild,
+ cmdDoc,
+ cmdFix,
+ cmdFmt,
+ cmdGet,
+ cmdInstall,
+ cmdList,
+ cmdRun,
+ cmdTest,
+ cmdVersion,
+ cmdVet,
+
+ helpGopath,
+ helpImportpath,
+ helpRemote,
+ helpTestflag,
+ helpTestfunc,
+}
+
+var exitStatus = 0
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+ log.SetFlags(0)
+
+ args := flag.Args()
+ if len(args) < 1 {
+ usage()
+ }
+
+ if args[0] == "help" {
+ help(args[1:])
+ return
+ }
+
+ for _, cmd := range commands {
+ if cmd.Name() == args[0] && cmd.Run != nil {
+ 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)
+ exit()
+ return
+ }
+ }
+
+ fmt.Fprintf(os.Stderr, "Unknown command %#q\n\n", args[0])
+ usage()
+}
+
+var usageTemplate = `Go is a tool for managing Go source code.
+
+Usage: go command [arguments]
+
+The commands are:
+{{range .}}{{if .Run}}
+ {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
+
+Use "go help [command]" for more information about a command.
+
+Additional help topics:
+{{range .}}{{if not .Run}}
+ {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
+
+Use "go help [topic]" for more information about that topic.
+
+`
+
+var helpTemplate = `{{if .Run}}usage: go {{.UsageLine}}
+
+{{end}}{{.Long | trim}}
+`
+
+var documentationTemplate = `// 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.
+
+/*
+{{range .}}{{if .Short}}{{.Short | capitalize}}
+
+{{end}}{{if .Run}}Usage:
+
+ go {{.UsageLine}}
+
+{{end}}{{.Long | trim}}
+
+
+{{end}}*/
+package documentation
+
+// NOTE: cmdDoc is in fmt.go.
+`
+
+// 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))
+ if err := t.Execute(w, data); 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) {
+ tmpl(w, usageTemplate, commands)
+}
+
+func usage() {
+ printUsage(os.Stderr)
+ os.Exit(2)
+}
+
+// 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" {
+ buf := new(bytes.Buffer)
+ printUsage(buf)
+ usage := &Command{Long: buf.String()}
+ tmpl(os.Stdout, documentationTemplate, append([]*Command{usage}, commands...))
+ return
+ }
+
+ for _, cmd := range 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'
+}
+
+// importPaths returns the import paths to use for the given command line.
+func importPaths(args []string) []string {
+ if len(args) == 0 {
+ return []string{"."}
+ }
+ var out []string
+ for _, a := range args {
+ if isLocalPath(a) && strings.Contains(a, "...") {
+ out = append(out, allPackagesInFS(a)...)
+ continue
+ }
+ if a == "all" || a == "std" || strings.Contains(a, "...") {
+ out = append(out, allPackages(a)...)
+ continue
+ }
+ out = append(out, a)
+ }
+ return out
+}
+
+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...)
+ exitStatus = 1
+}
+
+var logf = log.Printf
+
+func exitIfErrors() {
+ if exitStatus != 0 {
+ exit()
+ }
+}
+
+func run(cmdargs ...interface{}) {
+ cmdline := stringList(cmdargs...)
+ cmd := exec.Command(cmdline[0], cmdline[1:]...)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ errorf("%v", err)
+ }
+}
+
+func runOut(dir string, cmdargs ...interface{}) []byte {
+ cmdline := stringList(cmdargs...)
+ cmd := exec.Command(cmdline[0], cmdline[1:]...)
+ cmd.Dir = dir
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ os.Stderr.Write(out)
+ errorf("%v", err)
+ out = nil
+ }
+ return out
+}
+
+// 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.
+func matchPattern(pattern string) func(name string) bool {
+ re := regexp.QuoteMeta(pattern)
+ re = strings.Replace(re, `\.\.\.`, `.*`, -1)
+ reg := regexp.MustCompile(`^` + re + `$`)
+ return func(name string) bool {
+ return reg.MatchString(name)
+ }
+}
+
+// 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)
+// or a path including "...".
+func allPackages(pattern string) []string {
+ match := func(string) bool { return true }
+ if pattern != "all" && pattern != "std" {
+ match = matchPattern(pattern)
+ }
+
+ have := map[string]bool{
+ "builtin": true, // ignore pseudo-package that exists only for documentation
+ }
+ if !buildContext.CgoEnabled {
+ have["runtime/cgo"] = true // ignore during walk
+ }
+ var pkgs []string
+
+ // Commands
+ goroot := build.Path[0].Path
+ cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator)
+ filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error {
+ if err != nil || !fi.IsDir() {
+ return nil
+ }
+ name := path[len(cmd):]
+ // Commands are all in cmd/, not in subdirectories.
+ if strings.Contains(name, string(filepath.Separator)) {
+ return filepath.SkipDir
+ }
+
+ _, err = build.ScanDir(path)
+ if err != nil {
+ return nil
+ }
+
+ // We use, e.g., cmd/gofmt as the pseudo import path for gofmt.
+ name = "cmd/" + name
+ if !have[name] {
+ have[name] = true
+ if match(name) {
+ pkgs = append(pkgs, name)
+ }
+ }
+ return nil
+ })
+
+ for _, t := range build.Path {
+ if pattern == "std" && !t.Goroot {
+ continue
+ }
+ src := t.SrcDir() + string(filepath.Separator)
+ filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
+ if err != nil || !fi.IsDir() {
+ return nil
+ }
+
+ // Avoid .foo, _foo, and testdata directory trees.
+ _, elem := filepath.Split(path)
+ if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
+ return filepath.SkipDir
+ }
+
+ name := filepath.ToSlash(path[len(src):])
+ if pattern == "std" && strings.Contains(name, ".") {
+ return filepath.SkipDir
+ }
+ if have[name] {
+ return nil
+ }
+ have[name] = true
+
+ _, err = build.ScanDir(path)
+ if err != nil {
+ return nil
+ }
+
+ if match(name) {
+ pkgs = append(pkgs, name)
+ }
+
+ // Avoid go/build test data.
+ // TODO: Move it into a testdata directory.
+ if path == filepath.Join(build.Path[0].SrcDir(), "go/build") {
+ return filepath.SkipDir
+ }
+
+ return nil
+ })
+ }
+
+ 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 {
+ // 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
+ }
+
+ // Avoid .foo, _foo, and testdata directory trees.
+ _, elem := filepath.Split(path)
+ if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
+ return filepath.SkipDir
+ }
+
+ name := prefix + filepath.ToSlash(path)
+ if !match(name) {
+ return nil
+ }
+ if _, err = build.ScanDir(path); err != nil {
+ return nil
+ }
+ pkgs = append(pkgs, name)
+ return nil
+ })
+
+ if len(pkgs) == 0 {
+ fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
+ }
+ return pkgs
+}
+
+// stringList's arguments should be a sequence of string or []string values.
+// stringList flattens them into a single []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")
+ }
+ }
+ return x
+}
+
+// isLocalPath returns true if arg is an import path denoting
+// a local file system directory. That is, it returns true if the
+// path begins with ./ or ../ .
+func isLocalPath(arg string) bool {
+ return arg == "." || arg == ".." || strings.HasPrefix(arg, "./") || strings.HasPrefix(arg, "../")
+}
diff --git a/src/cmd/go/mkdoc.sh b/src/cmd/go/mkdoc.sh
new file mode 100755
index 000000000..7768baeb6
--- /dev/null
+++ b/src/cmd/go/mkdoc.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+# 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.
+
+go help documentation > doc.go
+gofmt -w doc.go
+
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
new file mode 100644
index 000000000..09fa67127
--- /dev/null
+++ b/src/cmd/go/pkg.go
@@ -0,0 +1,445 @@
+// 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 main
+
+import (
+ "go/build"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+ "time"
+)
+
+// A Package describes a single package found in a directory.
+type Package 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
+ ImportPath string // import path of package in dir
+ Name string `json:",omitempty"` // package name
+ Doc string `json:",omitempty"` // package documentation string
+ Dir string `json:",omitempty"` // directory containing package sources
+ Version string `json:",omitempty"` // version of installed package (TODO)
+ Standard bool `json:",omitempty"` // is this package part of the standard Go library?
+ Stale bool `json:",omitempty"` // would 'go install' do anything for this package?
+ Incomplete bool `json:",omitempty"` // was there an error loading this package or dependencies?
+ Error *PackageError `json:",omitempty"` // error loading this package (not dependencies)
+
+ // Source files
+ GoFiles []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles and XTestGoFiles)
+ TestGoFiles []string `json:",omitempty"` // _test.go source files internal to the package they are testing
+ XTestGoFiles []string `json:",omitempty"` //_test.go source files external to the package they are testing
+ CFiles []string `json:",omitempty"` // .c source files
+ HFiles []string `json:",omitempty"` // .h source files
+ SFiles []string `json:",omitempty"` // .s source files
+ CgoFiles []string `json:",omitempty"` // .go sources files that import "C"
+ CgoCFLAGS []string `json:",omitempty"` // cgo: flags for C compiler
+ CgoLDFLAGS []string `json:",omitempty"` // cgo: flags for linker
+
+ // Dependency information
+ Imports []string `json:",omitempty"` // import paths used by this package
+ Deps []string `json:",omitempty"` // all (recursively) imported dependencies
+ DepsErrors []*PackageError `json:",omitempty"` // errors loading dependencies
+
+ // Unexported fields are not part of the public API.
+ t *build.Tree
+ pkgdir string
+ info *build.DirInfo
+ imports []*Package
+ deps []*Package
+ gofiles []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
+ target string // installed file for this package (may be executable)
+ fake bool // synthesized package
+}
+
+// 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
+ Err string // the error itself
+}
+
+func (p *PackageError) Error() string {
+ return 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 returns true if 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{}
+
+// 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)
+}
+
+// loadPackage scans directory named by arg,
+// which is either an import path or a file system path
+// (if the latter, must be rooted or begin with . or ..),
+// and returns a *Package describing the package
+// found in that directory.
+func loadPackage(arg string, stk *importStack) *Package {
+ stk.push(arg)
+ defer stk.pop()
+
+ // Check package cache.
+ if p := packageCache[arg]; p != nil {
+ return reusePackage(p, stk)
+ }
+
+ // Find basic information about package path.
+ t, importPath, err := build.FindTree(arg)
+ dir := ""
+ // Maybe it is a standard command.
+ if err != nil && strings.HasPrefix(arg, "cmd/") {
+ goroot := build.Path[0]
+ p := filepath.Join(goroot.Path, "src", arg)
+ if st, err1 := os.Stat(p); err1 == nil && st.IsDir() {
+ t = goroot
+ importPath = arg
+ dir = p
+ err = nil
+ }
+ }
+ // Maybe it is a path to a standard command.
+ if err != nil && (filepath.IsAbs(arg) || isLocalPath(arg)) {
+ arg, _ := filepath.Abs(arg)
+ goroot := build.Path[0]
+ cmd := filepath.Join(goroot.Path, "src", "cmd") + string(filepath.Separator)
+ if st, err1 := os.Stat(arg); err1 == nil && st.IsDir() && strings.HasPrefix(arg, cmd) {
+ t = goroot
+ importPath = filepath.FromSlash(arg[len(cmd):])
+ dir = arg
+ err = nil
+ }
+ }
+ if err != nil {
+ p := &Package{
+ ImportPath: arg,
+ Error: &PackageError{
+ ImportStack: stk.copy(),
+ Err: err.Error(),
+ },
+ Incomplete: true,
+ }
+ packageCache[arg] = p
+ return p
+ }
+
+ if dir == "" {
+ dir = filepath.Join(t.SrcDir(), filepath.FromSlash(importPath))
+ }
+
+ // Maybe we know the package by its directory.
+ if p := packageCache[dir]; p != nil {
+ packageCache[importPath] = p
+ return reusePackage(p, stk)
+ }
+
+ return scanPackage(&buildContext, t, arg, importPath, dir, stk)
+}
+
+func reusePackage(p *Package, stk *importStack) *Package {
+ // We use p.imports==nil to detect a package that
+ // is in the midst of its own loadPackage call
+ // (all the recursion below happens before p.imports gets set).
+ if p.imports == nil {
+ if p.Error == nil {
+ p.Error = &PackageError{
+ ImportStack: stk.copy(),
+ Err: "import loop",
+ }
+ }
+ p.Incomplete = true
+ }
+ if p.Error != nil && stk.shorterThan(p.Error.ImportStack) {
+ p.Error.ImportStack = stk.copy()
+ }
+ return p
+}
+
+// firstSentence returns the first sentence of the document text.
+// The sentence ends after the first period followed by a space.
+// The returned sentence will have no \n \r or \t characters and
+// will use only single spaces between words.
+func firstSentence(text string) string {
+ var b []byte
+ space := true
+Loop:
+ for i := 0; i < len(text); i++ {
+ switch c := text[i]; c {
+ case ' ', '\t', '\r', '\n':
+ if !space {
+ space = true
+ if len(b) > 0 && b[len(b)-1] == '.' {
+ break Loop
+ }
+ b = append(b, ' ')
+ }
+ default:
+ space = false
+ b = append(b, c)
+ }
+ }
+ return string(b)
+}
+
+func scanPackage(ctxt *build.Context, t *build.Tree, arg, importPath, dir string, stk *importStack) *Package {
+ // Read the files in the directory to learn the structure
+ // of the package.
+ p := &Package{
+ ImportPath: importPath,
+ Dir: dir,
+ Standard: t.Goroot && !strings.Contains(importPath, "."),
+ t: t,
+ }
+ packageCache[dir] = p
+ packageCache[importPath] = p
+
+ info, err := ctxt.ScanDir(dir)
+ if err != nil {
+ p.Error = &PackageError{
+ ImportStack: stk.copy(),
+ Err: err.Error(),
+ }
+ p.Incomplete = true
+ return p
+ }
+
+ p.info = info
+ p.Name = info.Package
+ p.Doc = firstSentence(info.PackageComment.Text())
+ p.Imports = info.Imports
+ p.GoFiles = info.GoFiles
+ p.TestGoFiles = info.TestGoFiles
+ p.XTestGoFiles = info.XTestGoFiles
+ p.CFiles = info.CFiles
+ p.HFiles = info.HFiles
+ p.SFiles = info.SFiles
+ p.CgoFiles = info.CgoFiles
+ p.CgoCFLAGS = info.CgoCFLAGS
+ p.CgoLDFLAGS = info.CgoLDFLAGS
+
+ if info.Package == "main" {
+ _, elem := filepath.Split(importPath)
+ p.target = filepath.Join(t.BinDir(), elem)
+ if ctxt.GOOS == "windows" {
+ p.target += ".exe"
+ }
+ } else {
+ p.target = filepath.Join(t.PkgDir(), filepath.FromSlash(importPath)+".a")
+ }
+
+ var built time.Time
+ if fi, err := os.Stat(p.target); err == nil {
+ built = fi.ModTime()
+ }
+
+ // Build list of full paths to all Go files in the package,
+ // for use by commands like go fmt.
+ for _, f := range info.GoFiles {
+ p.gofiles = append(p.gofiles, filepath.Join(dir, f))
+ }
+ for _, f := range info.CgoFiles {
+ p.gofiles = append(p.gofiles, filepath.Join(dir, f))
+ }
+ for _, f := range info.TestGoFiles {
+ p.gofiles = append(p.gofiles, filepath.Join(dir, f))
+ }
+ for _, f := range info.XTestGoFiles {
+ p.gofiles = append(p.gofiles, filepath.Join(dir, f))
+ }
+
+ sort.Strings(p.gofiles)
+
+ srcss := [][]string{
+ p.GoFiles,
+ p.CFiles,
+ p.HFiles,
+ p.SFiles,
+ p.CgoFiles,
+ }
+Stale:
+ for _, srcs := range srcss {
+ for _, src := range srcs {
+ if fi, err := os.Stat(filepath.Join(p.Dir, src)); err != nil || fi.ModTime().After(built) {
+ //println("STALE", p.ImportPath, "needs", src, err)
+ p.Stale = true
+ break Stale
+ }
+ }
+ }
+
+ importPaths := p.Imports
+ // Packages that use cgo import runtime/cgo implicitly,
+ // except runtime/cgo itself.
+ if len(info.CgoFiles) > 0 && (!p.Standard || p.ImportPath != "runtime/cgo") {
+ importPaths = append(importPaths, "runtime/cgo")
+ }
+ // Everything depends on runtime, except runtime and unsafe.
+ if !p.Standard || (p.ImportPath != "runtime" && p.ImportPath != "unsafe") {
+ importPaths = append(importPaths, "runtime")
+ }
+
+ // Record package under both import path and full directory name.
+ packageCache[dir] = p
+ packageCache[importPath] = p
+
+ // Build list of imported packages and full dependency list.
+ imports := make([]*Package, 0, len(p.Imports))
+ deps := make(map[string]bool)
+ for _, path := range importPaths {
+ if path == "C" {
+ continue
+ }
+ deps[path] = true
+ p1 := loadPackage(path, stk)
+ imports = append(imports, p1)
+ for _, dep := range p1.Deps {
+ deps[dep] = true
+ }
+ if p1.Stale {
+ p.Stale = true
+ }
+ if p1.Incomplete {
+ p.Incomplete = true
+ }
+ // p1.target can be empty only if p1 is not a real package,
+ // such as package unsafe or the temporary packages
+ // created during go test.
+ if !p.Stale && p1.target != "" {
+ if fi, err := os.Stat(p1.target); err != nil || fi.ModTime().After(built) {
+ //println("STALE", p.ImportPath, "needs", p1.target, err)
+ //println("BUILT", built.String(), "VS", fi.ModTime().String())
+ p.Stale = true
+ }
+ }
+ }
+ p.imports = imports
+
+ 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 := packageCache[dep]
+ if p1 == nil {
+ panic("impossible: missing entry in package cache for " + dep + " imported by " + p.ImportPath)
+ }
+ p.deps = append(p.deps, p1)
+ if p1.Error != nil {
+ p.DepsErrors = append(p.DepsErrors, p1.Error)
+ }
+ }
+
+ // unsafe is a fake package and is never out-of-date.
+ if p.Standard && p.ImportPath == "unsafe" {
+ p.Stale = false
+ p.target = ""
+ }
+
+ return p
+}
+
+// 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 {
+ args = importPaths(args)
+ var pkgs []*Package
+ var stk importStack
+ for _, arg := range args {
+ pkg := loadPackage(arg, &stk)
+ if pkg.Error != nil {
+ errorf("%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 {
+ args = importPaths(args)
+ var pkgs []*Package
+ var stk importStack
+ for _, arg := range args {
+ pkgs = append(pkgs, loadPackage(arg, &stk))
+ }
+ 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 {
+ errorf("%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
+ errorf("%s", err)
+ }
+ }
+ }
+ exitIfErrors()
+ return pkgs
+}
diff --git a/src/cmd/go/run.go b/src/cmd/go/run.go
new file mode 100644
index 000000000..714cd4051
--- /dev/null
+++ b/src/cmd/go/run.go
@@ -0,0 +1,57 @@
+// 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 main
+
+import "strings"
+
+var cmdRun = &Command{
+ UsageLine: "run [-a] [-n] [-x] gofiles... [arguments...]",
+ Short: "compile and run Go program",
+ Long: `
+Run compiles and runs the main package comprising the named Go source files.
+
+The -a flag forces reinstallation of packages that are already up-to-date.
+The -n flag prints the commands but does not run them.
+The -x flag prints the commands.
+
+See also: go build.
+ `,
+}
+
+func init() {
+ cmdRun.Run = runRun // break init loop
+
+ cmdRun.Flag.BoolVar(&buildA, "a", false, "")
+ cmdRun.Flag.BoolVar(&buildN, "n", false, "")
+ cmdRun.Flag.BoolVar(&buildX, "x", false, "")
+}
+
+func runRun(cmd *Command, args []string) {
+ var b builder
+ b.init()
+ i := 0
+ for i < len(args) && strings.HasSuffix(args[i], ".go") {
+ i++
+ }
+ files, cmdArgs := args[:i], args[i:]
+ p := goFilesPackage(files, "")
+ p.target = "" // must build - not up to date
+ a1 := b.action(modeBuild, modeBuild, p)
+ a := &action{f: (*builder).runProgram, args: cmdArgs, deps: []*action{a1}}
+ b.do(a)
+}
+
+// runProgram is the action for running a binary that has already
+// been compiled. We ignore exit status.
+func (b *builder) runProgram(a *action) error {
+ if buildN || buildX {
+ b.showcmd("", "%s %s", a.deps[0].target, strings.Join(a.args, " "))
+ if buildN {
+ return nil
+ }
+ }
+ run(a.deps[0].target, a.args)
+ return nil
+}
diff --git a/src/cmd/go/script b/src/cmd/go/script
new file mode 100755
index 000000000..340a7e824
--- /dev/null
+++ b/src/cmd/go/script
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+x() {
+ echo '--- ' "$@"
+ "$@"
+ echo '---'
+ echo
+}
+
+x go help
+x go help build
+x go help clean
+x go help install
+x go help fix
+x go help fmt
+x go help get
+x go help list
+x go help test
+x go help version
+x go help vet
+x go help gopath
+x go help importpath
+x go help remote
diff --git a/src/cmd/go/script.txt b/src/cmd/go/script.txt
new file mode 100644
index 000000000..a67214658
--- /dev/null
+++ b/src/cmd/go/script.txt
@@ -0,0 +1,352 @@
+--- go help
+usage: go command [arguments]
+
+go manages Go source code.
+
+The commands are:
+
+ build compile and install packages and dependencies
+ clean remove intermediate objects
+ fix run gofix on packages
+ fmt run gofmt -w on packages
+ get download and install packages and dependencies
+ install install packages and dependencies
+ list list packages
+ test test packages
+ version print Go version
+ vet run govet on packages
+
+Use "go help [command]" for more information about a command.
+
+Additional help topics:
+
+ gopath GOPATH environment variable
+ importpath description of import paths
+ remote remote import path syntax
+
+Use "go help [topic]" for more information about that topic.
+
+---
+
+--- go help build
+usage: go build [-n] [-v] [importpath...]
+
+Build compiles the packages named by the import paths,
+along with their dependencies, but it does not install the results.
+
+The -n flag prints the commands but does not run them.
+The -v flag prints the commands.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go install, go get, go clean.
+---
+
+--- go help clean
+usage: go clean [-nuke] [importpath...]
+
+Clean removes intermediate object files generated during
+the compilation of the packages named by the import paths,
+but by default it does not remove the installed package binaries.
+
+The -nuke flag causes clean to remove the installed package binaries too.
+
+TODO: Clean does not clean dependencies of the packages.
+
+For more about import paths, see 'go help importpath'.
+---
+
+--- go help install
+usage: go install [-n] [-v] [importpath...]
+
+Install compiles and installs the packages named by the import paths,
+along with their dependencies.
+
+The -n flag prints the commands but does not run them.
+The -v flag prints the commands.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go build, go get, go clean.
+---
+
+--- go help fix
+usage: go fix [importpath...]
+
+Fix runs the gofix command on the packages named by the import paths.
+
+For more about gofix, see 'godoc gofix'.
+For more about import paths, see 'go help importpath'.
+
+To run gofix with specific options, run gofix itself.
+
+See also: go fmt, go vet.
+---
+
+--- go help fmt
+usage: go fmt [importpath...]
+
+Fmt runs the command 'gofmt -w' on the packages named by the import paths.
+
+For more about gofmt, see 'godoc gofmt'.
+For more about import paths, see 'go help importpath'.
+
+To run gofmt with specific options, run gofmt itself.
+
+See also: go fix, go vet.
+---
+
+--- go help get
+usage: go get [importpath...]
+
+Get downloads and installs the packages named by the import paths,
+along with their dependencies.
+
+After downloading the code, 'go get' looks for a tag beginning
+with "go." that corresponds to the local Go version.
+For Go "release.r58" it looks for a tag named "go.r58".
+For "weekly.2011-06-03" it looks for "go.weekly.2011-06-03".
+If the specific "go.X" tag is not found, it uses the latest earlier
+version it can find. Otherwise, it uses the default version for
+the version control system: HEAD for git, tip for Mercurial,
+and so on.
+
+TODO: Explain versions better.
+
+For more about import paths, see 'go help importpath'.
+
+For more about how 'go get' finds source code to
+download, see 'go help remote'.
+
+See also: go build, go install, go clean.
+---
+
+--- go help list
+usage: go list [-f format] [-json] [importpath...]
+
+List lists the packages named by the import paths.
+
+The default output shows the package name and file system location:
+
+ books /home/you/src/google-api-go-client.googlecode.com/hg/books/v1
+ oauth /home/you/src/goauth2.googlecode.com/hg/oauth
+ sqlite /home/you/src/gosqlite.googlecode.com/hg/sqlite
+
+The -f flag specifies an alternate format for the list,
+using the syntax of package template. The default output
+is equivalent to -f '{{.Name}} {{.Dir}}' The struct
+being passed to the template is:
+
+ type Package struct {
+ Name string // package name
+ Doc string // package documentation string
+ GoFiles []string // names of Go source files in package
+ ImportPath string // import path denoting package
+ Imports []string // import paths used by this package
+ Deps []string // all (recursively) imported dependencies
+ Dir string // directory containing package sources
+ Version string // version of installed package
+ }
+
+The -json flag causes the package data to be printed in JSON format.
+
+For more about import paths, see 'go help importpath'.
+---
+
+--- go help test
+usage: go test [importpath...]
+
+Test runs gotest to test the packages named by the import paths.
+It prints a summary of the test results in the format:
+
+ test archive/tar
+ FAIL archive/zip
+ test compress/gzip
+ ...
+
+followed by gotest output for each failed package.
+
+For more about import paths, see 'go help importpath'.
+
+See also: go build, go compile, go vet.
+---
+
+--- go help version
+usage: go version
+
+Version prints the Go version, as reported by runtime.Version.
+---
+
+--- go help vet
+usage: go vet [importpath...]
+
+Vet runs the govet command on the packages named by the import paths.
+
+For more about govet, see 'godoc govet'.
+For more about import paths, see 'go help importpath'.
+
+To run govet with specific options, run govet itself.
+
+See also: go fmt, go fix.
+---
+
+--- go help gopath
+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.
+
+GOPATH must be set to build and install packages outside the
+standard Go tree.
+
+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/ is stripped
+so that you can add DIR/bin to your PATH to get at the
+installed commands.
+
+Here's an example directory layout:
+
+ GOPATH=/home/user/gocode
+
+ /home/user/gocode/
+ 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.
+---
+
+--- go help importpath
+Many commands apply to a set of packages named by import paths:
+
+ go action [importpath...]
+
+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 (see 'go help gopath').
+
+If no import paths are given, the action applies to the
+package in the current directory.
+
+The special import path "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.
+
+An import path can also name a package to be downloaded from
+a remote repository. Run 'go help remote' 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 'project.googlecode.com/'.
+---
+
+--- go help remote
+An import path (see 'go help importpath') denotes a package
+stored in the local file system. 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 (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"
+
+ Google Code Project Hosting (Git, Mercurial, Subversion)
+
+ import "project.googlecode.com/git"
+ import "project.googlecode.com/git/sub/directory"
+
+ import "project.googlecode.com/hg"
+ import "project.googlecode.com/hg/sub/directory"
+
+ import "project.googlecode.com/svn/trunk"
+ import "project.googlecode.com/svn/trunk/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"
+
+For code hosted on other servers, 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.com/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 git://, then https://, then http://.
+
+New downloaded packages are written to the first directory
+listed in the GOPATH environment variable (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 install' for more.
+---
+
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
new file mode 100644
index 000000000..6cd49fe5a
--- /dev/null
+++ b/src/cmd/go/test.go
@@ -0,0 +1,681 @@
+// 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 main
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/build"
+ "go/parser"
+ "go/token"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "text/template"
+ "time"
+ "unicode"
+ "unicode/utf8"
+)
+
+// Break init loop.
+func init() {
+ cmdTest.Run = runTest
+}
+
+var cmdTest = &Command{
+ CustomFlags: true,
+ UsageLine: "test [-c] [-file a.go -file b.go ...] [-p n] [-x] [importpath...] [flags for test binary]",
+ 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.
+
+By default, go test needs no arguments. It compiles and tests the package
+with source in the current directory, including tests, and runs the tests.
+If file names are given (with flag -file=test.go, one per extra test source file),
+only those test files are added to the package. (The non-test files are always
+compiled.)
+
+The package is built in a temporary directory so it does not interfere with the
+non-test installation.
+
+See 'go help testflag' for details about flags handled by 'go test'
+and the test binary.
+
+See 'go help importpath' for more about import paths.
+
+See also: go build, go vet.
+ `,
+}
+
+var helpTestflag = &Command{
+ UsageLine: "testflag",
+ Short: "description of 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.
+
+The flags handled by 'go test' are:
+
+ -c Compile the test binary to test.out but do not run it.
+
+ -file a.go
+ Use only the tests in the source file a.go.
+ Multiple -file flags may be provided.
+
+ -p n
+ Compile and test up to n packages in parallel.
+ The default value is the number of CPUs available.
+
+ -x Print each subcommand go test executes.
+
+The resulting test binary, called test.out, has its own flags:
+
+ -test.v
+ Verbose output: log all tests as they are run.
+
+ -test.run pattern
+ Run only those tests matching the regular expression.
+
+ -test.bench pattern
+ Run benchmarks matching the regular expression.
+ By default, no benchmarks run.
+
+ -test.cpuprofile cpu.out
+ Write a CPU profile to the specified file before exiting.
+
+ -test.memprofile mem.out
+ Write a memory profile to the specified file when all tests
+ are complete.
+
+ -test.memprofilerate n
+ Enable more precise (and expensive) memory profiles by setting
+ runtime.MemProfileRate. See 'godoc runtime MemProfileRate'.
+ To profile all memory allocations, use -test.memprofilerate=1
+ and set the environment variable GOGC=off to disable the
+ garbage collector, provided the test can run in the available
+ memory without garbage collection.
+
+ -test.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.
+
+ -test.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.
+
+ -test.timeout t
+ If a test runs longer than t, panic.
+
+ -test.benchtime n
+ Run enough iterations of each benchmark to take n seconds.
+ The default is 1 second.
+
+ -test.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.
+
+For convenience, each of these -test.X flags of the test binary is
+also available as the flag -X in 'go test' itself. Flags not listed
+here are passed through unaltered. For instance, the command
+
+ go test -x -v -cpuprofile=prof.out -dir=testdata -update -file x_test.go
+
+will compile the test binary using x_test.go and then run it as
+
+ test.out -test.v -test.cpuprofile=prof.out -dir=testdata -update
+ `,
+}
+
+var helpTestfunc = &Command{
+ UsageLine: "testfunc",
+ Short: "description of 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 is any alphanumeric string
+not starting 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 and os.Stderr.
+That output is compared against the function's doc comment.
+An example without a doc comment is compiled but not executed.
+
+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:
+
+ // The output of this example function.
+ func ExamplePrintln() {
+ Println("The output of this example function.")
+ }
+
+See the documentation of the testing package for more information.
+ `,
+}
+
+var (
+ testC bool // -c flag
+ testP int // -p flag
+ testX bool // -x flag
+ testV bool // -v flag
+ testFiles []string // -file flag(s) TODO: not respected
+ testArgs []string
+ testShowPass bool // whether to display passing output
+ testBench bool
+)
+
+func runTest(cmd *Command, args []string) {
+ var pkgArgs []string
+ pkgArgs, testArgs = testFlags(args)
+
+ // show test PASS output when no packages
+ // are listed (implicitly current directory: "go test")
+ // or when the -v flag has been given.
+ testShowPass = len(pkgArgs) == 0 || testV
+
+ pkgs := packagesForBuild(pkgArgs)
+ if len(pkgs) == 0 {
+ fatalf("no packages to test")
+ }
+
+ if testC && len(pkgs) != 1 {
+ fatalf("cannot use -c flag with multiple packages")
+ }
+
+ buildX = testX
+ if testP > 0 {
+ buildP = testP
+ }
+
+ var b builder
+ b.init()
+
+ var builds, runs, prints []*action
+
+ // Prepare build + run + print actions for all packages being tested.
+ for _, p := range pkgs {
+ buildTest, runTest, printTest, err := b.test(p)
+ if err != nil {
+ errorf("%s", err)
+ continue
+ }
+ builds = append(builds, buildTest)
+ runs = append(runs, runTest)
+ prints = append(prints, printTest)
+ }
+
+ // Ultimately the goal is to print the output.
+ root := &action{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])
+ }
+ }
+
+ // If we are benchmarking, force everything to
+ // happen in serial. Could instead allow all the
+ // builds to run before any benchmarks start,
+ // but try this for now.
+ if testBench {
+ for i, a := range builds {
+ if i > 0 {
+ // Make build of test i depend on
+ // completing the run of test i-1.
+ a.deps = append(a.deps, runs[i-1])
+ }
+ }
+ }
+
+ // If we are building any out-of-date packages other
+ // than those under test, warn.
+ okBuild := map[*Package]bool{}
+ for _, p := range pkgs {
+ okBuild[p] = true
+ }
+
+ warned := false
+ for _, a := range actionList(root) {
+ if a.p != nil && a.f != nil && !okBuild[a.p] && !a.p.fake {
+ okBuild[a.p] = true // don't warn again
+ if !warned {
+ fmt.Fprintf(os.Stderr, "warning: building out-of-date packages:\n")
+ warned = true
+ }
+ fmt.Fprintf(os.Stderr, "\t%s\n", a.p.ImportPath)
+ }
+ }
+ if warned {
+ fmt.Fprintf(os.Stderr, "installing these packages with 'go install' will speed future tests.\n\n")
+ }
+
+ b.do(root)
+}
+
+func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, err error) {
+ if len(p.info.TestGoFiles)+len(p.info.XTestGoFiles) == 0 {
+ build := &action{p: p}
+ run := &action{p: p}
+ print := &action{f: (*builder).notest, p: p, deps: []*action{build}}
+ return build, run, print, nil
+ }
+
+ // Build Package structs describing:
+ // ptest - package + test files
+ // pxtest - package of external test files
+ // pmain - test.out binary
+ var ptest, pxtest, pmain *Package
+
+ // go/build does not distinguish the dependencies used
+ // by the TestGoFiles from the dependencies used by the
+ // XTestGoFiles, so we build one list and use it for both
+ // ptest and pxtest. No harm done.
+ var imports []*Package
+ var stk importStack
+ stk.push(p.ImportPath + "_test")
+ for _, path := range p.info.TestImports {
+ p1 := loadPackage(path, &stk)
+ if p1.Error != nil {
+ return nil, nil, nil, p1.Error
+ }
+ imports = append(imports, p1)
+ }
+ stk.pop()
+
+ // The ptest package needs to be importable under the
+ // same import path that p has, but we cannot put it in
+ // the usual place in the temporary tree, because then
+ // other tests will see it as the real package.
+ // Instead we make a _test directory under the import path
+ // and then repeat the import path there. We tell the
+ // compiler and linker to look in that _test directory first.
+ //
+ // That is, if the package under test is unicode/utf8,
+ // then the normal place to write the package archive is
+ // $WORK/unicode/utf8.a, but we write the test package archive to
+ // $WORK/unicode/utf8/_test/unicode/utf8.a.
+ // We write the external test package archive to
+ // $WORK/unicode/utf8/_test/unicode/utf8_test.a.
+ testDir := filepath.Join(b.work, filepath.FromSlash(p.ImportPath+"/_test"))
+ ptestObj := filepath.Join(testDir, filepath.FromSlash(p.ImportPath+".a"))
+ pxtestObj := filepath.Join(testDir, filepath.FromSlash(p.ImportPath+"_test.a"))
+
+ // Create the directory for the .a files.
+ ptestDir, _ := filepath.Split(ptestObj)
+ if err := b.mkdir(ptestDir); err != nil {
+ return nil, nil, nil, err
+ }
+ if err := writeTestmain(filepath.Join(testDir, "_testmain.go"), p); err != nil {
+ return nil, nil, nil, err
+ }
+
+ // Test package.
+ if len(p.info.TestGoFiles) > 0 {
+ ptest = new(Package)
+ *ptest = *p
+ ptest.GoFiles = nil
+ ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
+ ptest.GoFiles = append(ptest.GoFiles, p.info.TestGoFiles...)
+ ptest.target = ""
+ ptest.Imports = stringList(p.info.Imports, p.info.TestImports)
+ ptest.imports = append(append([]*Package{}, p.imports...), imports...)
+ ptest.pkgdir = testDir
+ ptest.fake = true
+ a := b.action(modeBuild, modeBuild, ptest)
+ a.objdir = testDir + string(filepath.Separator)
+ a.objpkg = ptestObj
+ a.target = ptestObj
+ a.link = false
+ } else {
+ ptest = p
+ }
+
+ // External test package.
+ if len(p.info.XTestGoFiles) > 0 {
+ pxtest = &Package{
+ Name: p.Name + "_test",
+ ImportPath: p.ImportPath + "_test",
+ Dir: p.Dir,
+ GoFiles: p.info.XTestGoFiles,
+ Imports: p.info.TestImports,
+ t: p.t,
+ info: &build.DirInfo{},
+ imports: imports,
+ pkgdir: testDir,
+ fake: true,
+ }
+ pxtest.imports = append(pxtest.imports, ptest)
+ a := b.action(modeBuild, modeBuild, pxtest)
+ a.objdir = testDir + string(filepath.Separator)
+ a.objpkg = pxtestObj
+ a.target = pxtestObj
+ }
+
+ // Action for building test.out.
+ pmain = &Package{
+ Name: "main",
+ Dir: testDir,
+ GoFiles: []string{"_testmain.go"},
+ t: p.t,
+ info: &build.DirInfo{},
+ imports: []*Package{ptest},
+ fake: true,
+ }
+ if pxtest != nil {
+ pmain.imports = append(pmain.imports, pxtest)
+ }
+
+ // The generated main also imports testing and regexp.
+ stk.push("testmain")
+ ptesting := loadPackage("testing", &stk)
+ if ptesting.Error != nil {
+ return nil, nil, nil, ptesting.Error
+ }
+ pregexp := loadPackage("regexp", &stk)
+ if pregexp.Error != nil {
+ return nil, nil, nil, pregexp.Error
+ }
+ pmain.imports = append(pmain.imports, ptesting, pregexp)
+
+ a := b.action(modeBuild, modeBuild, pmain)
+ a.objdir = testDir + string(filepath.Separator)
+ a.objpkg = filepath.Join(testDir, "main.a")
+ a.target = filepath.Join(testDir, "test.out") + b.exe
+ pmainAction := a
+
+ if testC {
+ // -c flag: create action to copy binary to ./test.out.
+ runAction = &action{
+ f: (*builder).install,
+ deps: []*action{pmainAction},
+ p: pmain,
+ target: "test.out" + b.exe,
+ }
+ printAction = &action{p: p, deps: []*action{runAction}} // nop
+ } else {
+ // run test
+ runAction = &action{
+ f: (*builder).runTest,
+ deps: []*action{pmainAction},
+ p: p,
+ ignoreFail: true,
+ }
+ printAction = &action{
+ f: (*builder).printTest,
+ deps: []*action{runAction},
+ p: p,
+ }
+ }
+
+ return pmainAction, runAction, printAction, nil
+}
+
+// runTest is the action for running a test binary.
+func (b *builder) runTest(a *action) error {
+ args := stringList(a.deps[0].target, testArgs)
+ a.testOutput = new(bytes.Buffer)
+
+ if buildN || buildX {
+ b.showcmd("", "%s", strings.Join(args, " "))
+ if buildN {
+ return nil
+ }
+ }
+
+ if a.failed {
+ // We were unable to build the binary.
+ a.failed = false
+ fmt.Fprintf(a.testOutput, "FAIL\t%s [build failed]\n", a.p.ImportPath)
+ exitStatus = 1
+ return nil
+ }
+
+ cmd := exec.Command(args[0], args[1:]...)
+ cmd.Dir = a.p.Dir
+ var buf bytes.Buffer
+ cmd.Stdout = &buf
+ cmd.Stderr = &buf
+
+ t0 := time.Now()
+ err := cmd.Start()
+
+ // This is a last-ditch deadline to detect and
+ // stop wedged test binaries, to keep the builders
+ // running.
+ const deadline = 10 * time.Minute
+
+ tick := time.NewTimer(deadline)
+ if err == nil {
+ done := make(chan error)
+ go func() {
+ done <- cmd.Wait()
+ }()
+ select {
+ case err = <-done:
+ // ok
+ case <-tick.C:
+ cmd.Process.Kill()
+ err = <-done
+ fmt.Fprintf(&buf, "*** Test killed: ran too long.\n")
+ }
+ tick.Stop()
+ }
+ out := buf.Bytes()
+ t1 := time.Now()
+ t := fmt.Sprintf("%.3fs", t1.Sub(t0).Seconds())
+ if err == nil {
+ fmt.Fprintf(a.testOutput, "ok \t%s\t%s\n", a.p.ImportPath, t)
+ if testShowPass {
+ a.testOutput.Write(out)
+ }
+ return nil
+ }
+
+ fmt.Fprintf(a.testOutput, "FAIL\t%s\t%s\n", a.p.ImportPath, t)
+ exitStatus = 1
+ if len(out) > 0 {
+ a.testOutput.Write(out)
+ // assume printing the test binary's exit status is superfluous
+ } else {
+ fmt.Fprintf(a.testOutput, "%s\n", err)
+ }
+ return nil
+}
+
+// printTest is the action for printing a test result.
+func (b *builder) printTest(a *action) error {
+ run := a.deps[0]
+ os.Stdout.Write(run.testOutput.Bytes())
+ run.testOutput = nil
+ return nil
+}
+
+// notest is the action for testing a package with no test files.
+func (b *builder) notest(a *action) error {
+ fmt.Printf("? \t%s\t[no test files]\n", a.p.ImportPath)
+ return nil
+}
+
+// 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)
+}
+
+// writeTestmain writes the _testmain.go file for package p to
+// the file named out.
+func writeTestmain(out string, p *Package) error {
+ t := &testFuncs{
+ Package: p,
+ Info: p.info,
+ }
+ for _, file := range p.info.TestGoFiles {
+ if err := t.load(filepath.Join(p.Dir, file), "_test", &t.NeedTest); err != nil {
+ return err
+ }
+ }
+ for _, file := range p.info.XTestGoFiles {
+ if err := t.load(filepath.Join(p.Dir, file), "_xtest", &t.NeedXtest); err != nil {
+ return err
+ }
+ }
+
+ f, err := os.Create(out)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ if err := testmainTmpl.Execute(f, t); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+type testFuncs struct {
+ Tests []testFunc
+ Benchmarks []testFunc
+ Examples []testFunc
+ Package *Package
+ Info *build.DirInfo
+ NeedTest bool
+ NeedXtest bool
+}
+
+type testFunc struct {
+ Package string // imported package name (_test or _xtest)
+ Name string // function name
+ Output string // output, for examples
+}
+
+var testFileSet = token.NewFileSet()
+
+func (t *testFuncs) load(filename, pkg string, seen *bool) error {
+ f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments)
+ if err != nil {
+ return 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 isTest(name, "Test"):
+ t.Tests = append(t.Tests, testFunc{pkg, name, ""})
+ *seen = true
+ case isTest(name, "Benchmark"):
+ t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, ""})
+ *seen = true
+ case isTest(name, "Example"):
+ output := n.Doc.Text()
+ if output == "" {
+ // Don't run examples with no output.
+ continue
+ }
+ t.Examples = append(t.Examples, testFunc{pkg, name, output})
+ *seen = true
+ }
+ }
+
+ return nil
+}
+
+var testmainTmpl = template.Must(template.New("main").Parse(`
+package main
+
+import (
+ "regexp"
+ "testing"
+
+{{if .NeedTest}}
+ _test {{.Package.ImportPath | printf "%q"}}
+{{end}}
+{{if .NeedXtest}}
+ _xtest {{.Package.ImportPath | printf "%s_test" | 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"}}},
+{{end}}
+}
+
+var matchPat string
+var matchRe *regexp.Regexp
+
+func matchString(pat, str string) (result bool, err error) {
+ if matchRe == nil || matchPat != pat {
+ matchPat = pat
+ matchRe, err = regexp.Compile(matchPat)
+ if err != nil {
+ return
+ }
+ }
+ return matchRe.MatchString(str), nil
+}
+
+func main() {
+ testing.Main(matchString, tests, benchmarks, examples)
+}
+
+`))
diff --git a/src/cmd/go/testflag.go b/src/cmd/go/testflag.go
new file mode 100644
index 000000000..a3cacd657
--- /dev/null
+++ b/src/cmd/go/testflag.go
@@ -0,0 +1,215 @@
+// 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 main
+
+import (
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+)
+
+// 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.
+
+var usageMessage = `Usage of go test:
+ -c=false: compile but do not run the test binary
+ -file=file_test.go: specify file to use for tests;
+ use multiple times for multiple files
+ -p=n: build and test up to n packages in parallel
+ -x=false: print command lines as they are executed
+
+ // These flags can be passed with or without a "test." prefix: -v or -test.v.
+ -bench="": passes -test.bench to test
+ -benchtime=1: passes -test.benchtime to test
+ -cpu="": passes -test.cpu to test
+ -cpuprofile="": passes -test.cpuprofile to test
+ -memprofile="": passes -test.memprofile to test
+ -memprofilerate=0: passes -test.memprofilerate to test
+ -parallel=0: passes -test.parallel to test
+ -run="": passes -test.run to test
+ -short=false: passes -test.short to test
+ -timeout=0: passes -test.timeout to test
+ -v=false: passes -test.v to test
+`
+
+// usage prints a usage message and exits.
+func testUsage() {
+ fmt.Fprint(os.Stderr, usageMessage)
+ exitStatus = 2
+ exit()
+}
+
+// testFlagSpec defines a flag we know about.
+type testFlagSpec struct {
+ name string
+ isBool bool
+ passToTest bool // pass to Test
+ multiOK bool // OK to have multiple instances
+ present bool // flag has been seen
+}
+
+// testFlagDefn is the set of flags we process.
+var testFlagDefn = []*testFlagSpec{
+ // local.
+ {name: "c", isBool: true},
+ {name: "file", multiOK: true},
+ {name: "p"},
+ {name: "x", isBool: true},
+
+ // passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
+ {name: "bench", passToTest: true},
+ {name: "benchtime", passToTest: true},
+ {name: "cpu", passToTest: true},
+ {name: "cpuprofile", passToTest: true},
+ {name: "memprofile", passToTest: true},
+ {name: "memprofilerate", passToTest: true},
+ {name: "parallel", passToTest: true},
+ {name: "run", passToTest: true},
+ {name: "short", isBool: true, passToTest: true},
+ {name: "timeout", passToTest: true},
+ {name: "v", isBool: true, passToTest: true},
+}
+
+// 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
+// test.out'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
+ 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 := testFlag(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{}
+ }
+ passToTest = append(passToTest, args[i])
+ continue
+ }
+ switch f.name {
+ case "c":
+ setBoolFlag(&testC, value)
+ case "p":
+ setIntFlag(&testP, value)
+ case "x":
+ setBoolFlag(&testX, value)
+ case "v":
+ setBoolFlag(&testV, value)
+ case "file":
+ testFiles = append(testFiles, value)
+ case "bench":
+ // record that we saw the flag; don't care about the value
+ testBench = true
+ }
+ if extraWord {
+ i++
+ }
+ if f.passToTest {
+ passToTest = append(passToTest, "-test."+f.name+"="+value)
+ }
+ }
+ return
+}
+
+// testFlag sees if argument i is a known flag and returns its definition, value, and whether it consumed an extra word.
+func testFlag(args []string, i int) (f *testFlagSpec, value string, extra bool) {
+ arg := args[i]
+ if strings.HasPrefix(arg, "--") { // reduce two minuses to one
+ arg = arg[1:]
+ }
+ switch arg {
+ case "-?", "-h", "-help":
+ usage()
+ }
+ if arg == "" || arg[0] != '-' {
+ return
+ }
+ name := arg[1:]
+ // If there's already "test.", drop it for now.
+ if strings.HasPrefix(name, "test.") {
+ name = name[5:]
+ }
+ equals := strings.Index(name, "=")
+ if equals >= 0 {
+ value = name[equals+1:]
+ name = name[:equals]
+ }
+ for _, f = range testFlagDefn {
+ if name == f.name {
+ // Booleans are special because they have modes -x, -x=true, -x=false.
+ if f.isBool {
+ if equals < 0 { // otherwise, it's been set and will be verified in setBoolFlag
+ value = "true"
+ } else {
+ // verify it parses
+ setBoolFlag(new(bool), value)
+ }
+ } else { // Non-booleans must have a value.
+ extra = equals < 0
+ if extra {
+ if i+1 >= len(args) {
+ usage()
+ }
+ value = args[i+1]
+ }
+ }
+ if f.present && !f.multiOK {
+ usage()
+ }
+ f.present = true
+ return
+ }
+ }
+ f = nil
+ return
+}
+
+// setBoolFlag sets the addressed boolean to the value.
+func setBoolFlag(flag *bool, value string) {
+ x, err := strconv.ParseBool(value)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "go test: illegal bool flag value %s\n", value)
+ usage()
+ }
+ *flag = x
+}
+
+// setIntFlag sets the addressed integer to the value.
+func setIntFlag(flag *int, value string) {
+ x, err := strconv.Atoi(value)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "go test: illegal int flag value %s\n", value)
+ usage()
+ }
+ *flag = x
+}
diff --git a/src/cmd/go/vcs.go b/src/cmd/go/vcs.go
new file mode 100644
index 000000000..da35048d5
--- /dev/null
+++ b/src/cmd/go/vcs.go
@@ -0,0 +1,425 @@
+// 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 main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "os"
+ "os/exec"
+ "regexp"
+ "strings"
+)
+
+// 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 // command to download a fresh copy of a repository
+ downloadCmd string // command to download updates into an existing repository
+
+ tagCmd []tagCmd // commands to list tags
+ tagDefault string // default tag to use
+ tagSyncCmd string // command to sync to specific tag
+}
+
+// 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,
+}
+
+// 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: "clone -U {repo} {dir}",
+ downloadCmd: "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 go.1 branch
+ // and make changes in both, without constantly
+ // editing .hgtags.
+ tagCmd: []tagCmd{
+ {"tags", `^(\S+)`},
+ {"branches", `^(\S+)`},
+ },
+ tagDefault: "default",
+ tagSyncCmd: "update -r {tag}",
+}
+
+// vcsGit describes how to use Git.
+var vcsGit = &vcsCmd{
+ name: "Git",
+ cmd: "git",
+
+ createCmd: "clone {repo} {dir}",
+ downloadCmd: "fetch",
+
+ tagCmd: []tagCmd{{"tag", `^(\S+)$`}},
+ tagDefault: "master",
+ tagSyncCmd: "checkout {tag}",
+}
+
+// vcsBzr describes how to use Bazaar.
+var vcsBzr = &vcsCmd{
+ name: "Bazaar",
+ cmd: "bzr",
+
+ createCmd: "branch {repo} {dir}",
+
+ // Without --overwrite bzr will not pull tags that changed.
+ // Replace by --overwrite-tags after http://pad.lv/681792 goes in.
+ downloadCmd: "pull --overwrite",
+
+ tagCmd: []tagCmd{{"tags", `^(\S+)`}},
+ tagDefault: "revno:-1",
+ tagSyncCmd: "update -r {tag}",
+}
+
+// vcsSvn describes how to use Subversion.
+var vcsSvn = &vcsCmd{
+ name: "Subversion",
+ cmd: "svn",
+
+ createCmd: "checkout {repo} {dir}",
+ downloadCmd: "update",
+
+ // There is no tag command in subversion.
+ // The branch information is all in the path names.
+}
+
+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, false, cmd, keyval)
+ 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, true, cmd, keyval)
+}
+
+// run1 is the generalized implementation of run and runOutput.
+func (v *vcsCmd) run1(dir string, output bool, cmdline string, keyval []string) ([]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)
+ }
+
+ cmd := exec.Command(v.cmd, args...)
+ cmd.Dir = dir
+ if 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
+ out := buf.Bytes()
+ err := cmd.Run()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " "))
+ os.Stderr.Write(out)
+ return nil, err
+ }
+ return out, nil
+}
+
+// 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 {
+ return v.run(".", v.createCmd, "dir", dir, "repo", repo)
+}
+
+// download downloads any new changes for the repo in dir.
+func (v *vcsCmd) download(dir string) error {
+ return v.run(dir, v.downloadCmd)
+}
+
+// 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)
+ tags = append(tags, re.FindAllString(string(out), -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 == "" {
+ return nil
+ }
+ return v.run(dir, v.tagSyncCmd, "tag", tag)
+}
+
+// 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
+
+ regexp *regexp.Regexp // cached compiled form of re
+}
+
+// vcsForImportPath analyzes importPath to determine the
+// version control system, and code repository to use.
+// On return, repo is the repository URL and root is the
+// import path corresponding to the root of the repository
+// (thus root is a prefix of importPath).
+func vcsForImportPath(importPath string) (vcs *vcsCmd, repo, root string, err error) {
+ 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"])
+ }
+ return vcs, match["repo"], match["root"], nil
+ }
+ return nil, "", "", fmt.Errorf("unrecognized import path %q", importPath)
+}
+
+// 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 lists the known vcs paths.
+var vcsPaths = []*vcsPath{
+ // Google Code - new syntax
+ {
+ prefix: "code.google.com/",
+ re: `^(?P<root>code\.google\.com/p/(?P<project>[a-z0-9\-]+)(\.(?P<subrepo>[a-z0-9\-]+))?)(/[A-Za-z0-9_.\-]+)*$`,
+ repo: "https://{root}",
+ check: googleCodeVCS,
+ },
+
+ // Google Code - old syntax
+ {
+ re: `^(?P<project>[a-z0-9_\-.]+)\.googlecode\.com/(git|hg|svn)(?P<path>/.*)?$`,
+ check: oldGoogleCode,
+ },
+
+ // Github
+ {
+ prefix: "github.com/",
+ re: `^(?P<root>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-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,
+ },
+
+ // Launchpad
+ {
+ 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,
+ },
+
+ // General syntax for any server.
+ {
+ re: `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(?P<vcs>bzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`,
+ },
+}
+
+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)
+ }
+}
+
+// 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
+}
+
+var googleCheckout = regexp.MustCompile(`id="checkoutcmd">(hg|git|svn)`)
+
+// googleCodeVCS determines the version control system for
+// a code.google.com repository, by scraping the project's
+// /source/checkout page.
+func googleCodeVCS(match map[string]string) error {
+ if err := noVCSSuffix(match); err != nil {
+ return err
+ }
+ data, err := httpGET(expand(match, "https://code.google.com/p/{project}/source/checkout?repo={subrepo}"))
+ if err != nil {
+ return err
+ }
+
+ if m := googleCheckout.FindSubmatch(data); m != nil {
+ if vcs := vcsByCmd(string(m[1])); vcs != nil {
+ // Subversion requires the old URLs.
+ // TODO: Test.
+ if vcs == vcsSvn {
+ if match["subrepo"] != "" {
+ return fmt.Errorf("sub-repositories not supported in Google Code Subversion projects")
+ }
+ match["repo"] = expand(match, "https://{project}.googlecode.com/svn")
+ }
+ match["vcs"] = vcs.cmd
+ return nil
+ }
+ }
+
+ return fmt.Errorf("unable to detect version control system for code.google.com/ path")
+}
+
+// oldGoogleCode is invoked for old-style foo.googlecode.com paths.
+// It prints an error giving the equivalent new path.
+func oldGoogleCode(match map[string]string) error {
+ return fmt.Errorf("invalid Google Code import path: use %s instead",
+ expand(match, "code.google.com/p/{project}{path}"))
+}
+
+// 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/1.0/repositories/{bitname}")
+ data, err := httpGET(url)
+ if err != nil {
+ return err
+ }
+ 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 := httpGET(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/src/cmd/go/version.go b/src/cmd/go/version.go
new file mode 100644
index 000000000..09e2f1633
--- /dev/null
+++ b/src/cmd/go/version.go
@@ -0,0 +1,25 @@
+// 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 main
+
+import (
+ "fmt"
+ "runtime"
+)
+
+var cmdVersion = &Command{
+ Run: runVersion,
+ UsageLine: "version",
+ Short: "print Go version",
+ Long: `Version prints the Go version, as reported by runtime.Version.`,
+}
+
+func runVersion(cmd *Command, args []string) {
+ if len(args) != 0 {
+ cmd.Usage()
+ }
+
+ fmt.Printf("go version %s\n", runtime.Version())
+}
diff --git a/src/cmd/go/vet.go b/src/cmd/go/vet.go
new file mode 100644
index 000000000..52c320032
--- /dev/null
+++ b/src/cmd/go/vet.go
@@ -0,0 +1,30 @@
+// 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 main
+
+var cmdVet = &Command{
+ Run: runVet,
+ UsageLine: "vet [importpath...]",
+ Short: "run govet on packages",
+ Long: `
+Vet runs the govet command on the packages named by the import paths.
+
+For more about govet, see 'godoc govet'.
+For more about import paths, see 'go help importpath'.
+
+To run govet with specific options, run govet itself.
+
+See also: go fmt, go fix.
+ `,
+}
+
+func runVet(cmd *Command, args []string) {
+ for _, pkg := range packages(args) {
+ // Use pkg.gofiles instead of pkg.Dir so that
+ // the command only applies to this package,
+ // not to packages in subdirectories.
+ run("govet", relPaths(pkg.gofiles))
+ }
+}