ソースを参照

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>
Albin Kerouanton 1 年間 前
コミット
64de635626
2 ファイル変更71 行追加0 行削除
  1. 46 0
      internal/multierror/multierror.go
  2. 25 0
      internal/multierror/multierror_test.go

+ 46 - 0
internal/multierror/multierror.go

@@ -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 - 0
internal/multierror/multierror_test.go

@@ -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)
+	})
+}