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

plumbing: the commit walker can skip externally-seen commits #586

Merged
merged 1 commit into from
Sep 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions plumbing/object/commit_walker.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import (
)

type commitPreIterator struct {
seen map[plumbing.Hash]bool
stack []CommitIter
start *Commit
seenExternal map[plumbing.Hash]bool
seen map[plumbing.Hash]bool
stack []CommitIter
start *Commit
}

// NewCommitPreorderIter returns a CommitIter that walks the commit history,
Expand All @@ -20,16 +21,21 @@ type commitPreIterator struct {
// and will return the error. Other errors might be returned if the history
// cannot be traversed (e.g. missing objects). Ignore allows to skip some
// commits from being iterated.
func NewCommitPreorderIter(c *Commit, ignore []plumbing.Hash) CommitIter {
func NewCommitPreorderIter(
c *Commit,
seenExternal map[plumbing.Hash]bool,
ignore []plumbing.Hash,
) CommitIter {
seen := make(map[plumbing.Hash]bool)
for _, h := range ignore {
seen[h] = true
}

return &commitPreIterator{
seen: seen,
stack: make([]CommitIter, 0),
start: c,
seenExternal: seenExternal,
seen: seen,
stack: make([]CommitIter, 0),
start: c,
}
}

Expand Down Expand Up @@ -57,7 +63,7 @@ func (w *commitPreIterator) Next() (*Commit, error) {
}
}

if w.seen[c.Hash] {
if w.seen[c.Hash] || w.seenExternal[c.Hash] {
continue
}

Expand Down
28 changes: 26 additions & 2 deletions plumbing/object/commit_walker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func (s *CommitWalkerSuite) TestCommitPreIterator(c *C) {
commit := s.commit(c, s.Fixture.Head)

var commits []*Commit
NewCommitPreorderIter(commit, nil).ForEach(func(c *Commit) error {
NewCommitPreorderIter(commit, nil, nil).ForEach(func(c *Commit) error {
commits = append(commits, c)
return nil
})
Expand All @@ -42,7 +42,7 @@ func (s *CommitWalkerSuite) TestCommitPreIteratorWithIgnore(c *C) {
commit := s.commit(c, s.Fixture.Head)

var commits []*Commit
NewCommitPreorderIter(commit, []plumbing.Hash{
NewCommitPreorderIter(commit, nil, []plumbing.Hash{
plumbing.NewHash("af2d6a6954d532f8ffb47615169c8fdf9d383a1a"),
}).ForEach(func(c *Commit) error {
commits = append(commits, c)
Expand All @@ -60,6 +60,30 @@ func (s *CommitWalkerSuite) TestCommitPreIteratorWithIgnore(c *C) {
}
}

func (s *CommitWalkerSuite) TestCommitPreIteratorWithSeenExternal(c *C) {
commit := s.commit(c, s.Fixture.Head)

var commits []*Commit
seenExternal := map[plumbing.Hash]bool{
plumbing.NewHash("af2d6a6954d532f8ffb47615169c8fdf9d383a1a"): true,
}
NewCommitPreorderIter(commit, seenExternal, nil).
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) TestCommitPostIterator(c *C) {
commit := s.commit(c, s.Fixture.Head)

Expand Down
2 changes: 1 addition & 1 deletion plumbing/revlist/revlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func reachableObjects(
ignore []plumbing.Hash,
cb func(h plumbing.Hash),
) error {
i := object.NewCommitPreorderIter(commit, ignore)
i := object.NewCommitPreorderIter(commit, seen, ignore)
for {
commit, err := i.Next()
if err == io.EOF {
Expand Down
2 changes: 1 addition & 1 deletion remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ func isFastForward(s storer.EncodedObjectStorer, old, new plumbing.Hash) (bool,
}

found := false
iter := object.NewCommitPreorderIter(c, nil)
iter := object.NewCommitPreorderIter(c, nil, nil)
return found, iter.ForEach(func(c *object.Commit) error {
if c.Hash != old {
return nil
Expand Down
6 changes: 3 additions & 3 deletions repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ func (r *Repository) Log(o *LogOptions) (object.CommitIter, error) {
return nil, err
}

return object.NewCommitPreorderIter(commit, nil), nil
return object.NewCommitPreorderIter(commit, nil, nil), nil
}

// Tags returns all the References from Tags. This method returns all the tag
Expand Down Expand Up @@ -949,7 +949,7 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err
commit = c
}
case revision.CaretReg:
history := object.NewCommitPreorderIter(commit, nil)
history := object.NewCommitPreorderIter(commit, nil, nil)

re := item.(revision.CaretReg).Regexp
negate := item.(revision.CaretReg).Negate
Expand Down Expand Up @@ -979,7 +979,7 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err

commit = c
case revision.AtDate:
history := object.NewCommitPreorderIter(commit, nil)
history := object.NewCommitPreorderIter(commit, nil, nil)

date := item.(revision.AtDate).Date

Expand Down