From 58a4407acb04b329e94e92977b1414feb309d5de Mon Sep 17 00:00:00 2001 From: zeripath Date: Mon, 15 Aug 2022 02:22:13 +0100 Subject: [PATCH] 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 Signed-off-by: Andrew Thornton Co-authored-by: techknowlogick --- modules/git/repo_commit.go | 46 ++++++++++++++++++------------------- routers/api/v1/repo/wiki.go | 4 ++-- routers/web/repo/wiki.go | 4 ++-- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index 7ff23af42..d3731cb92 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -7,6 +7,8 @@ package git import ( "bytes" + "encoding/hex" + "fmt" "io" "strconv" "strings" @@ -209,9 +211,9 @@ func (repo *Repository) CommitsByFileAndRange(revision, file string, page int) ( }() go func() { 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), - prettyLogFormat, "--", file). + "--skip="+strconv.Itoa(skip), "--", file). Run(&RunOpts{ Dir: repo.Path, Stdout: stdoutWriter, @@ -224,32 +226,30 @@ func (repo *Repository) CommitsByFileAndRange(revision, file string, page int) ( } }() - if skip > 0 { - _, err := io.CopyN(io.Discard, stdoutReader, int64(skip*41)) - if err != nil { + commits := []*Commit{} + shaline := [41]byte{} + var sha1 SHA1 + for { + n, err := io.ReadFull(stdoutReader, shaline[:]) + if err != nil || n < 40 { 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 } + 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 diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index a3a590492..d423bddbb 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -427,9 +427,9 @@ func ListPageRevisions(ctx *context.APIContext) { } // get Commit Count - commitsHistory, err := wikiRepo.CommitsByFileAndRangeNoFollow("master", pageFilename, page) + commitsHistory, err := wikiRepo.CommitsByFileAndRange("master", pageFilename, page) if err != nil { - ctx.Error(http.StatusInternalServerError, "CommitsByFileAndRangeNoFollow", err) + ctx.Error(http.StatusInternalServerError, "CommitsByFileAndRange", err) return } diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go index 1af511f50..4cd5856ea 100644 --- a/routers/web/repo/wiki.go +++ b/routers/web/repo/wiki.go @@ -360,12 +360,12 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) } // get Commit Count - commitsHistory, err := wikiRepo.CommitsByFileAndRangeNoFollow("master", pageFilename, page) + commitsHistory, err := wikiRepo.CommitsByFileAndRange("master", pageFilename, page) if err != nil { if wikiRepo != nil { wikiRepo.Close() } - ctx.ServerError("CommitsByFileAndRangeNoFollow", err) + ctx.ServerError("CommitsByFileAndRange", err) return nil, nil } ctx.Data["Commits"] = git_model.ConvertFromGitCommit(commitsHistory, ctx.Repo.Repository)