aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/go-errors/errors/error.go
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2019-11-03 20:47:29 +0100
committerMichael Muré <batolettre@gmail.com>2019-11-03 20:47:29 +0100
commitcb8236c9c22007eb622b7219c58d3342f1f53d50 (patch)
treee232e5362486065d9b28bb55b9791690efb50c08 /vendor/github.com/go-errors/errors/error.go
parent163ea9c93306c387f84ff0b85c2d8fca4c01e449 (diff)
downloadgit-bug-cb8236c9c22007eb622b7219c58d3342f1f53d50.tar.gz
termui: migrate to awesome-gocui instead of the old fork I had
Diffstat (limited to 'vendor/github.com/go-errors/errors/error.go')
-rw-r--r--vendor/github.com/go-errors/errors/error.go217
1 files changed, 217 insertions, 0 deletions
diff --git a/vendor/github.com/go-errors/errors/error.go b/vendor/github.com/go-errors/errors/error.go
new file mode 100644
index 00000000..60062a43
--- /dev/null
+++ b/vendor/github.com/go-errors/errors/error.go
@@ -0,0 +1,217 @@
+// Package errors provides errors that have stack-traces.
+//
+// This is particularly useful when you want to understand the
+// state of execution when an error was returned unexpectedly.
+//
+// It provides the type *Error which implements the standard
+// golang error interface, so you can use this library interchangably
+// with code that is expecting a normal error return.
+//
+// For example:
+//
+// package crashy
+//
+// import "github.com/go-errors/errors"
+//
+// var Crashed = errors.Errorf("oh dear")
+//
+// func Crash() error {
+// return errors.New(Crashed)
+// }
+//
+// This can be called as follows:
+//
+// package main
+//
+// import (
+// "crashy"
+// "fmt"
+// "github.com/go-errors/errors"
+// )
+//
+// func main() {
+// err := crashy.Crash()
+// if err != nil {
+// if errors.Is(err, crashy.Crashed) {
+// fmt.Println(err.(*errors.Error).ErrorStack())
+// } else {
+// panic(err)
+// }
+// }
+// }
+//
+// This package was original written to allow reporting to Bugsnag,
+// but after I found similar packages by Facebook and Dropbox, it
+// was moved to one canonical location so everyone can benefit.
+package errors
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "runtime"
+)
+
+// The maximum number of stackframes on any error.
+var MaxStackDepth = 50
+
+// Error is an error with an attached stacktrace. It can be used
+// wherever the builtin error interface is expected.
+type Error struct {
+ Err error
+ stack []uintptr
+ frames []StackFrame
+ prefix string
+}
+
+// New makes an Error from the given value. If that value is already an
+// error then it will be used directly, if not, it will be passed to
+// fmt.Errorf("%v"). The stacktrace will point to the line of code that
+// called New.
+func New(e interface{}) *Error {
+ var err error
+
+ switch e := e.(type) {
+ case error:
+ err = e
+ default:
+ err = fmt.Errorf("%v", e)
+ }
+
+ stack := make([]uintptr, MaxStackDepth)
+ length := runtime.Callers(2, stack[:])
+ return &Error{
+ Err: err,
+ stack: stack[:length],
+ }
+}
+
+// Wrap makes an Error from the given value. If that value is already an
+// error then it will be used directly, if not, it will be passed to
+// fmt.Errorf("%v"). The skip parameter indicates how far up the stack
+// to start the stacktrace. 0 is from the current call, 1 from its caller, etc.
+func Wrap(e interface{}, skip int) *Error {
+ var err error
+
+ switch e := e.(type) {
+ case *Error:
+ return e
+ case error:
+ err = e
+ default:
+ err = fmt.Errorf("%v", e)
+ }
+
+ stack := make([]uintptr, MaxStackDepth)
+ length := runtime.Callers(2+skip, stack[:])
+ return &Error{
+ Err: err,
+ stack: stack[:length],
+ }
+}
+
+// WrapPrefix makes an Error from the given value. If that value is already an
+// error then it will be used directly, if not, it will be passed to
+// fmt.Errorf("%v"). The prefix parameter is used to add a prefix to the
+// error message when calling Error(). The skip parameter indicates how far
+// up the stack to start the stacktrace. 0 is from the current call,
+// 1 from its caller, etc.
+func WrapPrefix(e interface{}, prefix string, skip int) *Error {
+
+ err := Wrap(e, 1+skip)
+
+ if err.prefix != "" {
+ prefix = fmt.Sprintf("%s: %s", prefix, err.prefix)
+ }
+
+ return &Error{
+ Err: err.Err,
+ stack: err.stack,
+ prefix: prefix,
+ }
+
+}
+
+// Is detects whether the error is equal to a given error. Errors
+// are considered equal by this function if they are the same object,
+// or if they both contain the same error inside an errors.Error.
+func Is(e error, original error) bool {
+
+ if e == original {
+ return true
+ }
+
+ if e, ok := e.(*Error); ok {
+ return Is(e.Err, original)
+ }
+
+ if original, ok := original.(*Error); ok {
+ return Is(e, original.Err)
+ }
+
+ return false
+}
+
+// Errorf creates a new error with the given message. You can use it
+// as a drop-in replacement for fmt.Errorf() to provide descriptive
+// errors in return values.
+func Errorf(format string, a ...interface{}) *Error {
+ return Wrap(fmt.Errorf(format, a...), 1)
+}
+
+// Error returns the underlying error's message.
+func (err *Error) Error() string {
+
+ msg := err.Err.Error()
+ if err.prefix != "" {
+ msg = fmt.Sprintf("%s: %s", err.prefix, msg)
+ }
+
+ return msg
+}
+
+// Stack returns the callstack formatted the same way that go does
+// in runtime/debug.Stack()
+func (err *Error) Stack() []byte {
+ buf := bytes.Buffer{}
+
+ for _, frame := range err.StackFrames() {
+ buf.WriteString(frame.String())
+ }
+
+ return buf.Bytes()
+}
+
+// Callers satisfies the bugsnag ErrorWithCallerS() interface
+// so that the stack can be read out.
+func (err *Error) Callers() []uintptr {
+ return err.stack
+}
+
+// ErrorStack returns a string that contains both the
+// error message and the callstack.
+func (err *Error) ErrorStack() string {
+ return err.TypeName() + " " + err.Error() + "\n" + string(err.Stack())
+}
+
+// StackFrames returns an array of frames containing information about the
+// stack.
+func (err *Error) StackFrames() []StackFrame {
+ if err.frames == nil {
+ err.frames = make([]StackFrame, len(err.stack))
+
+ for i, pc := range err.stack {
+ err.frames[i] = NewStackFrame(pc)
+ }
+ }
+
+ return err.frames
+}
+
+// TypeName returns the type this error. e.g. *errors.stringError.
+func (err *Error) TypeName() string {
+ if _, ok := err.Err.(uncaughtPanic); ok {
+ return "panic"
+ }
+ return reflect.TypeOf(err.Err).String()
+}