Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit f1a93f9

Browse files
committed
core: *Iter.ForEach method
1 parent 86a411c commit f1a93f9

File tree

11 files changed

+223
-44
lines changed

11 files changed

+223
-44
lines changed

commit.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,20 @@ func (iter *CommitIter) Next() (*Commit, error) {
154154
return commit, commit.Decode(obj)
155155
}
156156

157+
// ForEach call the cb function for each commit contained on this iter until
158+
// an error happends or the end of the iter is reached. If ErrStop is sent
159+
// the iteration is stop but no error is returned
160+
func (iter *CommitIter) ForEach(cb func(*Commit) error) error {
161+
return iter.ObjectIter.ForEach(func(obj core.Object) error {
162+
commit := &Commit{r: iter.r}
163+
if err := commit.Decode(obj); err != nil {
164+
return err
165+
}
166+
167+
return cb(commit)
168+
})
169+
}
170+
157171
type commitSorterer struct {
158172
l []*Commit
159173
}

core/object.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,28 @@ func (iter *ObjectLookupIter) Next() (Object, error) {
139139
return obj, err
140140
}
141141

142+
// ForEach call the cb function for each object contained on this iter until
143+
// an error happends or the end of the iter is reached. If ErrStop is sent
144+
// the iteration is stop but no error is returned
145+
func (iter *ObjectLookupIter) ForEach(cb func(Object) error) error {
146+
for _, hash := range iter.series {
147+
obj, err := iter.storage.Get(hash)
148+
if err != nil {
149+
return err
150+
}
151+
152+
if err := cb(obj); err != nil {
153+
if err == ErrStop {
154+
return nil
155+
}
156+
157+
return nil
158+
}
159+
}
160+
161+
return nil
162+
}
163+
142164
// Close releases any resources used by the iterator.
143165
func (iter *ObjectLookupIter) Close() {
144166
iter.pos = len(iter.series)
@@ -173,6 +195,23 @@ func (iter *ObjectSliceIter) Next() (Object, error) {
173195
return obj, nil
174196
}
175197

198+
// ForEach call the cb function for each object contained on this iter until
199+
// an error happends or the end of the iter is reached. If ErrStop is sent
200+
// the iteration is stop but no error is returned
201+
func (iter *ObjectSliceIter) ForEach(cb func(Object) error) error {
202+
for _, o := range iter.series {
203+
if err := cb(o); err != nil {
204+
if err == ErrStop {
205+
return nil
206+
}
207+
208+
return nil
209+
}
210+
}
211+
212+
return nil
213+
}
214+
176215
// Close releases any resources used by the iterator.
177216
func (iter *ObjectSliceIter) Close() {
178217
iter.pos = len(iter.series)

core/reference.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,23 @@ func (iter *ReferenceSliceIter) Next() (*Reference, error) {
178178
return obj, nil
179179
}
180180

181+
// ForEach call the cb function for each reference contained on this iter until
182+
// an error happends or the end of the iter is reached. If ErrStop is sent
183+
// the iteration is stop but no error is returned
184+
func (iter *ReferenceSliceIter) ForEach(cb func(*Reference) error) error {
185+
for _, r := range iter.series {
186+
if err := cb(r); err != nil {
187+
if err == ErrStop {
188+
return nil
189+
}
190+
191+
return nil
192+
}
193+
}
194+
195+
return nil
196+
}
197+
181198
// Close releases any resources used by the iterator.
182199
func (iter *ReferenceSliceIter) Close() {
183200
iter.pos = len(iter.series)

core/reference_test.go

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package core
22

3-
import . "gopkg.in/check.v1"
3+
import (
4+
"io"
5+
6+
. "gopkg.in/check.v1"
7+
)
48

59
type ReferenceSuite struct{}
610

@@ -62,3 +66,58 @@ func (s *ReferenceSuite) TestIsTag(c *C) {
6266
r := NewHashReference(ReferenceName("refs/tags/v3.1."), ZeroHash)
6367
c.Assert(r.IsTag(), Equals, true)
6468
}
69+
70+
func (s *ReferenceSuite) TestReferenceSliceIterNext(c *C) {
71+
slice := []*Reference{
72+
NewReferenceFromStrings("foo", "foo"),
73+
NewReferenceFromStrings("bar", "bar"),
74+
}
75+
76+
i := NewReferenceSliceIter(slice)
77+
foo, err := i.Next()
78+
c.Assert(err, IsNil)
79+
c.Assert(foo == slice[0], Equals, true)
80+
81+
bar, err := i.Next()
82+
c.Assert(err, IsNil)
83+
c.Assert(bar == slice[1], Equals, true)
84+
85+
empty, err := i.Next()
86+
c.Assert(err, Equals, io.EOF)
87+
c.Assert(empty, IsNil)
88+
}
89+
90+
func (s *ReferenceSuite) TestReferenceSliceIterForEach(c *C) {
91+
slice := []*Reference{
92+
NewReferenceFromStrings("foo", "foo"),
93+
NewReferenceFromStrings("bar", "bar"),
94+
}
95+
96+
i := NewReferenceSliceIter(slice)
97+
var count int
98+
i.ForEach(func(r *Reference) error {
99+
c.Assert(r == slice[count], Equals, true)
100+
count++
101+
return nil
102+
})
103+
104+
c.Assert(count, Equals, 2)
105+
}
106+
107+
func (s *ReferenceSuite) TestReferenceSliceIterForEachStop(c *C) {
108+
slice := []*Reference{
109+
NewReferenceFromStrings("foo", "foo"),
110+
NewReferenceFromStrings("bar", "bar"),
111+
}
112+
113+
i := NewReferenceSliceIter(slice)
114+
115+
var count int
116+
i.ForEach(func(r *Reference) error {
117+
c.Assert(r == slice[count], Equals, true)
118+
count++
119+
return ErrStop
120+
})
121+
122+
c.Assert(count, Equals, 1)
123+
}

core/storage.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package core
22

3+
import "errors"
4+
5+
//ErrStop is used to stop a ForEach function in an Iter
6+
var ErrStop = errors.New("stop iter")
7+
38
// Storage storage of objects and references
49
type Storage interface {
510
ObjectStorage() ObjectStorage
@@ -17,6 +22,7 @@ type ObjectStorage interface {
1722
// ObjectIter is a generic closable interface for iterating over objects.
1823
type ObjectIter interface {
1924
Next() (Object, error)
25+
ForEach(func(Object) error) error
2026
Close()
2127
}
2228

@@ -30,5 +36,6 @@ type ReferenceStorage interface {
3036
// ReferenceIter is a generic closable interface for iterating over references
3137
type ReferenceIter interface {
3238
Next() (*Reference, error)
39+
ForEach(func(*Reference) error) error
3340
Close()
3441
}

examples/basic/main.go

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package main
22

33
import (
44
"fmt"
5-
"io"
65
"os"
76

87
"gopkg.in/src-d/go-git.v4"
@@ -16,7 +15,7 @@ func main() {
1615
panic(err)
1716
}
1817

19-
if err = r.Clone(&git.RepositoryCloneOptions{URL: url, Depth: 1, SingleBranch: false}); err != nil {
18+
if err = r.Clone(&git.RepositoryCloneOptions{URL: url}); err != nil {
2019
panic(err)
2120
}
2221

@@ -28,20 +27,12 @@ func main() {
2827
defer iter.Close()
2928

3029
var count = 0
31-
for {
32-
//the commits are not shorted in any special order
33-
commit, err := iter.Next()
34-
if err != nil {
35-
if err == io.EOF {
36-
break
37-
}
38-
39-
panic(err)
40-
}
41-
30+
iter.ForEach(func(commit *git.Commit) error {
4231
count++
4332
fmt.Println(commit)
44-
}
33+
34+
return nil
35+
})
4536

4637
fmt.Println("total commits:", count)
4738
}

file.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ package git
22

33
import (
44
"bytes"
5+
"io"
56
"os"
67
"strings"
8+
9+
"gopkg.in/src-d/go-git.v4/core"
710
)
811

912
// File represents git file objects.
@@ -70,6 +73,33 @@ func (iter *FileIter) Next() (*File, error) {
7073
}
7174
}
7275

76+
// ForEach call the cb function for each file contained on this iter until
77+
// an error happends or the end of the iter is reached. If core.ErrStop is sent
78+
// the iteration is stop but no error is returned
79+
func (iter *FileIter) ForEach(cb func(*File) error) error {
80+
i := &FileIter{w: *NewTreeWalker(iter.w.r, iter.w.t)}
81+
defer i.Close()
82+
83+
for {
84+
f, err := i.Next()
85+
if err != nil {
86+
if err == io.EOF {
87+
return nil
88+
}
89+
90+
return err
91+
}
92+
93+
if err := cb(f); err != nil {
94+
if err == core.ErrStop {
95+
return nil
96+
}
97+
98+
return err
99+
}
100+
}
101+
}
102+
73103
func (iter *FileIter) Close() {
74104
iter.w.Close()
75105
}

repository.go

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package git
22

33
import (
44
"errors"
5-
"io"
65

76
"gopkg.in/src-d/go-git.v4/clients/common"
87
"gopkg.in/src-d/go-git.v4/core"
@@ -128,24 +127,14 @@ func (r *Repository) getAllRemoteRefences(remote *Remote) ([]*core.Reference, er
128127
i := remote.Refs()
129128
defer i.Close()
130129

131-
for {
132-
ref, err := i.Next()
133-
if err != nil {
134-
if err == io.EOF {
135-
break
136-
}
137-
138-
return nil, err
139-
}
140-
130+
return refs, i.ForEach(func(ref *core.Reference) error {
141131
if !ref.IsBranch() {
142-
continue
132+
return nil
143133
}
144134

145135
refs = append(refs, ref)
146-
}
147-
148-
return refs, nil
136+
return nil
137+
})
149138
}
150139

151140
func (r *Repository) createLocalReferences(ref *core.Reference) error {
@@ -234,24 +223,14 @@ func (r *Repository) getLocalReferences() ([]*core.Reference, error) {
234223
i := r.Refs()
235224
defer i.Close()
236225

237-
for {
238-
ref, err := i.Next()
239-
if err != nil {
240-
if err == io.EOF {
241-
break
242-
}
243-
244-
return nil, err
245-
}
246-
226+
return refs, i.ForEach(func(ref *core.Reference) error {
247227
if ref.Type() == core.SymbolicReference {
248-
continue
228+
return nil
249229
}
250230

251231
refs = append(refs, ref)
252-
}
253-
254-
return refs, nil
232+
return nil
233+
})
255234
}
256235

257236
// Commit return the commit with the given hash

tag.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,17 @@ func (iter *TagIter) Next() (*Tag, error) {
181181
tag := &Tag{r: iter.r}
182182
return tag, tag.Decode(obj)
183183
}
184+
185+
// ForEach call the cb function for each tag contained on this iter until
186+
// an error happends or the end of the iter is reached. If ErrStop is sent
187+
// the iteration is stop but no error is returned
188+
func (iter *TagIter) ForEach(cb func(*Tag) error) error {
189+
return iter.ObjectIter.ForEach(func(obj core.Object) error {
190+
tag := &Tag{r: iter.r}
191+
if err := tag.Decode(obj); err != nil {
192+
return err
193+
}
194+
195+
return cb(tag)
196+
})
197+
}

0 commit comments

Comments
 (0)