blob: 525b986e94ab6bfed120d7391a7d15d03c861dc4 [file] [log] [blame]
Tobias Bosch900dbc92019-06-24 09:31:39 -07001package main
2
3import (
4 "fmt"
5 "os/exec"
6 "runtime"
7 "strings"
8 "syscall"
9)
10
11type userError struct {
12 err string
13}
14
15var _ error = userError{}
16
17func (err userError) Error() string {
18 return err.err
19}
20
21func newUserErrorf(format string, v ...interface{}) userError {
22 return userError{err: fmt.Sprintf(format, v...)}
23}
24
25func newErrorwithSourceLocf(format string, v ...interface{}) error {
26 return newErrorwithSourceLocfInternal(2, format, v...)
27}
28
29func wrapErrorwithSourceLocf(err error, format string, v ...interface{}) error {
30 return newErrorwithSourceLocfInternal(2, "%s: %s", fmt.Sprintf(format, v...), err.Error())
31}
32
33// Based on the implementation of log.Output
34func newErrorwithSourceLocfInternal(skip int, format string, v ...interface{}) error {
35 _, file, line, ok := runtime.Caller(skip)
36 if !ok {
37 file = "???"
38 line = 0
39 }
40 if lastSlash := strings.LastIndex(file, "/"); lastSlash >= 0 {
41 file = file[lastSlash+1:]
42 }
43
44 return fmt.Errorf("%s:%d: %s", file, line, fmt.Sprintf(format, v...))
45}
46
47func getExitCode(err error) (exitCode int, ok bool) {
48 if err == nil {
49 return 0, true
50 }
51 if exiterr, ok := err.(*exec.ExitError); ok {
52 if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
53 return status.ExitStatus(), true
54 }
55 }
56 return 0, false
57}