OLD | NEW |
| (Empty) |
1 // Copyright 2013 Canonical Ltd. | |
2 // Licensed under the AGPLv3, see LICENCE file for details. | |
3 | |
4 package errors | |
5 | |
6 import ( | |
7 "fmt" | |
8 | |
9 "github.com/juju/loggo" | |
10 ) | |
11 | |
12 // wrapper defines a way to encapsulate an error inside another error. | |
13 type wrapper struct { | |
14 // Err is the underlying error. | |
15 err error | |
16 | |
17 // Msg is the annotation (prefix) of Err. | |
18 msg string | |
19 } | |
20 | |
21 // newer is implemented by error types that can add a context message | |
22 // while preserving their type. | |
23 type newer interface { | |
24 new(msg string) error | |
25 } | |
26 | |
27 // Error implements the error interface. | |
28 func (e *wrapper) Error() string { | |
29 if e.msg != "" || e.err == nil { | |
30 if e.err != nil { | |
31 return fmt.Sprintf("%s: %v", e.msg, e.err.Error()) | |
32 } | |
33 return e.msg | |
34 } | |
35 return e.err.Error() | |
36 } | |
37 | |
38 // wrap is a helper to construct an *wrapper. | |
39 func wrap(err error, format, suffix string, args ...interface{}) wrapper { | |
40 return wrapper{err, fmt.Sprintf(format+suffix, args...)} | |
41 } | |
42 | |
43 // Contextf prefixes any error stored in err with text formatted | |
44 // according to the format specifier. If err does not contain an | |
45 // error, Contextf does nothing. All errors created with functions | |
46 // from this package are preserved when wrapping. | |
47 func Contextf(err *error, format string, args ...interface{}) { | |
48 if *err == nil { | |
49 return | |
50 } | |
51 msg := fmt.Sprintf(format, args...) | |
52 errNewer, ok := (*err).(newer) | |
53 if ok { | |
54 *err = errNewer.new(msg) | |
55 return | |
56 } | |
57 *err = fmt.Errorf("%s: %v", msg, *err) | |
58 } | |
59 | |
60 // Maskf masks the given error (when it is not nil) with the given | |
61 // format string and arguments (like fmt.Sprintf), returning a new | |
62 // error. If *err is nil, Maskf does nothing. | |
63 func Maskf(err *error, format string, args ...interface{}) { | |
64 if *err == nil { | |
65 return | |
66 } | |
67 *err = fmt.Errorf("%s: %v", fmt.Sprintf(format, args...), *err) | |
68 } | |
69 | |
70 // notFound represents an error when something has not been found. | |
71 type notFound struct { | |
72 wrapper | |
73 } | |
74 | |
75 func (e *notFound) new(msg string) error { | |
76 return NewNotFound(e, msg) | |
77 } | |
78 | |
79 // NotFoundf returns an error which satisfies IsNotFound(). | |
80 func NotFoundf(format string, args ...interface{}) error { | |
81 return ¬Found{wrap(nil, format, " not found", args...)} | |
82 } | |
83 | |
84 // NewNotFound returns an error which wraps err that satisfies | |
85 // IsNotFound(). | |
86 func NewNotFound(err error, msg string) error { | |
87 return ¬Found{wrap(err, msg, "")} | |
88 } | |
89 | |
90 // IsNotFound reports whether err was created with NotFoundf() or | |
91 // NewNotFound(). | |
92 func IsNotFound(err error) bool { | |
93 _, ok := err.(*notFound) | |
94 return ok | |
95 } | |
96 | |
97 // unauthorized represents an error when an operation is unauthorized. | |
98 type unauthorized struct { | |
99 wrapper | |
100 } | |
101 | |
102 func (e *unauthorized) new(msg string) error { | |
103 return NewUnauthorized(e, msg) | |
104 } | |
105 | |
106 // Unauthorizedf returns an error which satisfies IsUnauthorized(). | |
107 func Unauthorizedf(format string, args ...interface{}) error { | |
108 return &unauthorized{wrap(nil, format, "", args...)} | |
109 } | |
110 | |
111 // NewUnauthorized returns an error which wraps err and satisfies | |
112 // IsUnauthorized(). | |
113 func NewUnauthorized(err error, msg string) error { | |
114 return &unauthorized{wrap(err, msg, "")} | |
115 } | |
116 | |
117 // IsUnauthorized reports whether err was created with Unauthorizedf() or | |
118 // NewUnauthorized(). | |
119 func IsUnauthorized(err error) bool { | |
120 _, ok := err.(*unauthorized) | |
121 return ok | |
122 } | |
123 | |
124 // notImplemented represents an error when something is not | |
125 // implemented. | |
126 type notImplemented struct { | |
127 wrapper | |
128 } | |
129 | |
130 func (e *notImplemented) new(msg string) error { | |
131 return NewNotImplemented(e, msg) | |
132 } | |
133 | |
134 // NotImplementedf returns an error which satisfies IsNotImplemented(). | |
135 func NotImplementedf(format string, args ...interface{}) error { | |
136 return ¬Implemented{wrap(nil, format, " not implemented", args...)} | |
137 } | |
138 | |
139 // NewNotImplemented returns an error which wraps err and satisfies | |
140 // IsNotImplemented(). | |
141 func NewNotImplemented(err error, msg string) error { | |
142 return ¬Implemented{wrap(err, msg, "")} | |
143 } | |
144 | |
145 // IsNotImplemented reports whether err was created with | |
146 // NotImplementedf() or NewNotImplemented(). | |
147 func IsNotImplemented(err error) bool { | |
148 _, ok := err.(*notImplemented) | |
149 return ok | |
150 } | |
151 | |
152 // alreadyExists represents and error when something already exists. | |
153 type alreadyExists struct { | |
154 wrapper | |
155 } | |
156 | |
157 func (e *alreadyExists) new(msg string) error { | |
158 return NewAlreadyExists(e, msg) | |
159 } | |
160 | |
161 // AlreadyExistsf returns an error which satisfies IsAlreadyExists(). | |
162 func AlreadyExistsf(format string, args ...interface{}) error { | |
163 return &alreadyExists{wrap(nil, format, " already exists", args...)} | |
164 } | |
165 | |
166 // NewAlreadyExists returns an error which wraps err and satisfies | |
167 // IsAlreadyExists(). | |
168 func NewAlreadyExists(err error, msg string) error { | |
169 return &alreadyExists{wrap(err, msg, "")} | |
170 } | |
171 | |
172 // IsAlreadyExists reports whether the error was created with | |
173 // AlreadyExistsf() or NewAlreadyExists(). | |
174 func IsAlreadyExists(err error) bool { | |
175 _, ok := err.(*alreadyExists) | |
176 return ok | |
177 } | |
178 | |
179 // notSupported represents an error when something is not supported. | |
180 type notSupported struct { | |
181 wrapper | |
182 } | |
183 | |
184 func (e *notSupported) new(msg string) error { | |
185 return NewNotSupported(e, msg) | |
186 } | |
187 | |
188 // NotSupportedf returns an error which satisfies IsNotSupported(). | |
189 func NotSupportedf(format string, args ...interface{}) error { | |
190 return ¬Supported{wrap(nil, format, " not supported", args...)} | |
191 } | |
192 | |
193 // NewNotSupported returns an error which wraps err and satisfies | |
194 // IsNotSupported(). | |
195 func NewNotSupported(err error, msg string) error { | |
196 return ¬Supported{wrap(err, msg, "")} | |
197 } | |
198 | |
199 // IsNotSupported reports whether the error was created with | |
200 // NotSupportedf() or NewNotSupported(). | |
201 func IsNotSupported(err error) bool { | |
202 _, ok := err.(*notSupported) | |
203 return ok | |
204 } | |
205 | |
206 // LoggedErrorf logs the error and return an error with the same text. | |
207 func LoggedErrorf(logger loggo.Logger, format string, a ...interface{}) error { | |
208 logger.Logf(loggo.ERROR, format, a...) | |
209 return fmt.Errorf(format, a...) | |
210 } | |
OLD | NEW |