diff options
Diffstat (limited to 'plumbing')
-rw-r--r-- | plumbing/storer/reference.go | 63 | ||||
-rw-r--r-- | plumbing/storer/reference_test.go | 99 |
2 files changed, 161 insertions, 1 deletions
diff --git a/plumbing/storer/reference.go b/plumbing/storer/reference.go index d821ecf..32265fe 100644 --- a/plumbing/storer/reference.go +++ b/plumbing/storer/reference.go @@ -28,6 +28,67 @@ type ReferenceIter interface { Close() } +type ReferenceFilteredIter struct { + ff func(r *plumbing.Reference) bool + iter ReferenceIter +} + +// NewReferenceFilteredIter returns a reference iterator for the given reference +// Iterator. This iterator will iterate only references that accomplish the +// provided function. +func NewReferenceFilteredIter( + ff func(r *plumbing.Reference) bool, iter ReferenceIter) ReferenceIter { + return &ReferenceFilteredIter{ff, iter} +} + +// Next returns the next reference from the iterator. If the iterator has reached +// the end it will return io.EOF as an error. +func (iter *ReferenceFilteredIter) Next() (*plumbing.Reference, error) { + for { + r, err := iter.iter.Next() + if err != nil { + return nil, err + } + + if iter.ff(r) { + return r, nil + } + + continue + } +} + +// ForEach call the cb function for each reference contained on this iter until +// an error happens or the end of the iter is reached. If ErrStop is sent +// the iteration is stopped but no error is returned. The iterator is closed. +func (iter *ReferenceFilteredIter) ForEach(cb func(*plumbing.Reference) error) error { + defer iter.Close() + for { + r, err := iter.Next() + if err == io.EOF { + break + } + if err != nil { + return err + } + + if err := cb(r); err != nil { + if err == ErrStop { + break + } + + return err + } + } + + return nil +} + +// Close releases any resources used by the iterator. +func (iter *ReferenceFilteredIter) Close() { + iter.iter.Close() +} + // ReferenceSliceIter implements ReferenceIter. It iterates over a series of // references stored in a slice and yields each one in turn when Next() is // called. @@ -41,7 +102,7 @@ type ReferenceSliceIter struct { // NewReferenceSliceIter returns a reference iterator for the given slice of // objects. -func NewReferenceSliceIter(series []*plumbing.Reference) *ReferenceSliceIter { +func NewReferenceSliceIter(series []*plumbing.Reference) ReferenceIter { return &ReferenceSliceIter{ series: series, } diff --git a/plumbing/storer/reference_test.go b/plumbing/storer/reference_test.go index ff7bd68..a6e301b 100644 --- a/plumbing/storer/reference_test.go +++ b/plumbing/storer/reference_test.go @@ -89,3 +89,102 @@ func (s *ReferenceSuite) TestReferenceSliceIterForEachStop(c *C) { c.Assert(count, Equals, 1) } + +func (s *ReferenceSuite) TestReferenceFilteredIterNext(c *C) { + slice := []*plumbing.Reference{ + plumbing.NewReferenceFromStrings("foo", "foo"), + plumbing.NewReferenceFromStrings("bar", "bar"), + } + + i := NewReferenceFilteredIter(func(r *plumbing.Reference) bool { + if r.Name() == "bar" { + return true + } + + return false + }, NewReferenceSliceIter(slice)) + foo, err := i.Next() + c.Assert(err, IsNil) + c.Assert(foo == slice[0], Equals, false) + c.Assert(foo == slice[1], Equals, true) + + empty, err := i.Next() + c.Assert(err, Equals, io.EOF) + c.Assert(empty, IsNil) +} + +func (s *ReferenceSuite) TestReferenceFilteredIterForEach(c *C) { + slice := []*plumbing.Reference{ + plumbing.NewReferenceFromStrings("foo", "foo"), + plumbing.NewReferenceFromStrings("bar", "bar"), + } + + i := NewReferenceFilteredIter(func(r *plumbing.Reference) bool { + if r.Name() == "bar" { + return true + } + + return false + }, NewReferenceSliceIter(slice)) + var count int + i.ForEach(func(r *plumbing.Reference) error { + c.Assert(r == slice[1], Equals, true) + count++ + return nil + }) + + c.Assert(count, Equals, 1) +} + +func (s *ReferenceSuite) TestReferenceFilteredIterError(c *C) { + slice := []*plumbing.Reference{ + plumbing.NewReferenceFromStrings("foo", "foo"), + plumbing.NewReferenceFromStrings("bar", "bar"), + } + + i := NewReferenceFilteredIter(func(r *plumbing.Reference) bool { + if r.Name() == "bar" { + return true + } + + return false + }, NewReferenceSliceIter(slice)) + var count int + exampleErr := errors.New("SOME ERROR") + err := i.ForEach(func(r *plumbing.Reference) error { + c.Assert(r == slice[1], Equals, true) + count++ + if count == 1 { + return exampleErr + } + + return nil + }) + + c.Assert(err, Equals, exampleErr) + c.Assert(count, Equals, 1) +} + +func (s *ReferenceSuite) TestReferenceFilteredIterForEachStop(c *C) { + slice := []*plumbing.Reference{ + plumbing.NewReferenceFromStrings("foo", "foo"), + plumbing.NewReferenceFromStrings("bar", "bar"), + } + + i := NewReferenceFilteredIter(func(r *plumbing.Reference) bool { + if r.Name() == "bar" { + return true + } + + return false + }, NewReferenceSliceIter(slice)) + + var count int + i.ForEach(func(r *plumbing.Reference) error { + c.Assert(r == slice[1], Equals, true) + count++ + return ErrStop + }) + + c.Assert(count, Equals, 1) +} |