aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing
diff options
context:
space:
mode:
Diffstat (limited to 'plumbing')
-rw-r--r--plumbing/storer/reference.go63
-rw-r--r--plumbing/storer/reference_test.go99
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)
+}