diff options
-rw-r--r-- | plumbing/object/commit_walker.go | 25 | ||||
-rw-r--r-- | plumbing/object/commit_walker_test.go | 41 | ||||
-rw-r--r-- | plumbing/reference.go | 23 | ||||
-rw-r--r-- | plumbing/reference_test.go | 5 |
4 files changed, 85 insertions, 9 deletions
diff --git a/plumbing/object/commit_walker.go b/plumbing/object/commit_walker.go index b986067..681ea5e 100644 --- a/plumbing/object/commit_walker.go +++ b/plumbing/object/commit_walker.go @@ -69,3 +69,28 @@ func (w *commitWalker) walk() error { return w.walk() } + +// WalkCommitHistoryPost walks the commit 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 WalkCommitHistoryPost(c *Commit, cb func(*Commit) error) error { + stack := []*Commit{c} + seen := make(map[plumbing.Hash]bool) + for len(stack) > 0 { + c := stack[len(stack)-1] + stack = stack[:len(stack)-1] + if seen[c.Hash] { + continue + } + seen[c.Hash] = true + if err := cb(c); err != nil { + return err + } + c.Parents().ForEach(func(pcm *Commit) error { + stack = append(stack, pcm) + return nil + }) + } + return nil +} diff --git a/plumbing/object/commit_walker_test.go b/plumbing/object/commit_walker_test.go index 67d6695..aa54de0 100644 --- a/plumbing/object/commit_walker_test.go +++ b/plumbing/object/commit_walker_test.go @@ -8,26 +8,53 @@ type CommitWalkerSuite struct { var _ = Suite(&CommitWalkerSuite{}) -func (s *CommitWalkerSuite) TestWalkerNext(c *C) { +func (s *CommitWalkerSuite) TestWalkHistory(c *C) { commit := s.commit(c, s.Fixture.Head) var commits []*Commit - WalkCommitHistory(commit, func(c *Commit) error { commits = append(commits, c) return nil }) - SortCommits(commits) c.Assert(commits, HasLen, 8) expected := []string{ - "b029517f6300c2da0f4b651b8642506cd6aaf45d", "b8e471f58bcbca63b07bda20e428190409c2db47", - "35e85108805c84807bc66a02d91535e1e24b38b9", "a5b8b09e2f8fcb0bb99d3ccb0958157b40890d69", - "1669dce138d9b841a518c64b10914d88f5e488ea", "af2d6a6954d532f8ffb47615169c8fdf9d383a1a", - "918c48b83bd081e863dbe1b80f8998f058cd8294", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5", + "6ecf0ef2c2dffb796033e5a02219af86ec6584e5", + "918c48b83bd081e863dbe1b80f8998f058cd8294", + "af2d6a6954d532f8ffb47615169c8fdf9d383a1a", + "1669dce138d9b841a518c64b10914d88f5e488ea", + "35e85108805c84807bc66a02d91535e1e24b38b9", + "b029517f6300c2da0f4b651b8642506cd6aaf45d", + "a5b8b09e2f8fcb0bb99d3ccb0958157b40890d69", + "b8e471f58bcbca63b07bda20e428190409c2db47", + } + for i, commit := range commits { + c.Assert(commit.Hash.String(), Equals, expected[i]) } +} + +func (s *CommitWalkerSuite) TestWalkHistoryPost(c *C) { + commit := s.commit(c, s.Fixture.Head) + + var commits []*Commit + WalkCommitHistoryPost(commit, func(c *Commit) error { + commits = append(commits, c) + return nil + }) + c.Assert(commits, HasLen, 8) + + expected := []string{ + "6ecf0ef2c2dffb796033e5a02219af86ec6584e5", + "918c48b83bd081e863dbe1b80f8998f058cd8294", + "af2d6a6954d532f8ffb47615169c8fdf9d383a1a", + "1669dce138d9b841a518c64b10914d88f5e488ea", + "a5b8b09e2f8fcb0bb99d3ccb0958157b40890d69", + "b8e471f58bcbca63b07bda20e428190409c2db47", + "b029517f6300c2da0f4b651b8642506cd6aaf45d", + "35e85108805c84807bc66a02d91535e1e24b38b9", + } for i, commit := range commits { c.Assert(commit.Hash.String(), Equals, expected[i]) } diff --git a/plumbing/reference.go b/plumbing/reference.go index 798c3dd..8fa103e 100644 --- a/plumbing/reference.go +++ b/plumbing/reference.go @@ -16,6 +16,16 @@ const ( ) var ( + refPrefixes = []string{ + refHeadPrefix, + refTagPrefix, + refRemotePrefix, + refNotePrefix, + refPrefix, + } +) + +var ( ErrReferenceNotFound = errors.New("reference not found") ) @@ -50,8 +60,17 @@ func (r ReferenceName) String() string { // Short returns the short name of a ReferenceName func (r ReferenceName) Short() string { - parts := strings.Split(string(r), "/") - return parts[len(parts)-1] + return r.removeRefPrefix() +} + +// Instead of hardcoding a number of components, we should remove the prefixes +// refHeadPrefix, refTagPrefix, refRemotePrefix, refNotePrefix and refPrefix +func (r ReferenceName) removeRefPrefix() string { + s := string(r) + for _, prefix := range refPrefixes { + s = strings.TrimPrefix(s, prefix) + } + return s } const ( diff --git a/plumbing/reference_test.go b/plumbing/reference_test.go index 849f159..6a695f4 100644 --- a/plumbing/reference_test.go +++ b/plumbing/reference_test.go @@ -18,6 +18,11 @@ func (s *ReferenceSuite) TestReferenceNameShort(c *C) { c.Assert(ExampleReferenceName.Short(), Equals, "v4") } +func (s *ReferenceSuite) TestReferenceNameWithSlash(c *C) { + r := ReferenceName("refs/remotes/origin/feature/AllowSlashes") + c.Assert(r.Short(), Equals, "origin/feature/AllowSlashes") +} + func (s *ReferenceSuite) TestNewReferenceFromStrings(c *C) { r := NewReferenceFromStrings("refs/heads/v4", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5") c.Assert(r.Type(), Equals, HashReference) |