forked from cerc-io/plugeth
d78f9b834a
The Azure SDK doesn't support Go 1.5 anymore. We can't upgrade it until Go 1.8 comes out.
111 lines
2.5 KiB
Go
111 lines
2.5 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
// OsExiter is the function used when the app exits. If not set defaults to os.Exit.
|
|
var OsExiter = os.Exit
|
|
|
|
// ErrWriter is used to write errors to the user. This can be anything
|
|
// implementing the io.Writer interface and defaults to os.Stderr.
|
|
var ErrWriter io.Writer = os.Stderr
|
|
|
|
// MultiError is an error that wraps multiple errors.
|
|
type MultiError struct {
|
|
Errors []error
|
|
}
|
|
|
|
// NewMultiError creates a new MultiError. Pass in one or more errors.
|
|
func NewMultiError(err ...error) MultiError {
|
|
return MultiError{Errors: err}
|
|
}
|
|
|
|
// Error implements the error interface.
|
|
func (m MultiError) Error() string {
|
|
errs := make([]string, len(m.Errors))
|
|
for i, err := range m.Errors {
|
|
errs[i] = err.Error()
|
|
}
|
|
|
|
return strings.Join(errs, "\n")
|
|
}
|
|
|
|
type ErrorFormatter interface {
|
|
Format(s fmt.State, verb rune)
|
|
}
|
|
|
|
// ExitCoder is the interface checked by `App` and `Command` for a custom exit
|
|
// code
|
|
type ExitCoder interface {
|
|
error
|
|
ExitCode() int
|
|
}
|
|
|
|
// ExitError fulfills both the builtin `error` interface and `ExitCoder`
|
|
type ExitError struct {
|
|
exitCode int
|
|
message interface{}
|
|
}
|
|
|
|
// NewExitError makes a new *ExitError
|
|
func NewExitError(message interface{}, exitCode int) *ExitError {
|
|
return &ExitError{
|
|
exitCode: exitCode,
|
|
message: message,
|
|
}
|
|
}
|
|
|
|
// Error returns the string message, fulfilling the interface required by
|
|
// `error`
|
|
func (ee *ExitError) Error() string {
|
|
return fmt.Sprintf("%v", ee.message)
|
|
}
|
|
|
|
// ExitCode returns the exit code, fulfilling the interface required by
|
|
// `ExitCoder`
|
|
func (ee *ExitError) ExitCode() int {
|
|
return ee.exitCode
|
|
}
|
|
|
|
// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if
|
|
// so prints the error to stderr (if it is non-empty) and calls OsExiter with the
|
|
// given exit code. If the given error is a MultiError, then this func is
|
|
// called on all members of the Errors slice.
|
|
func HandleExitCoder(err error) {
|
|
if err == nil {
|
|
return
|
|
}
|
|
|
|
if exitErr, ok := err.(ExitCoder); ok {
|
|
if err.Error() != "" {
|
|
if _, ok := exitErr.(ErrorFormatter); ok {
|
|
fmt.Fprintf(ErrWriter, "%+v\n", err)
|
|
} else {
|
|
fmt.Fprintln(ErrWriter, err)
|
|
}
|
|
}
|
|
OsExiter(exitErr.ExitCode())
|
|
return
|
|
}
|
|
|
|
if multiErr, ok := err.(MultiError); ok {
|
|
for _, merr := range multiErr.Errors {
|
|
HandleExitCoder(merr)
|
|
}
|
|
return
|
|
}
|
|
|
|
if err.Error() != "" {
|
|
if _, ok := err.(ErrorFormatter); ok {
|
|
fmt.Fprintf(ErrWriter, "%+v\n", err)
|
|
} else {
|
|
fmt.Fprintln(ErrWriter, err)
|
|
}
|
|
}
|
|
OsExiter(1)
|
|
}
|