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

Commit 9013848

Browse files
committed
WalkCommitHistory adn Commit.History
1 parent 6ebe214 commit 9013848

File tree

5 files changed

+144
-0
lines changed

5 files changed

+144
-0
lines changed

commit.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,18 @@ func (c *Commit) Decode(o core.Object) (err error) {
125125
}
126126
}
127127

128+
// History return a slice with the previous commits in the history of this commit
129+
func (c *Commit) History() ([]*Commit, error) {
130+
var commits []*Commit
131+
err := WalkCommitHistory(c, func(commit *Commit) error {
132+
commits = append(commits, commit)
133+
return nil
134+
})
135+
136+
ReverseSortCommits(commits)
137+
return commits, err
138+
}
139+
128140
func (c *Commit) String() string {
129141
return fmt.Sprintf(
130142
"%s %s\nAuthor: %s\nDate: %s\n",
@@ -193,3 +205,9 @@ func SortCommits(l []*Commit) {
193205
s := &commitSorterer{l}
194206
sort.Sort(s)
195207
}
208+
209+
// ReverseSortCommits sort a commit list by commit date, from newer to older.
210+
func ReverseSortCommits(l []*Commit) {
211+
s := &commitSorterer{l}
212+
sort.Sort(sort.Reverse(s))
213+
}

commit_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,14 @@ func (s *SuiteCommit) TestNumParents(c *C) {
7272
c.Assert(s.Commit.NumParents(), Equals, 2)
7373
}
7474

75+
func (s *SuiteCommit) TestHistory(c *C) {
76+
commits, err := s.Commit.History()
77+
c.Assert(err, IsNil)
78+
c.Assert(commits, HasLen, 5)
79+
c.Assert(commits[0].Hash.String(), Equals, s.Commit.Hash.String())
80+
c.Assert(commits[len(commits)-1].Hash.String(), Equals, "b029517f6300c2da0f4b651b8642506cd6aaf45d")
81+
}
82+
7583
func (s *SuiteCommit) TestString(c *C) {
7684
c.Assert(s.Commit.String(), Equals, ""+
7785
"commit 1669dce138d9b841a518c64b10914d88f5e488ea\n"+

commit_walker.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package git
2+
3+
import (
4+
"io"
5+
6+
"gopkg.in/src-d/go-git.v4/core"
7+
)
8+
9+
type commitWalker struct {
10+
seen map[core.Hash]bool
11+
stack []*CommitIter
12+
start *Commit
13+
cb func(*Commit) error
14+
}
15+
16+
// WalkCommitHistory walks the commit history
17+
func WalkCommitHistory(c *Commit, cb func(*Commit) error) error {
18+
w := &commitWalker{
19+
seen: make(map[core.Hash]bool),
20+
stack: make([]*CommitIter, 0),
21+
start: c,
22+
cb: cb,
23+
}
24+
25+
return w.walk()
26+
}
27+
28+
func (w *commitWalker) walk() error {
29+
var commit *Commit
30+
31+
if w.start != nil {
32+
commit = w.start
33+
w.start = nil
34+
} else {
35+
current := len(w.stack) - 1
36+
if current < 0 {
37+
return nil
38+
}
39+
40+
var err error
41+
commit, err = w.stack[current].Next()
42+
if err == io.EOF {
43+
w.stack = w.stack[:current]
44+
return w.walk()
45+
}
46+
47+
if err != nil {
48+
return err
49+
}
50+
}
51+
52+
// check and update seen
53+
if w.seen[commit.Hash] {
54+
return w.walk()
55+
}
56+
57+
w.seen[commit.Hash] = true
58+
if commit.NumParents() > 0 {
59+
w.stack = append(w.stack, commit.Parents())
60+
}
61+
62+
if err := w.cb(commit); err != nil {
63+
return err
64+
}
65+
66+
return w.walk()
67+
}

commit_walker_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package git
2+
3+
import . "gopkg.in/check.v1"
4+
5+
type CommitWalkerSuite struct {
6+
BaseSuite
7+
}
8+
9+
var _ = Suite(&CommitWalkerSuite{})
10+
11+
func (s *CommitWalkerSuite) TestWalkerNext(c *C) {
12+
r, err := s.Repository.Head()
13+
c.Assert(err, IsNil)
14+
15+
commit, err := s.Repository.Commit(r.Hash())
16+
c.Assert(err, IsNil)
17+
18+
var commits []*Commit
19+
20+
WalkCommitHistory(commit, func(c *Commit) error {
21+
commits = append(commits, c)
22+
return nil
23+
})
24+
25+
SortCommits(commits)
26+
c.Assert(commits, HasLen, 8)
27+
28+
expected := []string{
29+
"b029517f6300c2da0f4b651b8642506cd6aaf45d", "b8e471f58bcbca63b07bda20e428190409c2db47",
30+
"35e85108805c84807bc66a02d91535e1e24b38b9", "a5b8b09e2f8fcb0bb99d3ccb0958157b40890d69",
31+
"1669dce138d9b841a518c64b10914d88f5e488ea", "af2d6a6954d532f8ffb47615169c8fdf9d383a1a",
32+
"918c48b83bd081e863dbe1b80f8998f058cd8294", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
33+
}
34+
35+
for i, commit := range commits {
36+
c.Assert(commit.Hash.String(), Equals, expected[i])
37+
}
38+
}

examples/basic/main.go

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

33
import (
44
"fmt"
5+
"strings"
56

67
"github.com/fatih/color"
78

@@ -46,4 +47,16 @@ func main() {
4647
fmt.Printf("100644 blob %s %s\n", f.Hash, f.Name)
4748
return nil
4849
})
50+
51+
// List the history of the repository
52+
// > git log --oneline
53+
color.Blue("git log --oneline")
54+
55+
commits, _ := commit.History()
56+
for _, c := range commits {
57+
hash := c.Hash.String()
58+
line := strings.Split(c.Message, "\n")
59+
fmt.Println(hash[:7], line[0])
60+
}
61+
4962
}

0 commit comments

Comments
 (0)