refactor: decouple git.Repository(ctx) from git.Commit & git.Tree (#38464)

1. Storing "ctx" in a long-living object is wrong
2. Make the commit & tree cacheable (for the future performance
optimization)
3. Also fix some bad designs like `// FIXME: bad design, this field can
be nil if the commit is from "last commit cache"`

ref:
* #33893
This commit is contained in:
wxiaoguang
2026-07-15 17:30:01 +00:00
committed by GitHub
parent ed678b9d45
commit 82edc3da01
115 changed files with 730 additions and 862 deletions
+29 -28
View File
@@ -6,6 +6,7 @@ package repo
import (
"bytes"
gocontext "context"
"html/template"
"io"
"net/http"
@@ -78,8 +79,8 @@ type PageMeta struct {
}
// findEntryForFile finds the tree entry for a target filepath.
func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) {
entry, err := commit.GetTreeEntryByPath(target)
func findEntryForFile(ctx gocontext.Context, wikiRepo *git.Repository, commit *git.Commit, target string) (*git.TreeEntry, error) {
entry, err := commit.GetTreeEntryByPath(ctx, wikiRepo, target)
if err != nil && !git.IsErrNotExist(err) {
return nil, err
}
@@ -92,7 +93,7 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error)
if unescapedTarget, err = url.QueryUnescape(target); err != nil {
return nil, err
}
return commit.GetTreeEntryByPath(unescapedTarget)
return commit.GetTreeEntryByPath(ctx, wikiRepo, unescapedTarget)
}
func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) {
@@ -126,8 +127,8 @@ func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, err
// wikiContentsByEntry returns the contents of the wiki page referenced by the
// given tree entry. Writes to ctx if an error occurs.
func wikiContentsByEntry(ctx *context.Context, entry *git.TreeEntry) []byte {
reader, err := entry.Blob().DataAsync()
func wikiContentsByEntry(ctx *context.Context, wikiRepo *git.Repository, entry *git.TreeEntry) []byte {
reader, err := entry.Blob(wikiRepo).DataAsync()
if err != nil {
ctx.ServerError("Blob.Data", err)
return nil
@@ -144,10 +145,10 @@ func wikiContentsByEntry(ctx *context.Context, entry *git.TreeEntry) []byte {
// wikiEntryByName returns the entry of a wiki page, along with a boolean
// indicating whether the entry exists. Writes to ctx if an error occurs.
// The last return value indicates whether the file should be returned as a raw file
func wikiEntryByName(ctx *context.Context, commit *git.Commit, wikiName wiki_service.WebPath) (*git.TreeEntry, string, bool, bool) {
func wikiEntryByName(ctx *context.Context, wikiRepo *git.Repository, commit *git.Commit, wikiName wiki_service.WebPath) (*git.TreeEntry, string, bool, bool) {
isRaw := false
gitFilename := wiki_service.WebPathToGitPath(wikiName)
entry, err := findEntryForFile(commit, gitFilename)
entry, err := findEntryForFile(ctx, wikiRepo, commit, gitFilename)
if err != nil && !git.IsErrNotExist(err) {
ctx.ServerError("findEntryForFile", err)
return nil, "", false, false
@@ -155,7 +156,7 @@ func wikiEntryByName(ctx *context.Context, commit *git.Commit, wikiName wiki_ser
if entry == nil {
// check if the file without ".md" suffix exists
gitFilename := strings.TrimSuffix(gitFilename, ".md")
entry, err = findEntryForFile(commit, gitFilename)
entry, err = findEntryForFile(ctx, wikiRepo, commit, gitFilename)
if err != nil && !git.IsErrNotExist(err) {
ctx.ServerError("findEntryForFile", err)
return nil, "", false, false
@@ -170,12 +171,12 @@ func wikiEntryByName(ctx *context.Context, commit *git.Commit, wikiName wiki_ser
// wikiContentsByName returns the contents of a wiki page, along with a boolean
// indicating whether the page exists. Writes to ctx if an error occurs.
func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName wiki_service.WebPath) ([]byte, *git.TreeEntry, string, bool) {
entry, gitFilename, noEntry, _ := wikiEntryByName(ctx, commit, wikiName)
func wikiContentsByName(ctx *context.Context, wikiRepo *git.Repository, commit *git.Commit, wikiName wiki_service.WebPath) ([]byte, *git.TreeEntry, string, bool) {
entry, gitFilename, noEntry, _ := wikiEntryByName(ctx, wikiRepo, commit, wikiName)
if entry == nil {
return nil, nil, "", true
}
return wikiContentsByEntry(ctx, entry), entry, gitFilename, noEntry
return wikiContentsByEntry(ctx, wikiRepo, entry), entry, gitFilename, noEntry
}
func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
@@ -188,7 +189,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
}
// get the wiki pages list.
entries, err := commit.ListEntries()
entries, err := commit.Tree().ListEntries(ctx, wikiGitRepo)
if err != nil {
ctx.ServerError("ListEntries", err)
return nil, nil
@@ -233,7 +234,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
isFooter := pageName == "_Footer"
// lookup filename in wiki - get gitTree entry , real filename
entry, pageFilename, noEntry, isRaw := wikiEntryByName(ctx, commit, pageName)
entry, pageFilename, noEntry, isRaw := wikiEntryByName(ctx, wikiGitRepo, commit, pageName)
if noEntry {
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages")
}
@@ -245,7 +246,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
}
// get page content
data := wikiContentsByEntry(ctx, entry)
data := wikiContentsByEntry(ctx, wikiGitRepo, entry)
if ctx.Written() {
return nil, nil
}
@@ -283,7 +284,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
}
if !isSideBar {
sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar")
sidebarContent, _, _, _ := wikiContentsByName(ctx, wikiGitRepo, commit, "_Sidebar")
if ctx.Written() {
return nil, nil
}
@@ -295,7 +296,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
}
if !isFooter {
footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer")
footerContent, _, _, _ := wikiContentsByName(ctx, wikiGitRepo, commit, "_Footer")
if ctx.Written() {
return nil, nil
}
@@ -335,7 +336,7 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
ctx.Data["title"] = displayName
// lookup filename in wiki - get page content, gitTree entry , real filename
_, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
_, entry, pageFilename, noEntry := wikiContentsByName(ctx, wikiGitRepo, commit, pageName)
if noEntry {
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages")
}
@@ -375,7 +376,7 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
}
func renderEditPage(ctx *context.Context) {
_, commit, err := findWikiRepoCommit(ctx)
wikiGitRepo, commit, err := findWikiRepoCommit(ctx)
if err != nil {
if !git.IsErrNotExist(err) {
ctx.ServerError("GetBranchCommit", err)
@@ -396,7 +397,7 @@ func renderEditPage(ctx *context.Context) {
ctx.Data["title"] = displayName
// lookup filename in wiki - gitTree entry , real filename
entry, _, noEntry, isRaw := wikiEntryByName(ctx, commit, pageName)
entry, _, noEntry, isRaw := wikiEntryByName(ctx, wikiGitRepo, commit, pageName)
if noEntry {
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/?action=_pages")
}
@@ -408,7 +409,7 @@ func renderEditPage(ctx *context.Context) {
}
// get wiki page content
data := wikiContentsByEntry(ctx, entry)
data := wikiContentsByEntry(ctx, wikiGitRepo, entry)
if ctx.Written() {
return
}
@@ -543,27 +544,27 @@ func WikiPages(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.wiki.pages")
ctx.Data["CanWriteWiki"] = ctx.Repo.Permission.CanWrite(unit.TypeWiki) && !ctx.Repo.Repository.IsArchived
_, commit, err := findWikiRepoCommit(ctx)
wikiGitRepo, commit, err := findWikiRepoCommit(ctx)
if err != nil {
ctx.Redirect(ctx.Repo.RepoLink + "/wiki")
return
}
treePath := "" // To support list sub folders' pages in the future
tree, err := commit.SubTree(treePath)
tree, err := commit.SubTree(ctx, wikiGitRepo, treePath)
if err != nil {
ctx.ServerError("SubTree", err)
return
}
allEntries, err := tree.ListEntries()
allEntries, err := tree.ListEntries(ctx, wikiGitRepo)
if err != nil {
ctx.ServerError("ListEntries", err)
return
}
allEntries.CustomSort(base.NaturalSortCompare)
entries, _, err := allEntries.GetCommitsInfo(ctx, ctx.Repo.RepoLink, commit, treePath)
entries, _, err := allEntries.GetCommitsInfo(ctx, ctx.Repo.RepoLink, wikiGitRepo, commit, treePath)
if err != nil {
ctx.ServerError("GetCommitsInfo", err)
return
@@ -597,7 +598,7 @@ func WikiPages(ctx *context.Context) {
// WikiRaw outputs raw blob requested by user (image for example)
func WikiRaw(ctx *context.Context) {
_, commit, err := findWikiRepoCommit(ctx)
wikiGitRepo, commit, err := findWikiRepoCommit(ctx)
if err != nil {
if git.IsErrNotExist(err) {
ctx.NotFound(nil)
@@ -612,7 +613,7 @@ func WikiRaw(ctx *context.Context) {
var entry *git.TreeEntry
if commit != nil {
// Try to find a file with that name
entry, err = findEntryForFile(commit, providedGitPath)
entry, err = findEntryForFile(ctx, wikiGitRepo, commit, providedGitPath)
if err != nil && !git.IsErrNotExist(err) {
ctx.ServerError("findFile", err)
return
@@ -621,7 +622,7 @@ func WikiRaw(ctx *context.Context) {
if entry == nil {
// Try to find a wiki page with that name
providedGitPath = strings.TrimSuffix(providedGitPath, ".md")
entry, err = findEntryForFile(commit, providedGitPath)
entry, err = findEntryForFile(ctx, wikiGitRepo, commit, providedGitPath)
if err != nil && !git.IsErrNotExist(err) {
ctx.ServerError("findFile", err)
return
@@ -630,7 +631,7 @@ func WikiRaw(ctx *context.Context) {
}
if entry != nil {
if err = common.ServeBlob(ctx.Base, ctx.Repo.Repository, ctx.Repo.TreePath, entry.Blob(), nil); err != nil {
if err = common.ServeBlob(ctx.Base, ctx.Repo.Repository, ctx.Repo.TreePath, entry.Blob(wikiGitRepo), nil); err != nil {
ctx.ServerError("ServeBlob", err)
}
return