urfave-cli/errors.go

99 lines
2.2 KiB
Go
Raw Normal View History

2016-04-27 13:13:52 +00:00
package cli
import (
"fmt"
"io"
"os"
2016-04-27 13:13:52 +00:00
"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.
2016-04-27 13:13:52 +00:00
type MultiError struct {
Errors []error
}
// NewMultiError creates a new MultiError. Pass in one or more errors.
2016-04-27 13:13:52 +00:00
func NewMultiError(err ...error) MultiError {
return MultiError{Errors: err}
}
// Error implents the error interface.
2016-04-27 13:13:52 +00:00
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")
}
// ExitCoder is the interface checked by `App` and `Command` for a custom exit
// code
2016-04-27 13:13:52 +00:00
type ExitCoder interface {
error
2016-04-27 13:13:52 +00:00
ExitCode() int
}
// ExitError fulfills both the builtin `error` interface and `ExitCoder`
2016-04-27 13:13:52 +00:00
type ExitError struct {
exitCode int
message string
}
// NewExitError makes a new *ExitError
2016-04-27 13:13:52 +00:00
func NewExitError(message string, exitCode int) *ExitError {
return &ExitError{
exitCode: exitCode,
message: message,
}
}
// Error returns the string message, fulfilling the interface required by
// `error`
2016-04-27 13:13:52 +00:00
func (ee *ExitError) Error() string {
return ee.message
}
// ExitCode returns the exit code, fulfilling the interface required by
// `ExitCoder`
2016-04-27 13:13:52 +00:00
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() != "" {
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() != "" {
fmt.Fprintln(ErrWriter, err)
}
OsExiter(1)
}