| Index: go/src/infra/libs/infra_util/errors.go
|
| diff --git a/go/src/infra/libs/infra_util/errors.go b/go/src/infra/libs/infra_util/errors.go
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9676978745dc3eca4976d31d605ee2fc2f86d972
|
| --- /dev/null
|
| +++ b/go/src/infra/libs/infra_util/errors.go
|
| @@ -0,0 +1,71 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package infra_util
|
| +
|
| +import (
|
| + "bytes"
|
| + "fmt"
|
| + "sync"
|
| +)
|
| +
|
| +type MultiError []error
|
| +
|
| +func FanOutIn(hint int, producer func(chan<- func() error)) error {
|
| + funcChan := make(chan func() error, hint)
|
| + errChan := make(chan error)
|
| + go func() {
|
| + go func() {
|
| + defer close(funcChan)
|
| + producer(funcChan)
|
| + }()
|
| + grp := sync.WaitGroup{}
|
| + for f := range funcChan {
|
| + grp.Add(1)
|
| + f := f
|
| + go func() { defer grp.Done(); errChan <- f() }()
|
| + }
|
| + go func() { defer close(errChan); grp.Wait() }()
|
| + }()
|
| + return MultiErrorFromChan(errChan)
|
| +}
|
| +
|
| +func MultiErrorFromChan(in <-chan error) error {
|
| + ret := MultiError{}
|
| + for err := range in {
|
| + if err != nil {
|
| + ret = append(ret, err)
|
| + }
|
| + }
|
| + if len(ret) != 0 {
|
| + return &ret
|
| + }
|
| + return nil
|
| +}
|
| +
|
| +func (m *MultiError) Error() string {
|
| + if m == nil {
|
| + return "ME[]"
|
| + }
|
| + buf := &bytes.Buffer{}
|
| + fmt.Fprintf(buf, "ME[")
|
| + first := true
|
| + for _, e := range *m {
|
| + if !first {
|
| + fmt.Fprint(buf, ",")
|
| + }
|
| + first = false
|
| + fmt.Fprintf(buf, "%#v", e.Error())
|
| + }
|
| + fmt.Fprintf(buf, "]")
|
| + return buf.String()
|
| +}
|
| +
|
| +func (m *MultiError) ErrorStrings() StringSet {
|
| + ret := make(StringSet, len(*m))
|
| + for _, e := range *m {
|
| + ret.Add(e.Error())
|
| + }
|
| + return ret
|
| +}
|
|
|