github.com/hawser/git-hawser@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  }