Add a temporary drop-in replacement for errors.Join
As we have a hard time figuring out what moby/moby#46099 should look like, this drop-in replacement will solve the initial formatting problem we have. It's made internal such that we can remove it whenever we want and unlike moby/moby#46099 doesn't require thoughtful API changes. Signed-off-by: Albin Kerouanton <albinker@gmail.com> Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
220fba06e7
commit
64de635626
2 changed files with 71 additions and 0 deletions
46
internal/multierror/multierror.go
Normal file
46
internal/multierror/multierror.go
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
package multierror
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Join is a drop-in replacement for errors.Join with better formatting.
|
||||||
|
func Join(errs ...error) error {
|
||||||
|
n := 0
|
||||||
|
for _, err := range errs {
|
||||||
|
if err != nil {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if n == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
e := &joinError{
|
||||||
|
errs: make([]error, 0, n),
|
||||||
|
}
|
||||||
|
for _, err := range errs {
|
||||||
|
if err != nil {
|
||||||
|
e.errs = append(e.errs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
type joinError struct {
|
||||||
|
errs []error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *joinError) Error() string {
|
||||||
|
if len(e.errs) == 1 {
|
||||||
|
return strings.TrimSpace(e.errs[0].Error())
|
||||||
|
}
|
||||||
|
stringErrs := make([]string, 0, len(e.errs))
|
||||||
|
for _, subErr := range e.errs {
|
||||||
|
stringErrs = append(stringErrs, strings.Replace(subErr.Error(), "\n", "\n\t", -1))
|
||||||
|
}
|
||||||
|
return "* " + strings.Join(stringErrs, "\n* ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *joinError) Unwrap() []error {
|
||||||
|
return e.errs
|
||||||
|
}
|
25
internal/multierror/multierror_test.go
Normal file
25
internal/multierror/multierror_test.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package multierror
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gotest.tools/v3/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestErrorJoin(t *testing.T) {
|
||||||
|
t.Run("single", func(t *testing.T) {
|
||||||
|
err := Join(fmt.Errorf("invalid config: %w", Join(errors.New("foo"))))
|
||||||
|
const expected = `invalid config: foo`
|
||||||
|
assert.Equal(t, err.Error(), expected)
|
||||||
|
})
|
||||||
|
t.Run("multiple", func(t *testing.T) {
|
||||||
|
err := Join(errors.New("foobar"), fmt.Errorf("invalid config: \n%w", Join(errors.New("foo"), errors.New("bar"))))
|
||||||
|
const expected = `* foobar
|
||||||
|
* invalid config:
|
||||||
|
* foo
|
||||||
|
* bar`
|
||||||
|
assert.Equal(t, err.Error(), expected)
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in a new issue