Commit 8aef6e02 by Ian Lance Taylor

cmd/go: remove work directory on usage error

    
    Backport https://golang.org/cl/163237 from the master library:
    
        Ensure that cmd/go consistently calls base.Exit rather than os.Exit,
        so that we don't incorrectly leave the work directory around on exit.
    
        Test this by modifying the testsuite to run all the tests with TMPDIR
        set to a temporary directory, and then check that no files are left
        behind in that temporary directory. Adjust a couple of tests to make
        this approach work.
    
    Updates https://gcc.gnu.org/PR89406
    
    Reviewed-on: https://go-review.googlesource.com/c/163198

From-SVN: r269086
parent 2496137a
43e458ab704e04cdf347f3e74e0b0eff3de00a3d 4fbd06dc7b1b8fb665293399a2b6d5326435512f
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -146,7 +146,18 @@ func TestMain(m *testing.M) { ...@@ -146,7 +146,18 @@ func TestMain(m *testing.M) {
select {} select {}
} }
dir, err := ioutil.TempDir(os.Getenv("GOTMPDIR"), "cmd-go-test-") // Run with a temporary TMPDIR to check that the tests don't
// leave anything behind.
topTmpdir, err := ioutil.TempDir("", "cmd-go-test-")
if err != nil {
log.Fatal(err)
}
if !*testWork {
defer removeAll(topTmpdir)
}
os.Setenv(tempEnvName(), topTmpdir)
dir, err := ioutil.TempDir(topTmpdir, "tmpdir")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
...@@ -258,6 +269,23 @@ func TestMain(m *testing.M) { ...@@ -258,6 +269,23 @@ func TestMain(m *testing.M) {
removeAll(testTmpDir) // os.Exit won't run defer removeAll(testTmpDir) // os.Exit won't run defer
} }
if !*testWork {
// There shouldn't be anything left in topTmpdir.
dirf, err := os.Open(topTmpdir)
if err != nil {
log.Fatal(err)
}
names, err := dirf.Readdirnames(0)
if err != nil {
log.Fatal(err)
}
if len(names) > 0 {
log.Fatalf("unexpected files left in tmpdir: %v", names)
}
removeAll(topTmpdir)
}
os.Exit(r) os.Exit(r)
} }
...@@ -5020,7 +5048,8 @@ func TestExecBuildX(t *testing.T) { ...@@ -5020,7 +5048,8 @@ func TestExecBuildX(t *testing.T) {
obj := tg.path("main") obj := tg.path("main")
tg.run("build", "-x", "-o", obj, src) tg.run("build", "-x", "-o", obj, src)
sh := tg.path("test.sh") sh := tg.path("test.sh")
err := ioutil.WriteFile(sh, []byte("set -e\n"+tg.getStderr()), 0666) cmds := tg.getStderr()
err := ioutil.WriteFile(sh, []byte("set -e\n"+cmds), 0666)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -5051,6 +5080,12 @@ func TestExecBuildX(t *testing.T) { ...@@ -5051,6 +5080,12 @@ func TestExecBuildX(t *testing.T) {
if string(out) != "hello" { if string(out) != "hello" {
t.Fatalf("got %q; want %q", out, "hello") t.Fatalf("got %q; want %q", out, "hello")
} }
matches := regexp.MustCompile(`^WORK=(.*)\n`).FindStringSubmatch(cmds)
if len(matches) == 0 {
t.Fatal("no WORK directory")
}
tg.must(os.RemoveAll(matches[1]))
} }
func TestParallelNumber(t *testing.T) { func TestParallelNumber(t *testing.T) {
......
...@@ -82,7 +82,8 @@ func (c *Command) Name() string { ...@@ -82,7 +82,8 @@ func (c *Command) Name() string {
func (c *Command) Usage() { func (c *Command) Usage() {
fmt.Fprintf(os.Stderr, "usage: %s\n", c.UsageLine) fmt.Fprintf(os.Stderr, "usage: %s\n", c.UsageLine)
fmt.Fprintf(os.Stderr, "Run 'go help %s' for details.\n", c.LongName()) fmt.Fprintf(os.Stderr, "Run 'go help %s' for details.\n", c.LongName())
os.Exit(2) SetExitStatus(2)
Exit()
} }
// Runnable reports whether the command can be run; otherwise // Runnable reports whether the command can be run; otherwise
......
...@@ -66,7 +66,8 @@ func SyntaxError(cmd, msg string) { ...@@ -66,7 +66,8 @@ func SyntaxError(cmd, msg string) {
} else { } else {
fmt.Fprintf(os.Stderr, `run "go help %s" for more information`+"\n", cmd) fmt.Fprintf(os.Stderr, `run "go help %s" for more information`+"\n", cmd)
} }
os.Exit(2) base.SetExitStatus(2)
base.Exit()
} }
// AddKnownFlags registers the flags in defns with base.AddKnownFlag. // AddKnownFlags registers the flags in defns with base.AddKnownFlag.
......
...@@ -63,7 +63,8 @@ Args: ...@@ -63,7 +63,8 @@ Args:
helpSuccess = " " + strings.Join(args[:i], " ") helpSuccess = " " + strings.Join(args[:i], " ")
} }
fmt.Fprintf(os.Stderr, "go help %s: unknown help topic. Run '%s'.\n", strings.Join(args, " "), helpSuccess) fmt.Fprintf(os.Stderr, "go help %s: unknown help topic. Run '%s'.\n", strings.Join(args, " "), helpSuccess)
os.Exit(2) // failed at 'go help cmd' base.SetExitStatus(2) // failed at 'go help cmd'
base.Exit()
} }
if len(cmd.Commands) > 0 { if len(cmd.Commands) > 0 {
...@@ -167,7 +168,8 @@ func tmpl(w io.Writer, text string, data interface{}) { ...@@ -167,7 +168,8 @@ func tmpl(w io.Writer, text string, data interface{}) {
if ew.err != nil { if ew.err != nil {
// I/O error writing. Ignore write on closed pipe. // I/O error writing. Ignore write on closed pipe.
if strings.Contains(ew.err.Error(), "pipe") { if strings.Contains(ew.err.Error(), "pipe") {
os.Exit(1) base.SetExitStatus(1)
base.Exit()
} }
base.Fatalf("writing output: %v", ew.err) base.Fatalf("writing output: %v", ew.err)
} }
......
...@@ -76,7 +76,8 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) { ...@@ -76,7 +76,8 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
vetcmd.Stdout = out vetcmd.Stdout = out
if err := vetcmd.Run(); err != nil { if err := vetcmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "go vet: can't execute %s -flags: %v\n", tool, err) fmt.Fprintf(os.Stderr, "go vet: can't execute %s -flags: %v\n", tool, err)
os.Exit(2) base.SetExitStatus(2)
base.Exit()
} }
var analysisFlags []struct { var analysisFlags []struct {
Name string Name string
...@@ -85,7 +86,8 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) { ...@@ -85,7 +86,8 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
} }
if err := json.Unmarshal(out.Bytes(), &analysisFlags); err != nil { if err := json.Unmarshal(out.Bytes(), &analysisFlags); err != nil {
fmt.Fprintf(os.Stderr, "go vet: can't unmarshal JSON from %s -flags: %v", tool, err) fmt.Fprintf(os.Stderr, "go vet: can't unmarshal JSON from %s -flags: %v", tool, err)
os.Exit(2) base.SetExitStatus(2)
base.Exit()
} }
// Add vet's flags to vetflagDefn. // Add vet's flags to vetflagDefn.
...@@ -134,7 +136,8 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) { ...@@ -134,7 +136,8 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
if f == nil { if f == nil {
fmt.Fprintf(os.Stderr, "vet: flag %q not defined\n", args[i]) fmt.Fprintf(os.Stderr, "vet: flag %q not defined\n", args[i])
fmt.Fprintf(os.Stderr, "Run \"go help vet\" for more information\n") fmt.Fprintf(os.Stderr, "Run \"go help vet\" for more information\n")
os.Exit(2) base.SetExitStatus(2)
base.Exit()
} }
if f.Value != nil { if f.Value != nil {
if err := f.Value.Set(value); err != nil { if err := f.Value.Set(value); err != nil {
...@@ -182,5 +185,6 @@ func usage() { ...@@ -182,5 +185,6 @@ func usage() {
} }
fmt.Fprintf(os.Stderr, "Run '%s -help' for the vet tool's flags.\n", cmd) fmt.Fprintf(os.Stderr, "Run '%s -help' for the vet tool's flags.\n", cmd)
os.Exit(2) base.SetExitStatus(2)
base.Exit()
} }
...@@ -249,12 +249,14 @@ func (b *Builder) Init() { ...@@ -249,12 +249,14 @@ func (b *Builder) Init() {
if _, ok := cfg.OSArchSupportsCgo[cfg.Goos+"/"+cfg.Goarch]; !ok && cfg.BuildContext.Compiler == "gc" { if _, ok := cfg.OSArchSupportsCgo[cfg.Goos+"/"+cfg.Goarch]; !ok && cfg.BuildContext.Compiler == "gc" {
fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", cfg.Goos, cfg.Goarch) fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", cfg.Goos, cfg.Goarch)
os.Exit(2) base.SetExitStatus(2)
base.Exit()
} }
for _, tag := range cfg.BuildContext.BuildTags { for _, tag := range cfg.BuildContext.BuildTags {
if strings.Contains(tag, ",") { if strings.Contains(tag, ",") {
fmt.Fprintf(os.Stderr, "cmd/go: -tags space-separated list contains comma\n") fmt.Fprintf(os.Stderr, "cmd/go: -tags space-separated list contains comma\n")
os.Exit(2) base.SetExitStatus(2)
base.Exit()
} }
} }
} }
......
...@@ -2334,7 +2334,7 @@ func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool { ...@@ -2334,7 +2334,7 @@ func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool {
// version of GCC, so some systems have frozen on it. // version of GCC, so some systems have frozen on it.
// Now we pass an empty file on stdin, which should work at least for // Now we pass an empty file on stdin, which should work at least for
// GCC and clang. // GCC and clang.
cmdArgs := str.StringList(compiler, flag, "-c", "-x", "c", "-") cmdArgs := str.StringList(compiler, flag, "-c", "-x", "c", "-", "-o", os.DevNull)
if cfg.BuildN || cfg.BuildX { if cfg.BuildN || cfg.BuildX {
b.Showcmd(b.WorkDir, "%s || true", joinUnambiguously(cmdArgs)) b.Showcmd(b.WorkDir, "%s || true", joinUnambiguously(cmdArgs))
if cfg.BuildN { if cfg.BuildN {
......
...@@ -56,7 +56,8 @@ func checkGccgoBin() { ...@@ -56,7 +56,8 @@ func checkGccgoBin() {
return return
} }
fmt.Fprintf(os.Stderr, "cmd/go: gccgo: %s\n", gccgoErr) fmt.Fprintf(os.Stderr, "cmd/go: gccgo: %s\n", gccgoErr)
os.Exit(2) base.SetExitStatus(2)
base.Exit()
} }
func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) { func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
......
...@@ -29,7 +29,8 @@ func BuildInit() { ...@@ -29,7 +29,8 @@ func BuildInit() {
p, err := filepath.Abs(cfg.BuildPkgdir) p, err := filepath.Abs(cfg.BuildPkgdir)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "go %s: evaluating -pkgdir: %v\n", flag.Args()[0], err) fmt.Fprintf(os.Stderr, "go %s: evaluating -pkgdir: %v\n", flag.Args()[0], err)
os.Exit(2) base.SetExitStatus(2)
base.Exit()
} }
cfg.BuildPkgdir = p cfg.BuildPkgdir = p
} }
...@@ -41,16 +42,19 @@ func instrumentInit() { ...@@ -41,16 +42,19 @@ func instrumentInit() {
} }
if cfg.BuildRace && cfg.BuildMSan { if cfg.BuildRace && cfg.BuildMSan {
fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0]) fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0])
os.Exit(2) base.SetExitStatus(2)
base.Exit()
} }
if cfg.BuildMSan && !sys.MSanSupported(cfg.Goos, cfg.Goarch) { if cfg.BuildMSan && !sys.MSanSupported(cfg.Goos, cfg.Goarch) {
fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch) fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch)
os.Exit(2) base.SetExitStatus(2)
base.Exit()
} }
if cfg.BuildRace { if cfg.BuildRace {
if !sys.RaceDetectorSupported(cfg.Goos, cfg.Goarch) { if !sys.RaceDetectorSupported(cfg.Goos, cfg.Goarch) {
fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, linux/arm64, freebsd/amd64, netbsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0]) fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, linux/arm64, freebsd/amd64, netbsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
os.Exit(2) base.SetExitStatus(2)
base.Exit()
} }
} }
mode := "race" mode := "race"
...@@ -61,7 +65,8 @@ func instrumentInit() { ...@@ -61,7 +65,8 @@ func instrumentInit() {
if !cfg.BuildContext.CgoEnabled { if !cfg.BuildContext.CgoEnabled {
fmt.Fprintf(os.Stderr, "go %s: %s requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0], modeFlag) fmt.Fprintf(os.Stderr, "go %s: %s requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0], modeFlag)
os.Exit(2) base.SetExitStatus(2)
base.Exit()
} }
forcedGcflags = append(forcedGcflags, modeFlag) forcedGcflags = append(forcedGcflags, modeFlag)
forcedLdflags = append(forcedLdflags, modeFlag) forcedLdflags = append(forcedLdflags, modeFlag)
......
...@@ -400,6 +400,7 @@ func (ts *testScript) cmdCc(neg bool, args []string) { ...@@ -400,6 +400,7 @@ func (ts *testScript) cmdCc(neg bool, args []string) {
var b work.Builder var b work.Builder
b.Init() b.Init()
ts.cmdExec(neg, append(b.GccCmd(".", ""), args...)) ts.cmdExec(neg, append(b.GccCmd(".", ""), args...))
os.RemoveAll(b.WorkDir)
} }
// cd changes to a different directory. // cd changes to a different directory.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment