multierror.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  2. Copyright 2020 Docker, Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package multierror
  14. import (
  15. "strings"
  16. "github.com/hashicorp/go-multierror"
  17. )
  18. // Error wraps a multierror.Error and defines a default
  19. // formatting function that fits cli needs
  20. type Error struct {
  21. err *multierror.Error
  22. }
  23. func (e *Error) Error() string {
  24. if e == nil || e.err == nil {
  25. return ""
  26. }
  27. e.err.ErrorFormat = listErrorFunc
  28. return e.err.Error()
  29. }
  30. // WrappedErrors returns the list of errors that this Error is wrapping.
  31. // It is an implementation of the errwrap.Wrapper interface so that
  32. // multierror.Error can be used with that library.
  33. //
  34. // This method is not safe to be called concurrently and is no different
  35. // than accessing the Errors field directly. It is implemented only to
  36. // satisfy the errwrap.Wrapper interface.
  37. func (e *Error) WrappedErrors() []error {
  38. return e.err.WrappedErrors()
  39. }
  40. // Unwrap returns an error from Error (or nil if there are no errors)
  41. func (e *Error) Unwrap() error {
  42. if e == nil || e.err == nil {
  43. return nil
  44. }
  45. return e.err.Unwrap()
  46. }
  47. // ErrorOrNil returns an error interface if this Error represents
  48. // a list of errors, or returns nil if the list of errors is empty. This
  49. // function is useful at the end of accumulation to make sure that the value
  50. // returned represents the existence of errors.
  51. func (e *Error) ErrorOrNil() error {
  52. if e == nil || e.err == nil {
  53. return nil
  54. }
  55. if len(e.err.Errors) == 0 {
  56. return nil
  57. }
  58. return e
  59. }
  60. // Append adds an error to a multierror, if err is
  61. // not a multierror it will be converted to one
  62. func Append(err error, errs ...error) *Error {
  63. switch err := err.(type) {
  64. case *Error:
  65. if err == nil {
  66. err = new(Error)
  67. }
  68. for _, e := range errs {
  69. err.err = multierror.Append(err.err, e)
  70. }
  71. return err
  72. default:
  73. newErrs := make([]error, 0, len(errs)+1)
  74. if err != nil {
  75. newErrs = append(newErrs, err)
  76. }
  77. newErrs = append(newErrs, errs...)
  78. return Append(&Error{}, newErrs...)
  79. }
  80. }
  81. func listErrorFunc(errs []error) string {
  82. if len(errs) == 1 {
  83. return "Error: " + errs[0].Error()
  84. }
  85. messages := make([]string, len(errs))
  86. for i, err := range errs {
  87. messages[i] = "Error: " + err.Error()
  88. }
  89. return strings.Join(messages, "\n")
  90. }