]> source.dussan.org Git - gitea.git/commitdiff
Fix paging of file commit logs (#14831)
authorzeripath <art27@cantab.net>
Thu, 4 Mar 2021 00:48:19 +0000 (00:48 +0000)
committerGitHub <noreply@github.com>
Thu, 4 Mar 2021 00:48:19 +0000 (02:48 +0200)
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>
modules/git/repo_commit.go

index caf91e59fda3e1017e90535ecc371e45a56d9a94..5bf113ba49d9f99415d969e74897715977e4d135 100644 (file)
@@ -8,6 +8,8 @@ package git
 import (
        "bytes"
        "container/list"
+       "io"
+       "io/ioutil"
        "strconv"
        "strings"
 )
@@ -232,8 +234,38 @@ 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 {
+                       _ = stdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
+               } 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
        }