...

Source file src/sigs.k8s.io/cli-utils/pkg/multierror/multierror.go

Documentation: sigs.k8s.io/cli-utils/pkg/multierror

     1  // Copyright 2022 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package multierror
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  )
    10  
    11  const Prefix = "- "
    12  const Indent = "  "
    13  
    14  type Interface interface {
    15  	Errors() []error
    16  }
    17  
    18  // New returns a new MultiError wrapping the specified error list.
    19  func New(causes ...error) *MultiError {
    20  	return &MultiError{
    21  		Causes: causes,
    22  	}
    23  }
    24  
    25  // MultiError wraps multiple errors and formats them for multi-line output.
    26  type MultiError struct {
    27  	Causes []error
    28  }
    29  
    30  func (mve *MultiError) Errors() []error {
    31  	return mve.Causes
    32  }
    33  
    34  func (mve *MultiError) Error() string {
    35  	if len(mve.Causes) == 1 {
    36  		return mve.Causes[0].Error()
    37  	}
    38  	var b strings.Builder
    39  	_, _ = fmt.Fprintf(&b, "%d errors:\n", len(mve.Causes))
    40  	for _, err := range mve.Causes {
    41  		_, _ = fmt.Fprintf(&b, "%s\n", formatError(err))
    42  	}
    43  	return b.String()
    44  }
    45  
    46  func formatError(err error) string {
    47  	lines := strings.Split(err.Error(), "\n")
    48  	return Prefix + strings.Join(lines, fmt.Sprintf("\n%s", Indent))
    49  }
    50  
    51  // Wrap merges zero or more errors and/or MultiErrors into one error.
    52  // MultiErrors are recursively unwrapped to reduce depth.
    53  // If only one error is received, that error is returned without a wrapper.
    54  func Wrap(errs ...error) error {
    55  	if len(errs) == 0 {
    56  		return nil
    57  	}
    58  	errs = Unwrap(errs...)
    59  	var err error
    60  	switch {
    61  	case len(errs) == 0:
    62  		err = nil
    63  	case len(errs) == 1:
    64  		err = errs[0]
    65  	case len(errs) > 1:
    66  		err = &MultiError{
    67  			Causes: errs,
    68  		}
    69  	}
    70  	return err
    71  }
    72  
    73  // Unwrap flattens zero or more errors and/or MultiErrors into a list of errors.
    74  // MultiErrors are recursively unwrapped to reduce depth.
    75  func Unwrap(errs ...error) []error {
    76  	if len(errs) == 0 {
    77  		return nil
    78  	}
    79  	var errors []error
    80  	for _, err := range errs {
    81  		if mve, ok := err.(Interface); ok {
    82  			// Recursively unwrap MultiErrors
    83  			for _, cause := range mve.Errors() {
    84  				errors = append(errors, Unwrap(cause)...)
    85  			}
    86  		} else {
    87  			errors = append(errors, err)
    88  		}
    89  	}
    90  	return errors
    91  }
    92  

View as plain text