Refactor git attributes (#29356)

This commit is contained in:
KN4CK3R 2024-02-24 19:46:49 +01:00 committed by GitHub
parent 98ab9445d1
commit 4197e28100
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 101 additions and 100 deletions

35
modules/git/attribute.go Normal file
View 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]()
}

View File

@ -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,7 +291,14 @@ func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeRe
}
checker := &CheckAttributeReader{
Attributes: []string{"linguist-vendored", "linguist-generated", "linguist-language", "gitlab-language", "linguist-documentation", "linguist-detectable"},
Attributes: []string{
AttributeLinguistVendored,
AttributeLinguistGenerated,
AttributeLinguistDocumentation,
AttributeLinguistDetectable,
AttributeLinguistLanguage,
AttributeGitlabLanguage,
},
Repo: repo,
IndexFile: indexFilename,
WorkTree: worktree,
@ -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]()
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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()

View File

@ -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()

View File

@ -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()
}
}
}

View File

@ -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 {

View File

@ -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
}