| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 
 | // Package errors is an extension of and drop in replacement for the standard
// library errors package. Multiple errors can be composed into a single error,
// and single errors can be extended with new errors or with context. You can
// also check whether any of the extensions or compositions contains a certain
// error, allowing for more flexible error handling for complex processes.
package errors
import (
	"errors"
	"os"
)
// Error satisfies the error interface, and additionally keeps track of all
// extensions and compositions that have happened to the underlying errors.
type Error struct {
	ErrSet []error
}
// Error returns the composed error string of the Error, clustering errors by
// their composition and extension.
func (r Error) Error() string {
	s := "["
	for i, err := range r.ErrSet {
		if i != 0 {
			s = s + "; "
		}
		s = s + err.Error()
	}
	return s + "]"
}
// AddContext will add a string context to an error if the error is not nil. If
// the error is nil, then nil will be returned regardless of the context.
func AddContext(err error, context string) error {
	if err == nil {
		return nil
	}
	return Extend(err, New(context))
}
// Compose will compose all errors together into a single error, remembering
// each component error so that they can be checked for matches later using the
// `Contains` function.
//
// Any `nil` input errors will be ignored. If all input errors are `nil`, then
// `nil` will be returned.
func Compose(errs ...error) error {
	var r Error
	for _, err := range errs {
		// Handle nil errors.
		if err == nil {
			continue
		}
		r.ErrSet = append(r.ErrSet, err)
	}
	if len(r.ErrSet) == 0 {
		return nil
	}
	return r
}
// Contains will check whether the base error contains the cmp error. If the
// base err is a Error, then it will check whether there is a match on any of
// the underlying errors.
func Contains(base, cmp error) bool {
	// Check for the easy edge cases.
	if cmp == nil || base == nil {
		return false
	}
	if base == cmp {
		return true
	}
	switch v := base.(type) {
	case Error:
		for _, err := range v.ErrSet {
			if Contains(err, cmp) {
				return true
			}
		}
		return false
	default:
		return false
	}
}
// Extend will extend the first error with the second error, remembering each
// component error so that they can be checked for matches later using the
// `Contains` function.
//
// Any `nil` input will be ignored. If both inputs are `nil, then `nil` will be
// returned.
func Extend(err, extension error) error {
	// Check for nil edge cases. If both are nil, nil will be returned.
	if err == nil {
		return extension
	}
	if extension == nil {
		return err
	}
	var r Error
	// Check the original error for richness.
	switch v := err.(type) {
	case Error:
		r = v
	default:
		r.ErrSet = []error{v}
	}
	// Check the extension error for richness.
	switch v := extension.(type) {
	case Error:
		r.ErrSet = append(v.ErrSet, r.ErrSet...)
	default:
		r.ErrSet = append([]error{v}, r.ErrSet...)
	}
	// Return nil if the result has no underlying errors.
	if len(r.ErrSet) == 0 {
		return nil
	}
	return r
}
// IsOSNotExist returns true if any of the errors in the underlying composition
// return true for os.IsNotExist.
func IsOSNotExist(err error) bool {
	if err == nil {
		return false
	}
	switch v := err.(type) {
	case Error:
		for _, err := range v.ErrSet {
			if IsOSNotExist(err) {
				return true
			}
		}
		return false
	default:
		return os.IsNotExist(err)
	}
}
// New is a passthrough to the stdlib errors package, allowing
// NebulousLabs/errors to be a drop in replacement for the standard library
// errors package.
func New(s string) error {
	return errors.New(s)
}
 |