1
0
mirror of https://github.com/golang/go synced 2024-10-01 13:28:37 -06:00

cmd/go: split out cmd/go/internal/base

This is one CL in a long sequence of changes to break up the
go command from one package into a plausible group of packages.

This sequence is concerned only with moving code, not changing
or cleaning up code. There will still be more cleanup after this sequence.

The entire sequence will be submitted together: it is not a goal
for the tree to build at every step.

For #18653.

Change-Id: I7c5dde6e7fe4f390e6607303b4d42535c674eac3
Reviewed-on: https://go-review.googlesource.com/36193
Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
Russ Cox 2017-01-13 14:41:42 -05:00
parent b60e61ab1b
commit 6dc9e31f5e
27 changed files with 464 additions and 387 deletions

View File

@ -7,6 +7,7 @@ package main
import (
"bytes"
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"fmt"
"io"
"io/ioutil"
@ -18,7 +19,7 @@ import (
"strings"
)
var cmdBug = &Command{
var cmdBug = &base.Command{
Run: runBug,
UsageLine: "bug",
Short: "start a bug report",
@ -32,7 +33,7 @@ func init() {
cmdBug.Flag.BoolVar(&cfg.BuildV, "v", false, "")
}
func runBug(cmd *Command, args []string) {
func runBug(cmd *base.Command, args []string) {
var buf bytes.Buffer
buf.WriteString(bugHeader)
inspectGoVersion(&buf)

View File

@ -28,10 +28,11 @@ import (
"time"
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"cmd/go/internal/str"
)
var cmdBuild = &Command{
var cmdBuild = &base.Command{
UsageLine: "build [-o output] [-i] [build flags] [packages]",
Short: "compile packages and dependencies",
Long: `
@ -196,7 +197,7 @@ func init() {
// addBuildFlags adds the flags common to the build, clean, get,
// install, list, run, and test commands.
func addBuildFlags(cmd *Command) {
func addBuildFlags(cmd *base.Command) {
cmd.Flag.BoolVar(&cfg.BuildA, "a", false, "")
cmd.Flag.BoolVar(&cfg.BuildN, "n", false, "")
cmd.Flag.IntVar(&cfg.BuildP, "p", cfg.BuildP, "")
@ -219,11 +220,6 @@ func addBuildFlags(cmd *Command) {
cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "")
}
func addBuildFlagsNX(cmd *Command) {
cmd.Flag.BoolVar(&cfg.BuildN, "n", false, "")
cmd.Flag.BoolVar(&cfg.BuildX, "x", false, "")
}
func isSpaceByte(c byte) bool {
return c == ' ' || c == '\t' || c == '\n' || c == '\r'
}
@ -321,7 +317,7 @@ func buildModeInit() {
case "c-archive":
pkgsFilter = func(p []*Package) []*Package {
if len(p) != 1 || p[0].Name != "main" {
fatalf("-buildmode=c-archive requires exactly one main package")
base.Fatalf("-buildmode=c-archive requires exactly one main package")
}
return p
}
@ -350,7 +346,7 @@ func buildModeInit() {
codegenArg = "-shared"
case "darwin/amd64", "darwin/386":
default:
fatalf("-buildmode=c-shared not supported on %s\n", platform)
base.Fatalf("-buildmode=c-shared not supported on %s\n", platform)
}
}
ldBuildmode = "c-shared"
@ -370,14 +366,14 @@ func buildModeInit() {
ldBuildmode = "exe"
case "pie":
if gccgo {
fatalf("-buildmode=pie not supported by gccgo")
base.Fatalf("-buildmode=pie not supported by gccgo")
} else {
switch platform {
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
"android/amd64", "android/arm", "android/arm64", "android/386":
codegenArg = "-shared"
default:
fatalf("-buildmode=pie not supported on %s\n", platform)
base.Fatalf("-buildmode=pie not supported on %s\n", platform)
}
}
ldBuildmode = "pie"
@ -389,12 +385,12 @@ func buildModeInit() {
switch platform {
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
default:
fatalf("-buildmode=shared not supported on %s\n", platform)
base.Fatalf("-buildmode=shared not supported on %s\n", platform)
}
codegenArg = "-dynlink"
}
if cfg.BuildO != "" {
fatalf("-buildmode=shared and -o not supported together")
base.Fatalf("-buildmode=shared and -o not supported together")
}
ldBuildmode = "shared"
case "plugin":
@ -406,14 +402,14 @@ func buildModeInit() {
case "linux/amd64", "linux/arm", "linux/arm64", "linux/386",
"android/amd64", "android/arm", "android/arm64", "android/386":
default:
fatalf("-buildmode=plugin not supported on %s\n", platform)
base.Fatalf("-buildmode=plugin not supported on %s\n", platform)
}
codegenArg = "-dynlink"
}
cfg.ExeSuffix = ".so"
ldBuildmode = "plugin"
default:
fatalf("buildmode=%s not supported", cfg.BuildBuildmode)
base.Fatalf("buildmode=%s not supported", cfg.BuildBuildmode)
}
if cfg.BuildLinkshared {
if gccgo {
@ -423,7 +419,7 @@ func buildModeInit() {
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
buildAsmflags = append(buildAsmflags, "-D=GOBUILDMODE_shared=1")
default:
fatalf("-linkshared not supported on %s\n", platform)
base.Fatalf("-linkshared not supported on %s\n", platform)
}
codegenArg = "-dynlink"
// TODO(mwhudson): remove -w when that gets fixed in linker.
@ -447,7 +443,7 @@ func buildModeInit() {
}
}
func runBuild(cmd *Command, args []string) {
func runBuild(cmd *base.Command, args []string) {
instrumentInit()
buildModeInit()
var b builder
@ -487,9 +483,9 @@ func runBuild(cmd *Command, args []string) {
if cfg.BuildO != "" {
if len(pkgs) > 1 {
fatalf("go build: cannot use -o with multiple packages")
base.Fatalf("go build: cannot use -o with multiple packages")
} else if len(pkgs) == 0 {
fatalf("no packages to build")
base.Fatalf("no packages to build")
}
p := pkgs[0]
p.target = cfg.BuildO
@ -504,7 +500,7 @@ func runBuild(cmd *Command, args []string) {
if cfg.BuildBuildmode == "shared" {
pkgs := pkgsFilter(packages(args))
if libName, err := libname(args, pkgs); err != nil {
fatalf("%s", err.Error())
base.Fatalf("%s", err.Error())
} else {
a = b.libaction(libName, pkgs, modeBuild, depMode)
}
@ -517,7 +513,7 @@ func runBuild(cmd *Command, args []string) {
b.do(a)
}
var cmdInstall = &Command{
var cmdInstall = &base.Command{
UsageLine: "install [build flags] [packages]",
Short: "compile and install packages and dependencies",
Long: `
@ -592,13 +588,13 @@ func libname(args []string, pkgs []*Package) (string, error) {
return "lib" + libname + ".so", nil
}
func runInstall(cmd *Command, args []string) {
func runInstall(cmd *base.Command, args []string) {
installPackages(args, false)
}
func installPackages(args []string, forGet bool) {
if gobin != "" && !filepath.IsAbs(gobin) {
fatalf("cannot install, GOBIN must be an absolute path")
base.Fatalf("cannot install, GOBIN must be an absolute path")
}
instrumentInit()
@ -609,18 +605,18 @@ func installPackages(args []string, forGet bool) {
if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") {
switch {
case p.gobinSubdir:
errorf("go install: cannot install cross-compiled binaries when GOBIN is set")
base.Errorf("go install: cannot install cross-compiled binaries when GOBIN is set")
case p.cmdline:
errorf("go install: no install location for .go files listed on command line (GOBIN not set)")
base.Errorf("go install: no install location for .go files listed on command line (GOBIN not set)")
case p.ConflictDir != "":
errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir)
base.Errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir)
default:
errorf("go install: no install location for directory %s outside GOPATH\n"+
base.Errorf("go install: no install location for directory %s outside GOPATH\n"+
"\tFor more details see: 'go help gopath'", p.Dir)
}
}
}
exitIfErrors()
base.ExitIfErrors()
var b builder
b.init()
@ -629,7 +625,7 @@ func installPackages(args []string, forGet bool) {
var a *action
if cfg.BuildBuildmode == "shared" {
if libName, err := libname(args, pkgs); err != nil {
fatalf("%s", err.Error())
base.Fatalf("%s", err.Error())
} else {
a = b.libaction(libName, pkgs, modeInstall, modeInstall)
}
@ -658,7 +654,7 @@ func installPackages(args []string, forGet bool) {
}
}
b.do(a)
exitIfErrors()
base.ExitIfErrors()
// Success. If this command is 'go install' with no arguments
// and the current directory (the implicit argument) is a command,
@ -780,14 +776,14 @@ func (b *builder) init() {
} else {
b.work, err = ioutil.TempDir("", "go-build")
if err != nil {
fatalf("%s", err)
base.Fatalf("%s", err)
}
if cfg.BuildX || cfg.BuildWork {
fmt.Fprintf(os.Stderr, "WORK=%s\n", b.work)
}
if !cfg.BuildWork {
workdir := b.work
atexit(func() { os.RemoveAll(workdir) })
base.AtExit(func() { os.RemoveAll(workdir) })
}
}
}
@ -799,7 +795,7 @@ func goFilesPackage(gofiles []string) *Package {
// TODO: Remove this restriction.
for _, f := range gofiles {
if !strings.HasSuffix(f, ".go") {
fatalf("named files must be .go files")
base.Fatalf("named files must be .go files")
}
}
@ -816,10 +812,10 @@ func goFilesPackage(gofiles []string) *Package {
for _, file := range gofiles {
fi, err := os.Stat(file)
if err != nil {
fatalf("%s", err)
base.Fatalf("%s", err)
}
if fi.IsDir() {
fatalf("%s is a directory, should be a Go file", file)
base.Fatalf("%s is a directory, should be a Go file", file)
}
dir1, _ := filepath.Split(file)
if dir1 == "" {
@ -828,7 +824,7 @@ func goFilesPackage(gofiles []string) *Package {
if dir == "" {
dir = dir1
} else if dir != dir1 {
fatalf("named files must all be in one directory; have %s and %s", dir, dir1)
base.Fatalf("named files must all be in one directory; have %s and %s", dir, dir1)
}
dirent = append(dirent, fi)
}
@ -836,11 +832,11 @@ func goFilesPackage(gofiles []string) *Package {
var err error
if dir == "" {
dir = cwd
dir = base.Cwd
}
dir, err = filepath.Abs(dir)
if err != nil {
fatalf("%s", err)
base.Fatalf("%s", err)
}
bp, err := ctxt.ImportDir(dir, 0)
@ -895,7 +891,7 @@ func readpkglist(shlibpath string) (pkgs []*Package) {
} else {
pkglistbytes, err := readELFNote(shlibpath, "Go\x00\x00", 1)
if err != nil {
fatalf("readELFNote failed: %v", err)
base.Fatalf("readELFNote failed: %v", err)
}
scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes))
for scanner.Scan() {
@ -979,7 +975,7 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
var stk importStack
p1 := loadPackage("cmd/cgo", &stk)
if p1.Error != nil {
fatalf("load cmd/cgo: %v", p1.Error)
base.Fatalf("load cmd/cgo: %v", p1.Error)
}
a.cgo = b.action(depMode, depMode, p1)
a.deps = append(a.deps, a.cgo)
@ -1080,7 +1076,7 @@ func (b *builder) libaction(libname string, pkgs []*Package, mode, depMode build
a := &action{}
switch mode {
default:
fatalf("unrecognized mode %v", mode)
base.Fatalf("unrecognized mode %v", mode)
case modeBuild:
a.f = (*builder).linkShared
@ -1107,7 +1103,7 @@ func (b *builder) libaction(libname string, pkgs []*Package, mode, depMode build
var stk importStack
p := loadPackage("runtime/cgo", &stk)
if p.Error != nil {
fatalf("load runtime/cgo: %v", p.Error)
base.Fatalf("load runtime/cgo: %v", p.Error)
}
computeStale(p)
// If runtime/cgo is in another shared library, then that's
@ -1128,7 +1124,7 @@ func (b *builder) libaction(libname string, pkgs []*Package, mode, depMode build
var stk importStack
p := loadPackage("math", &stk)
if p.Error != nil {
fatalf("load math: %v", p.Error)
base.Fatalf("load math: %v", p.Error)
}
computeStale(p)
// If math is in another shared library, then that's
@ -1153,7 +1149,7 @@ func (b *builder) libaction(libname string, pkgs []*Package, mode, depMode build
if libdir == "" {
libdir = plibdir
} else if libdir != plibdir {
fatalf("multiple roots %s & %s", libdir, plibdir)
base.Fatalf("multiple roots %s & %s", libdir, plibdir)
}
}
a.target = filepath.Join(libdir, libname)
@ -1292,11 +1288,11 @@ func (b *builder) do(root *action) {
if err != nil {
if err == errPrintedOutput {
setExitStatus(2)
base.SetExitStatus(2)
} else if _, ok := err.(*build.NoGoError); ok && len(a.p.TestGoFiles) > 0 && b.testFilesOnlyOK {
// Ignore the "no buildable Go source files" error for a package with only test files.
} else {
errorf("%s", err)
base.Errorf("%s", err)
}
a.failed = true
}
@ -1342,8 +1338,8 @@ func (b *builder) do(root *action) {
a := b.ready.pop()
b.exec.Unlock()
handle(a)
case <-interrupted:
setExitStatus(1)
case <-base.Interrupted:
base.SetExitStatus(1)
return
}
}
@ -1465,7 +1461,7 @@ func (b *builder) build(a *action) (err error) {
sfiles = nil
}
cgoExe := tool("cgo")
cgoExe := base.Tool("cgo")
if a.cgo != nil && a.cgo.target != "" {
cgoExe = a.cgo.target
}
@ -1857,7 +1853,7 @@ func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode, force b
}
// On Windows, remove lingering ~ file from last attempt.
if toolIsWindows {
if base.ToolIsWindows {
if _, err := os.Stat(dst + "~"); err == nil {
os.Remove(dst + "~")
}
@ -1865,7 +1861,7 @@ func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode, force b
mayberemovefile(dst)
df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
if err != nil && toolIsWindows {
if err != nil && base.ToolIsWindows {
// Windows does not allow deletion of a binary file
// while it is executing. Try to move it out of the way.
// If the move fails, which is likely, we'll try again the
@ -1912,7 +1908,7 @@ func (b *builder) installHeader(a *action) error {
func (b *builder) cover(a *action, dst, src string, perm os.FileMode, varName string) error {
return b.run(a.objdir, "cover "+a.p.ImportPath, nil,
cfg.BuildToolexec,
tool("cover"),
base.Tool("cover"),
"-mode", a.p.coverMode,
"-var", varName,
"-o", dst,
@ -2018,7 +2014,7 @@ func (b *builder) showcmd(dir string, format string, args ...interface{}) {
func (b *builder) showOutput(dir, desc, out string) {
prefix := "# " + desc
suffix := "\n" + out
if reldir := shortPath(dir); reldir != dir {
if reldir := base.ShortPath(dir); reldir != dir {
suffix = strings.Replace(suffix, " "+dir, " "+reldir, -1)
suffix = strings.Replace(suffix, "\n"+dir, "\n"+reldir, -1)
}
@ -2029,29 +2025,6 @@ func (b *builder) showOutput(dir, desc, out string) {
b.print(prefix, suffix)
}
// shortPath returns an absolute or relative name for path, whatever is shorter.
func shortPath(path string) string {
if rel, err := filepath.Rel(cwd, path); err == nil && len(rel) < len(path) {
return rel
}
return path
}
// relPaths returns a copy of paths with absolute paths
// made relative to the current directory if they would be shorter.
func relPaths(paths []string) []string {
var out []string
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
@ -2316,11 +2289,11 @@ func (noToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error
type gcToolchain struct{}
func (gcToolchain) compiler() string {
return tool("compile")
return base.Tool("compile")
}
func (gcToolchain) linker() string {
return tool("link")
return base.Tool("link")
}
func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
@ -2370,7 +2343,7 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool,
}
}
args := []interface{}{cfg.BuildToolexec, tool("compile"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs}
args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs}
if ofile == archive {
args = append(args, "-pack")
}
@ -2388,7 +2361,7 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool,
func (gcToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]string, error) {
// Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
inc := filepath.Join(goroot, "pkg", "include")
args := []interface{}{cfg.BuildToolexec, tool("asm"), "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, buildAsmflags}
args := []interface{}{cfg.BuildToolexec, base.Tool("asm"), "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, buildAsmflags}
if p.ImportPath == "runtime" && cfg.Goarch == "386" {
for _, arg := range buildAsmflags {
if arg == "-dynlink" {
@ -2414,7 +2387,7 @@ func (gcToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]s
func toolVerify(b *builder, p *Package, newTool string, ofile string, args []interface{}) error {
newArgs := make([]interface{}, len(args))
copy(newArgs, args)
newArgs[1] = tool(newTool)
newArgs[1] = base.Tool(newTool)
newArgs[3] = ofile + ".new" // x.6 becomes x.6.new
if err := b.run(p.Dir, p.ImportPath, nil, newArgs...); err != nil {
return err
@ -2450,7 +2423,7 @@ func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s
// Since it used to not work that way, verify.
if !cfg.BuildN {
if _, err := os.Stat(absAfile); err != nil {
fatalf("os.Stat of archive file failed: %v", err)
base.Fatalf("os.Stat of archive file failed: %v", err)
}
}
@ -2600,7 +2573,7 @@ func (gcToolchain) ld(b *builder, root *action, out string, allactions []*action
dir, out = filepath.Split(out)
}
return b.run(dir, root.p.ImportPath, nil, cfg.BuildToolexec, tool("link"), "-o", out, importArgs, ldflags, mainpkg)
return b.run(dir, root.p.ImportPath, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, importArgs, ldflags, mainpkg)
}
func (gcToolchain) ldShared(b *builder, toplevelactions []*action, out string, allactions []*action) error {
@ -2631,7 +2604,7 @@ func (gcToolchain) ldShared(b *builder, toplevelactions []*action, out string, a
}
ldflags = append(ldflags, d.p.ImportPath+"="+d.target)
}
return b.run(".", out, nil, cfg.BuildToolexec, tool("link"), "-o", out, importArgs, ldflags)
return b.run(".", out, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, importArgs, ldflags)
}
func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
@ -2943,7 +2916,7 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
ldflags = append(ldflags, "-zdefs", "-shared", "-nostdlib", "-lgo", "-lgcc_s", "-lgcc", "-lc")
default:
fatalf("-buildmode=%s not supported for gccgo", buildmode)
base.Fatalf("-buildmode=%s not supported for gccgo", buildmode)
}
switch buildmode {

View File

@ -6,6 +6,7 @@ package main
import (
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"fmt"
"io/ioutil"
"os"
@ -13,7 +14,7 @@ import (
"strings"
)
var cmdClean = &Command{
var cmdClean = &base.Command{
UsageLine: "clean [-i] [-r] [-n] [-x] [build flags] [packages]",
Short: "remove object files",
Long: `
@ -75,7 +76,7 @@ func init() {
addBuildFlags(cmdClean)
}
func runClean(cmd *Command, args []string) {
func runClean(cmd *base.Command, args []string) {
for _, pkg := range packagesAndErrors(args) {
clean(pkg)
}
@ -113,12 +114,12 @@ func clean(p *Package) {
cleaned[p] = true
if p.Dir == "" {
errorf("can't load package: %v", p.Error)
base.Errorf("can't load package: %v", p.Error)
return
}
dirs, err := ioutil.ReadDir(p.Dir)
if err != nil {
errorf("go clean %s: %v", p.Dir, err)
base.Errorf("go clean %s: %v", p.Dir, err)
return
}
@ -193,7 +194,7 @@ func clean(p *Package) {
}
}
if err := os.RemoveAll(filepath.Join(p.Dir, name)); err != nil {
errorf("go clean: %v", err)
base.Errorf("go clean: %v", err)
}
}
continue
@ -232,7 +233,7 @@ func removeFile(f string) {
return
}
// Windows does not allow deletion of a binary file while it is executing.
if toolIsWindows {
if base.ToolIsWindows {
// Remove lingering ~ file from last attempt.
if _, err2 := os.Stat(f + "~"); err2 == nil {
os.Remove(f + "~")
@ -245,5 +246,5 @@ func removeFile(f string) {
return
}
}
errorf("go clean: %v", err)
base.Errorf("go clean: %v", err)
}

View File

@ -6,9 +6,12 @@
package main
import "cmd/go/internal/cfg"
import (
"cmd/go/internal/cfg"
"cmd/go/internal/base"
)
var cmdDoc = &Command{
var cmdDoc = &base.Command{
Run: runDoc,
UsageLine: "doc [-u] [-c] [package|[package.]symbol[.method]]",
CustomFlags: true,
@ -115,6 +118,6 @@ Flags:
`,
}
func runDoc(cmd *Command, args []string) {
run(cfg.BuildToolexec, tool("doc"), args)
func runDoc(cmd *base.Command, args []string) {
base.Run(cfg.BuildToolexec, base.Tool("doc"), args)
}

View File

@ -6,13 +6,14 @@ package main
import (
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"fmt"
"os"
"runtime"
"strings"
)
var cmdEnv = &Command{
var cmdEnv = &base.Command{
Run: runEnv,
UsageLine: "env [var ...]",
Short: "print Go environment information",
@ -40,7 +41,7 @@ func mkEnv() []cfg.EnvVar {
{"GOPATH", cfg.BuildContext.GOPATH},
{"GORACE", os.Getenv("GORACE")},
{"GOROOT", goroot},
{"GOTOOLDIR", toolDir},
{"GOTOOLDIR", base.ToolDir},
// disable escape codes in clang errors
{"TERM", "dumb"},
@ -98,7 +99,7 @@ func extraEnvVars() []cfg.EnvVar {
}
}
func runEnv(cmd *Command, args []string) {
func runEnv(cmd *base.Command, args []string) {
env := cfg.NewEnv
env = append(env, extraEnvVars()...)
if len(args) > 0 {

View File

@ -6,10 +6,11 @@ package main
import (
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"cmd/go/internal/str"
)
var cmdFix = &Command{
var cmdFix = &base.Command{
Run: runFix,
UsageLine: "fix [packages]",
Short: "run go tool fix on packages",
@ -25,11 +26,11 @@ See also: go fmt, go vet.
`,
}
func runFix(cmd *Command, args []string) {
func runFix(cmd *base.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(str.StringList(cfg.BuildToolexec, tool("fix"), relPaths(pkg.allgofiles)))
base.Run(str.StringList(cfg.BuildToolexec, base.Tool("fix"), base.RelPaths(pkg.allgofiles)))
}
}

View File

@ -5,16 +5,18 @@
package main
import (
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"cmd/go/internal/str"
"os"
"path/filepath"
)
func init() {
addBuildFlagsNX(cmdFmt)
cfg.AddBuildFlagsNX(&cmdFmt.Flag)
}
var cmdFmt = &Command{
var cmdFmt = &base.Command{
Run: runFmt,
UsageLine: "fmt [-n] [-x] [packages]",
Short: "run gofmt on package sources",
@ -34,20 +36,20 @@ See also: go fix, go vet.
`,
}
func runFmt(cmd *Command, args []string) {
func runFmt(cmd *base.Command, args []string) {
gofmt := gofmtPath()
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(str.StringList(gofmt, "-l", "-w", relPaths(pkg.allgofiles)))
base.Run(str.StringList(gofmt, "-l", "-w", base.RelPaths(pkg.allgofiles)))
}
}
func gofmtPath() string {
gofmt := "gofmt"
if toolIsWindows {
gofmt += toolWindowsExtension
if base.ToolIsWindows {
gofmt += base.ToolWindowsExtension
}
gofmtPath := filepath.Join(gobin, gofmt)

View File

@ -8,6 +8,7 @@ import (
"bufio"
"bytes"
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"fmt"
"io"
"log"
@ -19,7 +20,7 @@ import (
"strings"
)
var cmdGenerate = &Command{
var cmdGenerate = &base.Command{
Run: runGenerate,
UsageLine: "generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]",
Short: "generate Go files by processing source",
@ -136,7 +137,7 @@ func init() {
cmdGenerate.Flag.StringVar(&generateRunFlag, "run", "", "")
}
func runGenerate(cmd *Command, args []string) {
func runGenerate(cmd *base.Command, args []string) {
ignoreImports = true
if generateRunFlag != "" {
@ -196,13 +197,13 @@ func (g *Generator) run() (ok bool) {
if e != stop {
panic(e)
}
setExitStatus(1)
base.SetExitStatus(1)
}
}()
g.dir, g.file = filepath.Split(g.path)
g.dir = filepath.Clean(g.dir) // No final separator please.
if cfg.BuildV {
fmt.Fprintf(os.Stderr, "%s\n", shortPath(g.path))
fmt.Fprintf(os.Stderr, "%s\n", base.ShortPath(g.path))
}
// Scan for lines that start "//go:generate".
@ -265,7 +266,7 @@ func (g *Generator) run() (ok bool) {
g.exec(words)
}
if err != nil && err != io.EOF {
g.errorf("error reading %s: %s", shortPath(g.path), err)
g.errorf("error reading %s: %s", base.ShortPath(g.path), err)
}
return true
}
@ -355,7 +356,7 @@ var stop = fmt.Errorf("error in generation")
// It then exits the program (with exit status 1) because generation stops
// at the first error.
func (g *Generator) errorf(format string, args ...interface{}) {
fmt.Fprintf(os.Stderr, "%s:%d: %s\n", shortPath(g.path), g.lineNum,
fmt.Fprintf(os.Stderr, "%s:%d: %s\n", base.ShortPath(g.path), g.lineNum,
fmt.Sprintf(format, args...))
panic(stop)
}

View File

@ -6,6 +6,7 @@ package main
import (
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"cmd/go/internal/str"
"fmt"
"go/build"
@ -17,7 +18,7 @@ import (
"strings"
)
var cmdGet = &Command{
var cmdGet = &base.Command{
UsageLine: "get [-d] [-f] [-fix] [-insecure] [-t] [-u] [build flags] [packages]",
Short: "download and install packages and dependencies",
Long: `
@ -85,9 +86,9 @@ func init() {
cmdGet.Run = runGet // break init loop
}
func runGet(cmd *Command, args []string) {
func runGet(cmd *base.Command, args []string) {
if *getF && !*getU {
fatalf("go get: cannot use -f flag without -u")
base.Fatalf("go get: cannot use -f flag without -u")
}
// Disable any prompting for passwords by Git.
@ -127,7 +128,7 @@ func runGet(cmd *Command, args []string) {
for _, arg := range args {
download(arg, nil, &stk, mode)
}
exitIfErrors()
base.ExitIfErrors()
// Phase 2. Rescan packages and re-evaluate args list.
@ -220,7 +221,7 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
p := load(arg, mode)
if p.Error != nil && p.Error.hard {
errorf("%s", p.Error)
base.Errorf("%s", p.Error)
return
}
@ -257,7 +258,7 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
stk.push(arg)
err := downloadPackage(p)
if err != nil {
errorf("%s", &PackageError{ImportStack: stk.copy(), Err: err.Error()})
base.Errorf("%s", &PackageError{ImportStack: stk.copy(), Err: err.Error()})
stk.pop()
return
}
@ -293,7 +294,7 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
// Do not push here too, or else stk will say arg imports arg.
p := load(arg, mode)
if p.Error != nil {
errorf("%s", p.Error)
base.Errorf("%s", p.Error)
continue
}
pkgs = append(pkgs, p)
@ -304,12 +305,12 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
// due to wildcard expansion.
for _, p := range pkgs {
if *getFix {
run(cfg.BuildToolexec, str.StringList(tool("fix"), relPaths(p.allgofiles)))
base.Run(cfg.BuildToolexec, str.StringList(base.Tool("fix"), base.RelPaths(p.allgofiles)))
// The imports might have changed, so reload again.
p = reloadPackage(arg, stk)
if p.Error != nil {
errorf("%s", p.Error)
base.Errorf("%s", p.Error)
return
}
}
@ -346,7 +347,7 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
Err: "must be imported as " + path[j+len("vendor/"):],
}
stk.pop()
errorf("%s", err)
base.Errorf("%s", err)
continue
}
// If this is a test import, apply vendor lookup now.

View File

@ -4,7 +4,9 @@
package main
var helpC = &Command{
import "cmd/go/internal/base"
var helpC = &base.Command{
UsageLine: "c",
Short: "calling between Go and C",
Long: `
@ -26,7 +28,7 @@ the C or C++ compiler, respectively, to use.
`,
}
var helpPackages = &Command{
var helpPackages = &base.Command{
UsageLine: "packages",
Short: "description of package lists",
Long: `
@ -100,7 +102,7 @@ by the go tool, as are directories named "testdata".
`,
}
var helpImportPath = &Command{
var helpImportPath = &base.Command{
UsageLine: "importpath",
Short: "import path syntax",
Long: `
@ -277,7 +279,7 @@ See https://golang.org/s/go14customimport for details.
`,
}
var helpGopath = &Command{
var helpGopath = &base.Command{
UsageLine: "gopath",
Short: "GOPATH environment variable",
Long: `
@ -429,7 +431,7 @@ See https://golang.org/s/go15vendor for details.
`,
}
var helpEnvironment = &Command{
var helpEnvironment = &base.Command{
UsageLine: "environment",
Short: "environment variables",
Long: `
@ -511,7 +513,7 @@ Special-purpose environment variables:
`,
}
var helpFileType = &Command{
var helpFileType = &base.Command{
UsageLine: "filetype",
Short: "file types",
Long: `
@ -557,7 +559,7 @@ for more details.
`,
}
var helpBuildmode = &Command{
var helpBuildmode = &base.Command{
UsageLine: "buildmode",
Short: "description of build modes",
Long: `

View File

@ -0,0 +1,143 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package base defines shared basic pieces of the go command,
// in particular logging and the Command structure.
package base
import (
"cmd/go/internal/cfg"
"cmd/go/internal/str"
"flag"
"fmt"
"log"
"os"
"os/exec"
"strings"
"sync"
)
// 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)
}
// Runnable reports whether the command can be run; otherwise
// it is a documentation pseudo-command such as importpath.
func (c *Command) Runnable() bool {
return c.Run != nil
}
var atExitFuncs []func()
func AtExit(f func()) {
atExitFuncs = append(atExitFuncs, f)
}
func Exit() {
for _, f := range atExitFuncs {
f()
}
os.Exit(exitStatus)
}
func Fatalf(format string, args ...interface{}) {
Errorf(format, args...)
Exit()
}
func Errorf(format string, args ...interface{}) {
log.Printf(format, args...)
SetExitStatus(1)
}
func ExitIfErrors() {
if exitStatus != 0 {
Exit()
}
}
var exitStatus = 0
var exitMu sync.Mutex
func SetExitStatus(n int) {
exitMu.Lock()
if exitStatus < n {
exitStatus = n
}
exitMu.Unlock()
}
// Run runs the command, with stdout and stderr
// connected to the go command's own stdout and stderr.
// If the command fails, Run reports the error using Errorf.
func Run(cmdargs ...interface{}) {
cmdline := str.StringList(cmdargs...)
if cfg.BuildN || cfg.BuildX {
fmt.Printf("%s\n", strings.Join(cmdline, " "))
if cfg.BuildN {
return
}
}
cmd := exec.Command(cmdline[0], cmdline[1:]...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
Errorf("%v", err)
}
}
// RunStdin is like run but connects Stdin.
func RunStdin(cmdline []string) {
cmd := exec.Command(cmdline[0], cmdline[1:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = cfg.OrigEnv
StartSigHandlers()
if err := cmd.Run(); err != nil {
Errorf("%v", err)
}
}
// Usage is the usage-reporting function, filled in by package main
// but here for reference by other packages.
var Usage func()

View File

@ -0,0 +1,36 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package base
import (
"os"
"path/filepath"
)
var Cwd, _ = os.Getwd()
// ShortPath returns an absolute or relative name for path, whatever is shorter.
func ShortPath(path string) string {
if rel, err := filepath.Rel(Cwd, path); err == nil && len(rel) < len(path) {
return rel
}
return path
}
// RelPaths returns a copy of paths with absolute paths
// made relative to the current directory if they would be shorter.
func RelPaths(paths []string) []string {
var out []string
// TODO(rsc): Can this use Cwd from above?
pwd, _ := os.Getwd()
for _, p := range paths {
rel, err := filepath.Rel(pwd, p)
if err == nil && len(rel) < len(p) {
p = rel
}
out = append(out, p)
}
return out
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
package base
import (
"os"
@ -10,8 +10,8 @@ import (
"sync"
)
// interrupted is closed, if go process is interrupted.
var interrupted = make(chan struct{})
// Interrupted is closed when the go command receives an interrupt signal.
var Interrupted = make(chan struct{})
// processSignals setups signal handler.
func processSignals() {
@ -19,13 +19,13 @@ func processSignals() {
signal.Notify(sig, signalsToIgnore...)
go func() {
<-sig
close(interrupted)
close(Interrupted)
}()
}
var onceProcessSignals sync.Once
// startSigHandlers start signal handlers.
func startSigHandlers() {
// StartSigHandlers starts the signal handlers.
func StartSigHandlers() {
onceProcessSignals.Do(processSignals)
}

View File

@ -4,7 +4,7 @@
// +build plan9 windows
package main
package base
import (
"os"
@ -12,6 +12,6 @@ import (
var signalsToIgnore = []os.Signal{os.Interrupt}
// signalTrace is the signal to send to make a Go program
// crash with a stack trace.
var signalTrace os.Signal = nil
// SignalTrace is the signal to send to make a Go program
// crash with a stack trace (no such signal in this case).
var SignalTrace os.Signal = nil

View File

@ -4,7 +4,7 @@
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package main
package base
import (
"os"
@ -13,6 +13,6 @@ import (
var signalsToIgnore = []os.Signal{os.Interrupt, syscall.SIGQUIT}
// signalTrace is the signal to send to make a Go program
// SignalTrace is the signal to send to make a Go program
// crash with a stack trace.
var signalTrace os.Signal = syscall.SIGQUIT
var SignalTrace os.Signal = syscall.SIGQUIT

View File

@ -0,0 +1,53 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package base
import (
"fmt"
"go/build"
"os"
"path/filepath"
"runtime"
"cmd/go/internal/cfg"
)
// Configuration for finding tool binaries.
var (
ToolGOOS = runtime.GOOS
ToolGOARCH = runtime.GOARCH
ToolIsWindows = ToolGOOS == "windows"
ToolDir = build.ToolDir
)
const ToolWindowsExtension = ".exe"
// Tool returns the path to the named tool (for example, "vet").
// If the tool cannot be found, Tool exits the process.
func Tool(toolName string) string {
toolPath := filepath.Join(ToolDir, toolName)
if ToolIsWindows {
toolPath += ToolWindowsExtension
}
if len(cfg.BuildToolexec) > 0 {
return toolPath
}
// Give a nice message if there is no tool with that name.
if _, err := os.Stat(toolPath); err != nil {
if isInGoToolsRepo(toolName) {
fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get golang.org/x/tools/cmd/%s\n", toolName, toolName)
} else {
fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName)
}
SetExitStatus(2)
Exit()
}
return toolPath
}
// TODO: Delete.
func isInGoToolsRepo(toolName string) bool {
return false
}

View File

@ -7,6 +7,7 @@
package cfg
import (
"flag"
"go/build"
"runtime"
)
@ -57,3 +58,9 @@ var (
ExeSuffix string
Gopath []string
)
// AddBuildFlagsNX adds the -n and -x build flags to the flag set.
func AddBuildFlagsNX(flags *flag.FlagSet) {
flags.BoolVar(&BuildN, "n", false, "")
flags.BoolVar(&BuildX, "x", false, "")
}

View File

@ -7,6 +7,7 @@ package main
import (
"bufio"
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"encoding/json"
"io"
"os"
@ -14,7 +15,7 @@ import (
"text/template"
)
var cmdList = &Command{
var cmdList = &base.Command{
UsageLine: "list [-e] [-f format] [-json] [build flags] [packages]",
Short: "list packages",
Long: `
@ -146,7 +147,7 @@ var listFmt = cmdList.Flag.String("f", "{{.ImportPath}}", "")
var listJson = cmdList.Flag.Bool("json", false, "")
var nl = []byte{'\n'}
func runList(cmd *Command, args []string) {
func runList(cmd *base.Command, args []string) {
buildModeInit()
out := newTrackingWriter(os.Stdout)
defer out.w.Flush()
@ -157,7 +158,7 @@ func runList(cmd *Command, args []string) {
b, err := json.MarshalIndent(p, "", "\t")
if err != nil {
out.Flush()
fatalf("%s", err)
base.Fatalf("%s", err)
}
out.Write(b)
out.Write(nl)
@ -176,12 +177,12 @@ func runList(cmd *Command, args []string) {
}
tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt)
if err != nil {
fatalf("%s", err)
base.Fatalf("%s", err)
}
do = func(p *Package) {
if err := tmpl.Execute(out, p); err != nil {
out.Flush()
fatalf("%s", err)
base.Fatalf("%s", err)
}
if out.NeedNL() {
out.Write(nl)

View File

@ -8,78 +8,29 @@ import (
"bufio"
"bytes"
"cmd/go/internal/cfg"
"cmd/go/internal/str"
"cmd/go/internal/base"
"flag"
"fmt"
"go/build"
"io"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"runtime"
"strings"
"sync"
"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)
}
// Runnable reports whether the command can be run; otherwise
// it is a documentation pseudo-command such as importpath.
func (c *Command) Runnable() bool {
return c.Run != nil
}
// 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
var commands []*base.Command
func init() {
commands = []*Command{
commands = []*base.Command{
cmdBuild,
cmdClean,
cmdDoc,
@ -109,26 +60,15 @@ func init() {
}
}
var exitStatus = 0
var exitMu sync.Mutex
func setExitStatus(n int) {
exitMu.Lock()
if exitStatus < n {
exitStatus = n
}
exitMu.Unlock()
}
func main() {
_ = go11tag
flag.Usage = usage
flag.Usage = base.Usage
flag.Parse()
log.SetFlags(0)
args := flag.Args()
if len(args) < 1 {
usage()
base.Usage()
}
if args[0] == "help" {
@ -185,14 +125,14 @@ func main() {
args = cmd.Flag.Args()
}
cmd.Run(cmd, args)
exit()
base.Exit()
return
}
}
fmt.Fprintf(os.Stderr, "go: unknown subcommand %q\nRun 'go help' for usage.\n", args[0])
setExitStatus(2)
exit()
base.SetExitStatus(2)
base.Exit()
}
var usageTemplate = `Go is a tool for managing Go source code.
@ -289,7 +229,7 @@ func tmpl(w io.Writer, text string, data interface{}) {
if strings.Contains(ew.err.Error(), "pipe") {
os.Exit(1)
}
fatalf("writing output: %v", ew.err)
base.Fatalf("writing output: %v", ew.err)
}
if err != nil {
panic(err)
@ -313,7 +253,7 @@ func printUsage(w io.Writer) {
var usage func()
func init() {
usage = mainUsage
base.Usage = mainUsage
}
func mainUsage() {
@ -353,8 +293,8 @@ func help(args []string) {
fmt.Println()
buf := new(bytes.Buffer)
printUsage(buf)
usage := &Command{Long: buf.String()}
tmpl(&commentWriter{W: os.Stdout}, documentationTemplate, append([]*Command{usage}, commands...))
usage := &base.Command{Long: buf.String()}
tmpl(&commentWriter{W: os.Stdout}, documentationTemplate, append([]*base.Command{usage}, commands...))
fmt.Println("package main")
return
}
@ -422,52 +362,6 @@ func importPaths(args []string) []string {
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...)
setExitStatus(1)
}
func exitIfErrors() {
if exitStatus != 0 {
exit()
}
}
func run(cmdargs ...interface{}) {
cmdline := str.StringList(cmdargs...)
if cfg.BuildN || cfg.BuildX {
fmt.Printf("%s\n", strings.Join(cmdline, " "))
if cfg.BuildN {
return
}
}
cmd := exec.Command(cmdline[0], cmdline[1:]...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
errorf("%v", err)
}
}
// envForDir returns a copy of the environment
// suitable for running in the given directory.
// The environment is the current process's environment

View File

@ -7,6 +7,7 @@ package main
import (
"bytes"
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"cmd/go/internal/str"
"crypto/sha1"
"errors"
@ -422,7 +423,7 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
func setErrorPos(p *Package, importPos []token.Position) *Package {
if len(importPos) > 0 {
pos := importPos[0]
pos.Filename = shortPath(pos.Filename)
pos.Filename = base.ShortPath(pos.Filename)
p.Error.Pos = pos.String()
}
return p
@ -469,7 +470,7 @@ func vendoredImportPath(parent *Package, path string) (found string) {
}
if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || parent.ImportPath != "command-line-arguments" && !parent.local && filepath.Join(root, parent.ImportPath) != dir {
fatalf("unexpected directory layout:\n"+
base.Fatalf("unexpected directory layout:\n"+
" import path: %s\n"+
" root: %s\n"+
" dir: %s\n"+
@ -798,7 +799,7 @@ func expandScanner(err error) error {
// instead of just the first, as err.Error does.
var buf bytes.Buffer
for _, e := range err {
e.Pos.Filename = shortPath(e.Pos.Filename)
e.Pos.Filename = base.ShortPath(e.Pos.Filename)
buf.WriteString("\n")
buf.WriteString(e.Error())
}
@ -863,7 +864,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
}
_, elem := filepath.Split(p.Dir)
full := cfg.BuildContext.GOOS + "_" + cfg.BuildContext.GOARCH + "/" + elem
if cfg.BuildContext.GOOS != toolGOOS || cfg.BuildContext.GOARCH != toolGOARCH {
if cfg.BuildContext.GOOS != base.ToolGOOS || cfg.BuildContext.GOARCH != base.ToolGOARCH {
// Install cross-compiled binaries to subdirectories of bin.
elem = full
}
@ -902,7 +903,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
}
} else if !os.IsNotExist(err) {
fatalf("unexpected error reading %s: %v", shlibnamefile, err)
base.Fatalf("unexpected error reading %s: %v", shlibnamefile, err)
}
}
}
@ -1647,7 +1648,7 @@ func computeBuildID(p *Package) {
if p.Standard && p.ImportPath == "runtime/internal/sys" && cfg.BuildContext.Compiler != "gccgo" {
data, err := ioutil.ReadFile(filepath.Join(p.Dir, "zversion.go"))
if err != nil {
fatalf("go: %s", err)
base.Fatalf("go: %s", err)
}
fmt.Fprintf(h, "zversion %q\n", string(data))
}
@ -1667,8 +1668,6 @@ func computeBuildID(p *Package) {
p.buildID = fmt.Sprintf("%x", h.Sum(nil))
}
var cwd, _ = os.Getwd()
var cmdCache = map[string]*Package{}
// loadPackage is like loadImport but is used for command-line arguments,
@ -1723,13 +1722,13 @@ func loadPackage(arg string, stk *importStack) *Package {
// referring to io/ioutil rather than a hypothetical import of
// "./ioutil".
if build.IsLocalImport(arg) {
bp, _ := cfg.BuildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
bp, _ := cfg.BuildContext.ImportDir(filepath.Join(base.Cwd, arg), build.FindOnly)
if bp.ImportPath != "" && bp.ImportPath != "." {
arg = bp.ImportPath
}
}
return loadImport(arg, cwd, nil, stk, nil, 0)
return loadImport(arg, base.Cwd, nil, stk, nil, 0)
}
// packages returns the packages named by the
@ -1744,7 +1743,7 @@ func packages(args []string) []*Package {
var pkgs []*Package
for _, pkg := range packagesAndErrors(args) {
if pkg.Error != nil {
errorf("can't load package: %s", pkg.Error)
base.Errorf("can't load package: %s", pkg.Error)
continue
}
pkgs = append(pkgs, pkg)
@ -1794,7 +1793,7 @@ func packagesForBuild(args []string) []*Package {
printed := map[*PackageError]bool{}
for _, pkg := range pkgs {
if pkg.Error != nil {
errorf("can't load package: %s", pkg.Error)
base.Errorf("can't load package: %s", pkg.Error)
}
for _, err := range pkg.DepsErrors {
// Since these are errors in dependencies,
@ -1803,11 +1802,11 @@ func packagesForBuild(args []string) []*Package {
// Only print each once.
if !printed[err] {
printed[err] = true
errorf("%s", err)
base.Errorf("%s", err)
}
}
}
exitIfErrors()
base.ExitIfErrors()
// Check for duplicate loads of the same package.
// That should be impossible, but if it does happen then
@ -1819,11 +1818,11 @@ func packagesForBuild(args []string) []*Package {
for _, pkg := range packageList(pkgs) {
if seen[pkg.ImportPath] && !reported[pkg.ImportPath] {
reported[pkg.ImportPath] = true
errorf("internal error: duplicate loads of %s", pkg.ImportPath)
base.Errorf("internal error: duplicate loads of %s", pkg.ImportPath)
}
seen[pkg.ImportPath] = true
}
exitIfErrors()
base.ExitIfErrors()
return pkgs
}

View File

@ -6,6 +6,7 @@ package main
import (
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"cmd/go/internal/str"
"io/ioutil"
"os"
@ -164,7 +165,7 @@ func TestSharedLibName(t *testing.T) {
oldGopath := cfg.BuildContext.GOPATH
defer func() {
cfg.BuildContext.GOPATH = oldGopath
os.Chdir(cwd)
os.Chdir(base.Cwd)
err := os.RemoveAll(tmpGopath)
if err != nil {
t.Error(err)

View File

@ -6,6 +6,7 @@ package main
import (
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"cmd/go/internal/str"
"fmt"
"os"
@ -31,7 +32,7 @@ func findExecCmd() []string {
return execCmd
}
var cmdRun = &Command{
var cmdRun = &base.Command{
UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]",
Short: "compile and run Go program",
Long: `
@ -65,7 +66,7 @@ func printStderr(args ...interface{}) (int, error) {
return fmt.Fprint(os.Stderr, args...)
}
func runRun(cmd *Command, args []string) {
func runRun(cmd *base.Command, args []string) {
instrumentInit()
buildModeInit()
var b builder
@ -77,18 +78,18 @@ func runRun(cmd *Command, args []string) {
}
files, cmdArgs := args[:i], args[i:]
if len(files) == 0 {
fatalf("go run: no go files listed")
base.Fatalf("go run: no go files listed")
}
for _, file := range files {
if strings.HasSuffix(file, "_test.go") {
// goFilesPackage is going to assign this to TestGoFiles.
// Reject since it won't be part of the build.
fatalf("go run: cannot run *_test.go files (%s)", file)
base.Fatalf("go run: cannot run *_test.go files (%s)", file)
}
}
p := goFilesPackage(files)
if p.Error != nil {
fatalf("%s", p.Error)
base.Fatalf("%s", p.Error)
}
p.omitDWARF = true
if len(p.DepsErrors) > 0 {
@ -100,13 +101,13 @@ func runRun(cmd *Command, args []string) {
for _, err := range p.DepsErrors {
if !printed[err] {
printed[err] = true
errorf("%s", err)
base.Errorf("%s", err)
}
}
}
exitIfErrors()
base.ExitIfErrors()
if p.Name != "main" {
fatalf("go run: cannot run non-main package")
base.Fatalf("go run: cannot run non-main package")
}
p.target = "" // must build - not up to date
var src string
@ -121,7 +122,7 @@ func runRun(cmd *Command, args []string) {
if !cfg.BuildContext.CgoEnabled {
hint = " (cgo is disabled)"
}
fatalf("go run: no suitable source files%s", hint)
base.Fatalf("go run: no suitable source files%s", hint)
}
p.exeName = src[:len(src)-len(".go")] // name temporary executable for first go file
a1 := b.action(modeBuild, modeBuild, p)
@ -140,19 +141,6 @@ func (b *builder) runProgram(a *action) error {
}
}
runStdin(cmdline)
base.RunStdin(cmdline)
return nil
}
// runStdin is like run, but connects Stdin.
func runStdin(cmdline []string) {
cmd := exec.Command(cmdline[0], cmdline[1:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = cfg.OrigEnv
startSigHandlers()
if err := cmd.Run(); err != nil {
errorf("%v", err)
}
}

View File

@ -7,6 +7,7 @@ package main
import (
"bytes"
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"cmd/go/internal/str"
"errors"
"fmt"
@ -36,7 +37,7 @@ func init() {
const testUsage = "test [build/test flags] [packages] [build/test flags & test binary flags]"
var cmdTest = &Command{
var cmdTest = &base.Command{
CustomFlags: true,
UsageLine: testUsage,
Short: "test packages",
@ -109,7 +110,7 @@ The test binary also accepts flags that control execution of the test; these
flags are also accessible by 'go test'.
`
var helpTestflag = &Command{
var helpTestflag = &base.Command{
UsageLine: "testflag",
Short: "description of testing flags",
Long: `
@ -314,7 +315,7 @@ In the second example, the argument math is passed through to the test
binary, instead of being interpreted as the package list.
`
var helpTestfunc = &Command{
var helpTestfunc = &base.Command{
UsageLine: "testfunc",
Short: "description of testing functions",
Long: `
@ -401,7 +402,7 @@ var testMainDeps = map[string]bool{
"os": true,
}
func runTest(cmd *Command, args []string) {
func runTest(cmd *base.Command, args []string) {
var pkgArgs []string
pkgArgs, testArgs = testFlags(args)
@ -411,17 +412,17 @@ func runTest(cmd *Command, args []string) {
buildModeInit()
pkgs := packagesForBuild(pkgArgs)
if len(pkgs) == 0 {
fatalf("no packages to test")
base.Fatalf("no packages to test")
}
if testC && len(pkgs) != 1 {
fatalf("cannot use -c flag with multiple packages")
base.Fatalf("cannot use -c flag with multiple packages")
}
if testO != "" && len(pkgs) != 1 {
fatalf("cannot use -o flag with multiple packages")
base.Fatalf("cannot use -o flag with multiple packages")
}
if testProfile && len(pkgs) != 1 {
fatalf("cannot use test profile flag with multiple packages")
base.Fatalf("cannot use test profile flag with multiple packages")
}
// If a test timeout was given and is parseable, set our kill timeout
@ -556,9 +557,9 @@ func runTest(cmd *Command, args []string) {
failed := fmt.Sprintf("FAIL\t%s [setup failed]\n", p.ImportPath)
if p.ImportPath != "" {
errorf("# %s\n%s\n%s", p.ImportPath, str, failed)
base.Errorf("# %s\n%s\n%s", p.ImportPath, str, failed)
} else {
errorf("%s\n%s", str, failed)
base.Errorf("%s\n%s", str, failed)
}
continue
}
@ -964,11 +965,11 @@ func builderTest(b *builder, p *Package) (buildAction, runAction, printAction *a
if testC || testNeedBinary {
// -c or profiling flag: create action to copy binary to ./test.out.
target := filepath.Join(cwd, testBinary+cfg.ExeSuffix)
target := filepath.Join(base.Cwd, testBinary+cfg.ExeSuffix)
if testO != "" {
target = testO
if !filepath.IsAbs(target) {
target = filepath.Join(cwd, target)
target = filepath.Join(base.Cwd, target)
}
}
buildAction = &action{
@ -1110,7 +1111,7 @@ func builderRunTest(b *builder, a *action) error {
// We were unable to build the binary.
a.failed = false
fmt.Fprintf(a.testOutput, "FAIL\t%s [build failed]\n", a.p.ImportPath)
setExitStatus(1)
base.SetExitStatus(1)
return nil
}
@ -1153,7 +1154,7 @@ func builderRunTest(b *builder, a *action) error {
// running.
if err == nil {
tick := time.NewTimer(testKillTimeout)
startSigHandlers()
base.StartSigHandlers()
done := make(chan error)
go func() {
done <- cmd.Wait()
@ -1163,14 +1164,14 @@ func builderRunTest(b *builder, a *action) error {
case err = <-done:
// ok
case <-tick.C:
if signalTrace != nil {
if base.SignalTrace != nil {
// Send a quit signal in the hope that the program will print
// a stack trace and exit. Give it five seconds before resorting
// to Kill.
cmd.Process.Signal(signalTrace)
cmd.Process.Signal(base.SignalTrace)
select {
case err = <-done:
fmt.Fprintf(&buf, "*** Test killed with %v: ran too long (%v).\n", signalTrace, testKillTimeout)
fmt.Fprintf(&buf, "*** Test killed with %v: ran too long (%v).\n", base.SignalTrace, testKillTimeout)
break Outer
case <-time.After(5 * time.Second):
}
@ -1195,7 +1196,7 @@ func builderRunTest(b *builder, a *action) error {
return nil
}
setExitStatus(1)
base.SetExitStatus(1)
if len(out) > 0 {
a.testOutput.Write(out)
// assume printing the test binary's exit status is superfluous

View File

@ -6,6 +6,7 @@ package main
import (
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"flag"
"fmt"
"os"
@ -64,7 +65,7 @@ var testFlagDefn = []*testFlagSpec{
// add build flags to testFlagDefn
func init() {
var cmd Command
var cmd base.Command
addBuildFlags(&cmd)
cmd.Flag.VisitAll(func(f *flag.Flag) {
if f.Name == "v" {
@ -129,7 +130,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
}
if f.flagValue != nil {
if err := f.flagValue.Set(value); err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
base.Fatalf("invalid flag argument for -%s: %v", f.name, err)
}
} else {
// Test-only flags.
@ -145,7 +146,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
case "exec":
execCmd, err = splitQuotedFields(value)
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
base.Fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "bench":
// record that we saw the flag; don't care about the value
@ -172,7 +173,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
case "set", "count", "atomic":
cfg.TestCoverMode = value
default:
fatalf("invalid flag argument for -covermode: %q", value)
base.Fatalf("invalid flag argument for -covermode: %q", value)
}
testCover = true
case "outputdir":
@ -199,7 +200,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
if testProfile && outputDir == "" {
dir, err := os.Getwd()
if err != nil {
fatalf("error from os.Getwd: %s", err)
base.Fatalf("error from os.Getwd: %s", err)
}
passToTest = append(passToTest, "-test.outputdir", dir)
}
@ -216,7 +217,7 @@ func testFlag(args []string, i int) (f *testFlagSpec, value string, extra bool)
}
switch arg {
case "-?", "-h", "-help":
usage()
base.Usage()
}
if arg == "" || arg[0] != '-' {
return

View File

@ -5,18 +5,17 @@
package main
import (
"cmd/go/internal/cfg"
"fmt"
"go/build"
"os"
"os/exec"
"path/filepath"
"runtime"
"sort"
"strings"
"cmd/go/internal/cfg"
"cmd/go/internal/base"
)
var cmdTool = &Command{
var cmdTool = &base.Command{
Run: runTool,
UsageLine: "tool [-n] command [args...]",
Short: "run specified go tool",
@ -31,47 +30,13 @@ For more about each tool command, see 'go tool command -h'.
`,
}
var (
toolGOOS = runtime.GOOS
toolGOARCH = runtime.GOARCH
toolIsWindows = toolGOOS == "windows"
toolDir = build.ToolDir
toolN bool
)
var toolN bool
func init() {
cmdTool.Flag.BoolVar(&toolN, "n", false, "")
}
const toolWindowsExtension = ".exe"
func tool(toolName string) string {
toolPath := filepath.Join(toolDir, toolName)
if toolIsWindows {
toolPath += toolWindowsExtension
}
if len(cfg.BuildToolexec) > 0 {
return toolPath
}
// Give a nice message if there is no tool with that name.
if _, err := os.Stat(toolPath); err != nil {
if isInGoToolsRepo(toolName) {
fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get golang.org/x/tools/cmd/%s\n", toolName, toolName)
} else {
fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName)
}
setExitStatus(2)
exit()
}
return toolPath
}
func isInGoToolsRepo(toolName string) bool {
return false
}
func runTool(cmd *Command, args []string) {
func runTool(cmd *base.Command, args []string) {
if len(args) == 0 {
listTools()
return
@ -83,11 +48,11 @@ func runTool(cmd *Command, args []string) {
case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_':
default:
fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\n", toolName)
setExitStatus(2)
base.SetExitStatus(2)
return
}
}
toolPath := tool(toolName)
toolPath := base.Tool(toolName)
if toolPath == "" {
return
}
@ -119,24 +84,24 @@ func runTool(cmd *Command, args []string) {
if e, ok := err.(*exec.ExitError); !ok || !e.Exited() || cfg.BuildX {
fmt.Fprintf(os.Stderr, "go tool %s: %s\n", toolName, err)
}
setExitStatus(1)
base.SetExitStatus(1)
return
}
}
// listTools prints a list of the available tools in the tools directory.
func listTools() {
f, err := os.Open(toolDir)
f, err := os.Open(base.ToolDir)
if err != nil {
fmt.Fprintf(os.Stderr, "go tool: no tool directory: %s\n", err)
setExitStatus(2)
base.SetExitStatus(2)
return
}
defer f.Close()
names, err := f.Readdirnames(-1)
if err != nil {
fmt.Fprintf(os.Stderr, "go tool: can't read directory: %s\n", err)
setExitStatus(2)
base.SetExitStatus(2)
return
}
@ -145,8 +110,8 @@ func listTools() {
// Unify presentation by going to lower case.
name = strings.ToLower(name)
// If it's windows, don't show the .exe suffix.
if toolIsWindows && strings.HasSuffix(name, toolWindowsExtension) {
name = name[:len(name)-len(toolWindowsExtension)]
if base.ToolIsWindows && strings.HasSuffix(name, base.ToolWindowsExtension) {
name = name[:len(name)-len(base.ToolWindowsExtension)]
}
fmt.Println(name)
}

View File

@ -5,18 +5,19 @@
package main
import (
"cmd/go/internal/base"
"fmt"
"runtime"
)
var cmdVersion = &Command{
var cmdVersion = &base.Command{
Run: runVersion,
UsageLine: "version",
Short: "print Go version",
Long: `Version prints the Go version, as reported by runtime.Version.`,
}
func runVersion(cmd *Command, args []string) {
func runVersion(cmd *base.Command, args []string) {
if len(args) != 0 {
cmd.Usage()
}

View File

@ -8,6 +8,7 @@ import (
"path/filepath"
"cmd/go/internal/cfg"
"cmd/go/internal/base"
"cmd/go/internal/str"
)
@ -15,7 +16,7 @@ func init() {
addBuildFlags(cmdVet)
}
var cmdVet = &Command{
var cmdVet = &base.Command{
Run: runVet,
UsageLine: "vet [-n] [-x] [build flags] [packages]",
Short: "run go tool vet on packages",
@ -36,7 +37,7 @@ See also: go fmt, go fix.
`,
}
func runVet(cmd *Command, args []string) {
func runVet(cmd *base.Command, args []string) {
for _, p := range packages(args) {
// Vet expects to be given a set of files all from the same package.
// Run once for package p and once for package p_test.
@ -53,5 +54,5 @@ func runVetFiles(p *Package, files []string) {
for i := range files {
files[i] = filepath.Join(p.Dir, files[i])
}
run(cfg.BuildToolexec, tool("vet"), relPaths(files))
base.Run(cfg.BuildToolexec, base.Tool("vet"), base.RelPaths(files))
}