fix: repo home page 500 due to the timeout of "get last commit info" (#38678)

Regression of the ctx removal from "git.Repository" struct (the old code
was already wrong and can still cause 500, the "ctx removal" just makes
the problem easier to reproduce).

Merge duplicate code.

Reviewd by codex: no actionable findings.
This commit is contained in:
wxiaoguang
2026-07-28 19:12:53 +08:00
committed by GitHub
parent a75ed103f4
commit 0ab3d569b4
8 changed files with 113 additions and 200 deletions
-93
View File
@@ -7,101 +7,8 @@ package git
import (
"context"
"maps"
"path"
"sort"
"gitea.dev/modules/log"
)
// GetCommitsInfo gets information of all commits that are corresponding to these entries
func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, gitRepo *Repository, commit *Commit, treePath string) ([]CommitInfo, *Commit, error) {
entryPaths := make([]string, len(tes)+1)
// Get the commit for the treePath itself
entryPaths[0] = ""
for i, entry := range tes {
entryPaths[i+1] = entry.Name()
}
var err error
var revs map[string]*Commit
if gitRepo.LastCommitCache != nil {
var unHitPaths []string
revs, unHitPaths, err = getLastCommitForPathsByCache(ctx, commit.ID.String(), treePath, entryPaths, gitRepo.LastCommitCache)
if err != nil {
return nil, nil, err
}
if len(unHitPaths) > 0 {
sort.Strings(unHitPaths)
commits, err := GetLastCommitForPaths(ctx, gitRepo, commit, treePath, unHitPaths)
if err != nil {
return nil, nil, err
}
maps.Copy(revs, commits)
}
} else {
sort.Strings(entryPaths)
revs, err = GetLastCommitForPaths(ctx, gitRepo, commit, treePath, entryPaths)
}
if err != nil {
return nil, nil, err
}
commitsInfo := make([]CommitInfo, len(tes))
for i, entry := range tes {
commitsInfo[i] = CommitInfo{
Entry: entry,
}
// Check if we have found a commit for this entry in time
if entryCommit, ok := revs[entry.Name()]; ok {
commitsInfo[i].Commit = entryCommit
} else {
log.Debug("missing commit for %s", entry.Name())
}
// If the entry is a submodule, add a submodule file for this
if entry.IsSubModule() {
commitsInfo[i].SubmoduleFile, err = GetCommitInfoSubmoduleFile(ctx, repoLink, path.Join(treePath, entry.Name()), gitRepo, commit, entry.ID)
if err != nil {
return nil, nil, err
}
}
}
// Retrieve the commit for the treePath itself (see above). We basically
// get it for free during the tree traversal, and it's used for listing
// pages to display information about the newest commit for a given path.
var treeCommit *Commit
if treePath == "" {
treeCommit = commit
} else {
treeCommit = revs[""]
}
return commitsInfo, treeCommit, nil
}
func getLastCommitForPathsByCache(ctx context.Context, commitID, treePath string, paths []string, cache *LastCommitCache) (map[string]*Commit, []string, error) {
var unHitEntryPaths []string
results := make(map[string]*Commit)
for _, p := range paths {
lastCommit, err := cache.Get(ctx, commitID, path.Join(treePath, p))
if err != nil {
return nil, nil, err
}
if lastCommit != nil {
results[p] = lastCommit
continue
}
unHitEntryPaths = append(unHitEntryPaths, p)
}
return results, unHitEntryPaths, nil
}
// GetLastCommitForPaths returns last commit information
func GetLastCommitForPaths(ctx context.Context, gitRepo *Repository, commit *Commit, treePath string, paths []string) (map[string]*Commit, error) {
// We read backwards from the commit to obtain all of the commits