mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	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:
		@@ -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
 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							n, err = hex.Decode(sha1[:], shaline[0:40])
 | 
				
			||||||
 | 
							if n != 20 {
 | 
				
			||||||
 | 
								err = fmt.Errorf("invalid sha %q", string(shaline[:40]))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	stdout, err := io.ReadAll(stdoutReader)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	return repo.parsePrettyFormatLogToList(stdout)
 | 
							commit, err := repo.getCommit(sha1)
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 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 {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	return repo.parsePrettyFormatLogToList(stdout)
 | 
							commits = append(commits, commit)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FilesCountBetween return the number of files changed between two commits
 | 
					// FilesCountBetween return the number of files changed between two commits
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user