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

Commit c7fc75e

Browse files
committed
Add limiting options to git log
Signed-off-by: knqyf263 <[email protected]>
1 parent a0c8105 commit c7fc75e

File tree

5 files changed

+218
-2
lines changed

5 files changed

+218
-2
lines changed

Diff for: _examples/log/main.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

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

67
"gopkg.in/src-d/go-git.v4"
78
. "gopkg.in/src-d/go-git.v4/_examples"
@@ -31,7 +32,9 @@ func main() {
3132
CheckIfError(err)
3233

3334
// ... retrieves the commit history
34-
cIter, err := r.Log(&git.LogOptions{From: ref.Hash()})
35+
since := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
36+
until := time.Date(2019, 7, 30, 0, 0, 0, 0, time.UTC)
37+
cIter, err := r.Log(&git.LogOptions{From: ref.Hash(), Since: &since, Until: &until})
3538
CheckIfError(err)
3639

3740
// ... just iterates over the commits, printing it

Diff for: options.go

+9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"regexp"
66
"strings"
7+
"time"
78

89
"golang.org/x/crypto/openpgp"
910
"gopkg.in/src-d/go-git.v4/config"
@@ -348,6 +349,14 @@ type LogOptions struct {
348349
// It is equivalent to running `git log --all`.
349350
// If set on true, the From option will be ignored.
350351
All bool
352+
353+
// Show commits more recent than a specific date.
354+
// It is equivalent to running `git log --since <date>` or `git log --after <date>`.
355+
Since *time.Time
356+
357+
// Show commits older than a specific date.
358+
// It is equivalent to running `git log --until <date>` or `git log --before <date>`.
359+
Until *time.Time
351360
}
352361

353362
var (

Diff for: plumbing/object/commit_walker_limit.go

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package object
2+
3+
import (
4+
"io"
5+
"time"
6+
7+
"gopkg.in/src-d/go-git.v4/plumbing/storer"
8+
)
9+
10+
type commitLimitIter struct {
11+
sourceIter CommitIter
12+
limitOptions LogLimitOptions
13+
}
14+
15+
type LogLimitOptions struct {
16+
Since *time.Time
17+
Until *time.Time
18+
}
19+
20+
func NewCommitLimitIterFromIter(commitIter CommitIter, limitOptions LogLimitOptions) CommitIter {
21+
iterator := new(commitLimitIter)
22+
iterator.sourceIter = commitIter
23+
iterator.limitOptions = limitOptions
24+
return iterator
25+
}
26+
27+
func (c *commitLimitIter) Next() (*Commit, error) {
28+
for {
29+
commit, err := c.sourceIter.Next()
30+
if err != nil {
31+
return nil, err
32+
}
33+
34+
if c.limitOptions.Since != nil && commit.Committer.When.Before(*c.limitOptions.Since) {
35+
continue
36+
}
37+
if c.limitOptions.Until != nil && commit.Committer.When.After(*c.limitOptions.Until) {
38+
continue
39+
}
40+
return commit, nil
41+
}
42+
}
43+
44+
func (c *commitLimitIter) ForEach(cb func(*Commit) error) error {
45+
for {
46+
commit, nextErr := c.Next()
47+
if nextErr == io.EOF {
48+
break
49+
}
50+
if nextErr != nil {
51+
return nextErr
52+
}
53+
err := cb(commit)
54+
if err == storer.ErrStop {
55+
return nil
56+
} else if err != nil {
57+
return err
58+
}
59+
}
60+
return nil
61+
}
62+
63+
func (c *commitLimitIter) Close() {
64+
c.sourceIter.Close()
65+
}

Diff for: repository.go

+9
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,11 @@ func (r *Repository) Log(o *LogOptions) (object.CommitIter, error) {
10681068
it = r.logWithFile(*o.FileName, it, o.All)
10691069
}
10701070

1071+
if o.Since != nil || o.Until != nil {
1072+
limitOptions := object.LogLimitOptions{Since: o.Since, Until: o.Until}
1073+
it = r.logWithLimit(it, limitOptions)
1074+
}
1075+
10711076
return it, nil
10721077
}
10731078

@@ -1097,6 +1102,10 @@ func (*Repository) logWithFile(fileName string, commitIter object.CommitIter, ch
10971102
return object.NewCommitFileIterFromIter(fileName, commitIter, checkParent)
10981103
}
10991104

1105+
func (*Repository) logWithLimit(commitIter object.CommitIter, limitOptions object.LogLimitOptions) object.CommitIter {
1106+
return object.NewCommitLimitIterFromIter(commitIter, limitOptions)
1107+
}
1108+
11001109
func commitIterFunc(order LogOrder) func(c *object.Commit) object.CommitIter {
11011110
switch order {
11021111
case LogOrderDefault:

Diff for: repository_test.go

+131-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
"testing"
1515
"time"
1616

17+
fixtures "gopkg.in/src-d/go-git-fixtures.v3"
18+
1719
"golang.org/x/crypto/openpgp"
1820
"golang.org/x/crypto/openpgp/armor"
1921
openpgperr "golang.org/x/crypto/openpgp/errors"
@@ -32,7 +34,6 @@ import (
3234
"gopkg.in/src-d/go-billy.v4/memfs"
3335
"gopkg.in/src-d/go-billy.v4/osfs"
3436
"gopkg.in/src-d/go-billy.v4/util"
35-
"gopkg.in/src-d/go-git-fixtures.v3"
3637
)
3738

3839
type RepositorySuite struct {
@@ -1675,6 +1676,135 @@ func (s *RepositorySuite) TestLogFileWithError(c *C) {
16751676
c.Assert(err, NotNil)
16761677
}
16771678

1679+
func (s *RepositorySuite) TestLogLimitNext(c *C) {
1680+
r, _ := Init(memory.NewStorage(), nil)
1681+
err := r.clone(context.Background(), &CloneOptions{
1682+
URL: s.GetBasicLocalRepositoryURL(),
1683+
})
1684+
1685+
c.Assert(err, IsNil)
1686+
1687+
since := time.Date(2015, 4, 1, 0, 0, 0, 0, time.UTC)
1688+
cIter, err := r.Log(&LogOptions{Since: &since})
1689+
1690+
c.Assert(err, IsNil)
1691+
1692+
commitOrder := []plumbing.Hash{
1693+
plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"),
1694+
}
1695+
1696+
for _, o := range commitOrder {
1697+
commit, err := cIter.Next()
1698+
c.Assert(err, IsNil)
1699+
c.Assert(commit.Hash, Equals, o)
1700+
}
1701+
_, err = cIter.Next()
1702+
c.Assert(err, Equals, io.EOF)
1703+
}
1704+
1705+
func (s *RepositorySuite) TestLogLimitForEach(c *C) {
1706+
r, _ := Init(memory.NewStorage(), nil)
1707+
err := r.clone(context.Background(), &CloneOptions{
1708+
URL: s.GetBasicLocalRepositoryURL(),
1709+
})
1710+
1711+
c.Assert(err, IsNil)
1712+
1713+
since := time.Date(2015, 3, 31, 11, 54, 0, 0, time.UTC)
1714+
until := time.Date(2015, 4, 1, 0, 0, 0, 0, time.UTC)
1715+
cIter, err := r.Log(&LogOptions{Since: &since, Until: &until})
1716+
c.Assert(err, IsNil)
1717+
defer cIter.Close()
1718+
1719+
commitOrder := []plumbing.Hash{
1720+
plumbing.NewHash("918c48b83bd081e863dbe1b80f8998f058cd8294"),
1721+
}
1722+
1723+
expectedIndex := 0
1724+
err = cIter.ForEach(func(commit *object.Commit) error {
1725+
expectedCommitHash := commitOrder[expectedIndex]
1726+
c.Assert(commit.Hash.String(), Equals, expectedCommitHash.String())
1727+
expectedIndex++
1728+
return nil
1729+
})
1730+
c.Assert(err, IsNil)
1731+
c.Assert(expectedIndex, Equals, 1)
1732+
}
1733+
1734+
func (s *RepositorySuite) TestLogAllLimitForEach(c *C) {
1735+
r, _ := Init(memory.NewStorage(), nil)
1736+
err := r.clone(context.Background(), &CloneOptions{
1737+
URL: s.GetBasicLocalRepositoryURL(),
1738+
})
1739+
1740+
c.Assert(err, IsNil)
1741+
1742+
since := time.Date(2015, 3, 31, 11, 54, 0, 0, time.UTC)
1743+
until := time.Date(2015, 4, 1, 0, 0, 0, 0, time.UTC)
1744+
cIter, err := r.Log(&LogOptions{Since: &since, Until: &until, All: true})
1745+
c.Assert(err, IsNil)
1746+
defer cIter.Close()
1747+
1748+
commitOrder := []plumbing.Hash{
1749+
plumbing.NewHash("e8d3ffab552895c19b9fcf7aa264d277cde33881"),
1750+
plumbing.NewHash("918c48b83bd081e863dbe1b80f8998f058cd8294"),
1751+
}
1752+
1753+
expectedIndex := 0
1754+
err = cIter.ForEach(func(commit *object.Commit) error {
1755+
expectedCommitHash := commitOrder[expectedIndex]
1756+
c.Assert(commit.Hash.String(), Equals, expectedCommitHash.String())
1757+
expectedIndex++
1758+
return nil
1759+
})
1760+
c.Assert(err, IsNil)
1761+
c.Assert(expectedIndex, Equals, 2)
1762+
}
1763+
1764+
func (s *RepositorySuite) TestLogLimitWithOtherParamsFail(c *C) {
1765+
r, _ := Init(memory.NewStorage(), nil)
1766+
err := r.clone(context.Background(), &CloneOptions{
1767+
URL: s.GetBasicLocalRepositoryURL(),
1768+
})
1769+
c.Assert(err, IsNil)
1770+
1771+
since := time.Date(2015, 3, 31, 11, 54, 0, 0, time.UTC)
1772+
cIter, err := r.Log(&LogOptions{
1773+
Order: LogOrderCommitterTime,
1774+
Since: &since,
1775+
From: plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9"),
1776+
})
1777+
c.Assert(err, IsNil)
1778+
defer cIter.Close()
1779+
1780+
_, iterErr := cIter.Next()
1781+
c.Assert(iterErr, Equals, io.EOF)
1782+
}
1783+
1784+
func (s *RepositorySuite) TestLogLimitWithOtherParamsPass(c *C) {
1785+
r, _ := Init(memory.NewStorage(), nil)
1786+
err := r.clone(context.Background(), &CloneOptions{
1787+
URL: s.GetBasicLocalRepositoryURL(),
1788+
})
1789+
c.Assert(err, IsNil)
1790+
1791+
until := time.Date(2015, 3, 31, 11, 43, 0, 0, time.UTC)
1792+
cIter, err := r.Log(&LogOptions{
1793+
Order: LogOrderCommitterTime,
1794+
Until: &until,
1795+
From: plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9"),
1796+
})
1797+
c.Assert(err, IsNil)
1798+
defer cIter.Close()
1799+
1800+
commitVal, iterErr := cIter.Next()
1801+
c.Assert(iterErr, Equals, nil)
1802+
c.Assert(commitVal.Hash.String(), Equals, "b029517f6300c2da0f4b651b8642506cd6aaf45d")
1803+
1804+
_, iterErr = cIter.Next()
1805+
c.Assert(iterErr, Equals, io.EOF)
1806+
}
1807+
16781808
func (s *RepositorySuite) TestCommit(c *C) {
16791809
r, _ := Init(memory.NewStorage(), nil)
16801810
err := r.clone(context.Background(), &CloneOptions{

0 commit comments

Comments
 (0)