Skip to content
This repository was archived by the owner on Mar 23, 2021. It is now read-only.

Commit 7e4da01

Browse files
authored
main: do not print *exec.ExitError for -run (#61)
Instead, rely on the program to output something sensible on stdout/stderr. Exit with the exit code from the program we ran. For this we use a local version of *os.ProcessState.ExitStatus() https://go-review.googlesource.com/c/go/+/125443/ which is due to land in Go 1.12
1 parent 4cdfd9a commit 7e4da01

File tree

6 files changed

+91
-14
lines changed

6 files changed

+91
-14
lines changed

exitcode_plan9.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package main
2+
3+
import (
4+
"os"
5+
"syscall"
6+
)
7+
8+
// ExitCode returns the exit code of the exited process, or -1
9+
// if the process hasn't exited or was terminated by a signal.
10+
func ExitCode(p *os.ProcessState) int {
11+
// return -1 if the process hasn't started.
12+
if p == nil {
13+
return -1
14+
}
15+
return p.Sys().(syscall.WaitStatus).ExitStatus()
16+
}

exitcode_posix.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// +build darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris windows
2+
3+
package main
4+
5+
import (
6+
"os"
7+
"syscall"
8+
)
9+
10+
// ExitCode returns the exit code of the exited process, or -1
11+
// if the process hasn't exited or was terminated by a signal.
12+
func ExitCode(p *os.ProcessState) int {
13+
// return -1 if the process hasn't started.
14+
if p == nil {
15+
return -1
16+
}
17+
return p.Sys().(syscall.WaitStatus).ExitStatus()
18+
}

main.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ func main() {
5454

5555
func main1() int {
5656
if err := mainerr(); err != nil {
57+
if ee, ok := err.(*exec.ExitError); ok {
58+
return ExitCode(ee.ProcessState)
59+
}
5760
fmt.Fprintln(os.Stderr, err)
5861
return 1
5962
}

script_test.go

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"fmt"
5+
"io/ioutil"
56
"os"
67
"os/exec"
78
"runtime"
@@ -39,6 +40,41 @@ func (m gobinMain) Run() int {
3940
return m.m.Run()
4041
}
4142

43+
func TestExitCode(t *testing.T) {
44+
var err error
45+
self, err := os.Executable()
46+
if err != nil {
47+
t.Fatalf("failed to determine os.Executable: %v", err)
48+
}
49+
50+
temp, err := ioutil.TempDir("", "gobin-exitcode-test")
51+
if err != nil {
52+
t.Fatalf("failed to create temp directory for home: %v", err)
53+
}
54+
defer os.RemoveAll(temp)
55+
56+
cmd := exec.Command(self, "-run", "example.com/fail")
57+
cmd.Env = os.Environ()
58+
cmd.Env = append(cmd.Env, homeEnv(temp)...)
59+
cmd.Env = append(cmd.Env,
60+
"GOPROXY="+proxyURL,
61+
"TESTSCRIPT_COMMAND=gobin",
62+
)
63+
64+
err = cmd.Run()
65+
if err == nil {
66+
t.Fatalf("unexpected success")
67+
}
68+
ee, ok := err.(*exec.ExitError)
69+
if !ok {
70+
t.Fatalf("expected *exec.ExitError; got %T: %v", err, err)
71+
}
72+
want := 42
73+
if got := ExitCode(ee.ProcessState); want != got {
74+
t.Fatalf("expected exit code %v; got %v", want, got)
75+
}
76+
}
77+
4278
func TestScripts(t *testing.T) {
4379
var (
4480
pathToMod string // local path to this module
@@ -93,17 +129,8 @@ func TestScripts(t *testing.T) {
93129
"USERCACHEDIR="+ucd,
94130
)
95131

96-
if runtime.GOOS == "windows" {
97-
e.Vars = append(e.Vars,
98-
"USERPROFILE="+wd+"\\home",
99-
"LOCALAPPDATA="+wd+"\\appdata",
100-
"HOME="+wd+"\\home", // match USERPROFILE
101-
)
102-
} else {
103-
e.Vars = append(e.Vars,
104-
"HOME="+wd+"/home",
105-
)
106-
}
132+
e.Vars = append(e.Vars, homeEnv(wd)...)
133+
107134
return nil
108135
},
109136
}
@@ -112,3 +139,15 @@ func TestScripts(t *testing.T) {
112139
}
113140
testscript.Run(t, p)
114141
}
142+
143+
func homeEnv(base string) []string {
144+
if runtime.GOOS == "windows" {
145+
return []string{
146+
"USERPROFILE=" + base + "\\home",
147+
"LOCALAPPDATA=" + base + "\\appdata",
148+
"HOME=" + base + "\\home", // match USERPROFILE
149+
}
150+
} else {
151+
return []string{"HOME=" + base + "/home"}
152+
}
153+
}

testdata/failing_run.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
! gobin -run example.com/fail
22
stdout '^This will fail$'
3-
stderr '^exit status 42$'
3+
stderr '^It''s bad$'
44

55

testdata/mod/example.com_fail_v1.0.0.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import "fmt"
1414
import "os"
1515

1616
func main() {
17-
fmt.Println("This will fail")
18-
os.Exit(42)
17+
fmt.Println("This will fail")
18+
fmt.Fprintln(os.Stderr, "It's bad")
19+
os.Exit(42)
1920
}

0 commit comments

Comments
 (0)