aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeripath2021-03-04 11:53:28 +0000
committerGitHub2021-03-04 19:53:28 +0800
commite663f7459a85ea73e1b0501a18071112a0ed4fee (patch)
treef0641cc95cccbc170fe2c5854d9b9b96722e91da
parent7e85cba3e500c8548e7e21ad61bbb4c092c16503 (diff)
Fix paging of file commit logs (#14831) (#14879)
Backport #14831 Unfortunately `git log revision ... --skip=x -- path` skips the number of commits not the number of commits relating to the path. This PR changes the function to have a reader that reads and skips the necessary number of commits by hand instead. Fix #8716 Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: 6543 <6543@obermui.de>
-rw-r--r--modules/git/repo_commit.go39
1 files changed, 37 insertions, 2 deletions
diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go
index a00e59edb..70fe6fbcd 100644
--- a/modules/git/repo_commit.go
+++ b/modules/git/repo_commit.go
@@ -9,6 +9,8 @@ import (
"bytes"
"container/list"
"fmt"
+ "io"
+ "io/ioutil"
"strconv"
"strings"
@@ -327,8 +329,41 @@ func (repo *Repository) FileCommitsCount(revision, file string) (int64, error) {
// CommitsByFileAndRange return the commits according revison file and the page
func (repo *Repository) CommitsByFileAndRange(revision, file string, page int) (*list.List, error) {
- stdout, err := NewCommand("log", revision, "--follow", "--skip="+strconv.Itoa((page-1)*50),
- "--max-count="+strconv.Itoa(CommitsRangeSize), prettyLogFormat, "--", file).RunInDirBytes(repo.Path)
+ skip := (page - 1) * CommitsRangeSize
+
+ stdoutReader, stdoutWriter := io.Pipe()
+ defer func() {
+ _ = stdoutReader.Close()
+ _ = stdoutWriter.Close()
+ }()
+ go func() {
+ stderr := strings.Builder{}
+ err := NewCommand("log", revision, "--follow",
+ "--max-count="+strconv.Itoa(CommitsRangeSize*page),
+ prettyLogFormat, "--", file).
+ RunInDirPipeline(repo.Path, stdoutWriter, &stderr)
+ if err != nil {
+ if stderr.Len() > 0 {
+ err = fmt.Errorf("%v - %s", err, stderr.String())
+ }
+ _ = stdoutWriter.CloseWithError(err)
+ } else {
+ _ = stdoutWriter.Close()
+ }
+ }()
+
+ if skip > 0 {
+ _, err := io.CopyN(ioutil.Discard, stdoutReader, int64(skip*41))
+ if err != nil {
+ if err == io.EOF {
+ return list.New(), nil
+ }
+ _ = stdoutReader.CloseWithError(err)
+ return nil, err
+ }
+ }
+
+ stdout, err := ioutil.ReadAll(stdoutReader)
if err != nil {
return nil, err
}