From 31fee45604949934710ada68f0b307c4726fb4e8 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 15 Dec 2014 11:55:20 -0800 Subject: [PATCH 01/80] Initial commit --- README.md | 17 ++++++++++++ format.go | 23 ++++++++++++++++ format_test.go | 23 ++++++++++++++++ multierror.go | 54 ++++++++++++++++++++++++++++++++++++ multierror_test.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 185 insertions(+) create mode 100644 README.md create mode 100644 format.go create mode 100644 format_test.go create mode 100644 multierror.go create mode 100644 multierror_test.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..12629e7 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# go-multierror + +`go-multierror` is a package for Go that provides a mechanism for +representing a list of `error` values as a single `error`. + +This allows a function in Go to return an `error` that might actually +be a list of errors. If the caller knows this, they can unwrap the +list and access the errors. If the caller doesn't know, the error +formats to a nice human-readable format. + +## Installation and Docs + +Install using `go get github.com/hashicorp/go-multierror`. + +Full documentation is available at +http://godoc.org/github.com/hashicorp/go-multierror + diff --git a/format.go b/format.go new file mode 100644 index 0000000..5dd1ac1 --- /dev/null +++ b/format.go @@ -0,0 +1,23 @@ +package multierror + +import ( + "fmt" + "strings" +) + +// ErrorFormatFunc is a function callback that is called by Error to +// turn the list of errors into a string. +type ErrorFormatFunc func([]error) string + +// ListFormatFunc is a basic formatter that outputs the number of errors +// that occurred along with a bullet point list of the errors. +func ListFormatFunc(es []error) string { + points := make([]string, len(es)) + for i, err := range es { + points[i] = fmt.Sprintf("* %s", err) + } + + return fmt.Sprintf( + "%d error(s) occurred:\n\n%s", + len(es), strings.Join(points, "\n")) +} diff --git a/format_test.go b/format_test.go new file mode 100644 index 0000000..a3d7b8e --- /dev/null +++ b/format_test.go @@ -0,0 +1,23 @@ +package multierror + +import ( +"errors" +"testing" +) + +func TestListFormatFunc(t *testing.T) { + expected := `2 error(s) occurred: + +* foo +* bar` + + errors := []error{ + errors.New("foo"), + errors.New("bar"), + } + + actual := ListFormatFunc(errors) + if actual != expected { + t.Fatalf("bad: %#v", actual) + } +} diff --git a/multierror.go b/multierror.go new file mode 100644 index 0000000..64021a9 --- /dev/null +++ b/multierror.go @@ -0,0 +1,54 @@ +package multierror + +import ( + "fmt" +) + +// Error is an error type to track multiple errors. This is used to +// accumulate errors in cases and return them as a single "error". +type Error struct { + Errors []error + ErrorFormat ErrorFormatFunc +} + +func (e *Error) Error() string { + fn := e.ErrorFormat + if fn == nil { + fn = ListFormatFunc + } + + return fn(e.Errors) +} + +func (e *Error) GoString() string { + return fmt.Sprintf("*%#v", *e) +} + +// ErrorAppend is a helper function that will append more errors +// onto an Error in order to create a larger multi-error. +// +// If err is not a multierror.Error, then it will be turned into +// one. If any of the errs are multierr.Error, they will be flattened +// one level into err. +func ErrorAppend(err error, errs ...error) *Error { + if err == nil { + err = new(Error) + } + + switch err := err.(type) { + case *Error: + if err == nil { + err = new(Error) + } + + err.Errors = append(err.Errors, errs...) + return err + default: + newErrs := make([]error, len(errs)+1) + newErrs[0] = err + copy(newErrs[1:], errs) + return &Error{ + Errors: newErrs, + } + } +} diff --git a/multierror_test.go b/multierror_test.go new file mode 100644 index 0000000..17aae3f --- /dev/null +++ b/multierror_test.go @@ -0,0 +1,68 @@ +package multierror + +import ( + "errors" + "testing" +) + +func TestError_Impl(t *testing.T) { + var _ error = new(Error) +} + +func TestErrorError_custom(t *testing.T) { + errors := []error{ + errors.New("foo"), + errors.New("bar"), + } + + fn := func(es []error) string { + return "foo" + } + + multi := &Error{Errors: errors, ErrorFormat: fn} + if multi.Error() != "foo" { + t.Fatalf("bad: %s", multi.Error()) + } +} + +func TestErrorError_default(t *testing.T) { + expected := `2 error(s) occurred: + +* foo +* bar` + + errors := []error{ + errors.New("foo"), + errors.New("bar"), + } + + multi := &Error{Errors: errors} + if multi.Error() != expected { + t.Fatalf("bad: %s", multi.Error()) + } +} + +func TestErrorAppend_Error(t *testing.T) { + original := &Error{ + Errors: []error{errors.New("foo")}, + } + + result := ErrorAppend(original, errors.New("bar")) + if len(result.Errors) != 2 { + t.Fatalf("wrong len: %d", len(result.Errors)) + } + + original = &Error{} + result = ErrorAppend(original, errors.New("bar")) + if len(result.Errors) != 1 { + t.Fatalf("wrong len: %d", len(result.Errors)) + } +} + +func TestErrorAppend_NonError(t *testing.T) { + original := errors.New("foo") + result := ErrorAppend(original, errors.New("bar")) + if len(result.Errors) != 2 { + t.Fatalf("wrong len: %d", len(result.Errors)) + } +} From 351525aa3b455744221c953b77ab1395e2b24b7f Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 15 Dec 2014 11:55:27 -0800 Subject: [PATCH 02/80] fmt --- format.go | 4 ++-- format_test.go | 12 ++++++------ multierror.go | 14 +++++++------- multierror_test.go | 8 ++++---- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/format.go b/format.go index 5dd1ac1..bb65a12 100644 --- a/format.go +++ b/format.go @@ -1,8 +1,8 @@ package multierror import ( - "fmt" - "strings" + "fmt" + "strings" ) // ErrorFormatFunc is a function callback that is called by Error to diff --git a/format_test.go b/format_test.go index a3d7b8e..d7cee5d 100644 --- a/format_test.go +++ b/format_test.go @@ -1,8 +1,8 @@ package multierror import ( -"errors" -"testing" + "errors" + "testing" ) func TestListFormatFunc(t *testing.T) { @@ -16,8 +16,8 @@ func TestListFormatFunc(t *testing.T) { errors.New("bar"), } - actual := ListFormatFunc(errors) - if actual != expected { - t.Fatalf("bad: %#v", actual) - } + actual := ListFormatFunc(errors) + if actual != expected { + t.Fatalf("bad: %#v", actual) + } } diff --git a/multierror.go b/multierror.go index 64021a9..dc5a8b9 100644 --- a/multierror.go +++ b/multierror.go @@ -7,17 +7,17 @@ import ( // Error is an error type to track multiple errors. This is used to // accumulate errors in cases and return them as a single "error". type Error struct { - Errors []error - ErrorFormat ErrorFormatFunc + Errors []error + ErrorFormat ErrorFormatFunc } func (e *Error) Error() string { - fn := e.ErrorFormat - if fn == nil { - fn = ListFormatFunc - } + fn := e.ErrorFormat + if fn == nil { + fn = ListFormatFunc + } - return fn(e.Errors) + return fn(e.Errors) } func (e *Error) GoString() string { diff --git a/multierror_test.go b/multierror_test.go index 17aae3f..dd987b6 100644 --- a/multierror_test.go +++ b/multierror_test.go @@ -6,7 +6,7 @@ import ( ) func TestError_Impl(t *testing.T) { - var _ error = new(Error) + var _ error = new(Error) } func TestErrorError_custom(t *testing.T) { @@ -15,9 +15,9 @@ func TestErrorError_custom(t *testing.T) { errors.New("bar"), } - fn := func(es []error) string { - return "foo" - } + fn := func(es []error) string { + return "foo" + } multi := &Error{Errors: errors, ErrorFormat: fn} if multi.Error() != "foo" { From cc8c0521353341aa28332d4c4c3c26b6691b3e75 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 15 Dec 2014 11:58:17 -0800 Subject: [PATCH 03/80] Implement errwrap.Wrapper --- multierror.go | 11 +++++++++++ multierror_test.go | 13 +++++++++++++ 2 files changed, 24 insertions(+) diff --git a/multierror.go b/multierror.go index dc5a8b9..21a31f7 100644 --- a/multierror.go +++ b/multierror.go @@ -24,6 +24,17 @@ func (e *Error) GoString() string { return fmt.Sprintf("*%#v", *e) } +// WrappedErrors returns the list of errors that this Error is wrapping. +// It is an implementatin 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 implementd only to +// satisfy the errwrap.Wrapper interface. +func (e *Error) WrappedErrors() []error { + return e.Errors +} + // ErrorAppend is a helper function that will append more errors // onto an Error in order to create a larger multi-error. // diff --git a/multierror_test.go b/multierror_test.go index dd987b6..d5d3467 100644 --- a/multierror_test.go +++ b/multierror_test.go @@ -2,6 +2,7 @@ package multierror import ( "errors" + "reflect" "testing" ) @@ -42,6 +43,18 @@ func TestErrorError_default(t *testing.T) { } } +func TestErrorWrappedErrors(t *testing.T) { + errors := []error{ + errors.New("foo"), + errors.New("bar"), + } + + multi := &Error{Errors: errors} + if !reflect.DeepEqual(multi.Errors, multi.WrappedErrors()) { + t.Fatalf("bad: %s", multi.WrappedErrors()) + } +} + func TestErrorAppend_Error(t *testing.T) { original := &Error{ Errors: []error{errors.New("foo")}, From c951c293c13ff957d6667335a64693ac4cbb0665 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 15 Dec 2014 12:02:12 -0800 Subject: [PATCH 04/80] Move Append to a diff file --- append.go | 30 ++++++++++++++++++++++++++++++ append_test.go | 31 +++++++++++++++++++++++++++++++ multierror.go | 29 ----------------------------- multierror_test.go | 25 ------------------------- 4 files changed, 61 insertions(+), 54 deletions(-) create mode 100644 append.go create mode 100644 append_test.go diff --git a/append.go b/append.go new file mode 100644 index 0000000..75d46d7 --- /dev/null +++ b/append.go @@ -0,0 +1,30 @@ +package multierror + +// Append is a helper function that will append more errors +// onto an Error in order to create a larger multi-error. +// +// If err is not a multierror.Error, then it will be turned into +// one. If any of the errs are multierr.Error, they will be flattened +// one level into err. +func Append(err error, errs ...error) *Error { + if err == nil { + err = new(Error) + } + + switch err := err.(type) { + case *Error: + if err == nil { + err = new(Error) + } + + err.Errors = append(err.Errors, errs...) + return err + default: + newErrs := make([]error, len(errs)+1) + newErrs[0] = err + copy(newErrs[1:], errs) + return &Error{ + Errors: newErrs, + } + } +} diff --git a/append_test.go b/append_test.go new file mode 100644 index 0000000..2dc88f7 --- /dev/null +++ b/append_test.go @@ -0,0 +1,31 @@ +package multierror + +import ( + "errors" + "testing" +) + +func TestAppend_Error(t *testing.T) { + original := &Error{ + Errors: []error{errors.New("foo")}, + } + + result := Append(original, errors.New("bar")) + if len(result.Errors) != 2 { + t.Fatalf("wrong len: %d", len(result.Errors)) + } + + original = &Error{} + result = Append(original, errors.New("bar")) + if len(result.Errors) != 1 { + t.Fatalf("wrong len: %d", len(result.Errors)) + } +} + +func TestAppend_NonError(t *testing.T) { + original := errors.New("foo") + result := Append(original, errors.New("bar")) + if len(result.Errors) != 2 { + t.Fatalf("wrong len: %d", len(result.Errors)) + } +} diff --git a/multierror.go b/multierror.go index 21a31f7..70f0593 100644 --- a/multierror.go +++ b/multierror.go @@ -34,32 +34,3 @@ func (e *Error) GoString() string { func (e *Error) WrappedErrors() []error { return e.Errors } - -// ErrorAppend is a helper function that will append more errors -// onto an Error in order to create a larger multi-error. -// -// If err is not a multierror.Error, then it will be turned into -// one. If any of the errs are multierr.Error, they will be flattened -// one level into err. -func ErrorAppend(err error, errs ...error) *Error { - if err == nil { - err = new(Error) - } - - switch err := err.(type) { - case *Error: - if err == nil { - err = new(Error) - } - - err.Errors = append(err.Errors, errs...) - return err - default: - newErrs := make([]error, len(errs)+1) - newErrs[0] = err - copy(newErrs[1:], errs) - return &Error{ - Errors: newErrs, - } - } -} diff --git a/multierror_test.go b/multierror_test.go index d5d3467..60cbc18 100644 --- a/multierror_test.go +++ b/multierror_test.go @@ -54,28 +54,3 @@ func TestErrorWrappedErrors(t *testing.T) { t.Fatalf("bad: %s", multi.WrappedErrors()) } } - -func TestErrorAppend_Error(t *testing.T) { - original := &Error{ - Errors: []error{errors.New("foo")}, - } - - result := ErrorAppend(original, errors.New("bar")) - if len(result.Errors) != 2 { - t.Fatalf("wrong len: %d", len(result.Errors)) - } - - original = &Error{} - result = ErrorAppend(original, errors.New("bar")) - if len(result.Errors) != 1 { - t.Fatalf("wrong len: %d", len(result.Errors)) - } -} - -func TestErrorAppend_NonError(t *testing.T) { - original := errors.New("foo") - result := ErrorAppend(original, errors.New("bar")) - if len(result.Errors) != 2 { - t.Fatalf("wrong len: %d", len(result.Errors)) - } -} From 3412a9606733526c87d453265e84dfc428c3fb56 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 15 Dec 2014 12:02:41 -0800 Subject: [PATCH 05/80] LICENSE --- LICENSE | 353 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 353 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..82b4de9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,353 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor” + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version” + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution” + + means Covered Software of a particular Contributor. + +1.4. “Covered Software” + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses” + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form” + + means any form of the work other than Source Code Form. + +1.7. “Larger Work” + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License” + + means this document. + +1.9. “Licensable” + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications” + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License” + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” + + means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control” means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses” Notice + + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by + the Mozilla Public License, v. 2.0. From b86fdbf8a60fad315ca2c1b9f18c5c91efbf2ea5 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 15 Dec 2014 12:13:29 -0800 Subject: [PATCH 06/80] Update README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 12629e7..6633427 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,10 @@ be a list of errors. If the caller knows this, they can unwrap the list and access the errors. If the caller doesn't know, the error formats to a nice human-readable format. +`go-multierror` implements the +[errwrap](https://github.com/hashicorp/errwrap) interface so that it can +be used with that library, as well. + ## Installation and Docs Install using `go get github.com/hashicorp/go-multierror`. From 7624a15c166e945929ebe08e2c27b6d4098fc57f Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 15 Dec 2014 12:23:40 -0800 Subject: [PATCH 07/80] Update README --- README.md | 70 ++++++++++++++++++++++++++++++++++++++++++++++ multierror.go | 15 ++++++++++ multierror_test.go | 14 ++++++++++ 3 files changed, 99 insertions(+) diff --git a/README.md b/README.md index 6633427..e81be50 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,73 @@ Install using `go get github.com/hashicorp/go-multierror`. Full documentation is available at http://godoc.org/github.com/hashicorp/go-multierror +## Usage + +go-multierror is easy to use and purposely built to be unobtrusive in +existing Go applications/libraries that may not be aware of it. + +**Building a list of errors** + +The `Append` function is used to create a list of errors. This function +behaves a lot like the Go built-in `append` function: it doesn't matter +if the first argument is nil, a `multierror.Error`, or any other `error`, +the function behaves as you would expect. + +```go +var result error + +if err := step1(); err != nil { + result = multierror.Append(result, err) +} +if err := step2(); err != nil { + result = multierror.Append(result, err) +} + +return result +``` + +**Customizing the formatting of the errors** + +By specifying a custom `ErrorFormat`, you can customize the format +of the `Error() string` function: + +```go +var result *multierror.Error + +// ... accumulate errors here, maybe using Append + +if result != nil { + result.ErrorFormat = func([]error) string { + return "errors!" + } +} +``` + +**Accessing the list of errors** + +`multierror.Error` implements `error` so if the caller doesn't know about +multierror, it will work just fine. But if you're aware a multierror might +be returned, you can use type switches to access the list of errors: + +```go +if err := something(); err != nil { + if merr, ok := err.(*multierror.Error); ok { + // Use merr.Errors + } +} +``` + +**Returning a multierror only if there are errors** + +If you build a `multierror.Error`, you can use the `ErrorOrNil` function +to return an `error` implementation only if there are errors to return: + +```go +var result *multierror.Error + +// ... accumulate errors here + +// Return the `error` only if errors were added to the multierror, otherwise +// return nil since there are no errors. +return result.ErrorOrNil() +``` diff --git a/multierror.go b/multierror.go index 70f0593..2ea0827 100644 --- a/multierror.go +++ b/multierror.go @@ -20,6 +20,21 @@ func (e *Error) Error() string { return fn(e.Errors) } +// 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 { + return nil + } + if len(e.Errors) == 0 { + return nil + } + + return e +} + func (e *Error) GoString() string { return fmt.Sprintf("*%#v", *e) } diff --git a/multierror_test.go b/multierror_test.go index 60cbc18..3e78079 100644 --- a/multierror_test.go +++ b/multierror_test.go @@ -43,6 +43,20 @@ func TestErrorError_default(t *testing.T) { } } +func TestErrorErrorOrNil(t *testing.T) { + err := new(Error) + if err.ErrorOrNil() != nil { + t.Fatalf("bad: %#v", err.ErrorOrNil()) + } + + err.Errors = []error{errors.New("foo")} + if v := err.ErrorOrNil(); v == nil { + t.Fatal("should not be nil") + } else if !reflect.DeepEqual(v, err) { + t.Fatalf("bad: %#v", v) + } +} + func TestErrorWrappedErrors(t *testing.T) { errors := []error{ errors.New("foo"), From 180dbfc5c52c01243834401c569ac0390ca5e3f9 Mon Sep 17 00:00:00 2001 From: Max Nordlund Date: Tue, 6 Jan 2015 03:57:57 +0100 Subject: [PATCH 08/80] Remove unneeded nil check in Append --- append.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/append.go b/append.go index 75d46d7..408af5d 100644 --- a/append.go +++ b/append.go @@ -13,10 +13,6 @@ func Append(err error, errs ...error) *Error { switch err := err.(type) { case *Error: - if err == nil { - err = new(Error) - } - err.Errors = append(err.Errors, errs...) return err default: From 2167c8ec40776024589f483a6b836489e47e1049 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Wed, 7 Jan 2015 12:23:39 -0800 Subject: [PATCH 09/80] Add back nil check (reverts 180dbfc). Typed nils can reach the code path. We can't do an assignment to a struct field on a typed nil, so we still need to check and initialize. --- append.go | 9 +++++---- append_test.go | 7 +++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/append.go b/append.go index 408af5d..0d108b1 100644 --- a/append.go +++ b/append.go @@ -7,12 +7,13 @@ package multierror // one. If any of the errs are multierr.Error, they will be flattened // one level into err. func Append(err error, errs ...error) *Error { - if err == nil { - err = new(Error) - } - switch err := err.(type) { case *Error: + // Typed nils can reach here, so initialize if we are nil + if err == nil { + err = new(Error) + } + err.Errors = append(err.Errors, errs...) return err default: diff --git a/append_test.go b/append_test.go index 2dc88f7..3875899 100644 --- a/append_test.go +++ b/append_test.go @@ -20,6 +20,13 @@ func TestAppend_Error(t *testing.T) { if len(result.Errors) != 1 { t.Fatalf("wrong len: %d", len(result.Errors)) } + + // Test when a typed nil is passed + var e *Error + result = Append(e, errors.New("baz")) + if len(result.Errors) != 1 { + t.Fatalf("wrong len: %d", len(result.Errors)) + } } func TestAppend_NonError(t *testing.T) { From 77a3a4f68bd6b59bb0a361cf16ed5fa8489df350 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 26 Jan 2015 21:16:53 -0800 Subject: [PATCH 10/80] Handle nil in Append properly --- append.go | 11 ++++++++--- append_test.go | 7 +++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/append.go b/append.go index 0d108b1..d7b555c 100644 --- a/append.go +++ b/append.go @@ -17,9 +17,14 @@ func Append(err error, errs ...error) *Error { err.Errors = append(err.Errors, errs...) return err default: - newErrs := make([]error, len(errs)+1) - newErrs[0] = err - copy(newErrs[1:], errs) + newErrs := make([]error, 0, len(errs)+1) + if err != nil { + newErrs = append(newErrs, err) + } + for _, err := range errs { + newErrs = append(newErrs, err) + } + return &Error{ Errors: newErrs, } diff --git a/append_test.go b/append_test.go index 3875899..1fe8a4c 100644 --- a/append_test.go +++ b/append_test.go @@ -29,6 +29,13 @@ func TestAppend_Error(t *testing.T) { } } +func TestAppend_NilError(t *testing.T) { + var err error + result := Append(err, errors.New("bar")) + if len(result.Errors) != 1 { + t.Fatalf("wrong len: %d", len(result.Errors)) + } +} func TestAppend_NonError(t *testing.T) { original := errors.New("foo") result := Append(original, errors.New("bar")) From fcdddc395df1ddf4247c69bd436e84cfa0733f7e Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 26 Jan 2015 21:19:36 -0800 Subject: [PATCH 11/80] Slight code cleanup --- append.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/append.go b/append.go index d7b555c..8d22ee7 100644 --- a/append.go +++ b/append.go @@ -21,9 +21,7 @@ func Append(err error, errs ...error) *Error { if err != nil { newErrs = append(newErrs, err) } - for _, err := range errs { - newErrs = append(newErrs, err) - } + newErrs = append(newErrs, errs...) return &Error{ Errors: newErrs, From 4c21163ea4f2484b8808210b2d271396af025b8b Mon Sep 17 00:00:00 2001 From: Paul Hinze Date: Sun, 7 Jun 2015 21:27:13 -0500 Subject: [PATCH 12/80] Flatten Useful for cleaning up potentially nested multierrors before output. --- flatten.go | 18 ++++++++++++++++++ flatten_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 flatten.go create mode 100644 flatten_test.go diff --git a/flatten.go b/flatten.go new file mode 100644 index 0000000..f97da1e --- /dev/null +++ b/flatten.go @@ -0,0 +1,18 @@ +package multierror + +func Flatten(err error) error { + flatErr := new(Error) + flatten(err, flatErr) + return error(flatErr) +} + +func flatten(err error, flatErr *Error) { + switch err := err.(type) { + case *Error: + for _, e := range err.Errors { + flatten(e, flatErr) + } + default: + flatErr.Errors = append(flatErr.Errors, err) + } +} diff --git a/flatten_test.go b/flatten_test.go new file mode 100644 index 0000000..d16248f --- /dev/null +++ b/flatten_test.go @@ -0,0 +1,39 @@ +package multierror + +import ( + "errors" + "fmt" + "strings" + "testing" +) + +func TestFlatten(t *testing.T) { + original := &Error{ + Errors: []error{ + errors.New("one"), + &Error{ + Errors: []error{ + errors.New("two"), + &Error{ + Errors: []error{ + errors.New("three"), + }, + }, + }, + }, + }, + } + + expected := strings.TrimSpace(` +3 error(s) occurred: + +* one +* two +* three + `) + actual := fmt.Sprintf("%s", Flatten(original)) + + if expected != actual { + t.Fatalf("expected: %s, got: %s", expected, actual) + } +} From 3ec4037e09c13c22cfbe4bb60c8d9d46cf3ea10a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 7 Jun 2015 20:31:26 -0700 Subject: [PATCH 13/80] add docstring for flatten --- flatten.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flatten.go b/flatten.go index f97da1e..cfdbbe3 100644 --- a/flatten.go +++ b/flatten.go @@ -1,5 +1,7 @@ package multierror +// Flatten flattens the given error, merging any *Errors together into +// a single *Error. func Flatten(err error) error { flatErr := new(Error) flatten(err, flatErr) From 56912fb08d85084aa318edcf2bba735b97cf35c5 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 7 Jun 2015 20:35:21 -0700 Subject: [PATCH 14/80] if top-level error in flatten is not Error, return as-is /cc @phinze --- flatten.go | 10 ++++++++-- flatten_test.go | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/flatten.go b/flatten.go index cfdbbe3..aab8e9a 100644 --- a/flatten.go +++ b/flatten.go @@ -1,11 +1,17 @@ package multierror -// Flatten flattens the given error, merging any *Errors together into +// Flatten flattens the given error, merging any *Errors together into // a single *Error. func Flatten(err error) error { + // If it isn't an *Error, just return the error as-is + if _, ok := err.(*Error); !ok { + return err + } + + // Otherwise, make the result and flatten away! flatErr := new(Error) flatten(err, flatErr) - return error(flatErr) + return flatErr } func flatten(err error, flatErr *Error) { diff --git a/flatten_test.go b/flatten_test.go index d16248f..75218f1 100644 --- a/flatten_test.go +++ b/flatten_test.go @@ -3,6 +3,7 @@ package multierror import ( "errors" "fmt" + "reflect" "strings" "testing" ) @@ -37,3 +38,11 @@ func TestFlatten(t *testing.T) { t.Fatalf("expected: %s, got: %s", expected, actual) } } + +func TestFlatten_nonError(t *testing.T) { + err := errors.New("foo") + actual := Flatten(err) + if !reflect.DeepEqual(actual, err) { + t.Fatalf("bad: %#v", actual) + } +} From 0ea17d6d64fa0b4b87fd32ec5005824b348c474d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 16 Sep 2015 13:35:54 -0700 Subject: [PATCH 15/80] Prefix --- prefix.go | 37 +++++++++++++++++++++++++++++++++++++ prefix_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 prefix.go create mode 100644 prefix_test.go diff --git a/prefix.go b/prefix.go new file mode 100644 index 0000000..5c477ab --- /dev/null +++ b/prefix.go @@ -0,0 +1,37 @@ +package multierror + +import ( + "fmt" + + "github.com/hashicorp/errwrap" +) + +// Prefix is a helper function that will prefix some text +// to the given error. If the error is a multierror.Error, then +// it will be prefixed to each wrapped error. +// +// This is useful to use when appending multiple multierrors +// together in order to give better scoping. +func Prefix(err error, prefix string) error { + if err == nil { + return nil + } + + format := fmt.Sprintf("%s {{err}}", prefix) + switch err := err.(type) { + case *Error: + // Typed nils can reach here, so initialize if we are nil + if err == nil { + err = new(Error) + } + + // Wrap each of the errors + for i, e := range err.Errors { + err.Errors[i] = errwrap.Wrapf(format, e) + } + + return err + default: + return errwrap.Wrapf(format, err) + } +} diff --git a/prefix_test.go b/prefix_test.go new file mode 100644 index 0000000..1d4a6f6 --- /dev/null +++ b/prefix_test.go @@ -0,0 +1,33 @@ +package multierror + +import ( + "errors" + "testing" +) + +func TestPrefix_Error(t *testing.T) { + original := &Error{ + Errors: []error{errors.New("foo")}, + } + + result := Prefix(original, "bar") + if result.(*Error).Errors[0].Error() != "bar foo" { + t.Fatalf("bad: %s", result) + } +} + +func TestPrefix_NilError(t *testing.T) { + var err error + result := Prefix(err, "bar") + if result != nil { + t.Fatalf("bad: %#v", result) + } +} + +func TestPrefix_NonError(t *testing.T) { + original := errors.New("foo") + result := Prefix(original, "bar") + if result.Error() != "bar foo" { + t.Fatalf("bad: %s", result) + } +} From 2bb6fce64edeffc7a7219fce1bfb90b5927732b8 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 16 Sep 2015 13:50:24 -0700 Subject: [PATCH 16/80] append flattens one level, as the docs have always said --- append.go | 11 ++++++++++- append_test.go | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/append.go b/append.go index 8d22ee7..b51cbf8 100644 --- a/append.go +++ b/append.go @@ -14,7 +14,16 @@ func Append(err error, errs ...error) *Error { err = new(Error) } - err.Errors = append(err.Errors, errs...) + // Go through each error and flatten + for _, e := range errs { + switch e := e.(type) { + case *Error: + err.Errors = append(err.Errors, e.Errors...) + default: + err.Errors = append(err.Errors, e) + } + } + return err default: newErrs := make([]error, 0, len(errs)+1) diff --git a/append_test.go b/append_test.go index 1fe8a4c..fa5ccee 100644 --- a/append_test.go +++ b/append_test.go @@ -27,6 +27,16 @@ func TestAppend_Error(t *testing.T) { if len(result.Errors) != 1 { t.Fatalf("wrong len: %d", len(result.Errors)) } + + // Test flattening + original = &Error{ + Errors: []error{errors.New("foo")}, + } + + result = Append(original, Append(nil, errors.New("foo"), errors.New("bar"))) + if len(result.Errors) != 3 { + t.Fatalf("wrong len: %d", len(result.Errors)) + } } func TestAppend_NilError(t *testing.T) { From d30f09973e19c1dfcd120b2d9c4f168e68d6b5d5 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 16 Sep 2015 13:57:42 -0700 Subject: [PATCH 17/80] append should flatten --- append.go | 4 +--- append_test.go | 9 +++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/append.go b/append.go index b51cbf8..00afa9b 100644 --- a/append.go +++ b/append.go @@ -32,8 +32,6 @@ func Append(err error, errs ...error) *Error { } newErrs = append(newErrs, errs...) - return &Error{ - Errors: newErrs, - } + return Append(&Error{}, newErrs...) } } diff --git a/append_test.go b/append_test.go index fa5ccee..dfa79e2 100644 --- a/append_test.go +++ b/append_test.go @@ -46,6 +46,7 @@ func TestAppend_NilError(t *testing.T) { t.Fatalf("wrong len: %d", len(result.Errors)) } } + func TestAppend_NonError(t *testing.T) { original := errors.New("foo") result := Append(original, errors.New("bar")) @@ -53,3 +54,11 @@ func TestAppend_NonError(t *testing.T) { t.Fatalf("wrong len: %d", len(result.Errors)) } } + +func TestAppend_NonError_Error(t *testing.T) { + original := errors.New("foo") + result := Append(original, Append(nil, errors.New("bar"))) + if len(result.Errors) != 2 { + t.Fatalf("wrong len: %d", len(result.Errors)) + } +} From b06cdf77f3c0c938c09328e105f35e09d6e94fd0 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Wed, 10 Aug 2016 21:51:04 -0400 Subject: [PATCH 18/80] Add travis stuff --- .travis.yml | 12 ++++++++++++ Makefile | 31 +++++++++++++++++++++++++++++++ README.md | 6 ++++++ 3 files changed, 49 insertions(+) create mode 100644 .travis.yml create mode 100644 Makefile diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..4b865d1 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +sudo: false + +language: go + +go: + - 1.6 + +branches: + only: + - master + +script: make test testrace diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b97cd6e --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ +TEST?=./... + +default: test + +# test runs the test suite and vets the code. +test: generate + @echo "==> Running tests..." + @go list $(TEST) \ + | grep -v "/vendor/" \ + | xargs -n1 go test -timeout=60s -parallel=10 ${TESTARGS} + +# testrace runs the race checker +testrace: generate + @echo "==> Running tests (race)..." + @go list $(TEST) \ + | grep -v "/vendor/" \ + | xargs -n1 go test -timeout=60s -race ${TESTARGS} + +# updatedeps installs all the dependencies needed to run and build. +updatedeps: + @sh -c "'${CURDIR}/scripts/deps.sh' '${NAME}'" + +# generate runs `go generate` to build the dynamically generated source files. +generate: + @echo "==> Generating..." + @find . -type f -name '.DS_Store' -delete + @go list ./... \ + | grep -v "/vendor/" \ + | xargs -n1 go generate + +.PHONY: default test testrace updatedeps generate diff --git a/README.md b/README.md index e81be50..ead5830 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # go-multierror +[![Build Status](http://img.shields.io/travis/hashicorp/go-multierror.svg?style=flat-square)][travis] +[![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)][godocs] + +[travis]: https://travis-ci.org/hashicorp/go-multierror +[godocs]: https://godoc.org/github.com/hashicorp/go-multierror + `go-multierror` is a package for Go that provides a mechanism for representing a list of `error` values as a single `error`. From 8c5f0ad9360406a3807ce7de6bc73269a91a6e51 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Wed, 10 Aug 2016 21:57:21 -0400 Subject: [PATCH 19/80] Add deps script --- scripts/deps.sh | 54 +++ vendor/github.com/hashicorp/errwrap/LICENSE | 354 ++++++++++++++++++ vendor/github.com/hashicorp/errwrap/README.md | 89 +++++ .../github.com/hashicorp/errwrap/errwrap.go | 169 +++++++++ vendor/vendor.json | 13 + 5 files changed, 679 insertions(+) create mode 100755 scripts/deps.sh create mode 100644 vendor/github.com/hashicorp/errwrap/LICENSE create mode 100644 vendor/github.com/hashicorp/errwrap/README.md create mode 100644 vendor/github.com/hashicorp/errwrap/errwrap.go create mode 100644 vendor/vendor.json diff --git a/scripts/deps.sh b/scripts/deps.sh new file mode 100755 index 0000000..1d2fcf9 --- /dev/null +++ b/scripts/deps.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# +# This script updates dependencies using a temporary directory. This is required +# to avoid any auxillary dependencies that sneak into GOPATH. +set -e + +# Get the parent directory of where this script is. +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done +DIR="$(cd -P "$(dirname "$SOURCE")/.." && pwd)" + +# Change into that directory +cd "$DIR" + +# Get the name from the directory +NAME=${NAME:-"$(basename $(pwd))"} + +# Announce +echo "==> Updating dependencies..." + +echo "--> Making tmpdir..." +tmpdir=$(mktemp -d) +function cleanup { + rm -rf "${tmpdir}" +} +trap cleanup EXIT + +export GOPATH="${tmpdir}" +export PATH="${tmpdir}/bin:$PATH" + +mkdir -p "${tmpdir}/src/github.com/hashicorp" +pushd "${tmpdir}/src/github.com/hashicorp" &>/dev/null + +echo "--> Copying ${NAME}..." +cp -R "$DIR" "${tmpdir}/src/github.com/hashicorp/${NAME}" +pushd "${tmpdir}/src/github.com/hashicorp/${NAME}" &>/dev/null +rm -rf vendor/ + +echo "--> Installing dependency manager..." +go get -u github.com/kardianos/govendor +govendor init + +echo "--> Installing all dependencies (may take some time)..." +govendor fetch -v +outside + +echo "--> Vendoring..." +govendor add +external + +echo "--> Moving into place..." +vpath="${tmpdir}/src/github.com/hashicorp/${NAME}/vendor" +popd &>/dev/null +popd &>/dev/null +rm -rf vendor/ +cp -R "${vpath}" . diff --git a/vendor/github.com/hashicorp/errwrap/LICENSE b/vendor/github.com/hashicorp/errwrap/LICENSE new file mode 100644 index 0000000..c33dcc7 --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/LICENSE @@ -0,0 +1,354 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor” + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version” + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution” + + means Covered Software of a particular Contributor. + +1.4. “Covered Software” + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses” + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form” + + means any form of the work other than Source Code Form. + +1.7. “Larger Work” + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License” + + means this document. + +1.9. “Licensable” + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications” + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License” + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” + + means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control” means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses” Notice + + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by + the Mozilla Public License, v. 2.0. + diff --git a/vendor/github.com/hashicorp/errwrap/README.md b/vendor/github.com/hashicorp/errwrap/README.md new file mode 100644 index 0000000..1c95f59 --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/README.md @@ -0,0 +1,89 @@ +# errwrap + +`errwrap` is a package for Go that formalizes the pattern of wrapping errors +and checking if an error contains another error. + +There is a common pattern in Go of taking a returned `error` value and +then wrapping it (such as with `fmt.Errorf`) before returning it. The problem +with this pattern is that you completely lose the original `error` structure. + +Arguably the _correct_ approach is that you should make a custom structure +implementing the `error` interface, and have the original error as a field +on that structure, such [as this example](http://golang.org/pkg/os/#PathError). +This is a good approach, but you have to know the entire chain of possible +rewrapping that happens, when you might just care about one. + +`errwrap` formalizes this pattern (it doesn't matter what approach you use +above) by giving a single interface for wrapping errors, checking if a specific +error is wrapped, and extracting that error. + +## Installation and Docs + +Install using `go get github.com/hashicorp/errwrap`. + +Full documentation is available at +http://godoc.org/github.com/hashicorp/errwrap + +## Usage + +#### Basic Usage + +Below is a very basic example of its usage: + +```go +// A function that always returns an error, but wraps it, like a real +// function might. +func tryOpen() error { + _, err := os.Open("/i/dont/exist") + if err != nil { + return errwrap.Wrapf("Doesn't exist: {{err}}", err) + } + + return nil +} + +func main() { + err := tryOpen() + + // We can use the Contains helpers to check if an error contains + // another error. It is safe to do this with a nil error, or with + // an error that doesn't even use the errwrap package. + if errwrap.Contains(err, ErrNotExist) { + // Do something + } + if errwrap.ContainsType(err, new(os.PathError)) { + // Do something + } + + // Or we can use the associated `Get` functions to just extract + // a specific error. This would return nil if that specific error doesn't + // exist. + perr := errwrap.GetType(err, new(os.PathError)) +} +``` + +#### Custom Types + +If you're already making custom types that properly wrap errors, then +you can get all the functionality of `errwraps.Contains` and such by +implementing the `Wrapper` interface with just one function. Example: + +```go +type AppError { + Code ErrorCode + Err error +} + +func (e *AppError) WrappedErrors() []error { + return []error{e.Err} +} +``` + +Now this works: + +```go +err := &AppError{Err: fmt.Errorf("an error")} +if errwrap.ContainsType(err, fmt.Errorf("")) { + // This will work! +} +``` diff --git a/vendor/github.com/hashicorp/errwrap/errwrap.go b/vendor/github.com/hashicorp/errwrap/errwrap.go new file mode 100644 index 0000000..a733bef --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/errwrap.go @@ -0,0 +1,169 @@ +// Package errwrap implements methods to formalize error wrapping in Go. +// +// All of the top-level functions that take an `error` are built to be able +// to take any error, not just wrapped errors. This allows you to use errwrap +// without having to type-check and type-cast everywhere. +package errwrap + +import ( + "errors" + "reflect" + "strings" +) + +// WalkFunc is the callback called for Walk. +type WalkFunc func(error) + +// Wrapper is an interface that can be implemented by custom types to +// have all the Contains, Get, etc. functions in errwrap work. +// +// When Walk reaches a Wrapper, it will call the callback for every +// wrapped error in addition to the wrapper itself. Since all the top-level +// functions in errwrap use Walk, this means that all those functions work +// with your custom type. +type Wrapper interface { + WrappedErrors() []error +} + +// Wrap defines that outer wraps inner, returning an error type that +// can be cleanly used with the other methods in this package, such as +// Contains, GetAll, etc. +// +// This function won't modify the error message at all (the outer message +// will be used). +func Wrap(outer, inner error) error { + return &wrappedError{ + Outer: outer, + Inner: inner, + } +} + +// Wrapf wraps an error with a formatting message. This is similar to using +// `fmt.Errorf` to wrap an error. If you're using `fmt.Errorf` to wrap +// errors, you should replace it with this. +// +// format is the format of the error message. The string '{{err}}' will +// be replaced with the original error message. +func Wrapf(format string, err error) error { + outerMsg := "" + if err != nil { + outerMsg = err.Error() + } + + outer := errors.New(strings.Replace( + format, "{{err}}", outerMsg, -1)) + + return Wrap(outer, err) +} + +// Contains checks if the given error contains an error with the +// message msg. If err is not a wrapped error, this will always return +// false unless the error itself happens to match this msg. +func Contains(err error, msg string) bool { + return len(GetAll(err, msg)) > 0 +} + +// ContainsType checks if the given error contains an error with +// the same concrete type as v. If err is not a wrapped error, this will +// check the err itself. +func ContainsType(err error, v interface{}) bool { + return len(GetAllType(err, v)) > 0 +} + +// Get is the same as GetAll but returns the deepest matching error. +func Get(err error, msg string) error { + es := GetAll(err, msg) + if len(es) > 0 { + return es[len(es)-1] + } + + return nil +} + +// GetType is the same as GetAllType but returns the deepest matching error. +func GetType(err error, v interface{}) error { + es := GetAllType(err, v) + if len(es) > 0 { + return es[len(es)-1] + } + + return nil +} + +// GetAll gets all the errors that might be wrapped in err with the +// given message. The order of the errors is such that the outermost +// matching error (the most recent wrap) is index zero, and so on. +func GetAll(err error, msg string) []error { + var result []error + + Walk(err, func(err error) { + if err.Error() == msg { + result = append(result, err) + } + }) + + return result +} + +// GetAllType gets all the errors that are the same type as v. +// +// The order of the return value is the same as described in GetAll. +func GetAllType(err error, v interface{}) []error { + var result []error + + var search string + if v != nil { + search = reflect.TypeOf(v).String() + } + Walk(err, func(err error) { + var needle string + if err != nil { + needle = reflect.TypeOf(err).String() + } + + if needle == search { + result = append(result, err) + } + }) + + return result +} + +// Walk walks all the wrapped errors in err and calls the callback. If +// err isn't a wrapped error, this will be called once for err. If err +// is a wrapped error, the callback will be called for both the wrapper +// that implements error as well as the wrapped error itself. +func Walk(err error, cb WalkFunc) { + if err == nil { + return + } + + switch e := err.(type) { + case *wrappedError: + cb(e.Outer) + Walk(e.Inner, cb) + case Wrapper: + cb(err) + + for _, err := range e.WrappedErrors() { + Walk(err, cb) + } + default: + cb(err) + } +} + +// wrappedError is an implementation of error that has both the +// outer and inner errors. +type wrappedError struct { + Outer error + Inner error +} + +func (w *wrappedError) Error() string { + return w.Outer.Error() +} + +func (w *wrappedError) WrappedErrors() []error { + return []error{w.Outer, w.Inner} +} diff --git a/vendor/vendor.json b/vendor/vendor.json new file mode 100644 index 0000000..56de487 --- /dev/null +++ b/vendor/vendor.json @@ -0,0 +1,13 @@ +{ + "comment": "", + "ignore": "test", + "package": [ + { + "checksumSHA1": "cdOCt0Yb+hdErz8NAQqayxPmRsY=", + "path": "github.com/hashicorp/errwrap", + "revision": "7554cd9344cec97297fa6649b055a8c98c2a1e55", + "revisionTime": "2014-10-28T05:47:10Z" + } + ], + "rootPath": "github.com/hashicorp/go-multierror" +} From 2c87fda17de1def6ea288141b8e7600b888e535b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 6 Nov 2016 09:02:21 -0800 Subject: [PATCH 20/80] Singular message for a single error --- flatten_test.go | 2 +- format.go | 6 +++++- format_test.go | 19 +++++++++++++++++-- multierror_test.go | 2 +- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/flatten_test.go b/flatten_test.go index 75218f1..9fbacad 100644 --- a/flatten_test.go +++ b/flatten_test.go @@ -26,7 +26,7 @@ func TestFlatten(t *testing.T) { } expected := strings.TrimSpace(` -3 error(s) occurred: +3 errors occurred: * one * two diff --git a/format.go b/format.go index bb65a12..6c7a3cc 100644 --- a/format.go +++ b/format.go @@ -12,12 +12,16 @@ type ErrorFormatFunc func([]error) string // ListFormatFunc is a basic formatter that outputs the number of errors // that occurred along with a bullet point list of the errors. func ListFormatFunc(es []error) string { + if len(es) == 1 { + return fmt.Sprintf("1 error occurred:\n\n* %s", es[0]) + } + points := make([]string, len(es)) for i, err := range es { points[i] = fmt.Sprintf("* %s", err) } return fmt.Sprintf( - "%d error(s) occurred:\n\n%s", + "%d errors occurred:\n\n%s", len(es), strings.Join(points, "\n")) } diff --git a/format_test.go b/format_test.go index d7cee5d..3359e02 100644 --- a/format_test.go +++ b/format_test.go @@ -5,8 +5,23 @@ import ( "testing" ) -func TestListFormatFunc(t *testing.T) { - expected := `2 error(s) occurred: +func TestListFormatFuncSingle(t *testing.T) { + expected := `1 error occurred: + +* foo` + + errors := []error{ + errors.New("foo"), + } + + actual := ListFormatFunc(errors) + if actual != expected { + t.Fatalf("bad: %#v", actual) + } +} + +func TestListFormatFuncMultiple(t *testing.T) { + expected := `2 errors occurred: * foo * bar` diff --git a/multierror_test.go b/multierror_test.go index 3e78079..5567d1c 100644 --- a/multierror_test.go +++ b/multierror_test.go @@ -27,7 +27,7 @@ func TestErrorError_custom(t *testing.T) { } func TestErrorError_default(t *testing.T) { - expected := `2 error(s) occurred: + expected := `2 errors occurred: * foo * bar` From f3196d7c761140dfd6f201282665a9aac2bee0bf Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 16 Dec 2016 10:41:23 -0800 Subject: [PATCH 21/80] append should only append if error to append is non-nil --- append.go | 8 ++++++-- append_test.go | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/append.go b/append.go index 00afa9b..775b6e7 100644 --- a/append.go +++ b/append.go @@ -18,9 +18,13 @@ func Append(err error, errs ...error) *Error { for _, e := range errs { switch e := e.(type) { case *Error: - err.Errors = append(err.Errors, e.Errors...) + if e != nil { + err.Errors = append(err.Errors, e.Errors...) + } default: - err.Errors = append(err.Errors, e) + if e != nil { + err.Errors = append(err.Errors, e) + } } } diff --git a/append_test.go b/append_test.go index dfa79e2..58ddafa 100644 --- a/append_test.go +++ b/append_test.go @@ -47,6 +47,24 @@ func TestAppend_NilError(t *testing.T) { } } +func TestAppend_NilErrorArg(t *testing.T) { + var err error + var nilErr *Error + result := Append(err, nilErr) + if len(result.Errors) != 0 { + t.Fatalf("wrong len: %d", len(result.Errors)) + } +} + +func TestAppend_NilErrorIfaceArg(t *testing.T) { + var err error + var nilErr error + result := Append(err, nilErr) + if len(result.Errors) != 0 { + t.Fatalf("wrong len: %d", len(result.Errors)) + } +} + func TestAppend_NonError(t *testing.T) { original := errors.New("foo") result := Append(original, errors.New("bar")) From 63ca7e2937b4f9039b6e6f0384673368bf2a3d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20S=C3=A1gi-Kaz=C3=A1r?= Date: Thu, 22 Jun 2017 07:53:17 +0200 Subject: [PATCH 22/80] Fix typos --- multierror.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/multierror.go b/multierror.go index 2ea0827..89b1422 100644 --- a/multierror.go +++ b/multierror.go @@ -40,11 +40,11 @@ func (e *Error) GoString() string { } // WrappedErrors returns the list of errors that this Error is wrapping. -// It is an implementatin of the errwrap.Wrapper interface so that +// 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 implementd only to +// than accessing the Errors field directly. It is implemented only to // satisfy the errwrap.Wrapper interface. func (e *Error) WrappedErrors() []error { return e.Errors From 6f5c37adcf4157650107a86921e59387b50e207a Mon Sep 17 00:00:00 2001 From: Davor Kapsa Date: Thu, 28 Sep 2017 09:01:57 +0200 Subject: [PATCH 23/80] travis: update go version --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4b865d1..304a835 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ sudo: false language: go go: - - 1.6 + - 1.x branches: only: From bbca6551549492486ca1b0f8dee45553dd6aa6d7 Mon Sep 17 00:00:00 2001 From: French Ben Date: Wed, 31 Jan 2018 15:01:02 +0100 Subject: [PATCH 24/80] Update error output to be clean * Don't space out the error but append the next one * During a test, type the expected result instead of parsing it Signed-off-by: French Ben --- flatten_test.go | 12 +++++------- format.go | 6 +++--- format_test.go | 8 +++++--- multierror_test.go | 5 +++-- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/flatten_test.go b/flatten_test.go index 9fbacad..e99c410 100644 --- a/flatten_test.go +++ b/flatten_test.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "reflect" - "strings" "testing" ) @@ -25,13 +24,12 @@ func TestFlatten(t *testing.T) { }, } - expected := strings.TrimSpace(` -3 errors occurred: + expected := `3 errors occurred: + * one + * two + * three -* one -* two -* three - `) +` actual := fmt.Sprintf("%s", Flatten(original)) if expected != actual { diff --git a/format.go b/format.go index 6c7a3cc..47f13c4 100644 --- a/format.go +++ b/format.go @@ -13,7 +13,7 @@ type ErrorFormatFunc func([]error) string // that occurred along with a bullet point list of the errors. func ListFormatFunc(es []error) string { if len(es) == 1 { - return fmt.Sprintf("1 error occurred:\n\n* %s", es[0]) + return fmt.Sprintf("1 error occurred:\n\t* %s\n\n", es[0]) } points := make([]string, len(es)) @@ -22,6 +22,6 @@ func ListFormatFunc(es []error) string { } return fmt.Sprintf( - "%d errors occurred:\n\n%s", - len(es), strings.Join(points, "\n")) + "%d errors occurred:\n\t%s\n\n", + len(es), strings.Join(points, "\n\t")) } diff --git a/format_test.go b/format_test.go index 3359e02..2b6da1d 100644 --- a/format_test.go +++ b/format_test.go @@ -7,8 +7,9 @@ import ( func TestListFormatFuncSingle(t *testing.T) { expected := `1 error occurred: + * foo -* foo` +` errors := []error{ errors.New("foo"), @@ -22,9 +23,10 @@ func TestListFormatFuncSingle(t *testing.T) { func TestListFormatFuncMultiple(t *testing.T) { expected := `2 errors occurred: + * foo + * bar -* foo -* bar` +` errors := []error{ errors.New("foo"), diff --git a/multierror_test.go b/multierror_test.go index 5567d1c..2949c3b 100644 --- a/multierror_test.go +++ b/multierror_test.go @@ -28,9 +28,10 @@ func TestErrorError_custom(t *testing.T) { func TestErrorError_default(t *testing.T) { expected := `2 errors occurred: + * foo + * bar -* foo -* bar` +` errors := []error{ errors.New("foo"), From 52f73bd1b9707bccddb728b3043e1ff43e8895a8 Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Mon, 19 Feb 2018 12:27:35 -0500 Subject: [PATCH 25/80] Implement sort interface for error messages --- sort.go | 16 ++++++++++++++++ sort_test.go | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 sort.go create mode 100644 sort_test.go diff --git a/sort.go b/sort.go new file mode 100644 index 0000000..fecb14e --- /dev/null +++ b/sort.go @@ -0,0 +1,16 @@ +package multierror + +// Len implements sort.Interface function for length +func (err Error) Len() int { + return len(err.Errors) +} + +// Swap implements sort.Interface function for swapping elements +func (err Error) Swap(i, j int) { + err.Errors[i], err.Errors[j] = err.Errors[j], err.Errors[i] +} + +// Less implements sort.Interface function for determining order +func (err Error) Less(i, j int) bool { + return err.Errors[i].Error() < err.Errors[j].Error() +} diff --git a/sort_test.go b/sort_test.go new file mode 100644 index 0000000..7fd04e8 --- /dev/null +++ b/sort_test.go @@ -0,0 +1,52 @@ +package multierror + +import ( + "errors" + "reflect" + "sort" + "testing" +) + +func TestSortSingle(t *testing.T) { + errFoo := errors.New("foo") + + expected := []error{ + errFoo, + } + + err := &Error{ + Errors: []error{ + errFoo, + }, + } + + sort.Sort(err) + if !reflect.DeepEqual(err.Errors, expected) { + t.Fatalf("bad: %#v", err) + } +} + +func TestSortMultiple(t *testing.T) { + errBar := errors.New("bar") + errBaz := errors.New("baz") + errFoo := errors.New("foo") + + expected := []error{ + errBar, + errBaz, + errFoo, + } + + err := &Error{ + Errors: []error{ + errFoo, + errBar, + errBaz, + }, + } + + sort.Sort(err) + if !reflect.DeepEqual(err.Errors, expected) { + t.Fatalf("bad: %#v", err) + } +} From aa5ed92cc00e3d41e4252f1049f8541daf9ad2ee Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 23 Aug 2018 17:40:25 -0700 Subject: [PATCH 26/80] Remove vendors --- scripts/deps.sh | 54 --- vendor/github.com/hashicorp/errwrap/LICENSE | 354 ------------------ vendor/github.com/hashicorp/errwrap/README.md | 89 ----- .../github.com/hashicorp/errwrap/errwrap.go | 169 --------- vendor/vendor.json | 13 - 5 files changed, 679 deletions(-) delete mode 100755 scripts/deps.sh delete mode 100644 vendor/github.com/hashicorp/errwrap/LICENSE delete mode 100644 vendor/github.com/hashicorp/errwrap/README.md delete mode 100644 vendor/github.com/hashicorp/errwrap/errwrap.go delete mode 100644 vendor/vendor.json diff --git a/scripts/deps.sh b/scripts/deps.sh deleted file mode 100755 index 1d2fcf9..0000000 --- a/scripts/deps.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env bash -# -# This script updates dependencies using a temporary directory. This is required -# to avoid any auxillary dependencies that sneak into GOPATH. -set -e - -# Get the parent directory of where this script is. -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done -DIR="$(cd -P "$(dirname "$SOURCE")/.." && pwd)" - -# Change into that directory -cd "$DIR" - -# Get the name from the directory -NAME=${NAME:-"$(basename $(pwd))"} - -# Announce -echo "==> Updating dependencies..." - -echo "--> Making tmpdir..." -tmpdir=$(mktemp -d) -function cleanup { - rm -rf "${tmpdir}" -} -trap cleanup EXIT - -export GOPATH="${tmpdir}" -export PATH="${tmpdir}/bin:$PATH" - -mkdir -p "${tmpdir}/src/github.com/hashicorp" -pushd "${tmpdir}/src/github.com/hashicorp" &>/dev/null - -echo "--> Copying ${NAME}..." -cp -R "$DIR" "${tmpdir}/src/github.com/hashicorp/${NAME}" -pushd "${tmpdir}/src/github.com/hashicorp/${NAME}" &>/dev/null -rm -rf vendor/ - -echo "--> Installing dependency manager..." -go get -u github.com/kardianos/govendor -govendor init - -echo "--> Installing all dependencies (may take some time)..." -govendor fetch -v +outside - -echo "--> Vendoring..." -govendor add +external - -echo "--> Moving into place..." -vpath="${tmpdir}/src/github.com/hashicorp/${NAME}/vendor" -popd &>/dev/null -popd &>/dev/null -rm -rf vendor/ -cp -R "${vpath}" . diff --git a/vendor/github.com/hashicorp/errwrap/LICENSE b/vendor/github.com/hashicorp/errwrap/LICENSE deleted file mode 100644 index c33dcc7..0000000 --- a/vendor/github.com/hashicorp/errwrap/LICENSE +++ /dev/null @@ -1,354 +0,0 @@ -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. “Contributor” - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. “Contributor Version” - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor’s Contribution. - -1.3. “Contribution” - - means Covered Software of a particular Contributor. - -1.4. “Covered Software” - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. “Incompatible With Secondary Licenses” - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of version - 1.1 or earlier of the License, but not also under the terms of a - Secondary License. - -1.6. “Executable Form” - - means any form of the work other than Source Code Form. - -1.7. “Larger Work” - - means a work that combines Covered Software with other material, in a separate - file or files, that is not Covered Software. - -1.8. “License” - - means this document. - -1.9. “Licensable” - - means having the right to grant, to the maximum extent possible, whether at the - time of the initial grant or subsequently, any and all of the rights conveyed by - this License. - -1.10. “Modifications” - - means any of the following: - - a. any file in Source Code Form that results from an addition to, deletion - from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. “Patent Claims” of a Contributor - - means any patent claim(s), including without limitation, method, process, - and apparatus claims, in any patent Licensable by such Contributor that - would be infringed, but for the grant of the License, by the making, - using, selling, offering for sale, having made, import, or transfer of - either its Contributions or its Contributor Version. - -1.12. “Secondary License” - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. “Source Code Form” - - means the form of the work preferred for making modifications. - -1.14. “You” (or “Your”) - - means an individual or a legal entity exercising rights under this - License. For legal entities, “You” includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, “control” means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or as - part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its Contributions - or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution become - effective for each Contribution on the date the Contributor first distributes - such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under this - License. No additional rights or licenses will be implied from the distribution - or licensing of Covered Software under this License. Notwithstanding Section - 2.1(b) above, no patent license is granted by a Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party’s - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of its - Contributions. - - This License does not grant any rights in the trademarks, service marks, or - logos of any Contributor (except as may be necessary to comply with the - notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this License - (see Section 10.2) or under the terms of a Secondary License (if permitted - under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its Contributions - are its original creation(s) or it has sufficient rights to grant the - rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under applicable - copyright doctrines of fair use, fair dealing, or other equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under the - terms of this License. You must inform recipients that the Source Code Form - of the Covered Software is governed by the terms of this License, and how - they can obtain a copy of this License. You may not attempt to alter or - restrict the recipients’ rights in the Source Code Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this License, - or sublicense it under different terms, provided that the license for - the Executable Form does not attempt to limit or alter the recipients’ - rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for the - Covered Software. If the Larger Work is a combination of Covered Software - with a work governed by one or more Secondary Licenses, and the Covered - Software is not Incompatible With Secondary Licenses, this License permits - You to additionally distribute such Covered Software under the terms of - such Secondary License(s), so that the recipient of the Larger Work may, at - their option, further distribute the Covered Software under the terms of - either this License or such Secondary License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices (including - copyright notices, patent notices, disclaimers of warranty, or limitations - of liability) contained within the Source Code Form of the Covered - Software, except that You may alter any license notices to the extent - required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on behalf - of any Contributor. You must make it absolutely clear that any such - warranty, support, indemnity, or liability obligation is offered by You - alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, judicial - order, or regulation then You must: (a) comply with the terms of this License - to the maximum extent possible; and (b) describe the limitations and the code - they affect. Such description must be placed in a text file included with all - distributions of the Covered Software under this License. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing basis, - if such Contributor fails to notify You of the non-compliance by some - reasonable means prior to 60 days after You have come back into compliance. - Moreover, Your grants from a particular Contributor are reinstated on an - ongoing basis if such Contributor notifies You of the non-compliance by - some reasonable means, this is the first time You have received notice of - non-compliance with this License from such Contributor, and You become - compliant prior to 30 days after Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, counter-claims, - and cross-claims) alleging that a Contributor Version directly or - indirectly infringes any patent, then the rights granted to You by any and - all Contributors for the Covered Software under Section 2.1 of this License - shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an “as is” basis, without - warranty of any kind, either expressed, implied, or statutory, including, - without limitation, warranties that the Covered Software is free of defects, - merchantable, fit for a particular purpose or non-infringing. The entire - risk as to the quality and performance of the Covered Software is with You. - Should any Covered Software prove defective in any respect, You (not any - Contributor) assume the cost of any necessary servicing, repair, or - correction. This disclaimer of warranty constitutes an essential part of this - License. No use of any Covered Software is authorized under this License - except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from such - party’s negligence to the extent applicable law prohibits such limitation. - Some jurisdictions do not allow the exclusion or limitation of incidental or - consequential damages, so this exclusion and limitation may not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts of - a jurisdiction where the defendant maintains its principal place of business - and such litigation shall be governed by laws of that jurisdiction, without - reference to its conflict-of-law provisions. Nothing in this Section shall - prevent a party’s ability to bring cross-claims or counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject matter - hereof. If any provision of this License is held to be unenforceable, such - provision shall be reformed only to the extent necessary to make it - enforceable. Any law or regulation which provides that the language of a - contract shall be construed against the drafter shall not be used to construe - this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version of - the License under which You originally received the Covered Software, or - under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a modified - version of this License if you rename the license and remove any - references to the name of the license steward (except to note that such - modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses - If You choose to distribute Source Code Form that is Incompatible With - Secondary Licenses under the terms of this version of the License, the - notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, then -You may include the notice in a location (such as a LICENSE file in a relevant -directory) where a recipient would be likely to look for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - “Incompatible With Secondary Licenses” Notice - - This Source Code Form is “Incompatible - With Secondary Licenses”, as defined by - the Mozilla Public License, v. 2.0. - diff --git a/vendor/github.com/hashicorp/errwrap/README.md b/vendor/github.com/hashicorp/errwrap/README.md deleted file mode 100644 index 1c95f59..0000000 --- a/vendor/github.com/hashicorp/errwrap/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# errwrap - -`errwrap` is a package for Go that formalizes the pattern of wrapping errors -and checking if an error contains another error. - -There is a common pattern in Go of taking a returned `error` value and -then wrapping it (such as with `fmt.Errorf`) before returning it. The problem -with this pattern is that you completely lose the original `error` structure. - -Arguably the _correct_ approach is that you should make a custom structure -implementing the `error` interface, and have the original error as a field -on that structure, such [as this example](http://golang.org/pkg/os/#PathError). -This is a good approach, but you have to know the entire chain of possible -rewrapping that happens, when you might just care about one. - -`errwrap` formalizes this pattern (it doesn't matter what approach you use -above) by giving a single interface for wrapping errors, checking if a specific -error is wrapped, and extracting that error. - -## Installation and Docs - -Install using `go get github.com/hashicorp/errwrap`. - -Full documentation is available at -http://godoc.org/github.com/hashicorp/errwrap - -## Usage - -#### Basic Usage - -Below is a very basic example of its usage: - -```go -// A function that always returns an error, but wraps it, like a real -// function might. -func tryOpen() error { - _, err := os.Open("/i/dont/exist") - if err != nil { - return errwrap.Wrapf("Doesn't exist: {{err}}", err) - } - - return nil -} - -func main() { - err := tryOpen() - - // We can use the Contains helpers to check if an error contains - // another error. It is safe to do this with a nil error, or with - // an error that doesn't even use the errwrap package. - if errwrap.Contains(err, ErrNotExist) { - // Do something - } - if errwrap.ContainsType(err, new(os.PathError)) { - // Do something - } - - // Or we can use the associated `Get` functions to just extract - // a specific error. This would return nil if that specific error doesn't - // exist. - perr := errwrap.GetType(err, new(os.PathError)) -} -``` - -#### Custom Types - -If you're already making custom types that properly wrap errors, then -you can get all the functionality of `errwraps.Contains` and such by -implementing the `Wrapper` interface with just one function. Example: - -```go -type AppError { - Code ErrorCode - Err error -} - -func (e *AppError) WrappedErrors() []error { - return []error{e.Err} -} -``` - -Now this works: - -```go -err := &AppError{Err: fmt.Errorf("an error")} -if errwrap.ContainsType(err, fmt.Errorf("")) { - // This will work! -} -``` diff --git a/vendor/github.com/hashicorp/errwrap/errwrap.go b/vendor/github.com/hashicorp/errwrap/errwrap.go deleted file mode 100644 index a733bef..0000000 --- a/vendor/github.com/hashicorp/errwrap/errwrap.go +++ /dev/null @@ -1,169 +0,0 @@ -// Package errwrap implements methods to formalize error wrapping in Go. -// -// All of the top-level functions that take an `error` are built to be able -// to take any error, not just wrapped errors. This allows you to use errwrap -// without having to type-check and type-cast everywhere. -package errwrap - -import ( - "errors" - "reflect" - "strings" -) - -// WalkFunc is the callback called for Walk. -type WalkFunc func(error) - -// Wrapper is an interface that can be implemented by custom types to -// have all the Contains, Get, etc. functions in errwrap work. -// -// When Walk reaches a Wrapper, it will call the callback for every -// wrapped error in addition to the wrapper itself. Since all the top-level -// functions in errwrap use Walk, this means that all those functions work -// with your custom type. -type Wrapper interface { - WrappedErrors() []error -} - -// Wrap defines that outer wraps inner, returning an error type that -// can be cleanly used with the other methods in this package, such as -// Contains, GetAll, etc. -// -// This function won't modify the error message at all (the outer message -// will be used). -func Wrap(outer, inner error) error { - return &wrappedError{ - Outer: outer, - Inner: inner, - } -} - -// Wrapf wraps an error with a formatting message. This is similar to using -// `fmt.Errorf` to wrap an error. If you're using `fmt.Errorf` to wrap -// errors, you should replace it with this. -// -// format is the format of the error message. The string '{{err}}' will -// be replaced with the original error message. -func Wrapf(format string, err error) error { - outerMsg := "" - if err != nil { - outerMsg = err.Error() - } - - outer := errors.New(strings.Replace( - format, "{{err}}", outerMsg, -1)) - - return Wrap(outer, err) -} - -// Contains checks if the given error contains an error with the -// message msg. If err is not a wrapped error, this will always return -// false unless the error itself happens to match this msg. -func Contains(err error, msg string) bool { - return len(GetAll(err, msg)) > 0 -} - -// ContainsType checks if the given error contains an error with -// the same concrete type as v. If err is not a wrapped error, this will -// check the err itself. -func ContainsType(err error, v interface{}) bool { - return len(GetAllType(err, v)) > 0 -} - -// Get is the same as GetAll but returns the deepest matching error. -func Get(err error, msg string) error { - es := GetAll(err, msg) - if len(es) > 0 { - return es[len(es)-1] - } - - return nil -} - -// GetType is the same as GetAllType but returns the deepest matching error. -func GetType(err error, v interface{}) error { - es := GetAllType(err, v) - if len(es) > 0 { - return es[len(es)-1] - } - - return nil -} - -// GetAll gets all the errors that might be wrapped in err with the -// given message. The order of the errors is such that the outermost -// matching error (the most recent wrap) is index zero, and so on. -func GetAll(err error, msg string) []error { - var result []error - - Walk(err, func(err error) { - if err.Error() == msg { - result = append(result, err) - } - }) - - return result -} - -// GetAllType gets all the errors that are the same type as v. -// -// The order of the return value is the same as described in GetAll. -func GetAllType(err error, v interface{}) []error { - var result []error - - var search string - if v != nil { - search = reflect.TypeOf(v).String() - } - Walk(err, func(err error) { - var needle string - if err != nil { - needle = reflect.TypeOf(err).String() - } - - if needle == search { - result = append(result, err) - } - }) - - return result -} - -// Walk walks all the wrapped errors in err and calls the callback. If -// err isn't a wrapped error, this will be called once for err. If err -// is a wrapped error, the callback will be called for both the wrapper -// that implements error as well as the wrapped error itself. -func Walk(err error, cb WalkFunc) { - if err == nil { - return - } - - switch e := err.(type) { - case *wrappedError: - cb(e.Outer) - Walk(e.Inner, cb) - case Wrapper: - cb(err) - - for _, err := range e.WrappedErrors() { - Walk(err, cb) - } - default: - cb(err) - } -} - -// wrappedError is an implementation of error that has both the -// outer and inner errors. -type wrappedError struct { - Outer error - Inner error -} - -func (w *wrappedError) Error() string { - return w.Outer.Error() -} - -func (w *wrappedError) WrappedErrors() []error { - return []error{w.Outer, w.Inner} -} diff --git a/vendor/vendor.json b/vendor/vendor.json deleted file mode 100644 index 56de487..0000000 --- a/vendor/vendor.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "comment": "", - "ignore": "test", - "package": [ - { - "checksumSHA1": "cdOCt0Yb+hdErz8NAQqayxPmRsY=", - "path": "github.com/hashicorp/errwrap", - "revision": "7554cd9344cec97297fa6649b055a8c98c2a1e55", - "revisionTime": "2014-10-28T05:47:10Z" - } - ], - "rootPath": "github.com/hashicorp/go-multierror" -} From 886a7fbe3eb1c874d46f623bfa70af45f425b3d1 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 23 Aug 2018 17:40:42 -0700 Subject: [PATCH 27/80] Go.mod and v1.0.0 --- go.mod | 3 +++ go.sum | 4 ++++ 2 files changed, 7 insertions(+) create mode 100644 go.mod create mode 100644 go.sum diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..2534331 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/hashicorp/go-multierror + +require github.com/hashicorp/errwrap v1.0.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..85b1f8f --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce h1:prjrVgOk2Yg6w+PflHoszQNLTUh4kaByUcEWM/9uin4= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= From 4793e3ecca3544919d840be65ae8bc80a8494bf3 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Mon, 22 Jul 2019 13:50:01 -0700 Subject: [PATCH 28/80] go mod tidy --- go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.sum b/go.sum index 85b1f8f..e8238e9 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,2 @@ -github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce h1:prjrVgOk2Yg6w+PflHoszQNLTUh4kaByUcEWM/9uin4= -github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= From 8a900547274e48845fb8f288b633b1aa25aaf6c1 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Mon, 22 Jul 2019 13:56:41 -0700 Subject: [PATCH 29/80] Use go modules in CI. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 304a835..24b8038 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,4 +9,4 @@ branches: only: - master -script: make test testrace +script: env GO111MODULE=on make test testrace From e9c06a10a165eea696e6b8608b96546aa6dc3b2d Mon Sep 17 00:00:00 2001 From: Michele Date: Wed, 23 Oct 2019 10:55:45 -0700 Subject: [PATCH 30/80] Add circle CI, remove travis --- .circleci/config.yml | 59 ++++++++++++++++++++++++++++++++++++++++++++ .travis.yml | 12 --------- 2 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 .circleci/config.yml delete mode 100644 .travis.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..488dae5 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,59 @@ +version: 2.1 + +references: +  images: +    go: &GOLANG_IMAGE circleci/golang:latest +  environments: +    tmp: &TEST_RESULTS_PATH /tmp/test-results # path to where test results are saved + +# reusable 'executor' object for jobs +executors: +  go: +    docker: +      - image: *GOLANG_IMAGE +    environment: +      - TEST_RESULTS: *TEST_RESULTS_PATH + +jobs: +  go-test: +    executor: go +    steps: +      - checkout +      - run: mkdir -p $TEST_RESULTS + +      - restore_cache: # restore cache from dev-build job +          keys: +            - go-multierror-modcache-v1-{{ checksum "go.mod" }} + +      - run: go mod download + +      # Save go module cache if the go.mod file has changed +      - save_cache: +          key: go-multierror-modcache-v1-{{ checksum "go.mod" }} +          paths: +            - "/go/pkg/mod" + +      # check go fmt output because it does not report non-zero when there are fmt changes +      - run: +          name: check go fmt +          command: | +            files=$(go fmt ./...) +            if [ -n "$files" ]; then +              echo "The following file(s) do not conform to go fmt:" +              echo "$files" +              exit 1 +            fi +      # run go tests with gotestsum +      - run: | +          PACKAGE_NAMES=$(go list ./...) +          gotestsum --format=short-verbose --junitfile $TEST_RESULTS/gotestsum-report.xml -- $PACKAGE_NAMES +      - store_test_results: +          path: *TEST_RESULTS_PATH +      - store_artifacts: +          path: *TEST_RESULTS_PATH + +workflows: +  version: 2 +  test-and-build: +    jobs: +      - go-test diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 24b8038..0000000 --- a/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -sudo: false - -language: go - -go: - - 1.x - -branches: - only: - - master - -script: env GO111MODULE=on make test testrace From 5e6cd52db1122dd65107db936a4ce8dd86db80d1 Mon Sep 17 00:00:00 2001 From: Nick Ethier Date: Mon, 11 Nov 2019 12:58:22 -0500 Subject: [PATCH 31/80] add Group struct for collecting errors from goroutines into a multierror --- group.go | 38 ++++++++++++++++++++++++++++++++++++++ group_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 group.go create mode 100644 group_test.go diff --git a/group.go b/group.go new file mode 100644 index 0000000..9c29efb --- /dev/null +++ b/group.go @@ -0,0 +1,38 @@ +package multierror + +import "sync" + +// Group is a collection of goroutines which return errors that need to be +// coalesced. +type Group struct { + mutex sync.Mutex + err *Error + wg sync.WaitGroup +} + +// Go calls the given function in a new goroutine. +// +// If the function returns an error it is added to the group multierror which +// is returned by Wait. +func (g *Group) Go(f func() error) { + g.wg.Add(1) + + go func() { + defer g.wg.Done() + + if err := f(); err != nil { + g.mutex.Lock() + g.err = Append(g.err, err) + g.mutex.Unlock() + } + }() +} + +// Wait blocks until all function calls from the Go method have returned, then +// returns the multierror. +func (g *Group) Wait() *Error { + g.wg.Wait() + g.mutex.Lock() + defer g.mutex.Unlock() + return g.err +} diff --git a/group_test.go b/group_test.go new file mode 100644 index 0000000..9d472fd --- /dev/null +++ b/group_test.go @@ -0,0 +1,44 @@ +package multierror + +import ( + "errors" + "strings" + "testing" +) + +func TestGroup(t *testing.T) { + err1 := errors.New("group_test: 1") + err2 := errors.New("group_test: 2") + + cases := []struct { + errs []error + nilResult bool + }{ + {errs: []error{}, nilResult: true}, + {errs: []error{nil}, nilResult: true}, + {errs: []error{err1}}, + {errs: []error{err1, nil}}, + {errs: []error{err1, nil, err2}}, + } + + for _, tc := range cases { + var g Group + + for _, err := range tc.errs { + err := err + g.Go(func() error { return err }) + + } + + gErr := g.Wait() + if gErr != nil { + for i := range tc.errs { + if tc.errs[i] != nil && !strings.Contains(gErr.Error(), tc.errs[i].Error()) { + t.Fatalf("expected error to contain %q, actual: %v", tc.errs[i].Error(), gErr) + } + } + } else if !tc.nilResult { + t.Fatalf("Group.Wait() should not have returned nil for errs: %v", tc.errs) + } + } +} From ece20dc25a7a71cf2c162222fd1fc66b054b6f9d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 31 Mar 2020 08:34:31 -0700 Subject: [PATCH 32/80] update go.mod --- go.mod | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go.mod b/go.mod index 2534331..0afe8e6 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/hashicorp/go-multierror +go 1.14 + require github.com/hashicorp/errwrap v1.0.0 From 58e4f1897fb08fd76f5fd4e81e2c6c5dddb59899 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 31 Mar 2020 09:07:21 -0700 Subject: [PATCH 33/80] Support Go 1.13 errors.As/Is/Unwrap functionality The primary mechanism that enables this functionality is making `Unwrap` on the top-level Error return a new "chain" structure that uses state to keep track of the current error. The chain implements errors.Is/As so that it compares to that current underlying error. And it implements Unwrap to move on to the next error. A well-formed program using errors.Is/As/Unwrap exclusively will behave correctly with go-multierror in this case without dropping any errors. Direct comparisons such as `Unwrap() == myErr` will not work because we wrap in a chain. The user has to do `errors.Is(err, myErr)` which is the right thing to do anyways. When Unwrap is called on a top-level *Error, we create a shallow copy of the errors so that you can continue using *Error (modifying it, potentially in-place). There is a slight cost to this but it felt weird that calling Unwrap would share the same underlying data and cause potential data races. I think this is unlikely, but its also very unlikely the performance cost of the shallow copy of errors will matter either. Thanks to @felixge on Twitter for pushing me to do this, showing some examples on how it could be done, and providing feedback to this PR. --- multierror.go | 69 ++++++++++++++++++++++++++++++ multierror_test.go | 103 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) diff --git a/multierror.go b/multierror.go index 89b1422..33ebab3 100644 --- a/multierror.go +++ b/multierror.go @@ -1,6 +1,7 @@ package multierror import ( + "errors" "fmt" ) @@ -49,3 +50,71 @@ func (e *Error) GoString() string { func (e *Error) WrappedErrors() []error { return e.Errors } + +// Unwrap returns an error from Error (or nil if there are no errors). +// This error returned will further support Unwrap to get the next error, +// etc. The order will match the order of Errors in the multierror.Error +// at the time of calling. +// +// The resulting error supports errors.As/Is/Unwrap so you can continue +// to use the stdlib errors package to introspect further. +// +// This will perform a shallow copy of the errors slice. Any errors appended +// to this error after calling Unwrap will not be available until a new +// Unwrap is called on the multierror.Error. +func (e *Error) Unwrap() error { + // If we have no errors then we do nothing + if e == nil || len(e.Errors) == 0 { + return nil + } + + // Shallow copy the slice + errs := make([]error, len(e.Errors)) + copy(errs, e.Errors) + + return &chain{errors: errs} +} + +// chain implements the interfaces necessary for errors.Is/As/Unwrap to +// work in a deterministic way with multierror. A chain tracks a list of +// errors while accounting for the current represented error. This lets +// Is/As be meaningful. +// +// Unwrap returns the next error. In the cleanest form, Unwrap would return +// the wrapped error here but we can't do that if we want to properly +// get access to all the errors. Instead, users are recommended to use +// Is/As to get the correct error type out. +type chain struct { + idx int + errors []error +} + +// Error implements the error interface +func (e *chain) Error() string { + return e.current().Error() +} + +// Unwrap implements errors.Unwrap by returning the next error in the +// chain or nil if there are no more errors. +func (e *chain) Unwrap() error { + next := e.idx + 1 + if len(e.errors) <= next { + return nil + } + + return &chain{idx: next, errors: e.errors} +} + +// As implements errors.As by attempting to map to the current value. +func (e *chain) As(target interface{}) bool { + return errors.As(e.current(), target) +} + +// Is implements errors.Is by comparing the current value directly. +func (e *chain) Is(target error) bool { + return e.current() == target +} + +func (e *chain) current() error { + return e.errors[e.idx] +} diff --git a/multierror_test.go b/multierror_test.go index 2949c3b..789230e 100644 --- a/multierror_test.go +++ b/multierror_test.go @@ -69,3 +69,106 @@ func TestErrorWrappedErrors(t *testing.T) { t.Fatalf("bad: %s", multi.WrappedErrors()) } } + +func TestErrorUnwrap(t *testing.T) { + t.Run("with errors", func(t *testing.T) { + err := &Error{Errors: []error{ + errors.New("foo"), + errors.New("bar"), + errors.New("baz"), + }} + + var current error = err + for i := 0; i < len(err.Errors); i++ { + current = errors.Unwrap(current) + if !errors.Is(current, err.Errors[i]) { + t.Fatal("should be next value") + } + } + + if errors.Unwrap(current) != nil { + t.Fatal("should be nil at the end") + } + }) + + t.Run("with no errors", func(t *testing.T) { + err := &Error{Errors: nil} + if errors.Unwrap(err) != nil { + t.Fatal("should be nil") + } + }) + + t.Run("with nil multierror", func(t *testing.T) { + var err *Error + if errors.Unwrap(err) != nil { + t.Fatal("should be nil") + } + }) +} + +func TestErrorIs(t *testing.T) { + errBar := errors.New("bar") + + t.Run("with errBar", func(t *testing.T) { + err := &Error{Errors: []error{ + errors.New("foo"), + errBar, + errors.New("baz"), + }} + + if !errors.Is(err, errBar) { + t.Fatal("should be true") + } + }) + + t.Run("without errBar", func(t *testing.T) { + err := &Error{Errors: []error{ + errors.New("foo"), + errors.New("baz"), + }} + + if errors.Is(err, errBar) { + t.Fatal("should be false") + } + }) +} + +func TestErrorAs(t *testing.T) { + match := &nestedError{} + + t.Run("with the value", func(t *testing.T) { + err := &Error{Errors: []error{ + errors.New("foo"), + match, + errors.New("baz"), + }} + + var target *nestedError + if !errors.As(err, &target) { + t.Fatal("should be true") + } + if target == nil { + t.Fatal("target should not be nil") + } + }) + + t.Run("without the value", func(t *testing.T) { + err := &Error{Errors: []error{ + errors.New("foo"), + errors.New("baz"), + }} + + var target *nestedError + if errors.As(err, &target) { + t.Fatal("should be false") + } + if target != nil { + t.Fatal("target should be nil") + } + }) +} + +// nestedError implements error and is used for tests. +type nestedError struct{} + +func (*nestedError) Error() string { return "" } From 38eaa6a9544695191bf72cc827463e22ecfa24a1 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 31 Mar 2020 09:39:58 -0700 Subject: [PATCH 34/80] Unwrap: one error can be returned directly --- multierror.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/multierror.go b/multierror.go index 33ebab3..d2bbbe9 100644 --- a/multierror.go +++ b/multierror.go @@ -68,6 +68,11 @@ func (e *Error) Unwrap() error { return nil } + // If we have exactly one error, we can just return that directly. + if len(e.Errors) == 1 { + return e.Errors[0] + } + // Shallow copy the slice errs := make([]error, len(e.Errors)) copy(errs, e.Errors) From 22c4e2b73e0d1850bd91dc756c66c237fe04b1f9 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 31 Mar 2020 09:43:38 -0700 Subject: [PATCH 35/80] implement chain by just wrapping a slice Thanks to @rogpeppe on Twitter for pointing out we don't need a struct to take care of accounting and can instead just continue to reslice and wrap []error. --- multierror.go | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/multierror.go b/multierror.go index d2bbbe9..c1b5159 100644 --- a/multierror.go +++ b/multierror.go @@ -76,8 +76,7 @@ func (e *Error) Unwrap() error { // Shallow copy the slice errs := make([]error, len(e.Errors)) copy(errs, e.Errors) - - return &chain{errors: errs} + return chain(errs) } // chain implements the interfaces necessary for errors.Is/As/Unwrap to @@ -89,37 +88,29 @@ func (e *Error) Unwrap() error { // the wrapped error here but we can't do that if we want to properly // get access to all the errors. Instead, users are recommended to use // Is/As to get the correct error type out. -type chain struct { - idx int - errors []error -} +type chain []error // Error implements the error interface -func (e *chain) Error() string { - return e.current().Error() +func (e chain) Error() string { + return e[0].Error() } // Unwrap implements errors.Unwrap by returning the next error in the // chain or nil if there are no more errors. -func (e *chain) Unwrap() error { - next := e.idx + 1 - if len(e.errors) <= next { +func (e chain) Unwrap() error { + if len(e) == 1 { return nil } - return &chain{idx: next, errors: e.errors} + return chain(e[1:]) } // As implements errors.As by attempting to map to the current value. -func (e *chain) As(target interface{}) bool { - return errors.As(e.current(), target) +func (e chain) As(target interface{}) bool { + return errors.As(e[0], target) } // Is implements errors.Is by comparing the current value directly. -func (e *chain) Is(target error) bool { - return e.current() == target -} - -func (e *chain) current() error { - return e.errors[e.idx] +func (e chain) Is(target error) bool { + return e[0] == target } From 0c3d827a1e5a371fa426299e398ef78ad3554679 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 31 Mar 2020 09:52:58 -0700 Subject: [PATCH 36/80] Address feedback --- multierror.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/multierror.go b/multierror.go index c1b5159..6c51bd2 100644 --- a/multierror.go +++ b/multierror.go @@ -102,7 +102,7 @@ func (e chain) Unwrap() error { return nil } - return chain(e[1:]) + return e[1:] } // As implements errors.As by attempting to map to the current value. @@ -112,5 +112,5 @@ func (e chain) As(target interface{}) bool { // Is implements errors.Is by comparing the current value directly. func (e chain) Is(target error) bool { - return e[0] == target + return errors.Is(e[0], target) } From bcb7871369ffe1ab9dc509dac5ec4dac34ca2573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Geisend=C3=B6rfer?= Date: Tue, 31 Mar 2020 19:03:00 +0200 Subject: [PATCH 37/80] add test case for Unwrap + Errorf --- multierror_test.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/multierror_test.go b/multierror_test.go index 789230e..972c52d 100644 --- a/multierror_test.go +++ b/multierror_test.go @@ -2,6 +2,7 @@ package multierror import ( "errors" + "fmt" "reflect" "testing" ) @@ -121,6 +122,18 @@ func TestErrorIs(t *testing.T) { } }) + t.Run("with errBar wrapped by fmt.Errorf", func(t *testing.T) { + err := &Error{Errors: []error{ + errors.New("foo"), + fmt.Errorf("errorf: %w", errBar), + errors.New("baz"), + }} + + if !errors.Is(err, errBar) { + t.Fatal("should be true") + } + }) + t.Run("without errBar", func(t *testing.T) { err := &Error{Errors: []error{ errors.New("foo"), @@ -152,6 +165,22 @@ func TestErrorAs(t *testing.T) { } }) + t.Run("with the value wrapped by fmt.Errorf", func(t *testing.T) { + err := &Error{Errors: []error{ + errors.New("foo"), + fmt.Errorf("errorf: %w", match), + errors.New("baz"), + }} + + var target *nestedError + if !errors.As(err, &target) { + t.Fatal("should be true") + } + if target == nil { + t.Fatal("target should not be nil") + } + }) + t.Run("without the value", func(t *testing.T) { err := &Error{Errors: []error{ errors.New("foo"), From 8f5549246f78b5307a906a7253f05d08356aed1f Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 31 Mar 2020 10:19:21 -0700 Subject: [PATCH 38/80] Add precondition note to chain --- multierror.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/multierror.go b/multierror.go index 6c51bd2..d05dd92 100644 --- a/multierror.go +++ b/multierror.go @@ -88,6 +88,8 @@ func (e *Error) Unwrap() error { // the wrapped error here but we can't do that if we want to properly // get access to all the errors. Instead, users are recommended to use // Is/As to get the correct error type out. +// +// Precondition: []error is non-empty (len > 0) type chain []error // Error implements the error interface From 2004d9dba6b07a5b8d133209244f376680f9d472 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 31 Mar 2020 11:10:32 -0700 Subject: [PATCH 39/80] update README with usage examples including standard error methods --- README.md | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ead5830..e92fa61 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,10 @@ be a list of errors. If the caller knows this, they can unwrap the list and access the errors. If the caller doesn't know, the error formats to a nice human-readable format. -`go-multierror` implements the -[errwrap](https://github.com/hashicorp/errwrap) interface so that it can -be used with that library, as well. +`go-multierror` is fully compatible with the Go standard library +[errors](https://golang.org/pkg/errors/) package, including the +functions `As`, `Is`, and `Unwrap`. This provides a standardized approach +for introspecting on error values. ## Installation and Docs @@ -81,6 +82,39 @@ if err := something(); err != nil { } ``` +You can also use the standard [`errors.Unwrap`](https://golang.org/pkg/errors/#Unwrap) +function. This will continue to unwrap into subsequent errors until none exist. + +**Extracting an error** + +The standard library [`errors.As`](https://golang.org/pkg/errors/#As) +function can be used directly with a multierror to extract a specific error: + +```go +// Assume err is a multierror value +err := somefunc() + +// We want to know if "err" has a "RichErrorType" in it and extract it. +var errRich RichErrorType +if errors.As(err, &errRich) { + // It has it, and now errRich is populated. +} +``` + +**Checking for an exact error value** + +Some errors are returned as exact errors such as the [`ErrNotExist`](https://golang.org/pkg/os/#pkg-variables) +error in the `os` package. You can check if this error is present by using +the standard [`errors.Is`](https://golang.org/pkg/errors/#Is) function. + +```go +// Assume err is a multierror value +err := somefunc() +if errors.Is(err, os.ErrNotExist) { + // err contains os.ErrNotExist +} +``` + **Returning a multierror only if there are errors** If you build a `multierror.Error`, you can use the `ErrorOrNil` function From 3df56f46554f149c736e0b4498f092f05cc8ca6f Mon Sep 17 00:00:00 2001 From: Michael Golowka <72365+pcman312@users.noreply.github.com> Date: Fri, 26 Jun 2020 09:48:22 -0600 Subject: [PATCH 40/80] Update Append docs with nil error handling --- append.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/append.go b/append.go index 775b6e7..3e2589b 100644 --- a/append.go +++ b/append.go @@ -6,6 +6,8 @@ package multierror // If err is not a multierror.Error, then it will be turned into // one. If any of the errs are multierr.Error, they will be flattened // one level into err. +// Any nil errors within errs will be ignored. If err is nil, a new +// *Error will be returned. func Append(err error, errs ...error) *Error { switch err := err.(type) { case *Error: From d51a2315c1223966f20802b44e436a5bcb9b6db2 Mon Sep 17 00:00:00 2001 From: haoxin Date: Wed, 25 Nov 2020 14:11:28 +0800 Subject: [PATCH 41/80] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e92fa61..074a749 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)][godocs] [travis]: https://travis-ci.org/hashicorp/go-multierror -[godocs]: https://godoc.org/github.com/hashicorp/go-multierror +[godocs]: https://pkg.go.dev/github.com/hashicorp/go-multierror `go-multierror` is a package for Go that provides a mechanism for representing a list of `error` values as a single `error`. @@ -24,7 +24,7 @@ for introspecting on error values. Install using `go get github.com/hashicorp/go-multierror`. Full documentation is available at -http://godoc.org/github.com/hashicorp/go-multierror +https://pkg.go.dev/github.com/hashicorp/go-multierror ## Usage From 435d0fdac58b7c9dc810abe87307a097ba6de756 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Fri, 5 Mar 2021 15:24:51 -0800 Subject: [PATCH 42/80] Add required go version to docs Closes #37 --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index e92fa61..a946c43 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,24 @@ Install using `go get github.com/hashicorp/go-multierror`. Full documentation is available at http://godoc.org/github.com/hashicorp/go-multierror +### Requires go version 1.13 or newer + +`go-multierror` requires go version 1.13 or newer. Go 1.13 introduced +[error wrapping](https://golang.org/doc/go1.13#error_wrapping), which +this library takes advantage of. + +If you need to use an earlier version of go, you can use the +[v1.0.0](https://github.com/hashicorp/go-multierror/tree/v1.0.0) +tag, which doesn't rely on features in go 1.13. + +If you see compile errors that look like the below, it's likely that +you're on an older version of go. + +``` +/go/src/github.com/hashicorp/go-multierror/multierror.go:112:9: undefined: errors.As +/go/src/github.com/hashicorp/go-multierror/multierror.go:117:9: undefined: errors.Is +``` + ## Usage go-multierror is easy to use and purposely built to be unobtrusive in From 9cc5fd891eb79ebb409a48d8c6854e65fbe89e79 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Fri, 5 Mar 2021 15:26:09 -0800 Subject: [PATCH 43/80] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a946c43..e9d132d 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ If you need to use an earlier version of go, you can use the tag, which doesn't rely on features in go 1.13. If you see compile errors that look like the below, it's likely that -you're on an older version of go. +you're on an older version of go: ``` /go/src/github.com/hashicorp/go-multierror/multierror.go:112:9: undefined: errors.As From 78708dbe0f6f1383078ba6c47f7e19cc8f810488 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Fri, 5 Mar 2021 16:41:10 -0800 Subject: [PATCH 44/80] Carry over some changes from #26 --- .circleci/config.yml | 2 +- prefix_test.go | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 488dae5..c44dcbd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2.1 references:   images: -    go: &GOLANG_IMAGE circleci/golang:latest +    go: &GOLANG_IMAGE circleci/golang:1.13   environments:     tmp: &TEST_RESULTS_PATH /tmp/test-results # path to where test results are saved diff --git a/prefix_test.go b/prefix_test.go index 1d4a6f6..849ec3a 100644 --- a/prefix_test.go +++ b/prefix_test.go @@ -27,6 +27,9 @@ func TestPrefix_NilError(t *testing.T) { func TestPrefix_NonError(t *testing.T) { original := errors.New("foo") result := Prefix(original, "bar") + if result == nil { + t.Fatal("error result was nil") + } if result.Error() != "bar foo" { t.Fatalf("bad: %s", result) } From e27d23170e2b792ee617968384b794d2930b4924 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Fri, 5 Mar 2021 16:51:23 -0800 Subject: [PATCH 45/80] update badges to use circle --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 074a749..c9514ec 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ # go-multierror -[![Build Status](http://img.shields.io/travis/hashicorp/go-multierror.svg?style=flat-square)][travis] -[![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)][godocs] +[![CircleCI](https://img.shields.io/circleci/build/github/hashicorp/go-multierror/master)](https://circleci.com/gh/hashicorp/go-multierror) +[![Go Reference](https://pkg.go.dev/badge/github.com/hashicorp/go-multierror.svg)](https://pkg.go.dev/github.com/hashicorp/go-multierror) +![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/hashicorp/go-multierror) -[travis]: https://travis-ci.org/hashicorp/go-multierror +[circleci]: https://app.circleci.com/pipelines/github/hashicorp/go-multierror [godocs]: https://pkg.go.dev/github.com/hashicorp/go-multierror `go-multierror` is a package for Go that provides a mechanism for From eabd672ee8f2389db69282b7b530acce8f5c4a1a Mon Sep 17 00:00:00 2001 From: Michele Date: Mon, 8 Mar 2021 14:20:07 -0800 Subject: [PATCH 46/80] Fix CI config --- .circleci/config.yml | 211 ++++++++++++++++++++++++++++++++----------- 1 file changed, 158 insertions(+), 53 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c44dcbd..c593aff 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,59 +1,164 @@ -version: 2.1 +version: 2.1 + +orbs: + win: circleci/windows@2.2.0 references: -  images: -    go: &GOLANG_IMAGE circleci/golang:1.13 -  environments: -    tmp: &TEST_RESULTS_PATH /tmp/test-results # path to where test results are saved - -# reusable 'executor' object for jobs -executors: -  go: -    docker: -      - image: *GOLANG_IMAGE -    environment: -      - TEST_RESULTS: *TEST_RESULTS_PATH + environment: &ENVIRONMENT + TEST_RESULTS_PATH: &TEST_RESULTS_PATH /tmp/test-results + WIN_TEST_RESULTS: &WIN_TEST_RESULTS c:\Users\circleci\AppData\Local\Temp\test-results +commands: + run-gotests: + parameters: + cmd: + type: string + platform: + type: string + steps: + - run: + name: "Run go tests" + command: | + PACKAGE_NAMES=$(go list ./... | circleci tests split --split-by=timings --timings-type=classname) + echo "Running $(echo $PACKAGE_NAMES | wc -w) packages" + echo $PACKAGE_NAMES + << parameters.cmd >> --format=short-verbose --junitfile $TEST_RESULTS_PATH/go-multierror/gotestsum-report.xml -- -p 2 -cover -coverprofile=<< parameters.platform >>_cov_$CIRCLE_NODE_INDEX.part $PACKAGE_NAMES + jobs: -  go-test: -    executor: go -    steps: -      - checkout -      - run: mkdir -p $TEST_RESULTS - -      - restore_cache: # restore cache from dev-build job -          keys: -            - go-multierror-modcache-v1-{{ checksum "go.mod" }} - -      - run: go mod download - -      # Save go module cache if the go.mod file has changed -      - save_cache: -          key: go-multierror-modcache-v1-{{ checksum "go.mod" }} -          paths: -            - "/go/pkg/mod" - -      # check go fmt output because it does not report non-zero when there are fmt changes -      - run: -          name: check go fmt -          command: | -            files=$(go fmt ./...) -            if [ -n "$files" ]; then -              echo "The following file(s) do not conform to go fmt:" -              echo "$files" -              exit 1 -            fi -      # run go tests with gotestsum -      - run: | -          PACKAGE_NAMES=$(go list ./...) -          gotestsum --format=short-verbose --junitfile $TEST_RESULTS/gotestsum-report.xml -- $PACKAGE_NAMES -      - store_test_results: -          path: *TEST_RESULTS_PATH -      - store_artifacts: -          path: *TEST_RESULTS_PATH + linux-tests: + docker: + - image: docker.mirror.hashicorp.services/circleci/golang:<< parameters.go-version >> + parameters: + go-version: + type: string + environment: + <<: *ENVIRONMENT + parallelism: 4 + steps: + - run: go version + - checkout + - attach_workspace: + at: . + - run: mkdir -p $TEST_RESULTS_PATH/go-multierror + + # Restore go module cache if there is one + - restore_cache: + keys: + - linux-gomod-cache-v1-{{ checksum "go.mod" }} + + - run: go mod download + + # Save go module cache if the go.mod file has changed + - save_cache: + key: linux-gomod-cache-v1-{{ checksum "go.mod" }} + paths: + - "/go/pkg/mod" + + # Check go fmt output because it does not report non-zero when there are fmt changes + - run: + name: check go fmt + command: | + files=$(go fmt ./...) + if [ -n "$files" ]; then + echo "The following file(s) do not conform to go fmt:" + echo "$files" + exit 1 + fi + # Run go tests with gotestsum + - run-gotests: + cmd: "gotestsum" + platform: "linux" + + # Save coverage report parts + - persist_to_workspace: + root: . + paths: + - linux_cov_*.part + + - store_test_results: + path: *TEST_RESULTS_PATH + - store_artifacts: + path: *TEST_RESULTS_PATH + + windows-tests: + executor: + name: win/default + shell: bash --login -eo pipefail + environment: + <<: *ENVIRONMENT + working_directory: c:\gopath\src\github.com\hashicorp\go-multierror + parameters: + go-version: + type: string + gotestsum-version: + type: string + steps: + - run: git config --global core.autocrlf false + - checkout + - attach_workspace: + at: . + - run: + name: Setup (remove pre-installed go) + command: | + rm -rf "c:\Go" + mkdir -p $TEST_RESULTS_PATH/go-multierror + - restore_cache: + keys: + - win-golang-<< parameters.go-version >>-cache-v1 + - win-gomod-cache-{{ checksum "go.mod" }}-v1 + + - run: + name: Install go version << parameters.go-version >> + command: | + if [ ! -d "c:\go" ]; then + echo "Cache not found, installing new version of go" + curl --fail --location https://dl.google.com/go/go<< parameters.go-version >>.windows-amd64.zip --output go.zip + unzip go.zip -d "/c" + fi + - run: + command: go mod download + + - save_cache: + key: win-golang-<< parameters.go-version >>-cache-v1 + paths: + - /go + + - save_cache: + key: win-gomod-cache-{{ checksum "go.mod" }}-v1 + paths: + - c:\Windows\system32\config\systemprofile\go\pkg\mod + + - run: + name: Install gotestsum + command: | + curl --fail --location https://github.com/gotestyourself/gotestsum/releases/download/v<< parameters.gotestsum-version >>/gotestsum_<< parameters.gotestsum-version >>_windows_amd64.tar.gz --output gotestsum.tar.gz + tar -xvzf gotestsum.tar.gz + - run-gotests: + cmd: "./gotestsum.exe" + platform: "win" + + # Save coverage report parts + - persist_to_workspace: + root: . + paths: + - win_cov_*.part + + - store_test_results: + path: *WIN_TEST_RESULTS + - store_artifacts: + path: *WIN_TEST_RESULTS workflows: -  version: 2 -  test-and-build: -    jobs: -      - go-test + go-multierror: + jobs: + - linux-tests: + matrix: + parameters: + go-version: ["1.13", "1.14", "1.15"] + name: linux-test-go-<< matrix.go-version >> + - windows-tests: + matrix: + parameters: + go-version: ["1.13", "1.14", "1.15"] + gotestsum-version: ["0.4.1"] + name: win-test-go-<< matrix.go-version >> From af59c663db3f8243edf5eda89a73ba6ef19c7346 Mon Sep 17 00:00:00 2001 From: Michele Date: Mon, 8 Mar 2021 14:26:44 -0800 Subject: [PATCH 47/80] Upgrade gotestsum version --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c593aff..4918497 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -160,5 +160,5 @@ workflows: matrix: parameters: go-version: ["1.13", "1.14", "1.15"] - gotestsum-version: ["0.4.1"] + gotestsum-version: ["1.6.2"] name: win-test-go-<< matrix.go-version >> From ab6846acb1cf402787cde041fcff5f01c0b8e362 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Mon, 8 Mar 2021 14:41:51 -0800 Subject: [PATCH 48/80] we require go 1.13 Make sure we specify go v1.13, not 1.14 --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 0afe8e6..141cc4c 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module github.com/hashicorp/go-multierror -go 1.14 +go 1.13 require github.com/hashicorp/errwrap v1.0.0 From 0023bb0ab1225a10509dca08627b42bed25d74a5 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Thu, 11 Mar 2021 15:06:12 -0500 Subject: [PATCH 49/80] Check if multierror is nil in WrappedErrors This adds a check similar to `ErrorsOrNil` that ensures the multierror pointer is not nil before returning the Errors field. I believe this is fully backwards-compatible, because the former behavior is a runtime panic. --- multierror.go | 15 +++++++++------ multierror_test.go | 5 +++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/multierror.go b/multierror.go index d05dd92..f545743 100644 --- a/multierror.go +++ b/multierror.go @@ -40,14 +40,17 @@ func (e *Error) GoString() string { return fmt.Sprintf("*%#v", *e) } -// 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. +// 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. +// This method is not safe to be called concurrently. Unlike accessing the +// Errors field directly, this function also checks if the multierror is nil to +// prevent a null-pointer panic. It satisfies the errwrap.Wrapper interface. func (e *Error) WrappedErrors() []error { + if e == nil { + return nil + } return e.Errors } diff --git a/multierror_test.go b/multierror_test.go index 972c52d..ed1f08c 100644 --- a/multierror_test.go +++ b/multierror_test.go @@ -69,6 +69,11 @@ func TestErrorWrappedErrors(t *testing.T) { if !reflect.DeepEqual(multi.Errors, multi.WrappedErrors()) { t.Fatalf("bad: %s", multi.WrappedErrors()) } + + multi = nil + if err := multi.WrappedErrors(); err != nil { + t.Fatalf("bad: %#v", multi) + } } func TestErrorUnwrap(t *testing.T) { From 09b6bfc476a97af95d5721d25f5b74d5f1474a25 Mon Sep 17 00:00:00 2001 From: "hashicorp-copywrite[bot]" <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Date: Wed, 25 Jan 2023 18:34:39 +0000 Subject: [PATCH 50/80] [COMPLIANCE] Update MPL-2.0 LICENSE --- LICENSE | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LICENSE b/LICENSE index 82b4de9..e25da5f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,5 @@ +Copyright (c) 2014 HashiCorp, Inc. + Mozilla Public License, version 2.0 1. Definitions From 4c578bc55b5cf164f651d0f0762b40c5a6d40ee2 Mon Sep 17 00:00:00 2001 From: hc-github-team-es-release-engineering <82989873+hc-github-team-es-release-engineering@users.noreply.github.com> Date: Tue, 4 Apr 2023 20:06:51 +0100 Subject: [PATCH 51/80] Add workflow hashicorp/go-multierror/go-multierror --- .github/workflows/go-multierror.yml | 118 ++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 .github/workflows/go-multierror.yml diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml new file mode 100644 index 0000000..d1c0408 --- /dev/null +++ b/.github/workflows/go-multierror.yml @@ -0,0 +1,118 @@ +name: hashicorp/go-multierror/go-multierror +on: + push: + branches: + - master +jobs: + linux-tests: + runs-on: ubuntu-latest + container: + image: docker.mirror.hashicorp.services/circleci/golang:${{ matrix.go-version }} + env: + TEST_RESULTS_PATH: "/tmp/test-results" + WIN_TEST_RESULTS: c:\Users\circleci\AppData\Local\Temp\test-results + strategy: + matrix: + go-version: + - '1.13' + - '1.14' + - '1.15' + steps: + - run: go version + - uses: actions/checkout@v3.5.0 + - uses: actions/download-artifact@v3.0.1 + with: + path: "." + - run: mkdir -p $TEST_RESULTS_PATH/go-multierror + - name: restore_cache + uses: actions/cache@v3.3.1 + with: + key: linux-gomod-cache-v1-{{ checksum "go.mod" }} + restore-keys: linux-gomod-cache-v1-{{ checksum "go.mod" }} + path: "/go/pkg/mod" + - run: go mod download + - name: check go fmt + run: |- + files=$(go fmt ./...) + if [ -n "$files" ]; then + echo "The following file(s) do not conform to go fmt:" + echo "$files" + exit 1 + fi + - uses: "./.github/actions/run-gotests" + with: + cmd: gotestsum + platform: linux + - uses: actions/upload-artifact@v3.1.1 + with: + path: "./linux_cov_*.part" + - uses: actions/upload-artifact@v3.1.1 + with: + path: "/tmp/test-results" + - uses: actions/upload-artifact@v3.1.1 + with: + path: "/tmp/test-results" + windows-tests: + defaults: + run: + working-directory: c:\gopath\src\github.com\hashicorp\go-multierror + runs-on: ubuntu-latest + env: + TEST_RESULTS_PATH: "/tmp/test-results" + WIN_TEST_RESULTS: c:\Users\circleci\AppData\Local\Temp\test-results + strategy: + matrix: + go-version: + - '1.13' + - '1.14' + - '1.15' + gotestsum-version: + - 1.6.2 + steps: + - run: git config --global core.autocrlf false + - uses: actions/checkout@v3.5.0 + - uses: actions/download-artifact@v3.0.1 + with: + path: "." + - name: Setup (remove pre-installed go) + run: |- + rm -rf "c:\Go" + mkdir -p $TEST_RESULTS_PATH/go-multierror + - name: restore_cache + uses: actions/cache@v3.3.1 + with: + key: win-golang-${{ matrix.go-version }}-cache-v1 + restore-keys: |- + win-golang-${{ matrix.go-version }}-cache-v1 + win-gomod-cache-{{ checksum "go.mod" }}-v1 + path: "/go" + - name: Install go version ${{ matrix.go-version }} + run: |- + if [ ! -d "c:\go" ]; then + echo "Cache not found, installing new version of go" + curl --fail --location https://dl.google.com/go/go${{ matrix.go-version }}.windows-amd64.zip --output go.zip + unzip go.zip -d "/c" + fi + - run: go mod download + - name: save_cache + uses: actions/cache@v3.3.1 + with: + path: c:\Windows\system32\config\systemprofile\go\pkg\mod + key: win-gomod-cache-{{ checksum "go.mod" }}-v1 + - name: Install gotestsum + run: |- + curl --fail --location https://github.com/gotestyourself/gotestsum/releases/download/v${{ matrix.gotestsum-version }}/gotestsum_${{ matrix.gotestsum-version }}_windows_amd64.tar.gz --output gotestsum.tar.gz + tar -xvzf gotestsum.tar.gz + - uses: "./.github/actions/run-gotests" + with: + cmd: "./gotestsum.exe" + platform: win + - uses: actions/upload-artifact@v3.1.1 + with: + path: "./win_cov_*.part" + - uses: actions/upload-artifact@v3.1.1 + with: + path: c:\Users\circleci\AppData\Local\Temp\test-results + - uses: actions/upload-artifact@v3.1.1 + with: + path: c:\Users\circleci\AppData\Local\Temp\test-results From 5638b6f85a8b6eabd73c2f516e4c88d447cf5304 Mon Sep 17 00:00:00 2001 From: hc-github-team-es-release-engineering <82989873+hc-github-team-es-release-engineering@users.noreply.github.com> Date: Tue, 4 Apr 2023 20:06:52 +0100 Subject: [PATCH 52/80] Add composite action run-gotests --- .github/actions/run-gotests/action.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/actions/run-gotests/action.yml diff --git a/.github/actions/run-gotests/action.yml b/.github/actions/run-gotests/action.yml new file mode 100644 index 0000000..10aa3cd --- /dev/null +++ b/.github/actions/run-gotests/action.yml @@ -0,0 +1,16 @@ +name: run-gotests +inputs: + cmd: + required: false + platform: + required: false +runs: + using: composite + steps: + - name: Run go tests + run: |- + PACKAGE_NAMES=$(go list ./... | circleci tests split --split-by=timings --timings-type=classname) + echo "Running $(echo $PACKAGE_NAMES | wc -w) packages" + echo $PACKAGE_NAMES + ${{ inputs.cmd }} --format=short-verbose --junitfile $TEST_RESULTS_PATH/go-multierror/gotestsum-report.xml -- -p 2 -cover -coverprofile=${{ inputs.platform }}_cov_$CIRCLE_NODE_INDEX.part $PACKAGE_NAMES + shell: bash \ No newline at end of file From 6924f3d51c93600b51b76af8289ab8998328d70c Mon Sep 17 00:00:00 2001 From: shore Date: Tue, 4 Apr 2023 19:07:35 +0000 Subject: [PATCH 53/80] SHA-pin all 3rd-party actions --- .github/workflows/go-multierror.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index d1c0408..d165ffd 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -19,13 +19,13 @@ jobs: - '1.15' steps: - run: go version - - uses: actions/checkout@v3.5.0 - - uses: actions/download-artifact@v3.0.1 + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: path: "." - run: mkdir -p $TEST_RESULTS_PATH/go-multierror - name: restore_cache - uses: actions/cache@v3.3.1 + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 with: key: linux-gomod-cache-v1-{{ checksum "go.mod" }} restore-keys: linux-gomod-cache-v1-{{ checksum "go.mod" }} @@ -43,13 +43,13 @@ jobs: with: cmd: gotestsum platform: linux - - uses: actions/upload-artifact@v3.1.1 + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: path: "./linux_cov_*.part" - - uses: actions/upload-artifact@v3.1.1 + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: path: "/tmp/test-results" - - uses: actions/upload-artifact@v3.1.1 + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: path: "/tmp/test-results" windows-tests: @@ -70,8 +70,8 @@ jobs: - 1.6.2 steps: - run: git config --global core.autocrlf false - - uses: actions/checkout@v3.5.0 - - uses: actions/download-artifact@v3.0.1 + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: path: "." - name: Setup (remove pre-installed go) @@ -79,7 +79,7 @@ jobs: rm -rf "c:\Go" mkdir -p $TEST_RESULTS_PATH/go-multierror - name: restore_cache - uses: actions/cache@v3.3.1 + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 with: key: win-golang-${{ matrix.go-version }}-cache-v1 restore-keys: |- @@ -95,7 +95,7 @@ jobs: fi - run: go mod download - name: save_cache - uses: actions/cache@v3.3.1 + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 with: path: c:\Windows\system32\config\systemprofile\go\pkg\mod key: win-gomod-cache-{{ checksum "go.mod" }}-v1 @@ -107,12 +107,12 @@ jobs: with: cmd: "./gotestsum.exe" platform: win - - uses: actions/upload-artifact@v3.1.1 + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: path: "./win_cov_*.part" - - uses: actions/upload-artifact@v3.1.1 + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: path: c:\Users\circleci\AppData\Local\Temp\test-results - - uses: actions/upload-artifact@v3.1.1 + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: path: c:\Users\circleci\AppData\Local\Temp\test-results From 0d540d5b8b297eaa75517fe60715739ea521f651 Mon Sep 17 00:00:00 2001 From: shore Date: Tue, 4 Apr 2023 19:07:35 +0000 Subject: [PATCH 54/80] Restrict workflow permissions --- .github/workflows/go-multierror.yml | 180 ++++++++++++++-------------- 1 file changed, 91 insertions(+), 89 deletions(-) diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index d165ffd..b506d44 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -2,7 +2,7 @@ name: hashicorp/go-multierror/go-multierror on: push: branches: - - master + - master jobs: linux-tests: runs-on: ubuntu-latest @@ -14,44 +14,44 @@ jobs: strategy: matrix: go-version: - - '1.13' - - '1.14' - - '1.15' + - '1.13' + - '1.14' + - '1.15' steps: - - run: go version - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 - - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - path: "." - - run: mkdir -p $TEST_RESULTS_PATH/go-multierror - - name: restore_cache - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 - with: - key: linux-gomod-cache-v1-{{ checksum "go.mod" }} - restore-keys: linux-gomod-cache-v1-{{ checksum "go.mod" }} - path: "/go/pkg/mod" - - run: go mod download - - name: check go fmt - run: |- - files=$(go fmt ./...) - if [ -n "$files" ]; then - echo "The following file(s) do not conform to go fmt:" - echo "$files" - exit 1 - fi - - uses: "./.github/actions/run-gotests" - with: - cmd: gotestsum - platform: linux - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - path: "./linux_cov_*.part" - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - path: "/tmp/test-results" - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - path: "/tmp/test-results" + - run: go version + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + path: "." + - run: mkdir -p $TEST_RESULTS_PATH/go-multierror + - name: restore_cache + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + with: + key: linux-gomod-cache-v1-{{ checksum "go.mod" }} + restore-keys: linux-gomod-cache-v1-{{ checksum "go.mod" }} + path: "/go/pkg/mod" + - run: go mod download + - name: check go fmt + run: |- + files=$(go fmt ./...) + if [ -n "$files" ]; then + echo "The following file(s) do not conform to go fmt:" + echo "$files" + exit 1 + fi + - uses: "./.github/actions/run-gotests" + with: + cmd: gotestsum + platform: linux + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + path: "./linux_cov_*.part" + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + path: "/tmp/test-results" + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + path: "/tmp/test-results" windows-tests: defaults: run: @@ -63,56 +63,58 @@ jobs: strategy: matrix: go-version: - - '1.13' - - '1.14' - - '1.15' + - '1.13' + - '1.14' + - '1.15' gotestsum-version: - - 1.6.2 + - 1.6.2 steps: - - run: git config --global core.autocrlf false - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 - - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - path: "." - - name: Setup (remove pre-installed go) - run: |- - rm -rf "c:\Go" - mkdir -p $TEST_RESULTS_PATH/go-multierror - - name: restore_cache - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 - with: - key: win-golang-${{ matrix.go-version }}-cache-v1 - restore-keys: |- - win-golang-${{ matrix.go-version }}-cache-v1 - win-gomod-cache-{{ checksum "go.mod" }}-v1 - path: "/go" - - name: Install go version ${{ matrix.go-version }} - run: |- - if [ ! -d "c:\go" ]; then - echo "Cache not found, installing new version of go" - curl --fail --location https://dl.google.com/go/go${{ matrix.go-version }}.windows-amd64.zip --output go.zip - unzip go.zip -d "/c" - fi - - run: go mod download - - name: save_cache - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 - with: - path: c:\Windows\system32\config\systemprofile\go\pkg\mod - key: win-gomod-cache-{{ checksum "go.mod" }}-v1 - - name: Install gotestsum - run: |- - curl --fail --location https://github.com/gotestyourself/gotestsum/releases/download/v${{ matrix.gotestsum-version }}/gotestsum_${{ matrix.gotestsum-version }}_windows_amd64.tar.gz --output gotestsum.tar.gz - tar -xvzf gotestsum.tar.gz - - uses: "./.github/actions/run-gotests" - with: - cmd: "./gotestsum.exe" - platform: win - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - path: "./win_cov_*.part" - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - path: c:\Users\circleci\AppData\Local\Temp\test-results - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - path: c:\Users\circleci\AppData\Local\Temp\test-results + - run: git config --global core.autocrlf false + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + path: "." + - name: Setup (remove pre-installed go) + run: |- + rm -rf "c:\Go" + mkdir -p $TEST_RESULTS_PATH/go-multierror + - name: restore_cache + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + with: + key: win-golang-${{ matrix.go-version }}-cache-v1 + restore-keys: |- + win-golang-${{ matrix.go-version }}-cache-v1 + win-gomod-cache-{{ checksum "go.mod" }}-v1 + path: "/go" + - name: Install go version ${{ matrix.go-version }} + run: |- + if [ ! -d "c:\go" ]; then + echo "Cache not found, installing new version of go" + curl --fail --location https://dl.google.com/go/go${{ matrix.go-version }}.windows-amd64.zip --output go.zip + unzip go.zip -d "/c" + fi + - run: go mod download + - name: save_cache + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + with: + path: c:\Windows\system32\config\systemprofile\go\pkg\mod + key: win-gomod-cache-{{ checksum "go.mod" }}-v1 + - name: Install gotestsum + run: |- + curl --fail --location https://github.com/gotestyourself/gotestsum/releases/download/v${{ matrix.gotestsum-version }}/gotestsum_${{ matrix.gotestsum-version }}_windows_amd64.tar.gz --output gotestsum.tar.gz + tar -xvzf gotestsum.tar.gz + - uses: "./.github/actions/run-gotests" + with: + cmd: "./gotestsum.exe" + platform: win + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + path: "./win_cov_*.part" + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + path: c:\Users\circleci\AppData\Local\Temp\test-results + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + path: c:\Users\circleci\AppData\Local\Temp\test-results +permissions: + contents: read From e5ad733c78658ff33f340648b579880ce772ea97 Mon Sep 17 00:00:00 2001 From: shore Date: Tue, 4 Apr 2023 19:07:35 +0000 Subject: [PATCH 55/80] Add actionslint --- .github/workflows/actionlint.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/actionlint.yml diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml new file mode 100644 index 0000000..be82ea5 --- /dev/null +++ b/.github/workflows/actionlint.yml @@ -0,0 +1,14 @@ +# If the repository is public, be sure to change to GitHub hosted runners +name: Lint GitHub Actions Workflows +on: + push: + pull_request: +permissions: + contents: read +jobs: + actionlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + - name: "Check workflow files" + uses: docker://docker.mirror.hashicorp.services/rhysd/actionlint:latest From d8a99d247f76da6ad7cb7e8a6683a1ffa51fa3e3 Mon Sep 17 00:00:00 2001 From: shore Date: Tue, 4 Apr 2023 19:07:35 +0000 Subject: [PATCH 56/80] Add dependabot --- .github/dependabot.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8a90cca --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" \ No newline at end of file From 96e2aecc4e458d38bd344f89c081170b30cbba6d Mon Sep 17 00:00:00 2001 From: shore Date: Tue, 4 Apr 2023 19:07:35 +0000 Subject: [PATCH 57/80] Add CODEOWNERS --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..7d1ad67 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +# Submit a helpdesk ticket to add any team other than yours referenced in the CODEOWNERS file -- they must be added to collaborators and teams in the repository settings with maintainer privileges. Remove this file as soon as you have completed this From cf89e8b610a45e4ef3e203e025ea1eb587a2d36e Mon Sep 17 00:00:00 2001 From: Brian Shore Date: Tue, 4 Apr 2023 12:13:27 -0700 Subject: [PATCH 58/80] Update migration --- .github/actions/run-gotests/action.yml | 16 --- .github/dependabot.yml | 6 +- .github/workflows/actionlint.yml | 11 +- .github/workflows/go-multierror.yml | 145 ++++++++++--------------- CODEOWNERS | 2 +- 5 files changed, 72 insertions(+), 108 deletions(-) delete mode 100644 .github/actions/run-gotests/action.yml diff --git a/.github/actions/run-gotests/action.yml b/.github/actions/run-gotests/action.yml deleted file mode 100644 index 10aa3cd..0000000 --- a/.github/actions/run-gotests/action.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: run-gotests -inputs: - cmd: - required: false - platform: - required: false -runs: - using: composite - steps: - - name: Run go tests - run: |- - PACKAGE_NAMES=$(go list ./... | circleci tests split --split-by=timings --timings-type=classname) - echo "Running $(echo $PACKAGE_NAMES | wc -w) packages" - echo $PACKAGE_NAMES - ${{ inputs.cmd }} --format=short-verbose --junitfile $TEST_RESULTS_PATH/go-multierror/gotestsum-report.xml -- -p 2 -cover -coverprofile=${{ inputs.platform }}_cov_$CIRCLE_NODE_INDEX.part $PACKAGE_NAMES - shell: bash \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8a90cca..975d258 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,4 +4,8 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "daily" \ No newline at end of file + interval: "daily" + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index be82ea5..84d20ce 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -1,14 +1,19 @@ -# If the repository is public, be sure to change to GitHub hosted runners name: Lint GitHub Actions Workflows + on: push: - pull_request: + paths: + - .github/** + permissions: contents: read + jobs: actionlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 - name: "Check workflow files" uses: docker://docker.mirror.hashicorp.services/rhysd/actionlint:latest + with: + args: -color diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index b506d44..9ce9adc 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -1,120 +1,91 @@ name: hashicorp/go-multierror/go-multierror on: push: - branches: - - master + +permissions: + contents: read + jobs: - linux-tests: + go-fmt: runs-on: ubuntu-latest - container: - image: docker.mirror.hashicorp.services/circleci/golang:${{ matrix.go-version }} - env: - TEST_RESULTS_PATH: "/tmp/test-results" - WIN_TEST_RESULTS: c:\Users\circleci\AppData\Local\Temp\test-results - strategy: - matrix: - go-version: - - '1.13' - - '1.14' - - '1.15' steps: - run: go version - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 - - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: - path: "." - - run: mkdir -p $TEST_RESULTS_PATH/go-multierror - - name: restore_cache - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 - with: - key: linux-gomod-cache-v1-{{ checksum "go.mod" }} - restore-keys: linux-gomod-cache-v1-{{ checksum "go.mod" }} - path: "/go/pkg/mod" - - run: go mod download + go-version-file: go.mod - name: check go fmt run: |- - files=$(go fmt ./...) + files="$(go fmt ./...)" if [ -n "$files" ]; then echo "The following file(s) do not conform to go fmt:" echo "$files" exit 1 fi - - uses: "./.github/actions/run-gotests" - with: - cmd: gotestsum - platform: linux - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + + linux-tests: + runs-on: ubuntu-latest + env: + TEST_RESULTS_PATH: '/tmp/test-results' + strategy: + matrix: + go-version: + - '1.13' # oldest supported; named in go.mod + - 'oldstable' + - 'stable' + steps: + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: - path: "./linux_cov_*.part" - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + go-version: ${{ matrix.go-version }} + - uses: autero1/action-gotestsum@2e48af62f5248bd3b014f598cd1aa69a01dd36e3 # v1.0.0 with: - path: "/tmp/test-results" + gotestsum_version: 1.9.0 + - run: | + go version + go env + - run: mkdir -p "$TEST_RESULTS_PATH/go-multierror" + - name: Run go tests + env: + PLATFORM: linux + REPORT_FILE: ${{ env.TEST_RESULTS_PATH }}/go-multierror/gotestsum-report.xml + run: |- + gotestsum --format=short-verbose --junitfile ${{ env.REPORT_FILE }} -- -p 2 ./... - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: - path: "/tmp/test-results" + path: ${{ env.TEST_RESULTS_PATH }} + name: tests-linux + windows-tests: - defaults: - run: - working-directory: c:\gopath\src\github.com\hashicorp\go-multierror - runs-on: ubuntu-latest + runs-on: windows-latest env: - TEST_RESULTS_PATH: "/tmp/test-results" - WIN_TEST_RESULTS: c:\Users\circleci\AppData\Local\Temp\test-results + TEST_RESULTS_PATH: 'c:\Users\runneradmin\AppData\Local\Temp\test-results' strategy: matrix: go-version: - - '1.13' - - '1.14' - - '1.15' - gotestsum-version: - - 1.6.2 + - '1.13' # oldest supported; named in go.mod + - 'oldstable' + - 'stable' steps: - - run: git config --global core.autocrlf false - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 - - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: - path: "." - - name: Setup (remove pre-installed go) - run: |- - rm -rf "c:\Go" - mkdir -p $TEST_RESULTS_PATH/go-multierror - - name: restore_cache - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 - with: - key: win-golang-${{ matrix.go-version }}-cache-v1 - restore-keys: |- - win-golang-${{ matrix.go-version }}-cache-v1 - win-gomod-cache-{{ checksum "go.mod" }}-v1 - path: "/go" - - name: Install go version ${{ matrix.go-version }} - run: |- - if [ ! -d "c:\go" ]; then - echo "Cache not found, installing new version of go" - curl --fail --location https://dl.google.com/go/go${{ matrix.go-version }}.windows-amd64.zip --output go.zip - unzip go.zip -d "/c" - fi + go-version: ${{ matrix.go-version }} + - run: | + go version + go env + - run: git config --global core.autocrlf false - run: go mod download - - name: save_cache - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + - uses: autero1/action-gotestsum@2e48af62f5248bd3b014f598cd1aa69a01dd36e3 # v1.0.0 with: - path: c:\Windows\system32\config\systemprofile\go\pkg\mod - key: win-gomod-cache-{{ checksum "go.mod" }}-v1 - - name: Install gotestsum + gotestsum_version: 1.9.0 + - name: Run go tests + env: + PLATFORM: win + REPORT_FILE: ${{ env.TEST_RESULTS_PATH }}/go-multierror/gotestsum-report.xml run: |- - curl --fail --location https://github.com/gotestyourself/gotestsum/releases/download/v${{ matrix.gotestsum-version }}/gotestsum_${{ matrix.gotestsum-version }}_windows_amd64.tar.gz --output gotestsum.tar.gz - tar -xvzf gotestsum.tar.gz - - uses: "./.github/actions/run-gotests" - with: - cmd: "./gotestsum.exe" - platform: win - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - path: "./win_cov_*.part" + gotestsum.exe --format=short-verbose --junitfile ${{ env.REPORT_FILE }} -- -p 2 ./... - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 with: - path: c:\Users\circleci\AppData\Local\Temp\test-results - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - with: - path: c:\Users\circleci\AppData\Local\Temp\test-results -permissions: - contents: read + path: ${{ env.TEST_RESULTS_PATH }} + name: tests-windows diff --git a/CODEOWNERS b/CODEOWNERS index 7d1ad67..1b35cec 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -# Submit a helpdesk ticket to add any team other than yours referenced in the CODEOWNERS file -- they must be added to collaborators and teams in the repository settings with maintainer privileges. Remove this file as soon as you have completed this +* @hashicorp/release-engineering From a57a935e1a404c3e4a9326416feeb2aba8349036 Mon Sep 17 00:00:00 2001 From: Brian Shore Date: Tue, 4 Apr 2023 15:28:56 -0700 Subject: [PATCH 59/80] Remove CircleCI configuration --- .circleci/config.yml | 164 ------------------------------------------- 1 file changed, 164 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 4918497..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,164 +0,0 @@ -version: 2.1 - -orbs: - win: circleci/windows@2.2.0 - -references: - environment: &ENVIRONMENT - TEST_RESULTS_PATH: &TEST_RESULTS_PATH /tmp/test-results - WIN_TEST_RESULTS: &WIN_TEST_RESULTS c:\Users\circleci\AppData\Local\Temp\test-results - -commands: - run-gotests: - parameters: - cmd: - type: string - platform: - type: string - steps: - - run: - name: "Run go tests" - command: | - PACKAGE_NAMES=$(go list ./... | circleci tests split --split-by=timings --timings-type=classname) - echo "Running $(echo $PACKAGE_NAMES | wc -w) packages" - echo $PACKAGE_NAMES - << parameters.cmd >> --format=short-verbose --junitfile $TEST_RESULTS_PATH/go-multierror/gotestsum-report.xml -- -p 2 -cover -coverprofile=<< parameters.platform >>_cov_$CIRCLE_NODE_INDEX.part $PACKAGE_NAMES - -jobs: - linux-tests: - docker: - - image: docker.mirror.hashicorp.services/circleci/golang:<< parameters.go-version >> - parameters: - go-version: - type: string - environment: - <<: *ENVIRONMENT - parallelism: 4 - steps: - - run: go version - - checkout - - attach_workspace: - at: . - - run: mkdir -p $TEST_RESULTS_PATH/go-multierror - - # Restore go module cache if there is one - - restore_cache: - keys: - - linux-gomod-cache-v1-{{ checksum "go.mod" }} - - - run: go mod download - - # Save go module cache if the go.mod file has changed - - save_cache: - key: linux-gomod-cache-v1-{{ checksum "go.mod" }} - paths: - - "/go/pkg/mod" - - # Check go fmt output because it does not report non-zero when there are fmt changes - - run: - name: check go fmt - command: | - files=$(go fmt ./...) - if [ -n "$files" ]; then - echo "The following file(s) do not conform to go fmt:" - echo "$files" - exit 1 - fi - # Run go tests with gotestsum - - run-gotests: - cmd: "gotestsum" - platform: "linux" - - # Save coverage report parts - - persist_to_workspace: - root: . - paths: - - linux_cov_*.part - - - store_test_results: - path: *TEST_RESULTS_PATH - - store_artifacts: - path: *TEST_RESULTS_PATH - - windows-tests: - executor: - name: win/default - shell: bash --login -eo pipefail - environment: - <<: *ENVIRONMENT - working_directory: c:\gopath\src\github.com\hashicorp\go-multierror - parameters: - go-version: - type: string - gotestsum-version: - type: string - steps: - - run: git config --global core.autocrlf false - - checkout - - attach_workspace: - at: . - - run: - name: Setup (remove pre-installed go) - command: | - rm -rf "c:\Go" - mkdir -p $TEST_RESULTS_PATH/go-multierror - - restore_cache: - keys: - - win-golang-<< parameters.go-version >>-cache-v1 - - win-gomod-cache-{{ checksum "go.mod" }}-v1 - - - run: - name: Install go version << parameters.go-version >> - command: | - if [ ! -d "c:\go" ]; then - echo "Cache not found, installing new version of go" - curl --fail --location https://dl.google.com/go/go<< parameters.go-version >>.windows-amd64.zip --output go.zip - unzip go.zip -d "/c" - fi - - run: - command: go mod download - - - save_cache: - key: win-golang-<< parameters.go-version >>-cache-v1 - paths: - - /go - - - save_cache: - key: win-gomod-cache-{{ checksum "go.mod" }}-v1 - paths: - - c:\Windows\system32\config\systemprofile\go\pkg\mod - - - run: - name: Install gotestsum - command: | - curl --fail --location https://github.com/gotestyourself/gotestsum/releases/download/v<< parameters.gotestsum-version >>/gotestsum_<< parameters.gotestsum-version >>_windows_amd64.tar.gz --output gotestsum.tar.gz - tar -xvzf gotestsum.tar.gz - - run-gotests: - cmd: "./gotestsum.exe" - platform: "win" - - # Save coverage report parts - - persist_to_workspace: - root: . - paths: - - win_cov_*.part - - - store_test_results: - path: *WIN_TEST_RESULTS - - store_artifacts: - path: *WIN_TEST_RESULTS - -workflows: - go-multierror: - jobs: - - linux-tests: - matrix: - parameters: - go-version: ["1.13", "1.14", "1.15"] - name: linux-test-go-<< matrix.go-version >> - - windows-tests: - matrix: - parameters: - go-version: ["1.13", "1.14", "1.15"] - gotestsum-version: ["1.6.2"] - name: win-test-go-<< matrix.go-version >> From 8d8ba98d6f4b4ab4280ab067c8effbf8d8899ca9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Apr 2023 15:03:39 +0000 Subject: [PATCH 60/80] Bump autero1/action-gotestsum from 1.0.0 to 2.0.0 Bumps [autero1/action-gotestsum](https://github.com/autero1/action-gotestsum) from 1.0.0 to 2.0.0. - [Release notes](https://github.com/autero1/action-gotestsum/releases) - [Changelog](https://github.com/autero1/action-gotestsum/blob/master/CHANGELOG.md) - [Commits](https://github.com/autero1/action-gotestsum/compare/2e48af62f5248bd3b014f598cd1aa69a01dd36e3...7263b9d73912eec65f46337689e59fac865c425f) --- updated-dependencies: - dependency-name: autero1/action-gotestsum dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/go-multierror.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index 9ce9adc..be89fc7 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -38,7 +38,7 @@ jobs: - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: go-version: ${{ matrix.go-version }} - - uses: autero1/action-gotestsum@2e48af62f5248bd3b014f598cd1aa69a01dd36e3 # v1.0.0 + - uses: autero1/action-gotestsum@7263b9d73912eec65f46337689e59fac865c425f # v2.0.0 with: gotestsum_version: 1.9.0 - run: | @@ -76,7 +76,7 @@ jobs: go env - run: git config --global core.autocrlf false - run: go mod download - - uses: autero1/action-gotestsum@2e48af62f5248bd3b014f598cd1aa69a01dd36e3 # v1.0.0 + - uses: autero1/action-gotestsum@7263b9d73912eec65f46337689e59fac865c425f # v2.0.0 with: gotestsum_version: 1.9.0 - name: Run go tests From e818bbb5ceab9deec2b97dac3b5529e337f17121 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 14:14:07 +0000 Subject: [PATCH 61/80] Bump actions/checkout from 3.5.0 to 3.5.3 Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...c85c95e3d7251135ab7dc9ce3241c5835cc595a9) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/actionlint.yml | 2 +- .github/workflows/go-multierror.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index 84d20ce..d16757b 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -12,7 +12,7 @@ jobs: actionlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: "Check workflow files" uses: docker://docker.mirror.hashicorp.services/rhysd/actionlint:latest with: diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index 9ce9adc..d87575b 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - run: go version - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: go-version-file: go.mod @@ -34,7 +34,7 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: go-version: ${{ matrix.go-version }} @@ -67,7 +67,7 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: go-version: ${{ matrix.go-version }} From a2f4c443160726231b9abbee081b48e1201d163a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Sep 2023 14:53:44 +0000 Subject: [PATCH 62/80] Bump actions/upload-artifact from 3.1.2 to 3.1.3 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3.1.2 to 3.1.3. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/0b7f8abb1508181956e8e162db84b466c27e18ce...a8a3f3ad30e3422c9c7b888a15615d19a852ae32) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/go-multierror.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index d87575b..9430602 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -51,7 +51,7 @@ jobs: REPORT_FILE: ${{ env.TEST_RESULTS_PATH }}/go-multierror/gotestsum-report.xml run: |- gotestsum --format=short-verbose --junitfile ${{ env.REPORT_FILE }} -- -p 2 ./... - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: path: ${{ env.TEST_RESULTS_PATH }} name: tests-linux @@ -85,7 +85,7 @@ jobs: REPORT_FILE: ${{ env.TEST_RESULTS_PATH }}/go-multierror/gotestsum-report.xml run: |- gotestsum.exe --format=short-verbose --junitfile ${{ env.REPORT_FILE }} -- -p 2 ./... - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: path: ${{ env.TEST_RESULTS_PATH }} name: tests-windows From a38fc11d20a2c33b3938e340f73b637c2bf5316e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Sep 2023 15:06:11 +0000 Subject: [PATCH 63/80] Bump actions/checkout from 3.5.3 to 4.1.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 4.1.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/c85c95e3d7251135ab7dc9ce3241c5835cc595a9...8ade135a41bc03ea155e62e844d188df1ea18608) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/actionlint.yml | 2 +- .github/workflows/go-multierror.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index d16757b..1d8b7e5 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -12,7 +12,7 @@ jobs: actionlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - name: "Check workflow files" uses: docker://docker.mirror.hashicorp.services/rhysd/actionlint:latest with: diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index d87575b..d0261f5 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - run: go version - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: go-version-file: go.mod @@ -34,7 +34,7 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: go-version: ${{ matrix.go-version }} @@ -67,7 +67,7 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: go-version: ${{ matrix.go-version }} From 35f196aed6538086a06d8702ce2165796385779a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 14:34:59 +0000 Subject: [PATCH 64/80] Bump actions/checkout from 4.1.0 to 4.1.1 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8ade135a41bc03ea155e62e844d188df1ea18608...b4ffde65f46336ab88eb53be808477a3936bae11) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/actionlint.yml | 2 +- .github/workflows/go-multierror.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index 1d8b7e5..35cbd30 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -12,7 +12,7 @@ jobs: actionlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: "Check workflow files" uses: docker://docker.mirror.hashicorp.services/rhysd/actionlint:latest with: diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index 7b674eb..24037a9 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - run: go version - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: go-version-file: go.mod @@ -34,7 +34,7 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: go-version: ${{ matrix.go-version }} @@ -67,7 +67,7 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: go-version: ${{ matrix.go-version }} From 74413bf8b5961c23f560b1846c077bfa3dff2b79 Mon Sep 17 00:00:00 2001 From: "hashicorp-copywrite[bot]" <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 16:05:38 +0000 Subject: [PATCH 65/80] [COMPLIANCE] Add Copyright and License Headers --- append.go | 3 +++ append_test.go | 3 +++ flatten.go | 3 +++ flatten_test.go | 3 +++ format.go | 3 +++ format_test.go | 3 +++ group.go | 3 +++ group_test.go | 3 +++ multierror.go | 3 +++ multierror_test.go | 3 +++ prefix.go | 3 +++ prefix_test.go | 3 +++ sort.go | 3 +++ sort_test.go | 3 +++ 14 files changed, 42 insertions(+) diff --git a/append.go b/append.go index 3e2589b..683b665 100644 --- a/append.go +++ b/append.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package multierror // Append is a helper function that will append more errors diff --git a/append_test.go b/append_test.go index 58ddafa..e5179bf 100644 --- a/append_test.go +++ b/append_test.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package multierror import ( diff --git a/flatten.go b/flatten.go index aab8e9a..3fca40f 100644 --- a/flatten.go +++ b/flatten.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package multierror // Flatten flattens the given error, merging any *Errors together into diff --git a/flatten_test.go b/flatten_test.go index e99c410..2d81f12 100644 --- a/flatten_test.go +++ b/flatten_test.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package multierror import ( diff --git a/format.go b/format.go index 47f13c4..b06ae9a 100644 --- a/format.go +++ b/format.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package multierror import ( diff --git a/format_test.go b/format_test.go index 2b6da1d..77af2da 100644 --- a/format_test.go +++ b/format_test.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package multierror import ( diff --git a/group.go b/group.go index 9c29efb..48b68fc 100644 --- a/group.go +++ b/group.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package multierror import "sync" diff --git a/group_test.go b/group_test.go index 9d472fd..88795bf 100644 --- a/group_test.go +++ b/group_test.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package multierror import ( diff --git a/multierror.go b/multierror.go index f545743..b83d27f 100644 --- a/multierror.go +++ b/multierror.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package multierror import ( diff --git a/multierror_test.go b/multierror_test.go index ed1f08c..9fa41a2 100644 --- a/multierror_test.go +++ b/multierror_test.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package multierror import ( diff --git a/prefix.go b/prefix.go index 5c477ab..24ef743 100644 --- a/prefix.go +++ b/prefix.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package multierror import ( diff --git a/prefix_test.go b/prefix_test.go index 849ec3a..d0eb04a 100644 --- a/prefix_test.go +++ b/prefix_test.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package multierror import ( diff --git a/sort.go b/sort.go index fecb14e..b9f1f49 100644 --- a/sort.go +++ b/sort.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package multierror // Len implements sort.Interface function for length diff --git a/sort_test.go b/sort_test.go index 7fd04e8..b6ff44e 100644 --- a/sort_test.go +++ b/sort_test.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package multierror import ( From 8c185579adb99b4ac3d8f935131793db89e23d2b Mon Sep 17 00:00:00 2001 From: Daniel Bos Date: Fri, 1 Mar 2024 15:23:28 +0800 Subject: [PATCH 66/80] fix: handle nil pointer in Len function of Error struct Similar to `*Error.ErrorOrNil`, handle `nil` values for *Error gracefully, return a length of 0. --- sort.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sort.go b/sort.go index b9f1f49..1d34b4c 100644 --- a/sort.go +++ b/sort.go @@ -4,7 +4,11 @@ package multierror // Len implements sort.Interface function for length -func (err Error) Len() int { +func (err *Error) Len() int { + if err == nil { + return 0 + } + return len(err.Errors) } From 46643208e4465895e90fac2780d51223de05867d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Apr 2024 14:26:35 +0000 Subject: [PATCH 67/80] Bump actions/checkout from 4.1.1 to 4.1.4 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/b4ffde65f46336ab88eb53be808477a3936bae11...0ad4b8fadaa221de15dcec353f45205ec38ea70b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/actionlint.yml | 2 +- .github/workflows/go-multierror.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index 35cbd30..d8d579f 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -12,7 +12,7 @@ jobs: actionlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: "Check workflow files" uses: docker://docker.mirror.hashicorp.services/rhysd/actionlint:latest with: diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index 464e264..e151130 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - run: go version - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: go-version-file: go.mod @@ -34,7 +34,7 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: go-version: ${{ matrix.go-version }} @@ -67,7 +67,7 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 with: go-version: ${{ matrix.go-version }} From b8012ee3ba0c6acafd69f3a799d0f95086d34e7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 May 2024 09:38:04 -0700 Subject: [PATCH 68/80] Bump actions/setup-go from 4.0.0 to 5.0.1 (#103) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4.0.0 to 5.0.1. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/4d34df0c2316fe8122ab82dc22947d607c0c91f9...cdcb36043654635271a94b9a6d1392de5bb323a7) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/go-multierror.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index e151130..4a71e67 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -11,7 +11,7 @@ jobs: steps: - run: go version - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 + - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: go-version-file: go.mod - name: check go fmt @@ -35,7 +35,7 @@ jobs: - 'stable' steps: - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 + - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: go-version: ${{ matrix.go-version }} - uses: autero1/action-gotestsum@7263b9d73912eec65f46337689e59fac865c425f # v2.0.0 @@ -68,7 +68,7 @@ jobs: - 'stable' steps: - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 + - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: go-version: ${{ matrix.go-version }} - run: | From 5b9e054118cbb0f2c328868493544592446db375 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 May 2024 09:38:42 -0700 Subject: [PATCH 69/80] Bump github.com/hashicorp/errwrap from 1.0.0 to 1.1.0 (#72) Bumps [github.com/hashicorp/errwrap](https://github.com/hashicorp/errwrap) from 1.0.0 to 1.1.0. - [Release notes](https://github.com/hashicorp/errwrap/releases) - [Commits](https://github.com/hashicorp/errwrap/compare/v1.0.0...v1.1.0) --- updated-dependencies: - dependency-name: github.com/hashicorp/errwrap dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 141cc4c..0890149 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/hashicorp/go-multierror go 1.13 -require github.com/hashicorp/errwrap v1.0.0 +require github.com/hashicorp/errwrap v1.1.0 diff --git a/go.sum b/go.sum index e8238e9..f873874 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,2 @@ -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= From 2cacbcc3516161f638b673fe2b3f0113c49720ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 May 2024 09:40:25 -0700 Subject: [PATCH 70/80] Bump actions/checkout from 4.1.4 to 4.1.5 (#104) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.4 to 4.1.5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/0ad4b8fadaa221de15dcec353f45205ec38ea70b...44c2b7a8a4ea60a981eaca3cf939b5f4305c123b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/actionlint.yml | 2 +- .github/workflows/go-multierror.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index d8d579f..2b3897a 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -12,7 +12,7 @@ jobs: actionlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - name: "Check workflow files" uses: docker://docker.mirror.hashicorp.services/rhysd/actionlint:latest with: diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index 4a71e67..6116147 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - run: go version - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: go-version-file: go.mod @@ -34,7 +34,7 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: go-version: ${{ matrix.go-version }} @@ -67,7 +67,7 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: go-version: ${{ matrix.go-version }} From c3f9d48fa4aa986befa89b9c222875ddf5e1ad83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 15:15:02 -0700 Subject: [PATCH 71/80] Bump actions/upload-artifact from 3.1.3 to 4.3.3 (#101) * Bump actions/upload-artifact from 3.1.3 to 4.3.3 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3.1.3 to 4.3.3. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/a8a3f3ad30e3422c9c7b888a15615d19a852ae32...65462800fd760344b1a7b4382951275a0abb4808) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Resolve artifact naming conflicts --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Brian Shore --- .github/workflows/go-multierror.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index 6116147..2949c19 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -51,10 +51,10 @@ jobs: REPORT_FILE: ${{ env.TEST_RESULTS_PATH }}/go-multierror/gotestsum-report.xml run: |- gotestsum --format=short-verbose --junitfile ${{ env.REPORT_FILE }} -- -p 2 ./... - - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: path: ${{ env.TEST_RESULTS_PATH }} - name: tests-linux + name: tests-linux-${{ matrix.go-version }} windows-tests: runs-on: windows-latest @@ -85,7 +85,7 @@ jobs: REPORT_FILE: ${{ env.TEST_RESULTS_PATH }}/go-multierror/gotestsum-report.xml run: |- gotestsum.exe --format=short-verbose --junitfile ${{ env.REPORT_FILE }} -- -p 2 ./... - - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: path: ${{ env.TEST_RESULTS_PATH }} - name: tests-windows + name: tests-windows-${{ matrix.go-version }} From 6fa16eae919d27fdd2a107373fff9388795a6802 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 15:15:38 -0700 Subject: [PATCH 72/80] Bump actions/checkout from 4.1.5 to 4.1.7 (#107) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.5 to 4.1.7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/44c2b7a8a4ea60a981eaca3cf939b5f4305c123b...692973e3d937129bcbf40652eb9f2f61becf3332) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/actionlint.yml | 2 +- .github/workflows/go-multierror.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index 2b3897a..41ce66c 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -12,7 +12,7 @@ jobs: actionlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: "Check workflow files" uses: docker://docker.mirror.hashicorp.services/rhysd/actionlint:latest with: diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index 2949c19..b4c4f37 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - run: go version - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: go-version-file: go.mod @@ -34,7 +34,7 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: go-version: ${{ matrix.go-version }} @@ -67,7 +67,7 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: go-version: ${{ matrix.go-version }} From 807efe3ee319614a9e2342b08ff11ef119714088 Mon Sep 17 00:00:00 2001 From: Mukesh Choudhari Date: Mon, 18 Nov 2024 09:32:04 +0530 Subject: [PATCH 73/80] Update CODEOWNERS file in CODEOWNERS --- CODEOWNERS | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 1b35cec..3da71e0 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1,13 @@ -* @hashicorp/release-engineering +# Each line is a file pattern followed by one or more owners. +# More on CODEOWNERS files: https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners + +# Default owner +* @hashicorp/team-ip-compliance + +# Add override rules below. Each line is a file/folder pattern followed by one or more owners. +# Being an owner means those groups or individuals will be added as reviewers to PRs affecting +# those areas of the code. +# Examples: +# /docs/ @docs-team +# *.js @js-team +# *.go @go-team \ No newline at end of file From 801d9af693b1aac75f7c3bd71912a0924a3c2484 Mon Sep 17 00:00:00 2001 From: KaushikiAnand Date: Thu, 6 Mar 2025 14:30:24 +0530 Subject: [PATCH 74/80] workflow updation --- .github/workflows/go-multierror.yml | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index b4c4f37..349bce1 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -1,6 +1,7 @@ name: hashicorp/go-multierror/go-multierror on: push: + branches: [coverage-test] permissions: contents: read @@ -34,8 +35,8 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: go-version: ${{ matrix.go-version }} - uses: autero1/action-gotestsum@7263b9d73912eec65f46337689e59fac865c425f # v2.0.0 @@ -50,11 +51,16 @@ jobs: PLATFORM: linux REPORT_FILE: ${{ env.TEST_RESULTS_PATH }}/go-multierror/gotestsum-report.xml run: |- - gotestsum --format=short-verbose --junitfile ${{ env.REPORT_FILE }} -- -p 2 ./... + gotestsum --format=short-verbose --junitfile ${{ env.REPORT_FILE }} -- -p 2 -cover -coverprofile=coverage-linux.out ./... - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: path: ${{ env.TEST_RESULTS_PATH }} name: tests-linux-${{ matrix.go-version }} + - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + with: + path: coverage-linux.out + name: Coverage-report-linux-${{matrix.go-version}} + - run: go tool cover -func=coverage.out windows-tests: runs-on: windows-latest @@ -84,8 +90,13 @@ jobs: PLATFORM: win REPORT_FILE: ${{ env.TEST_RESULTS_PATH }}/go-multierror/gotestsum-report.xml run: |- - gotestsum.exe --format=short-verbose --junitfile ${{ env.REPORT_FILE }} -- -p 2 ./... + gotestsum.exe --format=short-verbose --junitfile ${{ env.REPORT_FILE }} -- -p 2 -cover -coverprofile=coverage-win.out ./... - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: path: ${{ env.TEST_RESULTS_PATH }} name: tests-windows-${{ matrix.go-version }} + - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + with: + path: coverage-win.out + name: Coverage-report-win-${{matrix.go-version}} + - run: go tool cover -func=coverage.out From dae604bdc22c1850c703fed30f0f71dad45f15ee Mon Sep 17 00:00:00 2001 From: KaushikiAnand Date: Thu, 6 Mar 2025 14:39:35 +0530 Subject: [PATCH 75/80] error correction --- .github/workflows/go-multierror.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index 349bce1..5e4068a 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -60,7 +60,7 @@ jobs: with: path: coverage-linux.out name: Coverage-report-linux-${{matrix.go-version}} - - run: go tool cover -func=coverage.out + - run: go tool cover -func=coverage-linux.out windows-tests: runs-on: windows-latest @@ -90,7 +90,7 @@ jobs: PLATFORM: win REPORT_FILE: ${{ env.TEST_RESULTS_PATH }}/go-multierror/gotestsum-report.xml run: |- - gotestsum.exe --format=short-verbose --junitfile ${{ env.REPORT_FILE }} -- -p 2 -cover -coverprofile=coverage-win.out ./... + gotestsum.exe --format=short-verbose --junitfile ${{ env.REPORT_FILE }} -- -p 2 -cover -coverprofile="coverage-win.out" ./... - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: path: ${{ env.TEST_RESULTS_PATH }} @@ -99,4 +99,4 @@ jobs: with: path: coverage-win.out name: Coverage-report-win-${{matrix.go-version}} - - run: go tool cover -func=coverage.out + - run: go tool cover -func=coverage-win.out From 9b46d8fc7baa5813b1aaac1d4c9aaea416bbbd72 Mon Sep 17 00:00:00 2001 From: KaushikiAnand Date: Thu, 6 Mar 2025 14:45:01 +0530 Subject: [PATCH 76/80] error correction --- .github/workflows/go-multierror.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index 5e4068a..02880c9 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -100,3 +100,4 @@ jobs: path: coverage-win.out name: Coverage-report-win-${{matrix.go-version}} - run: go tool cover -func=coverage-win.out + shell: cmd From 19bb39bb791eb995721a4d2eb934ebc2de9aad56 Mon Sep 17 00:00:00 2001 From: KaushikiAnand Date: Thu, 6 Mar 2025 15:06:33 +0530 Subject: [PATCH 77/80] IND-2500 workflow updated with unit test coverage --- .github/workflows/go-multierror.yml | 61 +++++++++++++++++++---------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index 02880c9..2a2f2ba 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -1,7 +1,7 @@ name: hashicorp/go-multierror/go-multierror on: - push: - branches: [coverage-test] + - push + - pull_request permissions: contents: read @@ -10,9 +10,12 @@ jobs: go-fmt: runs-on: ubuntu-latest steps: - - run: go version - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 + - name: Get go-version + run: go version + - name: Checkout code + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup go + uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: go-version-file: go.mod - name: check go fmt @@ -35,32 +38,40 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 + - name: Checkout code + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup go + uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: go-version: ${{ matrix.go-version }} - - uses: autero1/action-gotestsum@7263b9d73912eec65f46337689e59fac865c425f # v2.0.0 + - name: Install gotestsum + uses: autero1/action-gotestsum@7263b9d73912eec65f46337689e59fac865c425f # v2.0.0 with: gotestsum_version: 1.9.0 - - run: | + - name: Get go version and env + run: | go version go env - - run: mkdir -p "$TEST_RESULTS_PATH/go-multierror" + - name: Create test directory + run: mkdir -p "$TEST_RESULTS_PATH/go-multierror" - name: Run go tests env: PLATFORM: linux REPORT_FILE: ${{ env.TEST_RESULTS_PATH }}/go-multierror/gotestsum-report.xml run: |- gotestsum --format=short-verbose --junitfile ${{ env.REPORT_FILE }} -- -p 2 -cover -coverprofile=coverage-linux.out ./... - - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + - name: Upload and save artifacts + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: path: ${{ env.TEST_RESULTS_PATH }} name: tests-linux-${{ matrix.go-version }} - - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + - name: Upload coverage report + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: path: coverage-linux.out name: Coverage-report-linux-${{matrix.go-version}} - - run: go tool cover -func=coverage-linux.out + - name: Display coverage report + run: go tool cover -func=coverage-linux.out windows-tests: runs-on: windows-latest @@ -73,16 +84,21 @@ jobs: - 'oldstable' - 'stable' steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 + - name: Checkout code + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup Go + uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 with: go-version: ${{ matrix.go-version }} - - run: | + - name: Get go-version and env + run: | go version go env - run: git config --global core.autocrlf false - - run: go mod download - - uses: autero1/action-gotestsum@7263b9d73912eec65f46337689e59fac865c425f # v2.0.0 + - name: Download go modules + run: go mod download + - name: Install gotestsum + uses: autero1/action-gotestsum@7263b9d73912eec65f46337689e59fac865c425f # v2.0.0 with: gotestsum_version: 1.9.0 - name: Run go tests @@ -91,13 +107,16 @@ jobs: REPORT_FILE: ${{ env.TEST_RESULTS_PATH }}/go-multierror/gotestsum-report.xml run: |- gotestsum.exe --format=short-verbose --junitfile ${{ env.REPORT_FILE }} -- -p 2 -cover -coverprofile="coverage-win.out" ./... - - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + - name: Upload and save artifacts + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: path: ${{ env.TEST_RESULTS_PATH }} name: tests-windows-${{ matrix.go-version }} - - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + - name: Upload coverage test + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: path: coverage-win.out name: Coverage-report-win-${{matrix.go-version}} - - run: go tool cover -func=coverage-win.out + - name: Display coverage report + run: go tool cover -func=coverage-win.out shell: cmd From 9654520f956c0fdf8d6587b1340d139ed33573ac Mon Sep 17 00:00:00 2001 From: KaushikiAnand Date: Fri, 7 Mar 2025 13:16:11 +0530 Subject: [PATCH 78/80] IND-2525 workflow updated with linting, .go-version file added --- .github/workflows/go-multierror.yml | 12 ++++++++++++ .go-version | 1 + go.mod | 2 -- go.sum | 2 -- prefix.go | 6 ++---- 5 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 .go-version diff --git a/.github/workflows/go-multierror.yml b/.github/workflows/go-multierror.yml index 2a2f2ba..b3ab73e 100644 --- a/.github/workflows/go-multierror.yml +++ b/.github/workflows/go-multierror.yml @@ -27,6 +27,18 @@ jobs: exit 1 fi + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Setup go + uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 + with: + go-version-file: go.mod + - name: Run golangci-lint + uses: golangci/golangci-lint-action@08e2f20817b15149a52b5b3ebe7de50aff2ba8c5 + linux-tests: runs-on: ubuntu-latest env: diff --git a/.go-version b/.go-version new file mode 100644 index 0000000..d3456a9 --- /dev/null +++ b/.go-version @@ -0,0 +1 @@ +1.13 diff --git a/go.mod b/go.mod index 0890149..8b4ac9e 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,3 @@ module github.com/hashicorp/go-multierror go 1.13 - -require github.com/hashicorp/errwrap v1.1.0 diff --git a/go.sum b/go.sum index f873874..e69de29 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +0,0 @@ -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= diff --git a/prefix.go b/prefix.go index 24ef743..14bb32d 100644 --- a/prefix.go +++ b/prefix.go @@ -5,8 +5,6 @@ package multierror import ( "fmt" - - "github.com/hashicorp/errwrap" ) // Prefix is a helper function that will prefix some text @@ -30,11 +28,11 @@ func Prefix(err error, prefix string) error { // Wrap each of the errors for i, e := range err.Errors { - err.Errors[i] = errwrap.Wrapf(format, e) + err.Errors[i] = fmt.Errorf(format, e) } return err default: - return errwrap.Wrapf(format, err) + return fmt.Errorf(format, err) } } From f17afd4e0704d819943432604b9d863af2e8a881 Mon Sep 17 00:00:00 2001 From: KaushikiAnand Date: Fri, 7 Mar 2025 15:17:47 +0530 Subject: [PATCH 79/80] IND-2525 error correction --- prefix.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/prefix.go b/prefix.go index 14bb32d..c8ece03 100644 --- a/prefix.go +++ b/prefix.go @@ -18,7 +18,6 @@ func Prefix(err error, prefix string) error { return nil } - format := fmt.Sprintf("%s {{err}}", prefix) switch err := err.(type) { case *Error: // Typed nils can reach here, so initialize if we are nil @@ -28,11 +27,11 @@ func Prefix(err error, prefix string) error { // Wrap each of the errors for i, e := range err.Errors { - err.Errors[i] = fmt.Errorf(format, e) + err.Errors[i] = fmt.Errorf("%s %s", prefix, e) } return err default: - return fmt.Errorf(format, err) + return fmt.Errorf("%s %s", prefix, err) } } From dfebb8d175114d98c02b4512deb80a773b796938 Mon Sep 17 00:00:00 2001 From: sourcegraph Date: Fri, 2 May 2025 19:18:05 +0000 Subject: [PATCH 80/80] Append Hello World to all README.md files --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 71dd308..3beef97 100644 --- a/README.md +++ b/README.md @@ -148,3 +148,4 @@ var result *multierror.Error // return nil since there are no errors. return result.ErrorOrNil() ``` +Hello World