From 869bc4b6dacbca73d4e84d362d5cf93a5be69f9a Mon Sep 17 00:00:00 2001 From: Shlomi Noach Date: Thu, 16 Jun 2016 11:46:44 +0200 Subject: [PATCH] more attempts --- vendor/github.com/juju/errors/LICENSE | 191 +++++++ vendor/github.com/juju/errors/Makefile | 11 + vendor/github.com/juju/errors/README.md | 536 ++++++++++++++++++ vendor/github.com/juju/errors/doc.go | 81 +++ vendor/github.com/juju/errors/error.go | 122 ++++ vendor/github.com/juju/errors/error_test.go | 161 ++++++ vendor/github.com/juju/errors/errortypes.go | 284 ++++++++++ .../github.com/juju/errors/errortypes_test.go | 173 ++++++ vendor/github.com/juju/errors/example_test.go | 23 + vendor/github.com/juju/errors/export_test.go | 12 + vendor/github.com/juju/errors/functions.go | 330 +++++++++++ .../github.com/juju/errors/functions_test.go | 305 ++++++++++ vendor/github.com/juju/errors/package_test.go | 95 ++++ vendor/github.com/juju/errors/path.go | 35 ++ vendor/github.com/juju/errors/path_test.go | 29 + 15 files changed, 2388 insertions(+) create mode 100644 vendor/github.com/juju/errors/LICENSE create mode 100644 vendor/github.com/juju/errors/Makefile create mode 100644 vendor/github.com/juju/errors/README.md create mode 100644 vendor/github.com/juju/errors/doc.go create mode 100644 vendor/github.com/juju/errors/error.go create mode 100644 vendor/github.com/juju/errors/error_test.go create mode 100644 vendor/github.com/juju/errors/errortypes.go create mode 100644 vendor/github.com/juju/errors/errortypes_test.go create mode 100644 vendor/github.com/juju/errors/example_test.go create mode 100644 vendor/github.com/juju/errors/export_test.go create mode 100644 vendor/github.com/juju/errors/functions.go create mode 100644 vendor/github.com/juju/errors/functions_test.go create mode 100644 vendor/github.com/juju/errors/package_test.go create mode 100644 vendor/github.com/juju/errors/path.go create mode 100644 vendor/github.com/juju/errors/path_test.go diff --git a/vendor/github.com/juju/errors/LICENSE b/vendor/github.com/juju/errors/LICENSE new file mode 100644 index 0000000..ade9307 --- /dev/null +++ b/vendor/github.com/juju/errors/LICENSE @@ -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. + 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. diff --git a/vendor/github.com/juju/errors/Makefile b/vendor/github.com/juju/errors/Makefile new file mode 100644 index 0000000..ab7c2e6 --- /dev/null +++ b/vendor/github.com/juju/errors/Makefile @@ -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 diff --git a/vendor/github.com/juju/errors/README.md b/vendor/github.com/juju/errors/README.md new file mode 100644 index 0000000..ee24891 --- /dev/null +++ b/vendor/github.com/juju/errors/README.md @@ -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) \ No newline at end of file diff --git a/vendor/github.com/juju/errors/doc.go b/vendor/github.com/juju/errors/doc.go new file mode 100644 index 0000000..35b119a --- /dev/null +++ b/vendor/github.com/juju/errors/doc.go @@ -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 diff --git a/vendor/github.com/juju/errors/error.go b/vendor/github.com/juju/errors/error.go new file mode 100644 index 0000000..4799acb --- /dev/null +++ b/vendor/github.com/juju/errors/error.go @@ -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) +} diff --git a/vendor/github.com/juju/errors/error_test.go b/vendor/github.com/juju/errors/error_test.go new file mode 100644 index 0000000..ac1d2b4 --- /dev/null +++ b/vendor/github.com/juju/errors/error_test.go @@ -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 +} diff --git a/vendor/github.com/juju/errors/errortypes.go b/vendor/github.com/juju/errors/errortypes.go new file mode 100644 index 0000000..10b3b19 --- /dev/null +++ b/vendor/github.com/juju/errors/errortypes.go @@ -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 +} diff --git a/vendor/github.com/juju/errors/errortypes_test.go b/vendor/github.com/juju/errors/errortypes_test.go new file mode 100644 index 0000000..7cc2da9 --- /dev/null +++ b/vendor/github.com/juju/errors/errortypes_test.go @@ -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 == "" { + 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, + }, { + 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, + }, { + 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) +} diff --git a/vendor/github.com/juju/errors/example_test.go b/vendor/github.com/juju/errors/example_test.go new file mode 100644 index 0000000..2a79cf4 --- /dev/null +++ b/vendor/github.com/juju/errors/example_test.go @@ -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 + // +} diff --git a/vendor/github.com/juju/errors/export_test.go b/vendor/github.com/juju/errors/export_test.go new file mode 100644 index 0000000..db57ec8 --- /dev/null +++ b/vendor/github.com/juju/errors/export_test.go @@ -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 diff --git a/vendor/github.com/juju/errors/functions.go b/vendor/github.com/juju/errors/functions.go new file mode 100644 index 0000000..994208d --- /dev/null +++ b/vendor/github.com/juju/errors/functions.go @@ -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 +} diff --git a/vendor/github.com/juju/errors/functions_test.go b/vendor/github.com/juju/errors/functions_test.go new file mode 100644 index 0000000..7b1e43b --- /dev/null +++ b/vendor/github.com/juju/errors/functions_test.go @@ -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")) + } + } +} diff --git a/vendor/github.com/juju/errors/package_test.go b/vendor/github.com/juju/errors/package_test.go new file mode 100644 index 0000000..5bbb8f0 --- /dev/null +++ b/vendor/github.com/juju/errors/package_test.go @@ -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") +} diff --git a/vendor/github.com/juju/errors/path.go b/vendor/github.com/juju/errors/path.go new file mode 100644 index 0000000..3ec517c --- /dev/null +++ b/vendor/github.com/juju/errors/path.go @@ -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 +} diff --git a/vendor/github.com/juju/errors/path_test.go b/vendor/github.com/juju/errors/path_test.go new file mode 100644 index 0000000..ef4f34f --- /dev/null +++ b/vendor/github.com/juju/errors/path_test.go @@ -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) +}