This repository has been archived by the owner on Nov 27, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 252
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docker/api/multierror wraps go-multierror from hashicorp with our default error formating
- Loading branch information
Showing
5 changed files
with
146 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package multierror | ||
|
||
import ( | ||
"strings" | ||
|
||
"github.com/hashicorp/go-multierror" | ||
) | ||
|
||
// Error wraps a multierror.Error and defines a default | ||
// formatting function that fits cli needs | ||
type Error struct { | ||
err *multierror.Error | ||
} | ||
|
||
func (e *Error) Error() string { | ||
if e == nil || e.err == nil { | ||
return "" | ||
} | ||
e.err.ErrorFormat = listErrorFunc | ||
return e.err.Error() | ||
} | ||
|
||
// WrappedErrors returns the list of errors that this Error is wrapping. | ||
// It is an implementation of the errwrap.Wrapper interface so that | ||
// multierror.Error can be used with that library. | ||
// | ||
// This method is not safe to be called concurrently and is no different | ||
// than accessing the Errors field directly. It is implemented only to | ||
// satisfy the errwrap.Wrapper interface. | ||
func (e *Error) WrappedErrors() []error { | ||
return e.err.WrappedErrors() | ||
} | ||
|
||
// Unwrap returns an error from Error (or nil if there are no errors) | ||
func (e *Error) Unwrap() error { | ||
if e == nil || e.err == nil { | ||
return nil | ||
} | ||
return e.err.Unwrap() | ||
} | ||
|
||
// ErrorOrNil returns an error interface if this Error represents | ||
// a list of errors, or returns nil if the list of errors is empty. This | ||
// function is useful at the end of accumulation to make sure that the value | ||
// returned represents the existence of errors. | ||
func (e *Error) ErrorOrNil() error { | ||
if e == nil || e.err == nil { | ||
return nil | ||
} | ||
if len(e.err.Errors) == 0 { | ||
return nil | ||
} | ||
|
||
return e | ||
} | ||
|
||
// Append adds an error to a multierror, if err is | ||
// not a multierror it will be converted to one | ||
func Append(err error, errs ...error) *Error { | ||
switch err := err.(type) { | ||
case *Error: | ||
if err == nil { | ||
err = new(Error) | ||
} | ||
for _, e := range errs { | ||
err.err = multierror.Append(err.err, e) | ||
} | ||
return err | ||
default: | ||
newErrs := make([]error, 0, len(errs)+1) | ||
if err != nil { | ||
newErrs = append(newErrs, err) | ||
} | ||
newErrs = append(newErrs, errs...) | ||
|
||
return Append(&Error{}, newErrs...) | ||
} | ||
} | ||
|
||
func listErrorFunc(errs []error) string { | ||
if len(errs) == 1 { | ||
return errs[0].Error() | ||
} | ||
|
||
messages := make([]string, len(errs)) | ||
|
||
for i, err := range errs { | ||
messages[i] = err.Error() | ||
} | ||
|
||
return strings.Join(messages, "\n") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package multierror | ||
|
||
import ( | ||
"errors" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestSingleError(t *testing.T) { | ||
var err *Error | ||
err = Append(err, errors.New("error")) | ||
assert.Equal(t, 1, len(err.WrappedErrors())) | ||
} | ||
|
||
func TestGoError(t *testing.T) { | ||
var err error | ||
result := Append(err, errors.New("error")) | ||
assert.Equal(t, 1, len(result.WrappedErrors())) | ||
} | ||
|
||
func TestMultiError(t *testing.T) { | ||
var err *Error | ||
err = Append(err, | ||
errors.New("first"), | ||
errors.New("second"), | ||
) | ||
assert.Equal(t, 2, len(err.WrappedErrors())) | ||
assert.Equal(t, "first\nsecond", err.Error()) | ||
} | ||
|
||
func TestUnwrap(t *testing.T) { | ||
var err *Error | ||
assert.Equal(t, nil, errors.Unwrap(err)) | ||
|
||
err = Append(err, errors.New("first")) | ||
e := errors.Unwrap(err) | ||
assert.Equal(t, "first", e.Error()) | ||
} | ||
|
||
func TestErrorOrNil(t *testing.T) { | ||
var err *Error | ||
assert.Equal(t, nil, err.ErrorOrNil()) | ||
|
||
err = Append(err, errors.New("error")) | ||
e := err.ErrorOrNil() | ||
assert.Equal(t, "error", e.Error()) | ||
} |