Skip to content

Commit

Permalink
Merge pull request src-d#1206 from knqyf263/feature/add_log_limiting
Browse files Browse the repository at this point in the history
Add limiting options to git log
  • Loading branch information
mcuadros authored Aug 5, 2019
2 parents a0c8105 + c7fc75e commit 2661d86
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 2 deletions.
5 changes: 4 additions & 1 deletion _examples/log/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"fmt"
"time"

"gopkg.in/src-d/go-git.v4"
. "gopkg.in/src-d/go-git.v4/_examples"
Expand Down Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"regexp"
"strings"
"time"

"golang.org/x/crypto/openpgp"
"gopkg.in/src-d/go-git.v4/config"
Expand Down Expand Up @@ -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 (
Expand Down
65 changes: 65 additions & 0 deletions plumbing/object/commit_walker_limit.go
Original file line number Diff line number Diff line change
@@ -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()
}
9 changes: 9 additions & 0 deletions repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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:
Expand Down
132 changes: 131 additions & 1 deletion repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 {
Expand Down Expand Up @@ -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{
Expand Down

0 comments on commit 2661d86

Please sign in to comment.