Remove follow from commits by file (#20765)

The use of `--follow` makes getting these commits very slow on large repositories
as it results in searching the whole commit tree for a blob.

Now as nice as the results of `--follow` are, I am uncertain whether it is really
of sufficient importance to keep around.

Fix #20764

Signed-off-by: Andrew Thornton <art27@cantab.net>

Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
zeripath 2022-08-15 02:22:13 +01:00 committed by GitHub
parent 7ae297800e
commit 58a4407acb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 27 additions and 27 deletions

View file

@ -7,6 +7,8 @@ package git
import ( import (
"bytes" "bytes"
"encoding/hex"
"fmt"
"io" "io"
"strconv" "strconv"
"strings" "strings"
@ -209,9 +211,9 @@ func (repo *Repository) CommitsByFileAndRange(revision, file string, page int) (
}() }()
go func() { go func() {
stderr := strings.Builder{} stderr := strings.Builder{}
err := NewCommand(repo.Ctx, "log", revision, "--follow", err := NewCommand(repo.Ctx, "rev-list", revision,
"--max-count="+strconv.Itoa(setting.Git.CommitsRangeSize*page), "--max-count="+strconv.Itoa(setting.Git.CommitsRangeSize*page),
prettyLogFormat, "--", file). "--skip="+strconv.Itoa(skip), "--", file).
Run(&RunOpts{ Run(&RunOpts{
Dir: repo.Path, Dir: repo.Path,
Stdout: stdoutWriter, Stdout: stdoutWriter,
@ -224,32 +226,30 @@ func (repo *Repository) CommitsByFileAndRange(revision, file string, page int) (
} }
}() }()
if skip > 0 { commits := []*Commit{}
_, err := io.CopyN(io.Discard, stdoutReader, int64(skip*41)) shaline := [41]byte{}
if err != nil { var sha1 SHA1
for {
n, err := io.ReadFull(stdoutReader, shaline[:])
if err != nil || n < 40 {
if err == io.EOF { if err == io.EOF {
return []*Commit{}, nil err = nil
} }
_ = stdoutReader.CloseWithError(err) return commits, err
}
n, err = hex.Decode(sha1[:], shaline[0:40])
if n != 20 {
err = fmt.Errorf("invalid sha %q", string(shaline[:40]))
}
if err != nil {
return nil, err return nil, err
} }
commit, err := repo.getCommit(sha1)
if err != nil {
return nil, err
}
commits = append(commits, commit)
} }
stdout, err := io.ReadAll(stdoutReader)
if err != nil {
return nil, err
}
return repo.parsePrettyFormatLogToList(stdout)
}
// CommitsByFileAndRangeNoFollow return the commits according revision file and the page
func (repo *Repository) CommitsByFileAndRangeNoFollow(revision, file string, page int) ([]*Commit, error) {
stdout, _, err := NewCommand(repo.Ctx, "log", revision, "--skip="+strconv.Itoa((page-1)*50),
"--max-count="+strconv.Itoa(setting.Git.CommitsRangeSize), prettyLogFormat, "--", file).RunStdBytes(&RunOpts{Dir: repo.Path})
if err != nil {
return nil, err
}
return repo.parsePrettyFormatLogToList(stdout)
} }
// FilesCountBetween return the number of files changed between two commits // FilesCountBetween return the number of files changed between two commits

View file

@ -427,9 +427,9 @@ func ListPageRevisions(ctx *context.APIContext) {
} }
// get Commit Count // get Commit Count
commitsHistory, err := wikiRepo.CommitsByFileAndRangeNoFollow("master", pageFilename, page) commitsHistory, err := wikiRepo.CommitsByFileAndRange("master", pageFilename, page)
if err != nil { if err != nil {
ctx.Error(http.StatusInternalServerError, "CommitsByFileAndRangeNoFollow", err) ctx.Error(http.StatusInternalServerError, "CommitsByFileAndRange", err)
return return
} }

View file

@ -360,12 +360,12 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
} }
// get Commit Count // get Commit Count
commitsHistory, err := wikiRepo.CommitsByFileAndRangeNoFollow("master", pageFilename, page) commitsHistory, err := wikiRepo.CommitsByFileAndRange("master", pageFilename, page)
if err != nil { if err != nil {
if wikiRepo != nil { if wikiRepo != nil {
wikiRepo.Close() wikiRepo.Close()
} }
ctx.ServerError("CommitsByFileAndRangeNoFollow", err) ctx.ServerError("CommitsByFileAndRange", err)
return nil, nil return nil, nil
} }
ctx.Data["Commits"] = git_model.ConvertFromGitCommit(commitsHistory, ctx.Repo.Repository) ctx.Data["Commits"] = git_model.ConvertFromGitCommit(commitsHistory, ctx.Repo.Repository)