Refactor git attributes (#29356)
This commit is contained in:
parent
98ab9445d1
commit
4197e28100
35
modules/git/attribute.go
Normal file
35
modules/git/attribute.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
)
|
||||
|
||||
const (
|
||||
AttributeLinguistVendored = "linguist-vendored"
|
||||
AttributeLinguistGenerated = "linguist-generated"
|
||||
AttributeLinguistDocumentation = "linguist-documentation"
|
||||
AttributeLinguistDetectable = "linguist-detectable"
|
||||
AttributeLinguistLanguage = "linguist-language"
|
||||
AttributeGitlabLanguage = "gitlab-language"
|
||||
)
|
||||
|
||||
// true if "set"/"true", false if "unset"/"false", none otherwise
|
||||
func AttributeToBool(attr map[string]string, name string) optional.Option[bool] {
|
||||
switch attr[name] {
|
||||
case "set", "true":
|
||||
return optional.Some(true)
|
||||
case "unset", "false":
|
||||
return optional.Some(false)
|
||||
}
|
||||
return optional.None[bool]()
|
||||
}
|
||||
|
||||
func AttributeToString(attr map[string]string, name string) optional.Option[string] {
|
||||
if value, has := attr[name]; has && value != "unspecified" {
|
||||
return optional.Some(value)
|
||||
}
|
||||
return optional.None[string]()
|
||||
}
|
|
@ -11,7 +11,6 @@ import (
|
|||
"os"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
)
|
||||
|
||||
// CheckAttributeOpts represents the possible options to CheckAttribute
|
||||
|
@ -292,10 +291,17 @@ func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeRe
|
|||
}
|
||||
|
||||
checker := &CheckAttributeReader{
|
||||
Attributes: []string{"linguist-vendored", "linguist-generated", "linguist-language", "gitlab-language", "linguist-documentation", "linguist-detectable"},
|
||||
Repo: repo,
|
||||
IndexFile: indexFilename,
|
||||
WorkTree: worktree,
|
||||
Attributes: []string{
|
||||
AttributeLinguistVendored,
|
||||
AttributeLinguistGenerated,
|
||||
AttributeLinguistDocumentation,
|
||||
AttributeLinguistDetectable,
|
||||
AttributeLinguistLanguage,
|
||||
AttributeGitlabLanguage,
|
||||
},
|
||||
Repo: repo,
|
||||
IndexFile: indexFilename,
|
||||
WorkTree: worktree,
|
||||
}
|
||||
ctx, cancel := context.WithCancel(repo.Ctx)
|
||||
if err := checker.Init(ctx); err != nil {
|
||||
|
@ -317,23 +323,3 @@ func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeRe
|
|||
|
||||
return checker, deferable
|
||||
}
|
||||
|
||||
// true if "set"/"true", false if "unset"/"false", none otherwise
|
||||
func attributeToBool(attr map[string]string, name string) optional.Option[bool] {
|
||||
if value, has := attr[name]; has && value != "unspecified" {
|
||||
switch value {
|
||||
case "set", "true":
|
||||
return optional.Some(true)
|
||||
case "unset", "false":
|
||||
return optional.Some(false)
|
||||
}
|
||||
}
|
||||
return optional.None[bool]()
|
||||
}
|
||||
|
||||
func attributeToString(attr map[string]string, name string) optional.Option[string] {
|
||||
if value, has := attr[name]; has && value != "unspecified" {
|
||||
return optional.Some(value)
|
||||
}
|
||||
return optional.None[string]()
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
|
|||
select {
|
||||
case attr := <-wr.ReadAttribute():
|
||||
assert.Equal(t, ".gitignore\"\n", attr.Filename)
|
||||
assert.Equal(t, "linguist-vendored", attr.Attribute)
|
||||
assert.Equal(t, AttributeLinguistVendored, attr.Attribute)
|
||||
assert.Equal(t, "unspecified", attr.Value)
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
assert.FailNow(t, "took too long to read an attribute from the list")
|
||||
|
@ -38,7 +38,7 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
|
|||
select {
|
||||
case attr := <-wr.ReadAttribute():
|
||||
assert.Equal(t, ".gitignore\"\n", attr.Filename)
|
||||
assert.Equal(t, "linguist-vendored", attr.Attribute)
|
||||
assert.Equal(t, AttributeLinguistVendored, attr.Attribute)
|
||||
assert.Equal(t, "unspecified", attr.Value)
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
assert.FailNow(t, "took too long to read an attribute from the list")
|
||||
|
@ -77,21 +77,21 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, attributeTriple{
|
||||
Filename: "shouldbe.vendor",
|
||||
Attribute: "linguist-vendored",
|
||||
Attribute: AttributeLinguistVendored,
|
||||
Value: "set",
|
||||
}, attr)
|
||||
attr = <-wr.ReadAttribute()
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, attributeTriple{
|
||||
Filename: "shouldbe.vendor",
|
||||
Attribute: "linguist-generated",
|
||||
Attribute: AttributeLinguistGenerated,
|
||||
Value: "unspecified",
|
||||
}, attr)
|
||||
attr = <-wr.ReadAttribute()
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, attributeTriple{
|
||||
Filename: "shouldbe.vendor",
|
||||
Attribute: "linguist-language",
|
||||
Attribute: AttributeLinguistLanguage,
|
||||
Value: "unspecified",
|
||||
}, attr)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ package git
|
|||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -46,3 +48,20 @@ func mergeLanguageStats(stats map[string]int64) map[string]int64 {
|
|||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func TryReadLanguageAttribute(attrs map[string]string) optional.Option[string] {
|
||||
language := AttributeToString(attrs, AttributeLinguistLanguage)
|
||||
if language.Value() == "" {
|
||||
language = AttributeToString(attrs, AttributeGitlabLanguage)
|
||||
if language.Has() {
|
||||
raw := language.Value()
|
||||
// gitlab-language may have additional parameters after the language
|
||||
// ignore them and just use the main language
|
||||
// https://docs.gitlab.com/ee/user/project/highlighting.html#override-syntax-highlighting-for-a-file-type
|
||||
if idx := strings.IndexByte(raw, '?'); idx >= 0 {
|
||||
language = optional.Some(raw[:idx])
|
||||
}
|
||||
}
|
||||
}
|
||||
return language
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ package git
|
|||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/analyze"
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
|
@ -66,36 +65,27 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
|
|||
if checker != nil {
|
||||
attrs, err := checker.CheckPath(f.Name)
|
||||
if err == nil {
|
||||
isVendored = attributeToBool(attrs, "linguist-vendored")
|
||||
isVendored = AttributeToBool(attrs, AttributeLinguistVendored)
|
||||
if isVendored.ValueOrDefault(false) {
|
||||
return nil
|
||||
}
|
||||
|
||||
isGenerated = attributeToBool(attrs, "linguist-generated")
|
||||
isGenerated = AttributeToBool(attrs, AttributeLinguistGenerated)
|
||||
if isGenerated.ValueOrDefault(false) {
|
||||
return nil
|
||||
}
|
||||
|
||||
isDocumentation = attributeToBool(attrs, "linguist-documentation")
|
||||
isDocumentation = AttributeToBool(attrs, AttributeLinguistDocumentation)
|
||||
if isDocumentation.ValueOrDefault(false) {
|
||||
return nil
|
||||
}
|
||||
|
||||
isDetectable = attributeToBool(attrs, "linguist-detectable")
|
||||
isDetectable = AttributeToBool(attrs, AttributeLinguistDetectable)
|
||||
if !isDetectable.ValueOrDefault(true) {
|
||||
return nil
|
||||
}
|
||||
|
||||
hasLanguage := attributeToString(attrs, "linguist-language")
|
||||
if hasLanguage.Value() == "" {
|
||||
hasLanguage = attributeToString(attrs, "gitlab-language")
|
||||
if hasLanguage.Has() {
|
||||
language := hasLanguage.Value()
|
||||
if idx := strings.IndexByte(language, '?'); idx >= 0 {
|
||||
hasLanguage = optional.Some(language[:idx])
|
||||
}
|
||||
}
|
||||
}
|
||||
hasLanguage := TryReadLanguageAttribute(attrs)
|
||||
if hasLanguage.Value() != "" {
|
||||
language := hasLanguage.Value()
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ package git
|
|||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/analyze"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
@ -97,36 +96,27 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
|
|||
if checker != nil {
|
||||
attrs, err := checker.CheckPath(f.Name())
|
||||
if err == nil {
|
||||
isVendored = attributeToBool(attrs, "linguist-vendored")
|
||||
isVendored = AttributeToBool(attrs, AttributeLinguistVendored)
|
||||
if isVendored.ValueOrDefault(false) {
|
||||
continue
|
||||
}
|
||||
|
||||
isGenerated = attributeToBool(attrs, "linguist-generated")
|
||||
isGenerated = AttributeToBool(attrs, AttributeLinguistGenerated)
|
||||
if isGenerated.ValueOrDefault(false) {
|
||||
continue
|
||||
}
|
||||
|
||||
isDocumentation = attributeToBool(attrs, "linguist-documentation")
|
||||
isDocumentation = AttributeToBool(attrs, AttributeLinguistDocumentation)
|
||||
if isDocumentation.ValueOrDefault(false) {
|
||||
continue
|
||||
}
|
||||
|
||||
isDetectable = attributeToBool(attrs, "linguist-detectable")
|
||||
isDetectable = AttributeToBool(attrs, AttributeLinguistDetectable)
|
||||
if !isDetectable.ValueOrDefault(true) {
|
||||
continue
|
||||
}
|
||||
|
||||
hasLanguage := attributeToString(attrs, "linguist-language")
|
||||
if hasLanguage.Value() == "" {
|
||||
hasLanguage = attributeToString(attrs, "gitlab-language")
|
||||
if hasLanguage.Has() {
|
||||
language := hasLanguage.Value()
|
||||
if idx := strings.IndexByte(language, '?'); idx >= 0 {
|
||||
hasLanguage = optional.Some(language[:idx])
|
||||
}
|
||||
}
|
||||
}
|
||||
hasLanguage := TryReadLanguageAttribute(attrs)
|
||||
if hasLanguage.Value() != "" {
|
||||
language := hasLanguage.Value()
|
||||
|
||||
|
|
|
@ -635,11 +635,8 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry) {
|
|||
defer deferable()
|
||||
attrs, err := checker.CheckPath(ctx.Repo.TreePath)
|
||||
if err == nil {
|
||||
vendored, has := attrs["linguist-vendored"]
|
||||
ctx.Data["IsVendored"] = has && (vendored == "set" || vendored == "true")
|
||||
|
||||
generated, has := attrs["linguist-generated"]
|
||||
ctx.Data["IsGenerated"] = has && (generated == "set" || generated == "true")
|
||||
ctx.Data["IsVendored"] = git.AttributeToBool(attrs, git.AttributeLinguistVendored).Value()
|
||||
ctx.Data["IsGenerated"] = git.AttributeToBool(attrs, git.AttributeLinguistGenerated).Value()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/highlight"
|
||||
"code.gitea.io/gitea/modules/lfs"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
|
||||
|
@ -1181,41 +1182,30 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
|
|||
|
||||
for _, diffFile := range diff.Files {
|
||||
|
||||
gotVendor := false
|
||||
gotGenerated := false
|
||||
isVendored := optional.None[bool]()
|
||||
isGenerated := optional.None[bool]()
|
||||
if checker != nil {
|
||||
attrs, err := checker.CheckPath(diffFile.Name)
|
||||
if err == nil {
|
||||
if vendored, has := attrs["linguist-vendored"]; has {
|
||||
if vendored == "set" || vendored == "true" {
|
||||
diffFile.IsVendored = true
|
||||
gotVendor = true
|
||||
} else {
|
||||
gotVendor = vendored == "false"
|
||||
}
|
||||
}
|
||||
if generated, has := attrs["linguist-generated"]; has {
|
||||
if generated == "set" || generated == "true" {
|
||||
diffFile.IsGenerated = true
|
||||
gotGenerated = true
|
||||
} else {
|
||||
gotGenerated = generated == "false"
|
||||
}
|
||||
}
|
||||
if language, has := attrs["linguist-language"]; has && language != "unspecified" && language != "" {
|
||||
diffFile.Language = language
|
||||
} else if language, has := attrs["gitlab-language"]; has && language != "unspecified" && language != "" {
|
||||
diffFile.Language = language
|
||||
isVendored = git.AttributeToBool(attrs, git.AttributeLinguistVendored)
|
||||
isGenerated = git.AttributeToBool(attrs, git.AttributeLinguistGenerated)
|
||||
|
||||
language := git.TryReadLanguageAttribute(attrs)
|
||||
if language.Has() {
|
||||
diffFile.Language = language.Value()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !gotVendor {
|
||||
diffFile.IsVendored = analyze.IsVendor(diffFile.Name)
|
||||
if !isVendored.Has() {
|
||||
isVendored = optional.Some(analyze.IsVendor(diffFile.Name))
|
||||
}
|
||||
if !gotGenerated {
|
||||
diffFile.IsGenerated = analyze.IsGenerated(diffFile.Name)
|
||||
diffFile.IsVendored = isVendored.Value()
|
||||
|
||||
if !isGenerated.Has() {
|
||||
isGenerated = optional.Some(analyze.IsGenerated(diffFile.Name))
|
||||
}
|
||||
diffFile.IsGenerated = isGenerated.Value()
|
||||
|
||||
tailSection := diffFile.GetTailSection(gitRepo, opts.BeforeCommitID, opts.AfterCommitID)
|
||||
if tailSection != nil {
|
||||
|
|
|
@ -282,7 +282,7 @@ func TryGetContentLanguage(gitRepo *git.Repository, commitID, treePath string) (
|
|||
|
||||
filename2attribute2info, err := gitRepo.CheckAttribute(git.CheckAttributeOpts{
|
||||
CachedOnly: true,
|
||||
Attributes: []string{"linguist-language", "gitlab-language"},
|
||||
Attributes: []string{git.AttributeLinguistLanguage, git.AttributeGitlabLanguage},
|
||||
Filenames: []string{treePath},
|
||||
IndexFile: indexFilename,
|
||||
WorkTree: worktree,
|
||||
|
@ -291,13 +291,7 @@ func TryGetContentLanguage(gitRepo *git.Repository, commitID, treePath string) (
|
|||
return "", err
|
||||
}
|
||||
|
||||
language := filename2attribute2info[treePath]["linguist-language"]
|
||||
if language == "" || language == "unspecified" {
|
||||
language = filename2attribute2info[treePath]["gitlab-language"]
|
||||
}
|
||||
if language == "unspecified" {
|
||||
language = ""
|
||||
}
|
||||
language := git.TryReadLanguageAttribute(filename2attribute2info[treePath])
|
||||
|
||||
return language, nil
|
||||
return language.Value(), nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user