1
1
mirror of https://github.com/go-gitea/gitea synced 2025-07-23 02:38:35 +00:00

Refactor Git Attribute & performance optimization (#34154)

This PR moved git attributes related code to `modules/git/attribute` sub
package and moved language stats related code to
`modules/git/languagestats` sub package to make it easier to maintain.

And it also introduced a performance improvement which use the `git
check-attr --source` which can be run in a bare git repository so that
we don't need to create a git index file. The new parameter need a git
version >= 2.40 . If git version less than 2.40, it will fall back to
previous implementation.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: yp05327 <576951401@qq.com>
This commit is contained in:
Lunny Xiao
2025-04-11 06:41:29 -07:00
committed by GitHub
parent d725b78824
commit ae0af8ea5b
28 changed files with 875 additions and 587 deletions

View File

@@ -18,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/actions"
"code.gitea.io/gitea/modules/charset"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/git/attribute"
"code.gitea.io/gitea/modules/highlight"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
@@ -25,7 +26,6 @@ import (
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/context"
issue_service "code.gitea.io/gitea/services/issue"
files_service "code.gitea.io/gitea/services/repository/files"
"github.com/nektos/act/pkg/model"
)
@@ -147,6 +147,23 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) {
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_non_text_files")
}
// read all needed attributes which will be used later
// there should be no performance different between reading 2 or 4 here
attrsMap, err := attribute.CheckAttributes(ctx, ctx.Repo.GitRepo, ctx.Repo.CommitID, attribute.CheckAttributeOpts{
Filenames: []string{ctx.Repo.TreePath},
Attributes: []string{attribute.LinguistGenerated, attribute.LinguistVendored, attribute.LinguistLanguage, attribute.GitlabLanguage},
})
if err != nil {
ctx.ServerError("attribute.CheckAttributes", err)
return
}
attrs := attrsMap[ctx.Repo.TreePath]
if attrs == nil {
// this case shouldn't happen, just in case.
setting.PanicInDevOrTesting("no attributes found for %s", ctx.Repo.TreePath)
attrs = attribute.NewAttributes()
}
switch {
case isRepresentableAsText:
if fInfo.fileSize >= setting.UI.MaxDisplayFileSize {
@@ -209,11 +226,7 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) {
ctx.Data["NumLines"] = bytes.Count(buf, []byte{'\n'}) + 1
}
language, err := files_service.TryGetContentLanguage(ctx.Repo.GitRepo, ctx.Repo.CommitID, ctx.Repo.TreePath)
if err != nil {
log.Error("Unable to get file language for %-v:%s. Error: %v", ctx.Repo.Repository, ctx.Repo.TreePath, err)
}
language := attrs.GetLanguage().Value()
fileContent, lexerName, err := highlight.File(blob.Name(), language, buf)
ctx.Data["LexerName"] = lexerName
if err != nil {
@@ -283,17 +296,7 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) {
}
}
if ctx.Repo.GitRepo != nil {
checker, deferable := ctx.Repo.GitRepo.CheckAttributeReader(ctx.Repo.CommitID)
if checker != nil {
defer deferable()
attrs, err := checker.CheckPath(ctx.Repo.TreePath)
if err == nil {
ctx.Data["IsVendored"] = git.AttributeToBool(attrs, git.AttributeLinguistVendored).Value()
ctx.Data["IsGenerated"] = git.AttributeToBool(attrs, git.AttributeLinguistGenerated).Value()
}
}
}
ctx.Data["IsVendored"], ctx.Data["IsGenerated"] = attrs.GetVendored().Value(), attrs.GetGenerated().Value()
if fInfo.st.IsImage() && !fInfo.st.IsSvgImage() {
img, _, err := image.DecodeConfig(bytes.NewReader(buf))