aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--_examples/log/main.go5
-rw-r--r--options.go9
-rw-r--r--plumbing/object/commit_walker_limit.go65
-rw-r--r--repository.go9
-rw-r--r--repository_test.go132
5 files changed, 218 insertions, 2 deletions
diff --git a/_examples/log/main.go b/_examples/log/main.go
index ba0597a..5807515 100644
--- a/_examples/log/main.go
+++ b/_examples/log/main.go
@@ -2,6 +2,7 @@ package main
import (
"fmt"
+ "time"
"gopkg.in/src-d/go-git.v4"
. "gopkg.in/src-d/go-git.v4/_examples"
@@ -31,7 +32,9 @@ func main() {
CheckIfError(err)
// ... retrieves the commit history
- cIter, err := r.Log(&git.LogOptions{From: ref.Hash()})
+ since := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
+ until := time.Date(2019, 7, 30, 0, 0, 0, 0, time.UTC)
+ cIter, err := r.Log(&git.LogOptions{From: ref.Hash(), Since: &since, Until: &until})
CheckIfError(err)
// ... just iterates over the commits, printing it
diff --git a/options.go b/options.go
index 0f728e7..cc8f9c5 100644
--- a/options.go
+++ b/options.go
@@ -4,6 +4,7 @@ import (
"errors"
"regexp"
"strings"
+ "time"
"golang.org/x/crypto/openpgp"
"gopkg.in/src-d/go-git.v4/config"
@@ -348,6 +349,14 @@ type LogOptions struct {
// It is equivalent to running `git log --all`.
// If set on true, the From option will be ignored.
All bool
+
+ // Show commits more recent than a specific date.
+ // It is equivalent to running `git log --since <date>` or `git log --after <date>`.
+ Since *time.Time
+
+ // Show commits older than a specific date.
+ // It is equivalent to running `git log --until <date>` or `git log --before <date>`.
+ Until *time.Time
}
var (
diff --git a/plumbing/object/commit_walker_limit.go b/plumbing/object/commit_walker_limit.go
new file mode 100644
index 0000000..ee56e50
--- /dev/null
+++ b/plumbing/object/commit_walker_limit.go
@@ -0,0 +1,65 @@
+package object
+
+import (
+ "io"
+ "time"
+
+ "gopkg.in/src-d/go-git.v4/plumbing/storer"
+)
+
+type commitLimitIter struct {
+ sourceIter CommitIter
+ limitOptions LogLimitOptions
+}
+
+type LogLimitOptions struct {
+ Since *time.Time
+ Until *time.Time
+}
+
+func NewCommitLimitIterFromIter(commitIter CommitIter, limitOptions LogLimitOptions) CommitIter {
+ iterator := new(commitLimitIter)
+ iterator.sourceIter = commitIter
+ iterator.limitOptions = limitOptions
+ return iterator
+}
+
+func (c *commitLimitIter) Next() (*Commit, error) {
+ for {
+ commit, err := c.sourceIter.Next()
+ if err != nil {
+ return nil, err
+ }
+
+ if c.limitOptions.Since != nil && commit.Committer.When.Before(*c.limitOptions.Since) {
+ continue
+ }
+ if c.limitOptions.Until != nil && commit.Committer.When.After(*c.limitOptions.Until) {
+ continue
+ }
+ return commit, nil
+ }
+}
+
+func (c *commitLimitIter) ForEach(cb func(*Commit) error) error {
+ for {
+ commit, nextErr := c.Next()
+ if nextErr == io.EOF {
+ break
+ }
+ if nextErr != nil {
+ return nextErr
+ }
+ err := cb(commit)
+ if err == storer.ErrStop {
+ return nil
+ } else if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (c *commitLimitIter) Close() {
+ c.sourceIter.Close()
+}
diff --git a/repository.go b/repository.go
index 2251d6c..11269ef 100644
--- a/repository.go
+++ b/repository.go
@@ -1068,6 +1068,11 @@ func (r *Repository) Log(o *LogOptions) (object.CommitIter, error) {
it = r.logWithFile(*o.FileName, it, o.All)
}
+ if o.Since != nil || o.Until != nil {
+ limitOptions := object.LogLimitOptions{Since: o.Since, Until: o.Until}
+ it = r.logWithLimit(it, limitOptions)
+ }
+
return it, nil
}
@@ -1097,6 +1102,10 @@ func (*Repository) logWithFile(fileName string, commitIter object.CommitIter, ch
return object.NewCommitFileIterFromIter(fileName, commitIter, checkParent)
}
+func (*Repository) logWithLimit(commitIter object.CommitIter, limitOptions object.LogLimitOptions) object.CommitIter {
+ return object.NewCommitLimitIterFromIter(commitIter, limitOptions)
+}
+
func commitIterFunc(order LogOrder) func(c *object.Commit) object.CommitIter {
switch order {
case LogOrderDefault:
diff --git a/repository_test.go b/repository_test.go
index 5fc6aeb..e85311f 100644
--- a/repository_test.go
+++ b/repository_test.go
@@ -14,6 +14,8 @@ import (
"testing"
"time"
+ fixtures "gopkg.in/src-d/go-git-fixtures.v3"
+
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/armor"
openpgperr "golang.org/x/crypto/openpgp/errors"
@@ -32,7 +34,6 @@ import (
"gopkg.in/src-d/go-billy.v4/memfs"
"gopkg.in/src-d/go-billy.v4/osfs"
"gopkg.in/src-d/go-billy.v4/util"
- "gopkg.in/src-d/go-git-fixtures.v3"
)
type RepositorySuite struct {
@@ -1675,6 +1676,135 @@ func (s *RepositorySuite) TestLogFileWithError(c *C) {
c.Assert(err, NotNil)
}
+func (s *RepositorySuite) TestLogLimitNext(c *C) {
+ r, _ := Init(memory.NewStorage(), nil)
+ err := r.clone(context.Background(), &CloneOptions{
+ URL: s.GetBasicLocalRepositoryURL(),
+ })
+
+ c.Assert(err, IsNil)
+
+ since := time.Date(2015, 4, 1, 0, 0, 0, 0, time.UTC)
+ cIter, err := r.Log(&LogOptions{Since: &since})
+
+ c.Assert(err, IsNil)
+
+ commitOrder := []plumbing.Hash{
+ plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"),
+ }
+
+ for _, o := range commitOrder {
+ commit, err := cIter.Next()
+ c.Assert(err, IsNil)
+ c.Assert(commit.Hash, Equals, o)
+ }
+ _, err = cIter.Next()
+ c.Assert(err, Equals, io.EOF)
+}
+
+func (s *RepositorySuite) TestLogLimitForEach(c *C) {
+ r, _ := Init(memory.NewStorage(), nil)
+ err := r.clone(context.Background(), &CloneOptions{
+ URL: s.GetBasicLocalRepositoryURL(),
+ })
+
+ c.Assert(err, IsNil)
+
+ since := time.Date(2015, 3, 31, 11, 54, 0, 0, time.UTC)
+ until := time.Date(2015, 4, 1, 0, 0, 0, 0, time.UTC)
+ cIter, err := r.Log(&LogOptions{Since: &since, Until: &until})
+ c.Assert(err, IsNil)
+ defer cIter.Close()
+
+ commitOrder := []plumbing.Hash{
+ plumbing.NewHash("918c48b83bd081e863dbe1b80f8998f058cd8294"),
+ }
+
+ expectedIndex := 0
+ err = cIter.ForEach(func(commit *object.Commit) error {
+ expectedCommitHash := commitOrder[expectedIndex]
+ c.Assert(commit.Hash.String(), Equals, expectedCommitHash.String())
+ expectedIndex++
+ return nil
+ })
+ c.Assert(err, IsNil)
+ c.Assert(expectedIndex, Equals, 1)
+}
+
+func (s *RepositorySuite) TestLogAllLimitForEach(c *C) {
+ r, _ := Init(memory.NewStorage(), nil)
+ err := r.clone(context.Background(), &CloneOptions{
+ URL: s.GetBasicLocalRepositoryURL(),
+ })
+
+ c.Assert(err, IsNil)
+
+ since := time.Date(2015, 3, 31, 11, 54, 0, 0, time.UTC)
+ until := time.Date(2015, 4, 1, 0, 0, 0, 0, time.UTC)
+ cIter, err := r.Log(&LogOptions{Since: &since, Until: &until, All: true})
+ c.Assert(err, IsNil)
+ defer cIter.Close()
+
+ commitOrder := []plumbing.Hash{
+ plumbing.NewHash("e8d3ffab552895c19b9fcf7aa264d277cde33881"),
+ plumbing.NewHash("918c48b83bd081e863dbe1b80f8998f058cd8294"),
+ }
+
+ expectedIndex := 0
+ err = cIter.ForEach(func(commit *object.Commit) error {
+ expectedCommitHash := commitOrder[expectedIndex]
+ c.Assert(commit.Hash.String(), Equals, expectedCommitHash.String())
+ expectedIndex++
+ return nil
+ })
+ c.Assert(err, IsNil)
+ c.Assert(expectedIndex, Equals, 2)
+}
+
+func (s *RepositorySuite) TestLogLimitWithOtherParamsFail(c *C) {
+ r, _ := Init(memory.NewStorage(), nil)
+ err := r.clone(context.Background(), &CloneOptions{
+ URL: s.GetBasicLocalRepositoryURL(),
+ })
+ c.Assert(err, IsNil)
+
+ since := time.Date(2015, 3, 31, 11, 54, 0, 0, time.UTC)
+ cIter, err := r.Log(&LogOptions{
+ Order: LogOrderCommitterTime,
+ Since: &since,
+ From: plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9"),
+ })
+ c.Assert(err, IsNil)
+ defer cIter.Close()
+
+ _, iterErr := cIter.Next()
+ c.Assert(iterErr, Equals, io.EOF)
+}
+
+func (s *RepositorySuite) TestLogLimitWithOtherParamsPass(c *C) {
+ r, _ := Init(memory.NewStorage(), nil)
+ err := r.clone(context.Background(), &CloneOptions{
+ URL: s.GetBasicLocalRepositoryURL(),
+ })
+ c.Assert(err, IsNil)
+
+ until := time.Date(2015, 3, 31, 11, 43, 0, 0, time.UTC)
+ cIter, err := r.Log(&LogOptions{
+ Order: LogOrderCommitterTime,
+ Until: &until,
+ From: plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9"),
+ })
+ c.Assert(err, IsNil)
+ defer cIter.Close()
+
+ commitVal, iterErr := cIter.Next()
+ c.Assert(iterErr, Equals, nil)
+ c.Assert(commitVal.Hash.String(), Equals, "b029517f6300c2da0f4b651b8642506cd6aaf45d")
+
+ _, iterErr = cIter.Next()
+ c.Assert(iterErr, Equals, io.EOF)
+}
+
func (s *RepositorySuite) TestCommit(c *C) {
r, _ := Init(memory.NewStorage(), nil)
err := r.clone(context.Background(), &CloneOptions{