|
- 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 and calls OsExiter with the last exit code.
- 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 {
- code := handleMultiError(multiErr)
- OsExiter(code)
- return
- }
- }
-
- func handleMultiError(multiErr MultiError) int {
- code := 1
- for _, merr := range multiErr.Errors {
- if multiErr2, ok := merr.(MultiError); ok {
- code = handleMultiError(multiErr2)
- } else {
- fmt.Fprintln(ErrWriter, merr)
- if exitErr, ok := merr.(ExitCoder); ok {
- code = exitErr.ExitCode()
- }
- }
- }
- return code
- }
|