github.com/catandhorse/git-lfs@v2.5.2+incompatible/errors/errors.go (about) 1 // Package errors provides common error handling tools 2 // NOTE: Subject to change, do not rely on this package from outside git-lfs source 3 package errors 4 5 // The LFS error system provides a simple wrapper around Go errors and the 6 // ability to inspect errors. It is strongly influenced by Dave Cheney's post 7 // at http://dave.cheney.net/2014/12/24/inspecting-errors. 8 // 9 // When passing errors out of lfs package functions, the return type should 10 // always be `error`. The wrappedError details are not exported. If an error is 11 // the kind of error a caller should need to investigate, an IsXError() 12 // function is provided that tells the caller if the error is of that type. 13 // There should only be a handfull of cases where a simple `error` is 14 // insufficient. 15 // 16 // The error behaviors can be nested when created. For example, the not 17 // implemented error can also be marked as a fatal error: 18 // 19 // func LfsFunction() error { 20 // err := functionCall() 21 // if err != nil { 22 // return newFatalError(newNotImplementedError(err)) 23 // } 24 // return nil 25 // } 26 // 27 // Then in the caller: 28 // 29 // err := lfs.LfsFunction() 30 // if lfs.IsNotImplementedError(err) { 31 // log.Print("feature not implemented") 32 // } 33 // if lfs.IsFatalError(err) { 34 // os.Exit(1) 35 // } 36 // 37 // Wrapped errors contain a context, which is a map[string]string. These 38 // contexts can be accessed through the Error*Context functions. Calling these 39 // functions on a regular Go error will have no effect. 40 // 41 // Example: 42 // 43 // err := lfs.SomeFunction() 44 // errors.ErrorSetContext(err, "foo", "bar") 45 // errors.ErrorGetContext(err, "foo") // => "bar" 46 // errors.ErrorDelContext(err, "foo") 47 // 48 // Wrapped errors also contain the stack from the point at which they are 49 // called. Use the '%+v' printf verb to display. See the github.com/pkg/errors 50 // docs for more info: https://godoc.org/github.com/pkg/errors 51 52 import ( 53 "bytes" 54 "fmt" 55 56 "github.com/pkg/errors" 57 ) 58 59 // New returns an error with the supplied message. New also records the stack 60 // trace at thepoint it was called. 61 func New(message string) error { 62 return errors.New(message) 63 } 64 65 // Errorf formats according to a format specifier and returns the string 66 // as a value that satisfies error. 67 // Errorf also records the stack trace at the point it was called. 68 func Errorf(format string, args ...interface{}) error { 69 return errors.Errorf(format, args...) 70 } 71 72 // Wrap wraps an error with an additional message. 73 func Wrap(err error, msg string) error { 74 return newWrappedError(err, msg) 75 } 76 77 // Wrapf wraps an error with an additional formatted message. 78 func Wrapf(err error, format string, args ...interface{}) error { 79 if err == nil { 80 err = errors.New("") 81 } 82 83 message := fmt.Sprintf(format, args...) 84 85 return newWrappedError(err, message) 86 } 87 88 func StackTrace(err error) []string { 89 type stacktrace interface { 90 StackTrace() errors.StackTrace 91 } 92 93 if err, ok := err.(stacktrace); ok { 94 frames := err.StackTrace() 95 lines := make([]string, len(frames)) 96 for i, f := range frames { 97 lines[i] = fmt.Sprintf("%+v", f) 98 } 99 return lines 100 } 101 102 return nil 103 } 104 105 func Combine(errs []error) error { 106 if len(errs) == 0 { 107 return nil 108 } 109 110 var buf bytes.Buffer 111 for i, err := range errs { 112 if i > 0 { 113 buf.WriteString("\n") 114 } 115 buf.WriteString(err.Error()) 116 } 117 return fmt.Errorf(buf.String()) 118 } 119 120 func Cause(err error) error { 121 type causer interface { 122 Cause() error 123 } 124 125 if cause, ok := err.(causer); ok { 126 return Cause(cause.Cause()) 127 } 128 return err 129 }