more attempts
This commit is contained in:
parent
e0aca0a768
commit
869bc4b6da
191
vendor/github.com/juju/errors/LICENSE
generated
vendored
Normal file
191
vendor/github.com/juju/errors/LICENSE
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
All files in this repository are licensed as follows. If you contribute
|
||||||
|
to this repository, it is assumed that you license your contribution
|
||||||
|
under the same license unless you state otherwise.
|
||||||
|
|
||||||
|
All files Copyright (C) 2015 Canonical Ltd. unless otherwise specified in the file.
|
||||||
|
|
||||||
|
This software is licensed under the LGPLv3, included below.
|
||||||
|
|
||||||
|
As a special exception to the GNU Lesser General Public License version 3
|
||||||
|
("LGPL3"), the copyright holders of this Library give you permission to
|
||||||
|
convey to a third party a Combined Work that links statically or dynamically
|
||||||
|
to this Library without providing any Minimal Corresponding Source or
|
||||||
|
Minimal Application Code as set out in 4d or providing the installation
|
||||||
|
information set out in section 4e, provided that you comply with the other
|
||||||
|
provisions of LGPL3 and provided that you meet, for the Application the
|
||||||
|
terms and conditions of the license(s) which apply to the Application.
|
||||||
|
|
||||||
|
Except as stated in this special exception, the provisions of LGPL3 will
|
||||||
|
continue to comply in full to this Library. If you modify this Library, you
|
||||||
|
may apply this exception to your version of this Library, but you are not
|
||||||
|
obliged to do so. If you do not wish to do so, delete this exception
|
||||||
|
statement from your version. This exception does not (and cannot) modify any
|
||||||
|
license terms which apply to the Application, with which you must still
|
||||||
|
comply.
|
||||||
|
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
11
vendor/github.com/juju/errors/Makefile
generated
vendored
Normal file
11
vendor/github.com/juju/errors/Makefile
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
default: check
|
||||||
|
|
||||||
|
check:
|
||||||
|
go test && go test -compiler gccgo
|
||||||
|
|
||||||
|
docs:
|
||||||
|
godoc2md github.com/juju/errors > README.md
|
||||||
|
sed -i 's|\[godoc-link-here\]|[![GoDoc](https://godoc.org/github.com/juju/errors?status.svg)](https://godoc.org/github.com/juju/errors)|' README.md
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: default check docs
|
536
vendor/github.com/juju/errors/README.md
generated
vendored
Normal file
536
vendor/github.com/juju/errors/README.md
generated
vendored
Normal file
@ -0,0 +1,536 @@
|
|||||||
|
|
||||||
|
# errors
|
||||||
|
import "github.com/juju/errors"
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/juju/errors?status.svg)](https://godoc.org/github.com/juju/errors)
|
||||||
|
|
||||||
|
The juju/errors provides an easy way to annotate errors without losing the
|
||||||
|
orginal error context.
|
||||||
|
|
||||||
|
The exported `New` and `Errorf` functions are designed to replace the
|
||||||
|
`errors.New` and `fmt.Errorf` functions respectively. The same underlying
|
||||||
|
error is there, but the package also records the location at which the error
|
||||||
|
was created.
|
||||||
|
|
||||||
|
A primary use case for this library is to add extra context any time an
|
||||||
|
error is returned from a function.
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
This instead becomes:
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Trace(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
which just records the file and line number of the Trace call, or
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Annotate(err, "more context")
|
||||||
|
}
|
||||||
|
|
||||||
|
which also adds an annotation to the error.
|
||||||
|
|
||||||
|
When you want to check to see if an error is of a particular type, a helper
|
||||||
|
function is normally exported by the package that returned the error, like the
|
||||||
|
`os` package does. The underlying cause of the error is available using the
|
||||||
|
`Cause` function.
|
||||||
|
|
||||||
|
|
||||||
|
os.IsNotExist(errors.Cause(err))
|
||||||
|
|
||||||
|
The result of the `Error()` call on an annotated error is the annotations joined
|
||||||
|
with colons, then the result of the `Error()` method for the underlying error
|
||||||
|
that was the cause.
|
||||||
|
|
||||||
|
|
||||||
|
err := errors.Errorf("original")
|
||||||
|
err = errors.Annotatef(err, "context")
|
||||||
|
err = errors.Annotatef(err, "more context")
|
||||||
|
err.Error() -> "more context: context: original"
|
||||||
|
|
||||||
|
Obviously recording the file, line and functions is not very useful if you
|
||||||
|
cannot get them back out again.
|
||||||
|
|
||||||
|
|
||||||
|
errors.ErrorStack(err)
|
||||||
|
|
||||||
|
will return something like:
|
||||||
|
|
||||||
|
|
||||||
|
first error
|
||||||
|
github.com/juju/errors/annotation_test.go:193:
|
||||||
|
github.com/juju/errors/annotation_test.go:194: annotation
|
||||||
|
github.com/juju/errors/annotation_test.go:195:
|
||||||
|
github.com/juju/errors/annotation_test.go:196: more context
|
||||||
|
github.com/juju/errors/annotation_test.go:197:
|
||||||
|
|
||||||
|
The first error was generated by an external system, so there was no location
|
||||||
|
associated. The second, fourth, and last lines were generated with Trace calls,
|
||||||
|
and the other two through Annotate.
|
||||||
|
|
||||||
|
Sometimes when responding to an error you want to return a more specific error
|
||||||
|
for the situation.
|
||||||
|
|
||||||
|
|
||||||
|
if err := FindField(field); err != nil {
|
||||||
|
return errors.Wrap(err, errors.NotFoundf(field))
|
||||||
|
}
|
||||||
|
|
||||||
|
This returns an error where the complete error stack is still available, and
|
||||||
|
`errors.Cause()` will return the `NotFound` error.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## func AlreadyExistsf
|
||||||
|
``` go
|
||||||
|
func AlreadyExistsf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
AlreadyExistsf returns an error which satisfies IsAlreadyExists().
|
||||||
|
|
||||||
|
|
||||||
|
## func Annotate
|
||||||
|
``` go
|
||||||
|
func Annotate(other error, message string) error
|
||||||
|
```
|
||||||
|
Annotate is used to add extra context to an existing error. The location of
|
||||||
|
the Annotate call is recorded with the annotations. The file, line and
|
||||||
|
function are also recorded.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Annotate(err, "failed to frombulate")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
## func Annotatef
|
||||||
|
``` go
|
||||||
|
func Annotatef(other error, format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
Annotatef is used to add extra context to an existing error. The location of
|
||||||
|
the Annotate call is recorded with the annotations. The file, line and
|
||||||
|
function are also recorded.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Annotatef(err, "failed to frombulate the %s", arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
## func Cause
|
||||||
|
``` go
|
||||||
|
func Cause(err error) error
|
||||||
|
```
|
||||||
|
Cause returns the cause of the given error. This will be either the
|
||||||
|
original error, or the result of a Wrap or Mask call.
|
||||||
|
|
||||||
|
Cause is the usual way to diagnose errors that may have been wrapped by
|
||||||
|
the other errors functions.
|
||||||
|
|
||||||
|
|
||||||
|
## func DeferredAnnotatef
|
||||||
|
``` go
|
||||||
|
func DeferredAnnotatef(err *error, format string, args ...interface{})
|
||||||
|
```
|
||||||
|
DeferredAnnotatef annotates the given error (when it is not nil) with the given
|
||||||
|
format string and arguments (like fmt.Sprintf). If *err is nil, DeferredAnnotatef
|
||||||
|
does nothing. This method is used in a defer statement in order to annotate any
|
||||||
|
resulting error with the same message.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
defer DeferredAnnotatef(&err, "failed to frombulate the %s", arg)
|
||||||
|
|
||||||
|
|
||||||
|
## func Details
|
||||||
|
``` go
|
||||||
|
func Details(err error) string
|
||||||
|
```
|
||||||
|
Details returns information about the stack of errors wrapped by err, in
|
||||||
|
the format:
|
||||||
|
|
||||||
|
|
||||||
|
[{filename:99: error one} {otherfile:55: cause of error one}]
|
||||||
|
|
||||||
|
This is a terse alternative to ErrorStack as it returns a single line.
|
||||||
|
|
||||||
|
|
||||||
|
## func ErrorStack
|
||||||
|
``` go
|
||||||
|
func ErrorStack(err error) string
|
||||||
|
```
|
||||||
|
ErrorStack returns a string representation of the annotated error. If the
|
||||||
|
error passed as the parameter is not an annotated error, the result is
|
||||||
|
simply the result of the Error() method on that error.
|
||||||
|
|
||||||
|
If the error is an annotated error, a multi-line string is returned where
|
||||||
|
each line represents one entry in the annotation stack. The full filename
|
||||||
|
from the call stack is used in the output.
|
||||||
|
|
||||||
|
|
||||||
|
first error
|
||||||
|
github.com/juju/errors/annotation_test.go:193:
|
||||||
|
github.com/juju/errors/annotation_test.go:194: annotation
|
||||||
|
github.com/juju/errors/annotation_test.go:195:
|
||||||
|
github.com/juju/errors/annotation_test.go:196: more context
|
||||||
|
github.com/juju/errors/annotation_test.go:197:
|
||||||
|
|
||||||
|
|
||||||
|
## func Errorf
|
||||||
|
``` go
|
||||||
|
func Errorf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
Errorf creates a new annotated error and records the location that the
|
||||||
|
error is created. This should be a drop in replacement for fmt.Errorf.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
return errors.Errorf("validation failed: %s", message)
|
||||||
|
|
||||||
|
|
||||||
|
## func IsAlreadyExists
|
||||||
|
``` go
|
||||||
|
func IsAlreadyExists(err error) bool
|
||||||
|
```
|
||||||
|
IsAlreadyExists reports whether the error was created with
|
||||||
|
AlreadyExistsf() or NewAlreadyExists().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsNotFound
|
||||||
|
``` go
|
||||||
|
func IsNotFound(err error) bool
|
||||||
|
```
|
||||||
|
IsNotFound reports whether err was created with NotFoundf() or
|
||||||
|
NewNotFound().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsNotImplemented
|
||||||
|
``` go
|
||||||
|
func IsNotImplemented(err error) bool
|
||||||
|
```
|
||||||
|
IsNotImplemented reports whether err was created with
|
||||||
|
NotImplementedf() or NewNotImplemented().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsNotSupported
|
||||||
|
``` go
|
||||||
|
func IsNotSupported(err error) bool
|
||||||
|
```
|
||||||
|
IsNotSupported reports whether the error was created with
|
||||||
|
NotSupportedf() or NewNotSupported().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsNotValid
|
||||||
|
``` go
|
||||||
|
func IsNotValid(err error) bool
|
||||||
|
```
|
||||||
|
IsNotValid reports whether the error was created with NotValidf() or
|
||||||
|
NewNotValid().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsUnauthorized
|
||||||
|
``` go
|
||||||
|
func IsUnauthorized(err error) bool
|
||||||
|
```
|
||||||
|
IsUnauthorized reports whether err was created with Unauthorizedf() or
|
||||||
|
NewUnauthorized().
|
||||||
|
|
||||||
|
|
||||||
|
## func Mask
|
||||||
|
``` go
|
||||||
|
func Mask(other error) error
|
||||||
|
```
|
||||||
|
Mask hides the underlying error type, and records the location of the masking.
|
||||||
|
|
||||||
|
|
||||||
|
## func Maskf
|
||||||
|
``` go
|
||||||
|
func Maskf(other error, format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
Mask masks the given error with the given format string and arguments (like
|
||||||
|
fmt.Sprintf), returning a new error that maintains the error stack, but
|
||||||
|
hides the underlying error type. The error string still contains the full
|
||||||
|
annotations. If you want to hide the annotations, call Wrap.
|
||||||
|
|
||||||
|
|
||||||
|
## func New
|
||||||
|
``` go
|
||||||
|
func New(message string) error
|
||||||
|
```
|
||||||
|
New is a drop in replacement for the standard libary errors module that records
|
||||||
|
the location that the error is created.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
return errors.New("validation failed")
|
||||||
|
|
||||||
|
|
||||||
|
## func NewAlreadyExists
|
||||||
|
``` go
|
||||||
|
func NewAlreadyExists(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewAlreadyExists returns an error which wraps err and satisfies
|
||||||
|
IsAlreadyExists().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewNotFound
|
||||||
|
``` go
|
||||||
|
func NewNotFound(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewNotFound returns an error which wraps err that satisfies
|
||||||
|
IsNotFound().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewNotImplemented
|
||||||
|
``` go
|
||||||
|
func NewNotImplemented(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewNotImplemented returns an error which wraps err and satisfies
|
||||||
|
IsNotImplemented().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewNotSupported
|
||||||
|
``` go
|
||||||
|
func NewNotSupported(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewNotSupported returns an error which wraps err and satisfies
|
||||||
|
IsNotSupported().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewNotValid
|
||||||
|
``` go
|
||||||
|
func NewNotValid(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewNotValid returns an error which wraps err and satisfies IsNotValid().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewUnauthorized
|
||||||
|
``` go
|
||||||
|
func NewUnauthorized(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewUnauthorized returns an error which wraps err and satisfies
|
||||||
|
IsUnauthorized().
|
||||||
|
|
||||||
|
|
||||||
|
## func NotFoundf
|
||||||
|
``` go
|
||||||
|
func NotFoundf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
NotFoundf returns an error which satisfies IsNotFound().
|
||||||
|
|
||||||
|
|
||||||
|
## func NotImplementedf
|
||||||
|
``` go
|
||||||
|
func NotImplementedf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
NotImplementedf returns an error which satisfies IsNotImplemented().
|
||||||
|
|
||||||
|
|
||||||
|
## func NotSupportedf
|
||||||
|
``` go
|
||||||
|
func NotSupportedf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
NotSupportedf returns an error which satisfies IsNotSupported().
|
||||||
|
|
||||||
|
|
||||||
|
## func NotValidf
|
||||||
|
``` go
|
||||||
|
func NotValidf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
NotValidf returns an error which satisfies IsNotValid().
|
||||||
|
|
||||||
|
|
||||||
|
## func Trace
|
||||||
|
``` go
|
||||||
|
func Trace(other error) error
|
||||||
|
```
|
||||||
|
Trace adds the location of the Trace call to the stack. The Cause of the
|
||||||
|
resulting error is the same as the error parameter. If the other error is
|
||||||
|
nil, the result will be nil.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Trace(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
## func Unauthorizedf
|
||||||
|
``` go
|
||||||
|
func Unauthorizedf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
Unauthorizedf returns an error which satisfies IsUnauthorized().
|
||||||
|
|
||||||
|
|
||||||
|
## func Wrap
|
||||||
|
``` go
|
||||||
|
func Wrap(other, newDescriptive error) error
|
||||||
|
```
|
||||||
|
Wrap changes the Cause of the error. The location of the Wrap call is also
|
||||||
|
stored in the error stack.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
newErr := &packageError{"more context", private_value}
|
||||||
|
return errors.Wrap(err, newErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
## func Wrapf
|
||||||
|
``` go
|
||||||
|
func Wrapf(other, newDescriptive error, format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
Wrapf changes the Cause of the error, and adds an annotation. The location
|
||||||
|
of the Wrap call is also stored in the error stack.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Wrapf(err, simpleErrorType, "invalid value %q", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## type Err
|
||||||
|
``` go
|
||||||
|
type Err struct {
|
||||||
|
// contains filtered or unexported fields
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Err holds a description of an error along with information about
|
||||||
|
where the error was created.
|
||||||
|
|
||||||
|
It may be embedded in custom error types to add extra information that
|
||||||
|
this errors package can understand.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func NewErr
|
||||||
|
``` go
|
||||||
|
func NewErr(format string, args ...interface{}) Err
|
||||||
|
```
|
||||||
|
NewErr is used to return an Err for the purpose of embedding in other
|
||||||
|
structures. The location is not specified, and needs to be set with a call
|
||||||
|
to SetLocation.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
type FooError struct {
|
||||||
|
errors.Err
|
||||||
|
code int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFooError(code int) error {
|
||||||
|
err := &FooError{errors.NewErr("foo"), code}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) Cause
|
||||||
|
``` go
|
||||||
|
func (e *Err) Cause() error
|
||||||
|
```
|
||||||
|
The Cause of an error is the most recent error in the error stack that
|
||||||
|
meets one of these criteria: the original error that was raised; the new
|
||||||
|
error that was passed into the Wrap function; the most recently masked
|
||||||
|
error; or nil if the error itself is considered the Cause. Normally this
|
||||||
|
method is not invoked directly, but instead through the Cause stand alone
|
||||||
|
function.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) Error
|
||||||
|
``` go
|
||||||
|
func (e *Err) Error() string
|
||||||
|
```
|
||||||
|
Error implements error.Error.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) Location
|
||||||
|
``` go
|
||||||
|
func (e *Err) Location() (filename string, line int)
|
||||||
|
```
|
||||||
|
Location is the file and line of where the error was most recently
|
||||||
|
created or annotated.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) Message
|
||||||
|
``` go
|
||||||
|
func (e *Err) Message() string
|
||||||
|
```
|
||||||
|
Message returns the message stored with the most recent location. This is
|
||||||
|
the empty string if the most recent call was Trace, or the message stored
|
||||||
|
with Annotate or Mask.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) SetLocation
|
||||||
|
``` go
|
||||||
|
func (e *Err) SetLocation(callDepth int)
|
||||||
|
```
|
||||||
|
SetLocation records the source location of the error at callDepth stack
|
||||||
|
frames above the call.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) StackTrace
|
||||||
|
``` go
|
||||||
|
func (e *Err) StackTrace() []string
|
||||||
|
```
|
||||||
|
StackTrace returns one string for each location recorded in the stack of
|
||||||
|
errors. The first value is the originating error, with a line for each
|
||||||
|
other annotation or tracing of the error.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) Underlying
|
||||||
|
``` go
|
||||||
|
func (e *Err) Underlying() error
|
||||||
|
```
|
||||||
|
Underlying returns the previous error in the error stack, if any. A client
|
||||||
|
should not ever really call this method. It is used to build the error
|
||||||
|
stack and should not be introspected by client calls. Or more
|
||||||
|
specifically, clients should not depend on anything but the `Cause` of an
|
||||||
|
error.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- - -
|
||||||
|
Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
|
81
vendor/github.com/juju/errors/doc.go
generated
vendored
Normal file
81
vendor/github.com/juju/errors/doc.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// Copyright 2013, 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
/*
|
||||||
|
[godoc-link-here]
|
||||||
|
|
||||||
|
The juju/errors provides an easy way to annotate errors without losing the
|
||||||
|
orginal error context.
|
||||||
|
|
||||||
|
The exported `New` and `Errorf` functions are designed to replace the
|
||||||
|
`errors.New` and `fmt.Errorf` functions respectively. The same underlying
|
||||||
|
error is there, but the package also records the location at which the error
|
||||||
|
was created.
|
||||||
|
|
||||||
|
A primary use case for this library is to add extra context any time an
|
||||||
|
error is returned from a function.
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
This instead becomes:
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Trace(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
which just records the file and line number of the Trace call, or
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Annotate(err, "more context")
|
||||||
|
}
|
||||||
|
|
||||||
|
which also adds an annotation to the error.
|
||||||
|
|
||||||
|
When you want to check to see if an error is of a particular type, a helper
|
||||||
|
function is normally exported by the package that returned the error, like the
|
||||||
|
`os` package does. The underlying cause of the error is available using the
|
||||||
|
`Cause` function.
|
||||||
|
|
||||||
|
os.IsNotExist(errors.Cause(err))
|
||||||
|
|
||||||
|
The result of the `Error()` call on an annotated error is the annotations joined
|
||||||
|
with colons, then the result of the `Error()` method for the underlying error
|
||||||
|
that was the cause.
|
||||||
|
|
||||||
|
err := errors.Errorf("original")
|
||||||
|
err = errors.Annotatef(err, "context")
|
||||||
|
err = errors.Annotatef(err, "more context")
|
||||||
|
err.Error() -> "more context: context: original"
|
||||||
|
|
||||||
|
Obviously recording the file, line and functions is not very useful if you
|
||||||
|
cannot get them back out again.
|
||||||
|
|
||||||
|
errors.ErrorStack(err)
|
||||||
|
|
||||||
|
will return something like:
|
||||||
|
|
||||||
|
first error
|
||||||
|
github.com/juju/errors/annotation_test.go:193:
|
||||||
|
github.com/juju/errors/annotation_test.go:194: annotation
|
||||||
|
github.com/juju/errors/annotation_test.go:195:
|
||||||
|
github.com/juju/errors/annotation_test.go:196: more context
|
||||||
|
github.com/juju/errors/annotation_test.go:197:
|
||||||
|
|
||||||
|
The first error was generated by an external system, so there was no location
|
||||||
|
associated. The second, fourth, and last lines were generated with Trace calls,
|
||||||
|
and the other two through Annotate.
|
||||||
|
|
||||||
|
Sometimes when responding to an error you want to return a more specific error
|
||||||
|
for the situation.
|
||||||
|
|
||||||
|
if err := FindField(field); err != nil {
|
||||||
|
return errors.Wrap(err, errors.NotFoundf(field))
|
||||||
|
}
|
||||||
|
|
||||||
|
This returns an error where the complete error stack is still available, and
|
||||||
|
`errors.Cause()` will return the `NotFound` error.
|
||||||
|
|
||||||
|
*/
|
||||||
|
package errors
|
122
vendor/github.com/juju/errors/error.go
generated
vendored
Normal file
122
vendor/github.com/juju/errors/error.go
generated
vendored
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
// Copyright 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Err holds a description of an error along with information about
|
||||||
|
// where the error was created.
|
||||||
|
//
|
||||||
|
// It may be embedded in custom error types to add extra information that
|
||||||
|
// this errors package can understand.
|
||||||
|
type Err struct {
|
||||||
|
// message holds an annotation of the error.
|
||||||
|
message string
|
||||||
|
|
||||||
|
// cause holds the cause of the error as returned
|
||||||
|
// by the Cause method.
|
||||||
|
cause error
|
||||||
|
|
||||||
|
// previous holds the previous error in the error stack, if any.
|
||||||
|
previous error
|
||||||
|
|
||||||
|
// file and line hold the source code location where the error was
|
||||||
|
// created.
|
||||||
|
file string
|
||||||
|
line int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewErr is used to return an Err for the purpose of embedding in other
|
||||||
|
// structures. The location is not specified, and needs to be set with a call
|
||||||
|
// to SetLocation.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// type FooError struct {
|
||||||
|
// errors.Err
|
||||||
|
// code int
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func NewFooError(code int) error {
|
||||||
|
// err := &FooError{errors.NewErr("foo"), code}
|
||||||
|
// err.SetLocation(1)
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
func NewErr(format string, args ...interface{}) Err {
|
||||||
|
return Err{
|
||||||
|
message: fmt.Sprintf(format, args...),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Location is the file and line of where the error was most recently
|
||||||
|
// created or annotated.
|
||||||
|
func (e *Err) Location() (filename string, line int) {
|
||||||
|
return e.file, e.line
|
||||||
|
}
|
||||||
|
|
||||||
|
// Underlying returns the previous error in the error stack, if any. A client
|
||||||
|
// should not ever really call this method. It is used to build the error
|
||||||
|
// stack and should not be introspected by client calls. Or more
|
||||||
|
// specifically, clients should not depend on anything but the `Cause` of an
|
||||||
|
// error.
|
||||||
|
func (e *Err) Underlying() error {
|
||||||
|
return e.previous
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Cause of an error is the most recent error in the error stack that
|
||||||
|
// meets one of these criteria: the original error that was raised; the new
|
||||||
|
// error that was passed into the Wrap function; the most recently masked
|
||||||
|
// error; or nil if the error itself is considered the Cause. Normally this
|
||||||
|
// method is not invoked directly, but instead through the Cause stand alone
|
||||||
|
// function.
|
||||||
|
func (e *Err) Cause() error {
|
||||||
|
return e.cause
|
||||||
|
}
|
||||||
|
|
||||||
|
// Message returns the message stored with the most recent location. This is
|
||||||
|
// the empty string if the most recent call was Trace, or the message stored
|
||||||
|
// with Annotate or Mask.
|
||||||
|
func (e *Err) Message() string {
|
||||||
|
return e.message
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements error.Error.
|
||||||
|
func (e *Err) Error() string {
|
||||||
|
// We want to walk up the stack of errors showing the annotations
|
||||||
|
// as long as the cause is the same.
|
||||||
|
err := e.previous
|
||||||
|
if !sameError(Cause(err), e.cause) && e.cause != nil {
|
||||||
|
err = e.cause
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case err == nil:
|
||||||
|
return e.message
|
||||||
|
case e.message == "":
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s: %v", e.message, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLocation records the source location of the error at callDepth stack
|
||||||
|
// frames above the call.
|
||||||
|
func (e *Err) SetLocation(callDepth int) {
|
||||||
|
_, file, line, _ := runtime.Caller(callDepth + 1)
|
||||||
|
e.file = trimGoPath(file)
|
||||||
|
e.line = line
|
||||||
|
}
|
||||||
|
|
||||||
|
// StackTrace returns one string for each location recorded in the stack of
|
||||||
|
// errors. The first value is the originating error, with a line for each
|
||||||
|
// other annotation or tracing of the error.
|
||||||
|
func (e *Err) StackTrace() []string {
|
||||||
|
return errorStack(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ideally we'd have a way to check identity, but deep equals will do.
|
||||||
|
func sameError(e1, e2 error) bool {
|
||||||
|
return reflect.DeepEqual(e1, e2)
|
||||||
|
}
|
161
vendor/github.com/juju/errors/error_test.go
generated
vendored
Normal file
161
vendor/github.com/juju/errors/error_test.go
generated
vendored
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
// Copyright 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package errors_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
jc "github.com/juju/testing/checkers"
|
||||||
|
gc "gopkg.in/check.v1"
|
||||||
|
|
||||||
|
"github.com/juju/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type errorsSuite struct{}
|
||||||
|
|
||||||
|
var _ = gc.Suite(&errorsSuite{})
|
||||||
|
|
||||||
|
var someErr = errors.New("some error") //err varSomeErr
|
||||||
|
|
||||||
|
func (*errorsSuite) TestErrorString(c *gc.C) {
|
||||||
|
for i, test := range []struct {
|
||||||
|
message string
|
||||||
|
generator func() error
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
message: "uncomparable errors",
|
||||||
|
generator: func() error {
|
||||||
|
err := errors.Annotatef(newNonComparableError("uncomparable"), "annotation")
|
||||||
|
return errors.Annotatef(err, "another")
|
||||||
|
},
|
||||||
|
expected: "another: annotation: uncomparable",
|
||||||
|
}, {
|
||||||
|
message: "Errorf",
|
||||||
|
generator: func() error {
|
||||||
|
return errors.Errorf("first error")
|
||||||
|
},
|
||||||
|
expected: "first error",
|
||||||
|
}, {
|
||||||
|
message: "annotated error",
|
||||||
|
generator: func() error {
|
||||||
|
err := errors.Errorf("first error")
|
||||||
|
return errors.Annotatef(err, "annotation")
|
||||||
|
},
|
||||||
|
expected: "annotation: first error",
|
||||||
|
}, {
|
||||||
|
message: "test annotation format",
|
||||||
|
generator: func() error {
|
||||||
|
err := errors.Errorf("first %s", "error")
|
||||||
|
return errors.Annotatef(err, "%s", "annotation")
|
||||||
|
},
|
||||||
|
expected: "annotation: first error",
|
||||||
|
}, {
|
||||||
|
message: "wrapped error",
|
||||||
|
generator: func() error {
|
||||||
|
err := newError("first error")
|
||||||
|
return errors.Wrap(err, newError("detailed error"))
|
||||||
|
},
|
||||||
|
expected: "detailed error",
|
||||||
|
}, {
|
||||||
|
message: "wrapped annotated error",
|
||||||
|
generator: func() error {
|
||||||
|
err := errors.Errorf("first error")
|
||||||
|
err = errors.Annotatef(err, "annotated")
|
||||||
|
return errors.Wrap(err, fmt.Errorf("detailed error"))
|
||||||
|
},
|
||||||
|
expected: "detailed error",
|
||||||
|
}, {
|
||||||
|
message: "annotated wrapped error",
|
||||||
|
generator: func() error {
|
||||||
|
err := errors.Errorf("first error")
|
||||||
|
err = errors.Wrap(err, fmt.Errorf("detailed error"))
|
||||||
|
return errors.Annotatef(err, "annotated")
|
||||||
|
},
|
||||||
|
expected: "annotated: detailed error",
|
||||||
|
}, {
|
||||||
|
message: "traced, and annotated",
|
||||||
|
generator: func() error {
|
||||||
|
err := errors.New("first error")
|
||||||
|
err = errors.Trace(err)
|
||||||
|
err = errors.Annotate(err, "some context")
|
||||||
|
err = errors.Trace(err)
|
||||||
|
err = errors.Annotate(err, "more context")
|
||||||
|
return errors.Trace(err)
|
||||||
|
},
|
||||||
|
expected: "more context: some context: first error",
|
||||||
|
}, {
|
||||||
|
message: "traced, and annotated, masked and annotated",
|
||||||
|
generator: func() error {
|
||||||
|
err := errors.New("first error")
|
||||||
|
err = errors.Trace(err)
|
||||||
|
err = errors.Annotate(err, "some context")
|
||||||
|
err = errors.Maskf(err, "masked")
|
||||||
|
err = errors.Annotate(err, "more context")
|
||||||
|
return errors.Trace(err)
|
||||||
|
},
|
||||||
|
expected: "more context: masked: some context: first error",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
c.Logf("%v: %s", i, test.message)
|
||||||
|
err := test.generator()
|
||||||
|
ok := c.Check(err.Error(), gc.Equals, test.expected)
|
||||||
|
if !ok {
|
||||||
|
c.Logf("%#v", test.generator())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type embed struct {
|
||||||
|
errors.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
func newEmbed(format string, args ...interface{}) *embed {
|
||||||
|
err := &embed{errors.NewErr(format, args...)}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*errorsSuite) TestNewErr(c *gc.C) {
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
c.Skip("gccgo can't determine the location")
|
||||||
|
}
|
||||||
|
err := newEmbed("testing %d", 42) //err embedErr
|
||||||
|
c.Assert(err.Error(), gc.Equals, "testing 42")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, err)
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["embedErr"].String())
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ error = (*embed)(nil)
|
||||||
|
|
||||||
|
// This is an uncomparable error type, as it is a struct that supports the
|
||||||
|
// error interface (as opposed to a pointer type).
|
||||||
|
type error_ struct {
|
||||||
|
info string
|
||||||
|
slice []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a non-comparable error
|
||||||
|
func newNonComparableError(message string) error {
|
||||||
|
return error_{info: message}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e error_) Error() string {
|
||||||
|
return e.info
|
||||||
|
}
|
||||||
|
|
||||||
|
func newError(message string) error {
|
||||||
|
return testError{message}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The testError is a value type error for ease of seeing results
|
||||||
|
// when the test fails.
|
||||||
|
type testError struct {
|
||||||
|
message string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e testError) Error() string {
|
||||||
|
return e.message
|
||||||
|
}
|
284
vendor/github.com/juju/errors/errortypes.go
generated
vendored
Normal file
284
vendor/github.com/juju/errors/errortypes.go
generated
vendored
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
// Copyright 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// wrap is a helper to construct an *wrapper.
|
||||||
|
func wrap(err error, format, suffix string, args ...interface{}) Err {
|
||||||
|
newErr := Err{
|
||||||
|
message: fmt.Sprintf(format+suffix, args...),
|
||||||
|
previous: err,
|
||||||
|
}
|
||||||
|
newErr.SetLocation(2)
|
||||||
|
return newErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// notFound represents an error when something has not been found.
|
||||||
|
type notFound struct {
|
||||||
|
Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotFoundf returns an error which satisfies IsNotFound().
|
||||||
|
func NotFoundf(format string, args ...interface{}) error {
|
||||||
|
return ¬Found{wrap(nil, format, " not found", args...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotFound returns an error which wraps err that satisfies
|
||||||
|
// IsNotFound().
|
||||||
|
func NewNotFound(err error, msg string) error {
|
||||||
|
return ¬Found{wrap(err, msg, "")}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNotFound reports whether err was created with NotFoundf() or
|
||||||
|
// NewNotFound().
|
||||||
|
func IsNotFound(err error) bool {
|
||||||
|
err = Cause(err)
|
||||||
|
_, ok := err.(*notFound)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// userNotFound represents an error when an inexistent user is looked up.
|
||||||
|
type userNotFound struct {
|
||||||
|
Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserNotFoundf returns an error which satisfies IsUserNotFound().
|
||||||
|
func UserNotFoundf(format string, args ...interface{}) error {
|
||||||
|
return &userNotFound{wrap(nil, format, " user not found", args...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewUserNotFound returns an error which wraps err and satisfies
|
||||||
|
// IsUserNotFound().
|
||||||
|
func NewUserNotFound(err error, msg string) error {
|
||||||
|
return &userNotFound{wrap(err, msg, "")}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUserNotFound reports whether err was created with UserNotFoundf() or
|
||||||
|
// NewUserNotFound().
|
||||||
|
func IsUserNotFound(err error) bool {
|
||||||
|
err = Cause(err)
|
||||||
|
_, ok := err.(*userNotFound)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// unauthorized represents an error when an operation is unauthorized.
|
||||||
|
type unauthorized struct {
|
||||||
|
Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unauthorizedf returns an error which satisfies IsUnauthorized().
|
||||||
|
func Unauthorizedf(format string, args ...interface{}) error {
|
||||||
|
return &unauthorized{wrap(nil, format, "", args...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewUnauthorized returns an error which wraps err and satisfies
|
||||||
|
// IsUnauthorized().
|
||||||
|
func NewUnauthorized(err error, msg string) error {
|
||||||
|
return &unauthorized{wrap(err, msg, "")}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsUnauthorized reports whether err was created with Unauthorizedf() or
|
||||||
|
// NewUnauthorized().
|
||||||
|
func IsUnauthorized(err error) bool {
|
||||||
|
err = Cause(err)
|
||||||
|
_, ok := err.(*unauthorized)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// notImplemented represents an error when something is not
|
||||||
|
// implemented.
|
||||||
|
type notImplemented struct {
|
||||||
|
Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotImplementedf returns an error which satisfies IsNotImplemented().
|
||||||
|
func NotImplementedf(format string, args ...interface{}) error {
|
||||||
|
return ¬Implemented{wrap(nil, format, " not implemented", args...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotImplemented returns an error which wraps err and satisfies
|
||||||
|
// IsNotImplemented().
|
||||||
|
func NewNotImplemented(err error, msg string) error {
|
||||||
|
return ¬Implemented{wrap(err, msg, "")}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNotImplemented reports whether err was created with
|
||||||
|
// NotImplementedf() or NewNotImplemented().
|
||||||
|
func IsNotImplemented(err error) bool {
|
||||||
|
err = Cause(err)
|
||||||
|
_, ok := err.(*notImplemented)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// alreadyExists represents and error when something already exists.
|
||||||
|
type alreadyExists struct {
|
||||||
|
Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AlreadyExistsf returns an error which satisfies IsAlreadyExists().
|
||||||
|
func AlreadyExistsf(format string, args ...interface{}) error {
|
||||||
|
return &alreadyExists{wrap(nil, format, " already exists", args...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAlreadyExists returns an error which wraps err and satisfies
|
||||||
|
// IsAlreadyExists().
|
||||||
|
func NewAlreadyExists(err error, msg string) error {
|
||||||
|
return &alreadyExists{wrap(err, msg, "")}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAlreadyExists reports whether the error was created with
|
||||||
|
// AlreadyExistsf() or NewAlreadyExists().
|
||||||
|
func IsAlreadyExists(err error) bool {
|
||||||
|
err = Cause(err)
|
||||||
|
_, ok := err.(*alreadyExists)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// notSupported represents an error when something is not supported.
|
||||||
|
type notSupported struct {
|
||||||
|
Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotSupportedf returns an error which satisfies IsNotSupported().
|
||||||
|
func NotSupportedf(format string, args ...interface{}) error {
|
||||||
|
return ¬Supported{wrap(nil, format, " not supported", args...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotSupported returns an error which wraps err and satisfies
|
||||||
|
// IsNotSupported().
|
||||||
|
func NewNotSupported(err error, msg string) error {
|
||||||
|
return ¬Supported{wrap(err, msg, "")}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNotSupported reports whether the error was created with
|
||||||
|
// NotSupportedf() or NewNotSupported().
|
||||||
|
func IsNotSupported(err error) bool {
|
||||||
|
err = Cause(err)
|
||||||
|
_, ok := err.(*notSupported)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// notValid represents an error when something is not valid.
|
||||||
|
type notValid struct {
|
||||||
|
Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotValidf returns an error which satisfies IsNotValid().
|
||||||
|
func NotValidf(format string, args ...interface{}) error {
|
||||||
|
return ¬Valid{wrap(nil, format, " not valid", args...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotValid returns an error which wraps err and satisfies IsNotValid().
|
||||||
|
func NewNotValid(err error, msg string) error {
|
||||||
|
return ¬Valid{wrap(err, msg, "")}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNotValid reports whether the error was created with NotValidf() or
|
||||||
|
// NewNotValid().
|
||||||
|
func IsNotValid(err error) bool {
|
||||||
|
err = Cause(err)
|
||||||
|
_, ok := err.(*notValid)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// notProvisioned represents an error when something is not yet provisioned.
|
||||||
|
type notProvisioned struct {
|
||||||
|
Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotProvisionedf returns an error which satisfies IsNotProvisioned().
|
||||||
|
func NotProvisionedf(format string, args ...interface{}) error {
|
||||||
|
return ¬Provisioned{wrap(nil, format, " not provisioned", args...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotProvisioned returns an error which wraps err that satisfies
|
||||||
|
// IsNotProvisioned().
|
||||||
|
func NewNotProvisioned(err error, msg string) error {
|
||||||
|
return ¬Provisioned{wrap(err, msg, "")}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNotProvisioned reports whether err was created with NotProvisionedf() or
|
||||||
|
// NewNotProvisioned().
|
||||||
|
func IsNotProvisioned(err error) bool {
|
||||||
|
err = Cause(err)
|
||||||
|
_, ok := err.(*notProvisioned)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// notAssigned represents an error when something is not yet assigned to
|
||||||
|
// something else.
|
||||||
|
type notAssigned struct {
|
||||||
|
Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotAssignedf returns an error which satisfies IsNotAssigned().
|
||||||
|
func NotAssignedf(format string, args ...interface{}) error {
|
||||||
|
return ¬Assigned{wrap(nil, format, " not assigned", args...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotAssigned returns an error which wraps err that satisfies
|
||||||
|
// IsNotAssigned().
|
||||||
|
func NewNotAssigned(err error, msg string) error {
|
||||||
|
return ¬Assigned{wrap(err, msg, "")}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNotAssigned reports whether err was created with NotAssignedf() or
|
||||||
|
// NewNotAssigned().
|
||||||
|
func IsNotAssigned(err error) bool {
|
||||||
|
err = Cause(err)
|
||||||
|
_, ok := err.(*notAssigned)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// badRequest represents an error when a request has bad parameters.
|
||||||
|
type badRequest struct {
|
||||||
|
Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// BadRequestf returns an error which satisfies IsBadRequest().
|
||||||
|
func BadRequestf(format string, args ...interface{}) error {
|
||||||
|
return &badRequest{wrap(nil, format, "", args...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBadRequest returns an error which wraps err that satisfies
|
||||||
|
// IsBadRequest().
|
||||||
|
func NewBadRequest(err error, msg string) error {
|
||||||
|
return &badRequest{wrap(err, msg, "")}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsBadRequest reports whether err was created with BadRequestf() or
|
||||||
|
// NewBadRequest().
|
||||||
|
func IsBadRequest(err error) bool {
|
||||||
|
err = Cause(err)
|
||||||
|
_, ok := err.(*badRequest)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// methodNotAllowed represents an error when an HTTP request
|
||||||
|
// is made with an inappropriate method.
|
||||||
|
type methodNotAllowed struct {
|
||||||
|
Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// MethodNotAllowedf returns an error which satisfies IsMethodNotAllowed().
|
||||||
|
func MethodNotAllowedf(format string, args ...interface{}) error {
|
||||||
|
return &methodNotAllowed{wrap(nil, format, "", args...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMethodNotAllowed returns an error which wraps err that satisfies
|
||||||
|
// IsMethodNotAllowed().
|
||||||
|
func NewMethodNotAllowed(err error, msg string) error {
|
||||||
|
return &methodNotAllowed{wrap(err, msg, "")}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMethodNotAllowed reports whether err was created with MethodNotAllowedf() or
|
||||||
|
// NewMethodNotAllowed().
|
||||||
|
func IsMethodNotAllowed(err error) bool {
|
||||||
|
err = Cause(err)
|
||||||
|
_, ok := err.(*methodNotAllowed)
|
||||||
|
return ok
|
||||||
|
}
|
173
vendor/github.com/juju/errors/errortypes_test.go
generated
vendored
Normal file
173
vendor/github.com/juju/errors/errortypes_test.go
generated
vendored
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
// Copyright 2013, 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package errors_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
stderrors "errors"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/juju/errors"
|
||||||
|
jc "github.com/juju/testing/checkers"
|
||||||
|
gc "gopkg.in/check.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// errorInfo holds information about a single error type: a satisfier
|
||||||
|
// function, wrapping and variable arguments constructors and message
|
||||||
|
// suffix.
|
||||||
|
type errorInfo struct {
|
||||||
|
satisfier func(error) bool
|
||||||
|
argsConstructor func(string, ...interface{}) error
|
||||||
|
wrapConstructor func(error, string) error
|
||||||
|
suffix string
|
||||||
|
}
|
||||||
|
|
||||||
|
// allErrors holds information for all defined errors. When adding new
|
||||||
|
// errors, add them here as well to include them in tests.
|
||||||
|
var allErrors = []*errorInfo{
|
||||||
|
&errorInfo{errors.IsNotFound, errors.NotFoundf, errors.NewNotFound, " not found"},
|
||||||
|
&errorInfo{errors.IsUserNotFound, errors.UserNotFoundf, errors.NewUserNotFound, " user not found"},
|
||||||
|
&errorInfo{errors.IsUnauthorized, errors.Unauthorizedf, errors.NewUnauthorized, ""},
|
||||||
|
&errorInfo{errors.IsNotImplemented, errors.NotImplementedf, errors.NewNotImplemented, " not implemented"},
|
||||||
|
&errorInfo{errors.IsAlreadyExists, errors.AlreadyExistsf, errors.NewAlreadyExists, " already exists"},
|
||||||
|
&errorInfo{errors.IsNotSupported, errors.NotSupportedf, errors.NewNotSupported, " not supported"},
|
||||||
|
&errorInfo{errors.IsNotValid, errors.NotValidf, errors.NewNotValid, " not valid"},
|
||||||
|
&errorInfo{errors.IsNotProvisioned, errors.NotProvisionedf, errors.NewNotProvisioned, " not provisioned"},
|
||||||
|
&errorInfo{errors.IsNotAssigned, errors.NotAssignedf, errors.NewNotAssigned, " not assigned"},
|
||||||
|
&errorInfo{errors.IsMethodNotAllowed, errors.MethodNotAllowedf, errors.NewMethodNotAllowed, ""},
|
||||||
|
&errorInfo{errors.IsBadRequest, errors.BadRequestf, errors.NewBadRequest, ""},
|
||||||
|
}
|
||||||
|
|
||||||
|
type errorTypeSuite struct{}
|
||||||
|
|
||||||
|
var _ = gc.Suite(&errorTypeSuite{})
|
||||||
|
|
||||||
|
func (t *errorInfo) satisfierName() string {
|
||||||
|
value := reflect.ValueOf(t.satisfier)
|
||||||
|
f := runtime.FuncForPC(value.Pointer())
|
||||||
|
return f.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *errorInfo) equal(t0 *errorInfo) bool {
|
||||||
|
if t0 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return t.satisfierName() == t0.satisfierName()
|
||||||
|
}
|
||||||
|
|
||||||
|
type errorTest struct {
|
||||||
|
err error
|
||||||
|
message string
|
||||||
|
errInfo *errorInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func deferredAnnotatef(err error, format string, args ...interface{}) error {
|
||||||
|
errors.DeferredAnnotatef(&err, format, args...)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustSatisfy(c *gc.C, err error, errInfo *errorInfo) {
|
||||||
|
if errInfo != nil {
|
||||||
|
msg := fmt.Sprintf("%#v must satisfy %v", err, errInfo.satisfierName())
|
||||||
|
c.Check(err, jc.Satisfies, errInfo.satisfier, gc.Commentf(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustNotSatisfy(c *gc.C, err error, errInfo *errorInfo) {
|
||||||
|
if errInfo != nil {
|
||||||
|
msg := fmt.Sprintf("%#v must not satisfy %v", err, errInfo.satisfierName())
|
||||||
|
c.Check(err, gc.Not(jc.Satisfies), errInfo.satisfier, gc.Commentf(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkErrorMatches(c *gc.C, err error, message string, errInfo *errorInfo) {
|
||||||
|
if message == "<nil>" {
|
||||||
|
c.Check(err, gc.IsNil)
|
||||||
|
c.Check(errInfo, gc.IsNil)
|
||||||
|
} else {
|
||||||
|
c.Check(err, gc.ErrorMatches, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runErrorTests(c *gc.C, errorTests []errorTest, checkMustSatisfy bool) {
|
||||||
|
for i, t := range errorTests {
|
||||||
|
c.Logf("test %d: %T: %v", i, t.err, t.err)
|
||||||
|
checkErrorMatches(c, t.err, t.message, t.errInfo)
|
||||||
|
if checkMustSatisfy {
|
||||||
|
mustSatisfy(c, t.err, t.errInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check all other satisfiers to make sure none match.
|
||||||
|
for _, otherErrInfo := range allErrors {
|
||||||
|
if checkMustSatisfy && otherErrInfo.equal(t.errInfo) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
mustNotSatisfy(c, t.err, otherErrInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*errorTypeSuite) TestDeferredAnnotatef(c *gc.C) {
|
||||||
|
// Ensure DeferredAnnotatef annotates the errors.
|
||||||
|
errorTests := []errorTest{}
|
||||||
|
for _, errInfo := range allErrors {
|
||||||
|
errorTests = append(errorTests, []errorTest{{
|
||||||
|
deferredAnnotatef(nil, "comment"),
|
||||||
|
"<nil>",
|
||||||
|
nil,
|
||||||
|
}, {
|
||||||
|
deferredAnnotatef(stderrors.New("blast"), "comment"),
|
||||||
|
"comment: blast",
|
||||||
|
nil,
|
||||||
|
}, {
|
||||||
|
deferredAnnotatef(errInfo.argsConstructor("foo %d", 42), "comment %d", 69),
|
||||||
|
"comment 69: foo 42" + errInfo.suffix,
|
||||||
|
errInfo,
|
||||||
|
}, {
|
||||||
|
deferredAnnotatef(errInfo.argsConstructor(""), "comment"),
|
||||||
|
"comment: " + errInfo.suffix,
|
||||||
|
errInfo,
|
||||||
|
}, {
|
||||||
|
deferredAnnotatef(errInfo.wrapConstructor(stderrors.New("pow!"), "woo"), "comment"),
|
||||||
|
"comment: woo: pow!",
|
||||||
|
errInfo,
|
||||||
|
}}...)
|
||||||
|
}
|
||||||
|
|
||||||
|
runErrorTests(c, errorTests, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*errorTypeSuite) TestAllErrors(c *gc.C) {
|
||||||
|
errorTests := []errorTest{}
|
||||||
|
for _, errInfo := range allErrors {
|
||||||
|
errorTests = append(errorTests, []errorTest{{
|
||||||
|
nil,
|
||||||
|
"<nil>",
|
||||||
|
nil,
|
||||||
|
}, {
|
||||||
|
errInfo.argsConstructor("foo %d", 42),
|
||||||
|
"foo 42" + errInfo.suffix,
|
||||||
|
errInfo,
|
||||||
|
}, {
|
||||||
|
errInfo.argsConstructor(""),
|
||||||
|
errInfo.suffix,
|
||||||
|
errInfo,
|
||||||
|
}, {
|
||||||
|
errInfo.wrapConstructor(stderrors.New("pow!"), "prefix"),
|
||||||
|
"prefix: pow!",
|
||||||
|
errInfo,
|
||||||
|
}, {
|
||||||
|
errInfo.wrapConstructor(stderrors.New("pow!"), ""),
|
||||||
|
"pow!",
|
||||||
|
errInfo,
|
||||||
|
}, {
|
||||||
|
errInfo.wrapConstructor(nil, "prefix"),
|
||||||
|
"prefix",
|
||||||
|
errInfo,
|
||||||
|
}}...)
|
||||||
|
}
|
||||||
|
|
||||||
|
runErrorTests(c, errorTests, true)
|
||||||
|
}
|
23
vendor/github.com/juju/errors/example_test.go
generated
vendored
Normal file
23
vendor/github.com/juju/errors/example_test.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2013, 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package errors_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/juju/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleTrace() {
|
||||||
|
var err1 error = fmt.Errorf("something wicked this way comes")
|
||||||
|
var err2 error = nil
|
||||||
|
|
||||||
|
// Tracing a non nil error will return an error
|
||||||
|
fmt.Println(errors.Trace(err1))
|
||||||
|
// Tracing nil will return nil
|
||||||
|
fmt.Println(errors.Trace(err2))
|
||||||
|
|
||||||
|
// Output: something wicked this way comes
|
||||||
|
// <nil>
|
||||||
|
}
|
12
vendor/github.com/juju/errors/export_test.go
generated
vendored
Normal file
12
vendor/github.com/juju/errors/export_test.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// Copyright 2013, 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package errors
|
||||||
|
|
||||||
|
// Since variables are declared before the init block, in order to get the goPath
|
||||||
|
// we need to return it rather than just reference it.
|
||||||
|
func GoPath() string {
|
||||||
|
return goPath
|
||||||
|
}
|
||||||
|
|
||||||
|
var TrimGoPath = trimGoPath
|
330
vendor/github.com/juju/errors/functions.go
generated
vendored
Normal file
330
vendor/github.com/juju/errors/functions.go
generated
vendored
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
// Copyright 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// New is a drop in replacement for the standard libary errors module that records
|
||||||
|
// the location that the error is created.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// return errors.New("validation failed")
|
||||||
|
//
|
||||||
|
func New(message string) error {
|
||||||
|
err := &Err{message: message}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf creates a new annotated error and records the location that the
|
||||||
|
// error is created. This should be a drop in replacement for fmt.Errorf.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// return errors.Errorf("validation failed: %s", message)
|
||||||
|
//
|
||||||
|
func Errorf(format string, args ...interface{}) error {
|
||||||
|
err := &Err{message: fmt.Sprintf(format, args...)}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trace adds the location of the Trace call to the stack. The Cause of the
|
||||||
|
// resulting error is the same as the error parameter. If the other error is
|
||||||
|
// nil, the result will be nil.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// if err := SomeFunc(); err != nil {
|
||||||
|
// return errors.Trace(err)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
func Trace(other error) error {
|
||||||
|
if other == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := &Err{previous: other, cause: Cause(other)}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annotate is used to add extra context to an existing error. The location of
|
||||||
|
// the Annotate call is recorded with the annotations. The file, line and
|
||||||
|
// function are also recorded.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// if err := SomeFunc(); err != nil {
|
||||||
|
// return errors.Annotate(err, "failed to frombulate")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
func Annotate(other error, message string) error {
|
||||||
|
if other == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := &Err{
|
||||||
|
previous: other,
|
||||||
|
cause: Cause(other),
|
||||||
|
message: message,
|
||||||
|
}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annotatef is used to add extra context to an existing error. The location of
|
||||||
|
// the Annotate call is recorded with the annotations. The file, line and
|
||||||
|
// function are also recorded.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// if err := SomeFunc(); err != nil {
|
||||||
|
// return errors.Annotatef(err, "failed to frombulate the %s", arg)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
func Annotatef(other error, format string, args ...interface{}) error {
|
||||||
|
if other == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := &Err{
|
||||||
|
previous: other,
|
||||||
|
cause: Cause(other),
|
||||||
|
message: fmt.Sprintf(format, args...),
|
||||||
|
}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeferredAnnotatef annotates the given error (when it is not nil) with the given
|
||||||
|
// format string and arguments (like fmt.Sprintf). If *err is nil, DeferredAnnotatef
|
||||||
|
// does nothing. This method is used in a defer statement in order to annotate any
|
||||||
|
// resulting error with the same message.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// defer DeferredAnnotatef(&err, "failed to frombulate the %s", arg)
|
||||||
|
//
|
||||||
|
func DeferredAnnotatef(err *error, format string, args ...interface{}) {
|
||||||
|
if *err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newErr := &Err{
|
||||||
|
message: fmt.Sprintf(format, args...),
|
||||||
|
cause: Cause(*err),
|
||||||
|
previous: *err,
|
||||||
|
}
|
||||||
|
newErr.SetLocation(1)
|
||||||
|
*err = newErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap changes the Cause of the error. The location of the Wrap call is also
|
||||||
|
// stored in the error stack.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// if err := SomeFunc(); err != nil {
|
||||||
|
// newErr := &packageError{"more context", private_value}
|
||||||
|
// return errors.Wrap(err, newErr)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
func Wrap(other, newDescriptive error) error {
|
||||||
|
err := &Err{
|
||||||
|
previous: other,
|
||||||
|
cause: newDescriptive,
|
||||||
|
}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrapf changes the Cause of the error, and adds an annotation. The location
|
||||||
|
// of the Wrap call is also stored in the error stack.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// if err := SomeFunc(); err != nil {
|
||||||
|
// return errors.Wrapf(err, simpleErrorType, "invalid value %q", value)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
func Wrapf(other, newDescriptive error, format string, args ...interface{}) error {
|
||||||
|
err := &Err{
|
||||||
|
message: fmt.Sprintf(format, args...),
|
||||||
|
previous: other,
|
||||||
|
cause: newDescriptive,
|
||||||
|
}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mask masks the given error with the given format string and arguments (like
|
||||||
|
// fmt.Sprintf), returning a new error that maintains the error stack, but
|
||||||
|
// hides the underlying error type. The error string still contains the full
|
||||||
|
// annotations. If you want to hide the annotations, call Wrap.
|
||||||
|
func Maskf(other error, format string, args ...interface{}) error {
|
||||||
|
if other == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := &Err{
|
||||||
|
message: fmt.Sprintf(format, args...),
|
||||||
|
previous: other,
|
||||||
|
}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mask hides the underlying error type, and records the location of the masking.
|
||||||
|
func Mask(other error) error {
|
||||||
|
if other == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := &Err{
|
||||||
|
previous: other,
|
||||||
|
}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cause returns the cause of the given error. This will be either the
|
||||||
|
// original error, or the result of a Wrap or Mask call.
|
||||||
|
//
|
||||||
|
// Cause is the usual way to diagnose errors that may have been wrapped by
|
||||||
|
// the other errors functions.
|
||||||
|
func Cause(err error) error {
|
||||||
|
var diag error
|
||||||
|
if err, ok := err.(causer); ok {
|
||||||
|
diag = err.Cause()
|
||||||
|
}
|
||||||
|
if diag != nil {
|
||||||
|
return diag
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type causer interface {
|
||||||
|
Cause() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type wrapper interface {
|
||||||
|
// Message returns the top level error message,
|
||||||
|
// not including the message from the Previous
|
||||||
|
// error.
|
||||||
|
Message() string
|
||||||
|
|
||||||
|
// Underlying returns the Previous error, or nil
|
||||||
|
// if there is none.
|
||||||
|
Underlying() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type locationer interface {
|
||||||
|
Location() (string, int)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ wrapper = (*Err)(nil)
|
||||||
|
_ locationer = (*Err)(nil)
|
||||||
|
_ causer = (*Err)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Details returns information about the stack of errors wrapped by err, in
|
||||||
|
// the format:
|
||||||
|
//
|
||||||
|
// [{filename:99: error one} {otherfile:55: cause of error one}]
|
||||||
|
//
|
||||||
|
// This is a terse alternative to ErrorStack as it returns a single line.
|
||||||
|
func Details(err error) string {
|
||||||
|
if err == nil {
|
||||||
|
return "[]"
|
||||||
|
}
|
||||||
|
var s []byte
|
||||||
|
s = append(s, '[')
|
||||||
|
for {
|
||||||
|
s = append(s, '{')
|
||||||
|
if err, ok := err.(locationer); ok {
|
||||||
|
file, line := err.Location()
|
||||||
|
if file != "" {
|
||||||
|
s = append(s, fmt.Sprintf("%s:%d", file, line)...)
|
||||||
|
s = append(s, ": "...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cerr, ok := err.(wrapper); ok {
|
||||||
|
s = append(s, cerr.Message()...)
|
||||||
|
err = cerr.Underlying()
|
||||||
|
} else {
|
||||||
|
s = append(s, err.Error()...)
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
s = append(s, '}')
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
s = append(s, ' ')
|
||||||
|
}
|
||||||
|
s = append(s, ']')
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorStack returns a string representation of the annotated error. If the
|
||||||
|
// error passed as the parameter is not an annotated error, the result is
|
||||||
|
// simply the result of the Error() method on that error.
|
||||||
|
//
|
||||||
|
// If the error is an annotated error, a multi-line string is returned where
|
||||||
|
// each line represents one entry in the annotation stack. The full filename
|
||||||
|
// from the call stack is used in the output.
|
||||||
|
//
|
||||||
|
// first error
|
||||||
|
// github.com/juju/errors/annotation_test.go:193:
|
||||||
|
// github.com/juju/errors/annotation_test.go:194: annotation
|
||||||
|
// github.com/juju/errors/annotation_test.go:195:
|
||||||
|
// github.com/juju/errors/annotation_test.go:196: more context
|
||||||
|
// github.com/juju/errors/annotation_test.go:197:
|
||||||
|
func ErrorStack(err error) string {
|
||||||
|
return strings.Join(errorStack(err), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func errorStack(err error) []string {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want the first error first
|
||||||
|
var lines []string
|
||||||
|
for {
|
||||||
|
var buff []byte
|
||||||
|
if err, ok := err.(locationer); ok {
|
||||||
|
file, line := err.Location()
|
||||||
|
// Strip off the leading GOPATH/src path elements.
|
||||||
|
file = trimGoPath(file)
|
||||||
|
if file != "" {
|
||||||
|
buff = append(buff, fmt.Sprintf("%s:%d", file, line)...)
|
||||||
|
buff = append(buff, ": "...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cerr, ok := err.(wrapper); ok {
|
||||||
|
message := cerr.Message()
|
||||||
|
buff = append(buff, message...)
|
||||||
|
// If there is a cause for this error, and it is different to the cause
|
||||||
|
// of the underlying error, then output the error string in the stack trace.
|
||||||
|
var cause error
|
||||||
|
if err1, ok := err.(causer); ok {
|
||||||
|
cause = err1.Cause()
|
||||||
|
}
|
||||||
|
err = cerr.Underlying()
|
||||||
|
if cause != nil && !sameError(Cause(err), cause) {
|
||||||
|
if message != "" {
|
||||||
|
buff = append(buff, ": "...)
|
||||||
|
}
|
||||||
|
buff = append(buff, cause.Error()...)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buff = append(buff, err.Error()...)
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
lines = append(lines, string(buff))
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// reverse the lines to get the original error, which was at the end of
|
||||||
|
// the list, back to the start.
|
||||||
|
var result []string
|
||||||
|
for i := len(lines); i > 0; i-- {
|
||||||
|
result = append(result, lines[i-1])
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
305
vendor/github.com/juju/errors/functions_test.go
generated
vendored
Normal file
305
vendor/github.com/juju/errors/functions_test.go
generated
vendored
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
// Copyright 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package errors_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
jc "github.com/juju/testing/checkers"
|
||||||
|
gc "gopkg.in/check.v1"
|
||||||
|
|
||||||
|
"github.com/juju/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type functionSuite struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = gc.Suite(&functionSuite{})
|
||||||
|
|
||||||
|
func (*functionSuite) TestNew(c *gc.C) {
|
||||||
|
err := errors.New("testing") //err newTest
|
||||||
|
c.Assert(err.Error(), gc.Equals, "testing")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, err)
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["newTest"].String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*functionSuite) TestErrorf(c *gc.C) {
|
||||||
|
err := errors.Errorf("testing %d", 42) //err errorfTest
|
||||||
|
c.Assert(err.Error(), gc.Equals, "testing 42")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, err)
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["errorfTest"].String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*functionSuite) TestTrace(c *gc.C) {
|
||||||
|
first := errors.New("first")
|
||||||
|
err := errors.Trace(first) //err traceTest
|
||||||
|
c.Assert(err.Error(), gc.Equals, "first")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, first)
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["traceTest"].String())
|
||||||
|
|
||||||
|
c.Assert(errors.Trace(nil), gc.IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*functionSuite) TestAnnotate(c *gc.C) {
|
||||||
|
first := errors.New("first")
|
||||||
|
err := errors.Annotate(first, "annotation") //err annotateTest
|
||||||
|
c.Assert(err.Error(), gc.Equals, "annotation: first")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, first)
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["annotateTest"].String())
|
||||||
|
|
||||||
|
c.Assert(errors.Annotate(nil, "annotate"), gc.IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*functionSuite) TestAnnotatef(c *gc.C) {
|
||||||
|
first := errors.New("first")
|
||||||
|
err := errors.Annotatef(first, "annotation %d", 2) //err annotatefTest
|
||||||
|
c.Assert(err.Error(), gc.Equals, "annotation 2: first")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, first)
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["annotatefTest"].String())
|
||||||
|
|
||||||
|
c.Assert(errors.Annotatef(nil, "annotate"), gc.IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*functionSuite) TestDeferredAnnotatef(c *gc.C) {
|
||||||
|
// NOTE: this test fails with gccgo
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
c.Skip("gccgo can't determine the location")
|
||||||
|
}
|
||||||
|
first := errors.New("first")
|
||||||
|
test := func() (err error) {
|
||||||
|
defer errors.DeferredAnnotatef(&err, "deferred %s", "annotate")
|
||||||
|
return first
|
||||||
|
} //err deferredAnnotate
|
||||||
|
err := test()
|
||||||
|
c.Assert(err.Error(), gc.Equals, "deferred annotate: first")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, first)
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["deferredAnnotate"].String())
|
||||||
|
|
||||||
|
err = nil
|
||||||
|
errors.DeferredAnnotatef(&err, "deferred %s", "annotate")
|
||||||
|
c.Assert(err, gc.IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*functionSuite) TestWrap(c *gc.C) {
|
||||||
|
first := errors.New("first") //err wrapFirst
|
||||||
|
detailed := errors.New("detailed")
|
||||||
|
err := errors.Wrap(first, detailed) //err wrapTest
|
||||||
|
c.Assert(err.Error(), gc.Equals, "detailed")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, detailed)
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["wrapFirst"].String())
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["wrapTest"].String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*functionSuite) TestWrapOfNil(c *gc.C) {
|
||||||
|
detailed := errors.New("detailed")
|
||||||
|
err := errors.Wrap(nil, detailed) //err nilWrapTest
|
||||||
|
c.Assert(err.Error(), gc.Equals, "detailed")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, detailed)
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["nilWrapTest"].String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*functionSuite) TestWrapf(c *gc.C) {
|
||||||
|
first := errors.New("first") //err wrapfFirst
|
||||||
|
detailed := errors.New("detailed")
|
||||||
|
err := errors.Wrapf(first, detailed, "value %d", 42) //err wrapfTest
|
||||||
|
c.Assert(err.Error(), gc.Equals, "value 42: detailed")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, detailed)
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["wrapfFirst"].String())
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["wrapfTest"].String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*functionSuite) TestWrapfOfNil(c *gc.C) {
|
||||||
|
detailed := errors.New("detailed")
|
||||||
|
err := errors.Wrapf(nil, detailed, "value %d", 42) //err nilWrapfTest
|
||||||
|
c.Assert(err.Error(), gc.Equals, "value 42: detailed")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, detailed)
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["nilWrapfTest"].String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*functionSuite) TestMask(c *gc.C) {
|
||||||
|
first := errors.New("first")
|
||||||
|
err := errors.Mask(first) //err maskTest
|
||||||
|
c.Assert(err.Error(), gc.Equals, "first")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, err)
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["maskTest"].String())
|
||||||
|
|
||||||
|
c.Assert(errors.Mask(nil), gc.IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*functionSuite) TestMaskf(c *gc.C) {
|
||||||
|
first := errors.New("first")
|
||||||
|
err := errors.Maskf(first, "masked %d", 42) //err maskfTest
|
||||||
|
c.Assert(err.Error(), gc.Equals, "masked 42: first")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, err)
|
||||||
|
c.Assert(errors.Details(err), jc.Contains, tagToLocation["maskfTest"].String())
|
||||||
|
|
||||||
|
c.Assert(errors.Maskf(nil, "mask"), gc.IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*functionSuite) TestCause(c *gc.C) {
|
||||||
|
c.Assert(errors.Cause(nil), gc.IsNil)
|
||||||
|
c.Assert(errors.Cause(someErr), gc.Equals, someErr)
|
||||||
|
|
||||||
|
fmtErr := fmt.Errorf("simple")
|
||||||
|
c.Assert(errors.Cause(fmtErr), gc.Equals, fmtErr)
|
||||||
|
|
||||||
|
err := errors.Wrap(someErr, fmtErr)
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, fmtErr)
|
||||||
|
|
||||||
|
err = errors.Annotate(err, "annotated")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, fmtErr)
|
||||||
|
|
||||||
|
err = errors.Maskf(err, "maksed")
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, err)
|
||||||
|
|
||||||
|
// Look for a file that we know isn't there.
|
||||||
|
dir := c.MkDir()
|
||||||
|
_, err = os.Stat(filepath.Join(dir, "not-there"))
|
||||||
|
c.Assert(os.IsNotExist(err), jc.IsTrue)
|
||||||
|
|
||||||
|
err = errors.Annotatef(err, "wrap it")
|
||||||
|
// Now the error itself isn't a 'IsNotExist'.
|
||||||
|
c.Assert(os.IsNotExist(err), jc.IsFalse)
|
||||||
|
// However if we use the Check method, it is.
|
||||||
|
c.Assert(os.IsNotExist(errors.Cause(err)), jc.IsTrue)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *functionSuite) TestDetails(c *gc.C) {
|
||||||
|
if runtime.Compiler == "gccgo" {
|
||||||
|
c.Skip("gccgo can't determine the location")
|
||||||
|
}
|
||||||
|
c.Assert(errors.Details(nil), gc.Equals, "[]")
|
||||||
|
|
||||||
|
otherErr := fmt.Errorf("other")
|
||||||
|
checkDetails(c, otherErr, "[{other}]")
|
||||||
|
|
||||||
|
err0 := newEmbed("foo") //err TestStack#0
|
||||||
|
checkDetails(c, err0, "[{$TestStack#0$: foo}]")
|
||||||
|
|
||||||
|
err1 := errors.Annotate(err0, "bar") //err TestStack#1
|
||||||
|
checkDetails(c, err1, "[{$TestStack#1$: bar} {$TestStack#0$: foo}]")
|
||||||
|
|
||||||
|
err2 := errors.Trace(err1) //err TestStack#2
|
||||||
|
checkDetails(c, err2, "[{$TestStack#2$: } {$TestStack#1$: bar} {$TestStack#0$: foo}]")
|
||||||
|
}
|
||||||
|
|
||||||
|
type tracer interface {
|
||||||
|
StackTrace() []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*functionSuite) TestErrorStack(c *gc.C) {
|
||||||
|
for i, test := range []struct {
|
||||||
|
message string
|
||||||
|
generator func() error
|
||||||
|
expected string
|
||||||
|
tracer bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
message: "nil",
|
||||||
|
generator: func() error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
message: "raw error",
|
||||||
|
generator: func() error {
|
||||||
|
return fmt.Errorf("raw")
|
||||||
|
},
|
||||||
|
expected: "raw",
|
||||||
|
}, {
|
||||||
|
message: "single error stack",
|
||||||
|
generator: func() error {
|
||||||
|
return errors.New("first error") //err single
|
||||||
|
},
|
||||||
|
expected: "$single$: first error",
|
||||||
|
tracer: true,
|
||||||
|
}, {
|
||||||
|
message: "annotated error",
|
||||||
|
generator: func() error {
|
||||||
|
err := errors.New("first error") //err annotated-0
|
||||||
|
return errors.Annotate(err, "annotation") //err annotated-1
|
||||||
|
},
|
||||||
|
expected: "" +
|
||||||
|
"$annotated-0$: first error\n" +
|
||||||
|
"$annotated-1$: annotation",
|
||||||
|
tracer: true,
|
||||||
|
}, {
|
||||||
|
message: "wrapped error",
|
||||||
|
generator: func() error {
|
||||||
|
err := errors.New("first error") //err wrapped-0
|
||||||
|
return errors.Wrap(err, newError("detailed error")) //err wrapped-1
|
||||||
|
},
|
||||||
|
expected: "" +
|
||||||
|
"$wrapped-0$: first error\n" +
|
||||||
|
"$wrapped-1$: detailed error",
|
||||||
|
tracer: true,
|
||||||
|
}, {
|
||||||
|
message: "annotated wrapped error",
|
||||||
|
generator: func() error {
|
||||||
|
err := errors.Errorf("first error") //err ann-wrap-0
|
||||||
|
err = errors.Wrap(err, fmt.Errorf("detailed error")) //err ann-wrap-1
|
||||||
|
return errors.Annotatef(err, "annotated") //err ann-wrap-2
|
||||||
|
},
|
||||||
|
expected: "" +
|
||||||
|
"$ann-wrap-0$: first error\n" +
|
||||||
|
"$ann-wrap-1$: detailed error\n" +
|
||||||
|
"$ann-wrap-2$: annotated",
|
||||||
|
tracer: true,
|
||||||
|
}, {
|
||||||
|
message: "traced, and annotated",
|
||||||
|
generator: func() error {
|
||||||
|
err := errors.New("first error") //err stack-0
|
||||||
|
err = errors.Trace(err) //err stack-1
|
||||||
|
err = errors.Annotate(err, "some context") //err stack-2
|
||||||
|
err = errors.Trace(err) //err stack-3
|
||||||
|
err = errors.Annotate(err, "more context") //err stack-4
|
||||||
|
return errors.Trace(err) //err stack-5
|
||||||
|
},
|
||||||
|
expected: "" +
|
||||||
|
"$stack-0$: first error\n" +
|
||||||
|
"$stack-1$: \n" +
|
||||||
|
"$stack-2$: some context\n" +
|
||||||
|
"$stack-3$: \n" +
|
||||||
|
"$stack-4$: more context\n" +
|
||||||
|
"$stack-5$: ",
|
||||||
|
tracer: true,
|
||||||
|
}, {
|
||||||
|
message: "uncomparable, wrapped with a value error",
|
||||||
|
generator: func() error {
|
||||||
|
err := newNonComparableError("first error") //err mixed-0
|
||||||
|
err = errors.Trace(err) //err mixed-1
|
||||||
|
err = errors.Wrap(err, newError("value error")) //err mixed-2
|
||||||
|
err = errors.Maskf(err, "masked") //err mixed-3
|
||||||
|
err = errors.Annotate(err, "more context") //err mixed-4
|
||||||
|
return errors.Trace(err) //err mixed-5
|
||||||
|
},
|
||||||
|
expected: "" +
|
||||||
|
"first error\n" +
|
||||||
|
"$mixed-1$: \n" +
|
||||||
|
"$mixed-2$: value error\n" +
|
||||||
|
"$mixed-3$: masked\n" +
|
||||||
|
"$mixed-4$: more context\n" +
|
||||||
|
"$mixed-5$: ",
|
||||||
|
tracer: true,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
c.Logf("%v: %s", i, test.message)
|
||||||
|
err := test.generator()
|
||||||
|
expected := replaceLocations(test.expected)
|
||||||
|
stack := errors.ErrorStack(err)
|
||||||
|
ok := c.Check(stack, gc.Equals, expected)
|
||||||
|
if !ok {
|
||||||
|
c.Logf("%#v", err)
|
||||||
|
}
|
||||||
|
tracer, ok := err.(tracer)
|
||||||
|
c.Check(ok, gc.Equals, test.tracer)
|
||||||
|
if ok {
|
||||||
|
stackTrace := tracer.StackTrace()
|
||||||
|
c.Check(stackTrace, gc.DeepEquals, strings.Split(stack, "\n"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
95
vendor/github.com/juju/errors/package_test.go
generated
vendored
Normal file
95
vendor/github.com/juju/errors/package_test.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
// Copyright 2013, 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package errors_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
gc "gopkg.in/check.v1"
|
||||||
|
|
||||||
|
"github.com/juju/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test(t *testing.T) {
|
||||||
|
gc.TestingT(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkDetails(c *gc.C, err error, details string) {
|
||||||
|
c.Assert(err, gc.NotNil)
|
||||||
|
expectedDetails := replaceLocations(details)
|
||||||
|
c.Assert(errors.Details(err), gc.Equals, expectedDetails)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkErr(c *gc.C, err, cause error, msg string, details string) {
|
||||||
|
c.Assert(err, gc.NotNil)
|
||||||
|
c.Assert(err.Error(), gc.Equals, msg)
|
||||||
|
c.Assert(errors.Cause(err), gc.Equals, cause)
|
||||||
|
expectedDetails := replaceLocations(details)
|
||||||
|
c.Assert(errors.Details(err), gc.Equals, expectedDetails)
|
||||||
|
}
|
||||||
|
|
||||||
|
func replaceLocations(line string) string {
|
||||||
|
result := ""
|
||||||
|
for {
|
||||||
|
i := strings.Index(line, "$")
|
||||||
|
if i == -1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
result += line[0:i]
|
||||||
|
line = line[i+1:]
|
||||||
|
i = strings.Index(line, "$")
|
||||||
|
if i == -1 {
|
||||||
|
panic("no second $")
|
||||||
|
}
|
||||||
|
result += location(line[0:i]).String()
|
||||||
|
line = line[i+1:]
|
||||||
|
}
|
||||||
|
result += line
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func location(tag string) Location {
|
||||||
|
loc, ok := tagToLocation[tag]
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Sprintf("tag %q not found", tag))
|
||||||
|
}
|
||||||
|
return loc
|
||||||
|
}
|
||||||
|
|
||||||
|
type Location struct {
|
||||||
|
file string
|
||||||
|
line int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (loc Location) String() string {
|
||||||
|
return fmt.Sprintf("%s:%d", loc.file, loc.line)
|
||||||
|
}
|
||||||
|
|
||||||
|
var tagToLocation = make(map[string]Location)
|
||||||
|
|
||||||
|
func setLocationsForErrorTags(filename string) {
|
||||||
|
data, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
filename = "github.com/juju/errors/" + filename
|
||||||
|
lines := strings.Split(string(data), "\n")
|
||||||
|
for i, line := range lines {
|
||||||
|
if j := strings.Index(line, "//err "); j >= 0 {
|
||||||
|
tag := line[j+len("//err "):]
|
||||||
|
if _, found := tagToLocation[tag]; found {
|
||||||
|
panic(fmt.Sprintf("tag %q already processed previously", tag))
|
||||||
|
}
|
||||||
|
tagToLocation[tag] = Location{file: filename, line: i + 1}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
setLocationsForErrorTags("error_test.go")
|
||||||
|
setLocationsForErrorTags("functions_test.go")
|
||||||
|
}
|
35
vendor/github.com/juju/errors/path.go
generated
vendored
Normal file
35
vendor/github.com/juju/errors/path.go
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// Copyright 2013, 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// prefixSize is used internally to trim the user specific path from the
|
||||||
|
// front of the returned filenames from the runtime call stack.
|
||||||
|
var prefixSize int
|
||||||
|
|
||||||
|
// goPath is the deduced path based on the location of this file as compiled.
|
||||||
|
var goPath string
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
_, file, _, ok := runtime.Caller(0)
|
||||||
|
if ok {
|
||||||
|
// We know that the end of the file should be:
|
||||||
|
// github.com/juju/errors/path.go
|
||||||
|
size := len(file)
|
||||||
|
suffix := len("github.com/juju/errors/path.go")
|
||||||
|
goPath = file[:size-suffix]
|
||||||
|
prefixSize = len(goPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func trimGoPath(filename string) string {
|
||||||
|
if strings.HasPrefix(filename, goPath) {
|
||||||
|
return filename[prefixSize:]
|
||||||
|
}
|
||||||
|
return filename
|
||||||
|
}
|
29
vendor/github.com/juju/errors/path_test.go
generated
vendored
Normal file
29
vendor/github.com/juju/errors/path_test.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Copyright 2013, 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package errors_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path"
|
||||||
|
|
||||||
|
gc "gopkg.in/check.v1"
|
||||||
|
|
||||||
|
"github.com/juju/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type pathSuite struct{}
|
||||||
|
|
||||||
|
var _ = gc.Suite(&pathSuite{})
|
||||||
|
|
||||||
|
func (*pathSuite) TestGoPathSet(c *gc.C) {
|
||||||
|
c.Assert(errors.GoPath(), gc.Not(gc.Equals), "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*pathSuite) TestTrimGoPath(c *gc.C) {
|
||||||
|
relativeImport := "github.com/foo/bar/baz.go"
|
||||||
|
filename := path.Join(errors.GoPath(), relativeImport)
|
||||||
|
c.Assert(errors.TrimGoPath(filename), gc.Equals, relativeImport)
|
||||||
|
|
||||||
|
absoluteImport := "/usr/share/foo/bar/baz.go"
|
||||||
|
c.Assert(errors.TrimGoPath(absoluteImport), gc.Equals, absoluteImport)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user