aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2017-07-18 09:44:32 +0200
committerMáximo Cuadros <mcuadros@gmail.com>2017-07-18 09:44:32 +0200
commit95bfc7e1c1b7101f2cd605cda58c1fb43d501d35 (patch)
treec9f8a9a1da11acf6f9740323bee0a164125a6bde /plumbing
parentbebcb4f19a002ed2845baa9fbd725ac25b2e742c (diff)
downloadgo-git-95bfc7e1c1b7101f2cd605cda58c1fb43d501d35.tar.gz
plumbing: object, allow ignore commits in commit walkers
Diffstat (limited to 'plumbing')
-rw-r--r--plumbing/object/commit_walker.go48
-rw-r--r--plumbing/object/commit_walker_test.go73
2 files changed, 105 insertions, 16 deletions
diff --git a/plumbing/object/commit_walker.go b/plumbing/object/commit_walker.go
index 8d2c6e8..797c17a 100644
--- a/plumbing/object/commit_walker.go
+++ b/plumbing/object/commit_walker.go
@@ -18,10 +18,16 @@ type commitPreIterator struct {
// The given callback will be called for each visited commit. Each commit will
// be visited only once. If the callback returns an error, walking will stop
// and will return the error. Other errors might be returned if the history
-// cannot be traversed (e.g. missing objects).
-func NewCommitPreorderIter(c *Commit) CommitIter {
+// cannot be traversed (e.g. missing objects). Ignore allows to skip some
+// commits from being iterated.
+func NewCommitPreorderIter(c *Commit, ignore []plumbing.Hash) CommitIter {
+ seen := make(map[plumbing.Hash]bool)
+ for _, h := range ignore {
+ seen[h] = true
+ }
+
return &commitPreIterator{
- seen: make(map[plumbing.Hash]bool),
+ seen: seen,
stack: make([]CommitIter, 0),
start: c,
}
@@ -51,20 +57,33 @@ func (w *commitPreIterator) Next() (*Commit, error) {
}
}
- // check and update seen
if w.seen[c.Hash] {
continue
}
w.seen[c.Hash] = true
+
if c.NumParents() > 0 {
- w.stack = append(w.stack, c.Parents())
+ w.stack = append(w.stack, filteredParentIter(c, w.seen))
}
return c, nil
}
}
+func filteredParentIter(c *Commit, seen map[plumbing.Hash]bool) CommitIter {
+ var hashes []plumbing.Hash
+ for _, h := range c.ParentHashes {
+ if !seen[h] {
+ hashes = append(hashes, h)
+ }
+ }
+
+ return NewCommitIter(c.s,
+ storer.NewEncodedObjectLookupIter(c.s, plumbing.CommitObject, hashes),
+ )
+}
+
func (w *commitPreIterator) ForEach(cb func(*Commit) error) error {
for {
c, err := w.Next()
@@ -98,11 +117,16 @@ type commitPostIterator struct {
// history like WalkCommitHistory but in post-order. This means that after
// walking a merge commit, the merged commit will be walked before the base
// it was merged on. This can be useful if you wish to see the history in
-// chronological order.
-func NewCommitPostorderIter(c *Commit) CommitIter {
+// chronological order. Ignore allows to skip some commits from being iterated.
+func NewCommitPostorderIter(c *Commit, ignore []plumbing.Hash) CommitIter {
+ seen := make(map[plumbing.Hash]bool)
+ for _, h := range ignore {
+ seen[h] = true
+ }
+
return &commitPostIterator{
stack: []*Commit{c},
- seen: make(map[plumbing.Hash]bool),
+ seen: seen,
}
}
@@ -114,17 +138,17 @@ func (w *commitPostIterator) Next() (*Commit, error) {
c := w.stack[len(w.stack)-1]
w.stack = w.stack[:len(w.stack)-1]
+
if w.seen[c.Hash] {
continue
}
+
w.seen[c.Hash] = true
- err := c.Parents().ForEach(func(pcm *Commit) error {
- w.stack = append(w.stack, pcm)
+ return c, c.Parents().ForEach(func(p *Commit) error {
+ w.stack = append(w.stack, p)
return nil
})
-
- return c, err
}
}
diff --git a/plumbing/object/commit_walker_test.go b/plumbing/object/commit_walker_test.go
index 2a03057..81795f3 100644
--- a/plumbing/object/commit_walker_test.go
+++ b/plumbing/object/commit_walker_test.go
@@ -1,6 +1,7 @@
package object
import . "gopkg.in/check.v1"
+import "gopkg.in/src-d/go-git.v4/plumbing"
type CommitWalkerSuite struct {
BaseObjectsSuite
@@ -12,8 +13,7 @@ func (s *CommitWalkerSuite) TestCommitPreIterator(c *C) {
commit := s.commit(c, s.Fixture.Head)
var commits []*Commit
- wIter := NewCommitPreorderIter(commit)
- wIter.ForEach(func(c *Commit) error {
+ NewCommitPreorderIter(commit, nil).ForEach(func(c *Commit) error {
commits = append(commits, c)
return nil
})
@@ -35,12 +35,54 @@ func (s *CommitWalkerSuite) TestCommitPreIterator(c *C) {
}
}
+func (s *CommitWalkerSuite) TestCommitPreIteratorWithIgnore(c *C) {
+ commit := s.commit(c, s.Fixture.Head)
+
+ var commits []*Commit
+ NewCommitPreorderIter(commit, []plumbing.Hash{
+ plumbing.NewHash("af2d6a6954d532f8ffb47615169c8fdf9d383a1a"),
+ }).ForEach(func(c *Commit) error {
+ commits = append(commits, c)
+ return nil
+ })
+
+ c.Assert(commits, HasLen, 2)
+
+ expected := []string{
+ "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
+ "918c48b83bd081e863dbe1b80f8998f058cd8294",
+ }
+ for i, commit := range commits {
+ c.Assert(commit.Hash.String(), Equals, expected[i])
+ }
+}
+
+func (s *CommitWalkerSuite) TestCommitPreIteratorWithIgnoreFirst(c *C) {
+ commit := s.commit(c, s.Fixture.Head)
+
+ var commits []*Commit
+ NewCommitPreorderIter(commit, []plumbing.Hash{
+ plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"),
+ }).ForEach(func(c *Commit) error {
+ commits = append(commits, c)
+ return nil
+ })
+
+ c.Assert(commits, HasLen, 2)
+
+ expected := []string{
+ "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
+ }
+ for i, commit := range commits {
+ c.Assert(commit.Hash.String(), Equals, expected[i])
+ }
+}
+
func (s *CommitWalkerSuite) TestCommitPostIterator(c *C) {
commit := s.commit(c, s.Fixture.Head)
var commits []*Commit
- wIter := NewCommitPostorderIter(commit)
- wIter.ForEach(func(c *Commit) error {
+ NewCommitPostorderIter(commit, nil).ForEach(func(c *Commit) error {
commits = append(commits, c)
return nil
})
@@ -57,6 +99,29 @@ func (s *CommitWalkerSuite) TestCommitPostIterator(c *C) {
"b029517f6300c2da0f4b651b8642506cd6aaf45d",
"35e85108805c84807bc66a02d91535e1e24b38b9",
}
+
+ for i, commit := range commits {
+ c.Assert(commit.Hash.String(), Equals, expected[i])
+ }
+}
+
+func (s *CommitWalkerSuite) TestCommitPostIteratorWithIgnore(c *C) {
+ commit := s.commit(c, s.Fixture.Head)
+
+ var commits []*Commit
+ NewCommitPostorderIter(commit, []plumbing.Hash{
+ plumbing.NewHash("af2d6a6954d532f8ffb47615169c8fdf9d383a1a"),
+ }).ForEach(func(c *Commit) error {
+ commits = append(commits, c)
+ return nil
+ })
+
+ c.Assert(commits, HasLen, 2)
+
+ expected := []string{
+ "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
+ "918c48b83bd081e863dbe1b80f8998f058cd8294",
+ }
for i, commit := range commits {
c.Assert(commit.Hash.String(), Equals, expected[i])
}