full diff: https://github.com/pkg/errors/compare/v0.8.1...v0.9.1
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -152,7 +152,7 @@ github.com/prometheus/client_model d1d2010b5beead3fa1c5f271a5cf |
| 152 | 152 |
github.com/prometheus/common 287d3e634a1e550c9e463dd7e5a75a422c614505 # v0.7.0 |
| 153 | 153 |
github.com/prometheus/procfs 6d489fc7f1d9cd890a250f3ea3431b1744b9623f # v0.0.8 |
| 154 | 154 |
github.com/matttproud/golang_protobuf_extensions c12348ce28de40eed0136aa2b644d0ee0650e56c # v1.0.1 |
| 155 |
-github.com/pkg/errors ba968bfe8b2f7e042a574c888954fccecfa385b4 # v0.8.1 |
|
| 155 |
+github.com/pkg/errors 614d223910a179a466c1767a985424175c39b465 # v0.9.1 |
|
| 156 | 156 |
github.com/grpc-ecosystem/go-grpc-prometheus c225b8c3b01faf2899099b768856a9e916e5087b # v1.2.0 |
| 157 | 157 |
github.com/cespare/xxhash/v2 d7df74196a9e781ede915320c11c378c1b2f3a1f # v2.1.1 |
| 158 | 158 |
|
| ... | ... |
@@ -41,11 +41,18 @@ default: |
| 41 | 41 |
|
| 42 | 42 |
[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). |
| 43 | 43 |
|
| 44 |
+## Roadmap |
|
| 45 |
+ |
|
| 46 |
+With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows: |
|
| 47 |
+ |
|
| 48 |
+- 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible) |
|
| 49 |
+- 1.0. Final release. |
|
| 50 |
+ |
|
| 44 | 51 |
## Contributing |
| 45 | 52 |
|
| 46 |
-We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. |
|
| 53 |
+Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports. |
|
| 47 | 54 |
|
| 48 |
-Before proposing a change, please discuss your change by raising an issue. |
|
| 55 |
+Before sending a PR, please discuss your change by raising an issue. |
|
| 49 | 56 |
|
| 50 | 57 |
## License |
| 51 | 58 |
|
| ... | ... |
@@ -82,7 +82,7 @@ |
| 82 | 82 |
// |
| 83 | 83 |
// if err, ok := err.(stackTracer); ok {
|
| 84 | 84 |
// for _, f := range err.StackTrace() {
|
| 85 |
-// fmt.Printf("%+s:%d", f)
|
|
| 85 |
+// fmt.Printf("%+s:%d\n", f, f)
|
|
| 86 | 86 |
// } |
| 87 | 87 |
// } |
| 88 | 88 |
// |
| ... | ... |
@@ -159,6 +159,9 @@ type withStack struct {
|
| 159 | 159 |
|
| 160 | 160 |
func (w *withStack) Cause() error { return w.error }
|
| 161 | 161 |
|
| 162 |
+// Unwrap provides compatibility for Go 1.13 error chains. |
|
| 163 |
+func (w *withStack) Unwrap() error { return w.error }
|
|
| 164 |
+ |
|
| 162 | 165 |
func (w *withStack) Format(s fmt.State, verb rune) {
|
| 163 | 166 |
switch verb {
|
| 164 | 167 |
case 'v': |
| ... | ... |
@@ -241,6 +244,9 @@ type withMessage struct {
|
| 241 | 241 |
func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
|
| 242 | 242 |
func (w *withMessage) Cause() error { return w.cause }
|
| 243 | 243 |
|
| 244 |
+// Unwrap provides compatibility for Go 1.13 error chains. |
|
| 245 |
+func (w *withMessage) Unwrap() error { return w.cause }
|
|
| 246 |
+ |
|
| 244 | 247 |
func (w *withMessage) Format(s fmt.State, verb rune) {
|
| 245 | 248 |
switch verb {
|
| 246 | 249 |
case 'v': |
| 247 | 250 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,38 @@ |
| 0 |
+// +build go1.13 |
|
| 1 |
+ |
|
| 2 |
+package errors |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ stderrors "errors" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+// Is reports whether any error in err's chain matches target. |
|
| 9 |
+// |
|
| 10 |
+// The chain consists of err itself followed by the sequence of errors obtained by |
|
| 11 |
+// repeatedly calling Unwrap. |
|
| 12 |
+// |
|
| 13 |
+// An error is considered to match a target if it is equal to that target or if |
|
| 14 |
+// it implements a method Is(error) bool such that Is(target) returns true. |
|
| 15 |
+func Is(err, target error) bool { return stderrors.Is(err, target) }
|
|
| 16 |
+ |
|
| 17 |
+// As finds the first error in err's chain that matches target, and if so, sets |
|
| 18 |
+// target to that error value and returns true. |
|
| 19 |
+// |
|
| 20 |
+// The chain consists of err itself followed by the sequence of errors obtained by |
|
| 21 |
+// repeatedly calling Unwrap. |
|
| 22 |
+// |
|
| 23 |
+// An error matches target if the error's concrete value is assignable to the value |
|
| 24 |
+// pointed to by target, or if the error has a method As(interface{}) bool such that
|
|
| 25 |
+// As(target) returns true. In the latter case, the As method is responsible for |
|
| 26 |
+// setting target. |
|
| 27 |
+// |
|
| 28 |
+// As will panic if target is not a non-nil pointer to either a type that implements |
|
| 29 |
+// error, or to any interface type. As returns false if err is nil. |
|
| 30 |
+func As(err error, target interface{}) bool { return stderrors.As(err, target) }
|
|
| 31 |
+ |
|
| 32 |
+// Unwrap returns the result of calling the Unwrap method on err, if err's |
|
| 33 |
+// type contains an Unwrap method returning error. |
|
| 34 |
+// Otherwise, Unwrap returns nil. |
|
| 35 |
+func Unwrap(err error) error {
|
|
| 36 |
+ return stderrors.Unwrap(err) |
|
| 37 |
+} |
| ... | ... |
@@ -5,10 +5,13 @@ import ( |
| 5 | 5 |
"io" |
| 6 | 6 |
"path" |
| 7 | 7 |
"runtime" |
| 8 |
+ "strconv" |
|
| 8 | 9 |
"strings" |
| 9 | 10 |
) |
| 10 | 11 |
|
| 11 | 12 |
// Frame represents a program counter inside a stack frame. |
| 13 |
+// For historical reasons if Frame is interpreted as a uintptr |
|
| 14 |
+// its value represents the program counter + 1. |
|
| 12 | 15 |
type Frame uintptr |
| 13 | 16 |
|
| 14 | 17 |
// pc returns the program counter for this frame; |
| ... | ... |
@@ -37,6 +40,15 @@ func (f Frame) line() int {
|
| 37 | 37 |
return line |
| 38 | 38 |
} |
| 39 | 39 |
|
| 40 |
+// name returns the name of this function, if known. |
|
| 41 |
+func (f Frame) name() string {
|
|
| 42 |
+ fn := runtime.FuncForPC(f.pc()) |
|
| 43 |
+ if fn == nil {
|
|
| 44 |
+ return "unknown" |
|
| 45 |
+ } |
|
| 46 |
+ return fn.Name() |
|
| 47 |
+} |
|
| 48 |
+ |
|
| 40 | 49 |
// Format formats the frame according to the fmt.Formatter interface. |
| 41 | 50 |
// |
| 42 | 51 |
// %s source file |
| ... | ... |
@@ -54,22 +66,16 @@ func (f Frame) Format(s fmt.State, verb rune) {
|
| 54 | 54 |
case 's': |
| 55 | 55 |
switch {
|
| 56 | 56 |
case s.Flag('+'):
|
| 57 |
- pc := f.pc() |
|
| 58 |
- fn := runtime.FuncForPC(pc) |
|
| 59 |
- if fn == nil {
|
|
| 60 |
- io.WriteString(s, "unknown") |
|
| 61 |
- } else {
|
|
| 62 |
- file, _ := fn.FileLine(pc) |
|
| 63 |
- fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file) |
|
| 64 |
- } |
|
| 57 |
+ io.WriteString(s, f.name()) |
|
| 58 |
+ io.WriteString(s, "\n\t") |
|
| 59 |
+ io.WriteString(s, f.file()) |
|
| 65 | 60 |
default: |
| 66 | 61 |
io.WriteString(s, path.Base(f.file())) |
| 67 | 62 |
} |
| 68 | 63 |
case 'd': |
| 69 |
- fmt.Fprintf(s, "%d", f.line()) |
|
| 64 |
+ io.WriteString(s, strconv.Itoa(f.line())) |
|
| 70 | 65 |
case 'n': |
| 71 |
- name := runtime.FuncForPC(f.pc()).Name() |
|
| 72 |
- io.WriteString(s, funcname(name)) |
|
| 66 |
+ io.WriteString(s, funcname(f.name())) |
|
| 73 | 67 |
case 'v': |
| 74 | 68 |
f.Format(s, 's') |
| 75 | 69 |
io.WriteString(s, ":") |
| ... | ... |
@@ -77,6 +83,16 @@ func (f Frame) Format(s fmt.State, verb rune) {
|
| 77 | 77 |
} |
| 78 | 78 |
} |
| 79 | 79 |
|
| 80 |
+// MarshalText formats a stacktrace Frame as a text string. The output is the |
|
| 81 |
+// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs.
|
|
| 82 |
+func (f Frame) MarshalText() ([]byte, error) {
|
|
| 83 |
+ name := f.name() |
|
| 84 |
+ if name == "unknown" {
|
|
| 85 |
+ return []byte(name), nil |
|
| 86 |
+ } |
|
| 87 |
+ return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil
|
|
| 88 |
+} |
|
| 89 |
+ |
|
| 80 | 90 |
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). |
| 81 | 91 |
type StackTrace []Frame |
| 82 | 92 |
|
| ... | ... |
@@ -94,16 +110,30 @@ func (st StackTrace) Format(s fmt.State, verb rune) {
|
| 94 | 94 |
switch {
|
| 95 | 95 |
case s.Flag('+'):
|
| 96 | 96 |
for _, f := range st {
|
| 97 |
- fmt.Fprintf(s, "\n%+v", f) |
|
| 97 |
+ io.WriteString(s, "\n") |
|
| 98 |
+ f.Format(s, verb) |
|
| 98 | 99 |
} |
| 99 | 100 |
case s.Flag('#'):
|
| 100 | 101 |
fmt.Fprintf(s, "%#v", []Frame(st)) |
| 101 | 102 |
default: |
| 102 |
- fmt.Fprintf(s, "%v", []Frame(st)) |
|
| 103 |
+ st.formatSlice(s, verb) |
|
| 103 | 104 |
} |
| 104 | 105 |
case 's': |
| 105 |
- fmt.Fprintf(s, "%s", []Frame(st)) |
|
| 106 |
+ st.formatSlice(s, verb) |
|
| 107 |
+ } |
|
| 108 |
+} |
|
| 109 |
+ |
|
| 110 |
+// formatSlice will format this StackTrace into the given buffer as a slice of |
|
| 111 |
+// Frame, only valid when called with '%s' or '%v'. |
|
| 112 |
+func (st StackTrace) formatSlice(s fmt.State, verb rune) {
|
|
| 113 |
+ io.WriteString(s, "[") |
|
| 114 |
+ for i, f := range st {
|
|
| 115 |
+ if i > 0 {
|
|
| 116 |
+ io.WriteString(s, " ") |
|
| 117 |
+ } |
|
| 118 |
+ f.Format(s, verb) |
|
| 106 | 119 |
} |
| 120 |
+ io.WriteString(s, "]") |
|
| 107 | 121 |
} |
| 108 | 122 |
|
| 109 | 123 |
// stack represents a stack of program counters. |