-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommand_err.go
149 lines (123 loc) · 3.23 KB
/
command_err.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package cli
import (
"fmt"
"strings"
)
const (
// ExitCodeErrorApp is the exit code on application error
ExitCodeErrorApp = 1001
// ExitCodeErrorFlag is the exit code on flag error
ExitCodeErrorFlag = 1002
// ExitCodeNotFoundFlag is the exit code when a flag is not found
ExitCodeNotFoundFlag = 1003
// ExitCodeNotFoundCommand is the exit code when a command is not found
ExitCodeNotFoundCommand = 1004
)
// ExitCoder is the interface checked by `App` and `Command` for a custom exit
// code
type ExitCoder interface {
Error() string
Code() int
}
var _ ExitCoder = &ExitError{}
// ExitError fulfills both the builtin `error` interface and `ExitCoder`
type ExitError struct {
err error
code int
}
// NewExitError makes a new ExitError
func NewExitError(text string, code int) *ExitError {
return &ExitError{
code: code,
err: fmt.Errorf(text),
}
}
// WrapError wraps an error as ExitError
func WrapError(err error) *ExitError {
return &ExitError{
code: ExitCodeErrorApp,
err: err,
}
}
// NotFoundFlagError makes a new ExitError for missing flags
func NotFoundFlagError(name string) *ExitError {
return &ExitError{
code: ExitCodeNotFoundFlag,
err: fmt.Errorf("flag '%s' not found", name),
}
}
// FlagError makes a new ExitError for missing command
func FlagError(prefix, name string, err error) *ExitError {
return &ExitError{
code: ExitCodeErrorFlag,
err: fmt.Errorf("%s: failed to set a flag '%v': %w", prefix, name, err),
}
}
// NotFoundCommandError makes a new ExitError for missing command
func NotFoundCommandError(name string) *ExitError {
return &ExitError{
code: ExitCodeNotFoundCommand,
err: fmt.Errorf("command '%s' not found", name),
}
}
// WithCode creates a copy of the error with a code
func (x ExitError) WithCode(code int) *ExitError {
x.code = code
return &x
}
// Error returns the string message, fulfilling the interface required by
// `error`
func (x *ExitError) Error() string {
return x.err.Error()
}
// Code returns the exit code, fulfilling the interface required by
// `ExitCoder`
func (x *ExitError) Code() int {
return x.code
}
// Wrap wraps an error
func (x *ExitError) Wrap(err error) {
x.err = err
}
// Unwrap returns the underlying error
func (x *ExitError) Unwrap() error {
return x.err
}
var _ ExitCoder = &ExitErrorCollector{}
// ExitErrorCollector is an error that wraps multiple errors.
type ExitErrorCollector []error
// IsEmpty returns true if the collector is empty
func (errs ExitErrorCollector) IsEmpty() bool {
return len(errs) == 0
}
// Error implements the error interface.
func (errs ExitErrorCollector) Error() string {
messages := make([]string, len(errs))
for index, err := range errs {
messages[index] = err.Error()
}
return strings.Join(messages, "\n")
}
// Code returns the exit code, fulfilling the interface required by ExitCoder
func (errs ExitErrorCollector) Code() int {
for _, err := range errs {
if errx, ok := err.(ExitCoder); ok {
return errx.Code()
}
}
return ExitCodeErrorApp
}
// Wrap wraps an error
func (errs *ExitErrorCollector) Wrap(err error) {
*errs = append(*errs, err)
}
// Unwrap unwraps the error
func (errs ExitErrorCollector) Unwrap() error {
count := len(errs)
switch {
case count == 1:
return errs[0]
default:
return nil
}
}