diff options
author | zeripath | 2021-03-04 11:53:28 +0000 |
---|---|---|
committer | GitHub | 2021-03-04 19:53:28 +0800 |
commit | e663f7459a85ea73e1b0501a18071112a0ed4fee (patch) | |
tree | f0641cc95cccbc170fe2c5854d9b9b96722e91da | |
parent | 7e85cba3e500c8548e7e21ad61bbb4c092c16503 (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.go | 39 |
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 } |