Skip to content

Commit 4197e28

Browse files
authored
Refactor git attributes (go-gitea#29356)
1 parent 98ab944 commit 4197e28

File tree

9 files changed

+101
-100
lines changed

9 files changed

+101
-100
lines changed

modules/git/attribute.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package git
5+
6+
import (
7+
"code.gitea.io/gitea/modules/optional"
8+
)
9+
10+
const (
11+
AttributeLinguistVendored = "linguist-vendored"
12+
AttributeLinguistGenerated = "linguist-generated"
13+
AttributeLinguistDocumentation = "linguist-documentation"
14+
AttributeLinguistDetectable = "linguist-detectable"
15+
AttributeLinguistLanguage = "linguist-language"
16+
AttributeGitlabLanguage = "gitlab-language"
17+
)
18+
19+
// true if "set"/"true", false if "unset"/"false", none otherwise
20+
func AttributeToBool(attr map[string]string, name string) optional.Option[bool] {
21+
switch attr[name] {
22+
case "set", "true":
23+
return optional.Some(true)
24+
case "unset", "false":
25+
return optional.Some(false)
26+
}
27+
return optional.None[bool]()
28+
}
29+
30+
func AttributeToString(attr map[string]string, name string) optional.Option[string] {
31+
if value, has := attr[name]; has && value != "unspecified" {
32+
return optional.Some(value)
33+
}
34+
return optional.None[string]()
35+
}

modules/git/repo_attribute.go

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"os"
1212

1313
"code.gitea.io/gitea/modules/log"
14-
"code.gitea.io/gitea/modules/optional"
1514
)
1615

1716
// CheckAttributeOpts represents the possible options to CheckAttribute
@@ -292,10 +291,17 @@ func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeRe
292291
}
293292

294293
checker := &CheckAttributeReader{
295-
Attributes: []string{"linguist-vendored", "linguist-generated", "linguist-language", "gitlab-language", "linguist-documentation", "linguist-detectable"},
296-
Repo: repo,
297-
IndexFile: indexFilename,
298-
WorkTree: worktree,
294+
Attributes: []string{
295+
AttributeLinguistVendored,
296+
AttributeLinguistGenerated,
297+
AttributeLinguistDocumentation,
298+
AttributeLinguistDetectable,
299+
AttributeLinguistLanguage,
300+
AttributeGitlabLanguage,
301+
},
302+
Repo: repo,
303+
IndexFile: indexFilename,
304+
WorkTree: worktree,
299305
}
300306
ctx, cancel := context.WithCancel(repo.Ctx)
301307
if err := checker.Init(ctx); err != nil {
@@ -317,23 +323,3 @@ func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeRe
317323

318324
return checker, deferable
319325
}
320-
321-
// true if "set"/"true", false if "unset"/"false", none otherwise
322-
func attributeToBool(attr map[string]string, name string) optional.Option[bool] {
323-
if value, has := attr[name]; has && value != "unspecified" {
324-
switch value {
325-
case "set", "true":
326-
return optional.Some(true)
327-
case "unset", "false":
328-
return optional.Some(false)
329-
}
330-
}
331-
return optional.None[bool]()
332-
}
333-
334-
func attributeToString(attr map[string]string, name string) optional.Option[string] {
335-
if value, has := attr[name]; has && value != "unspecified" {
336-
return optional.Some(value)
337-
}
338-
return optional.None[string]()
339-
}

modules/git/repo_attribute_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
2424
select {
2525
case attr := <-wr.ReadAttribute():
2626
assert.Equal(t, ".gitignore\"\n", attr.Filename)
27-
assert.Equal(t, "linguist-vendored", attr.Attribute)
27+
assert.Equal(t, AttributeLinguistVendored, attr.Attribute)
2828
assert.Equal(t, "unspecified", attr.Value)
2929
case <-time.After(100 * time.Millisecond):
3030
assert.FailNow(t, "took too long to read an attribute from the list")
@@ -38,7 +38,7 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
3838
select {
3939
case attr := <-wr.ReadAttribute():
4040
assert.Equal(t, ".gitignore\"\n", attr.Filename)
41-
assert.Equal(t, "linguist-vendored", attr.Attribute)
41+
assert.Equal(t, AttributeLinguistVendored, attr.Attribute)
4242
assert.Equal(t, "unspecified", attr.Value)
4343
case <-time.After(100 * time.Millisecond):
4444
assert.FailNow(t, "took too long to read an attribute from the list")
@@ -77,21 +77,21 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
7777
assert.NoError(t, err)
7878
assert.EqualValues(t, attributeTriple{
7979
Filename: "shouldbe.vendor",
80-
Attribute: "linguist-vendored",
80+
Attribute: AttributeLinguistVendored,
8181
Value: "set",
8282
}, attr)
8383
attr = <-wr.ReadAttribute()
8484
assert.NoError(t, err)
8585
assert.EqualValues(t, attributeTriple{
8686
Filename: "shouldbe.vendor",
87-
Attribute: "linguist-generated",
87+
Attribute: AttributeLinguistGenerated,
8888
Value: "unspecified",
8989
}, attr)
9090
attr = <-wr.ReadAttribute()
9191
assert.NoError(t, err)
9292
assert.EqualValues(t, attributeTriple{
9393
Filename: "shouldbe.vendor",
94-
Attribute: "linguist-language",
94+
Attribute: AttributeLinguistLanguage,
9595
Value: "unspecified",
9696
}, attr)
9797
}

modules/git/repo_language_stats.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package git
66
import (
77
"strings"
88
"unicode"
9+
10+
"code.gitea.io/gitea/modules/optional"
911
)
1012

1113
const (
@@ -46,3 +48,20 @@ func mergeLanguageStats(stats map[string]int64) map[string]int64 {
4648
}
4749
return res
4850
}
51+
52+
func TryReadLanguageAttribute(attrs map[string]string) optional.Option[string] {
53+
language := AttributeToString(attrs, AttributeLinguistLanguage)
54+
if language.Value() == "" {
55+
language = AttributeToString(attrs, AttributeGitlabLanguage)
56+
if language.Has() {
57+
raw := language.Value()
58+
// gitlab-language may have additional parameters after the language
59+
// ignore them and just use the main language
60+
// https://docs.gitlab.com/ee/user/project/highlighting.html#override-syntax-highlighting-for-a-file-type
61+
if idx := strings.IndexByte(raw, '?'); idx >= 0 {
62+
language = optional.Some(raw[:idx])
63+
}
64+
}
65+
}
66+
return language
67+
}

modules/git/repo_language_stats_gogit.go

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package git
88
import (
99
"bytes"
1010
"io"
11-
"strings"
1211

1312
"code.gitea.io/gitea/modules/analyze"
1413
"code.gitea.io/gitea/modules/optional"
@@ -66,36 +65,27 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
6665
if checker != nil {
6766
attrs, err := checker.CheckPath(f.Name)
6867
if err == nil {
69-
isVendored = attributeToBool(attrs, "linguist-vendored")
68+
isVendored = AttributeToBool(attrs, AttributeLinguistVendored)
7069
if isVendored.ValueOrDefault(false) {
7170
return nil
7271
}
7372

74-
isGenerated = attributeToBool(attrs, "linguist-generated")
73+
isGenerated = AttributeToBool(attrs, AttributeLinguistGenerated)
7574
if isGenerated.ValueOrDefault(false) {
7675
return nil
7776
}
7877

79-
isDocumentation = attributeToBool(attrs, "linguist-documentation")
78+
isDocumentation = AttributeToBool(attrs, AttributeLinguistDocumentation)
8079
if isDocumentation.ValueOrDefault(false) {
8180
return nil
8281
}
8382

84-
isDetectable = attributeToBool(attrs, "linguist-detectable")
83+
isDetectable = AttributeToBool(attrs, AttributeLinguistDetectable)
8584
if !isDetectable.ValueOrDefault(true) {
8685
return nil
8786
}
8887

89-
hasLanguage := attributeToString(attrs, "linguist-language")
90-
if hasLanguage.Value() == "" {
91-
hasLanguage = attributeToString(attrs, "gitlab-language")
92-
if hasLanguage.Has() {
93-
language := hasLanguage.Value()
94-
if idx := strings.IndexByte(language, '?'); idx >= 0 {
95-
hasLanguage = optional.Some(language[:idx])
96-
}
97-
}
98-
}
88+
hasLanguage := TryReadLanguageAttribute(attrs)
9989
if hasLanguage.Value() != "" {
10090
language := hasLanguage.Value()
10191

modules/git/repo_language_stats_nogogit.go

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package git
88
import (
99
"bytes"
1010
"io"
11-
"strings"
1211

1312
"code.gitea.io/gitea/modules/analyze"
1413
"code.gitea.io/gitea/modules/log"
@@ -97,36 +96,27 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
9796
if checker != nil {
9897
attrs, err := checker.CheckPath(f.Name())
9998
if err == nil {
100-
isVendored = attributeToBool(attrs, "linguist-vendored")
99+
isVendored = AttributeToBool(attrs, AttributeLinguistVendored)
101100
if isVendored.ValueOrDefault(false) {
102101
continue
103102
}
104103

105-
isGenerated = attributeToBool(attrs, "linguist-generated")
104+
isGenerated = AttributeToBool(attrs, AttributeLinguistGenerated)
106105
if isGenerated.ValueOrDefault(false) {
107106
continue
108107
}
109108

110-
isDocumentation = attributeToBool(attrs, "linguist-documentation")
109+
isDocumentation = AttributeToBool(attrs, AttributeLinguistDocumentation)
111110
if isDocumentation.ValueOrDefault(false) {
112111
continue
113112
}
114113

115-
isDetectable = attributeToBool(attrs, "linguist-detectable")
114+
isDetectable = AttributeToBool(attrs, AttributeLinguistDetectable)
116115
if !isDetectable.ValueOrDefault(true) {
117116
continue
118117
}
119118

120-
hasLanguage := attributeToString(attrs, "linguist-language")
121-
if hasLanguage.Value() == "" {
122-
hasLanguage = attributeToString(attrs, "gitlab-language")
123-
if hasLanguage.Has() {
124-
language := hasLanguage.Value()
125-
if idx := strings.IndexByte(language, '?'); idx >= 0 {
126-
hasLanguage = optional.Some(language[:idx])
127-
}
128-
}
129-
}
119+
hasLanguage := TryReadLanguageAttribute(attrs)
130120
if hasLanguage.Value() != "" {
131121
language := hasLanguage.Value()
132122

routers/web/repo/view.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -635,11 +635,8 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry) {
635635
defer deferable()
636636
attrs, err := checker.CheckPath(ctx.Repo.TreePath)
637637
if err == nil {
638-
vendored, has := attrs["linguist-vendored"]
639-
ctx.Data["IsVendored"] = has && (vendored == "set" || vendored == "true")
640-
641-
generated, has := attrs["linguist-generated"]
642-
ctx.Data["IsGenerated"] = has && (generated == "set" || generated == "true")
638+
ctx.Data["IsVendored"] = git.AttributeToBool(attrs, git.AttributeLinguistVendored).Value()
639+
ctx.Data["IsGenerated"] = git.AttributeToBool(attrs, git.AttributeLinguistGenerated).Value()
643640
}
644641
}
645642
}

services/gitdiff/gitdiff.go

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"code.gitea.io/gitea/modules/highlight"
3030
"code.gitea.io/gitea/modules/lfs"
3131
"code.gitea.io/gitea/modules/log"
32+
"code.gitea.io/gitea/modules/optional"
3233
"code.gitea.io/gitea/modules/setting"
3334
"code.gitea.io/gitea/modules/translation"
3435

@@ -1181,41 +1182,30 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
11811182

11821183
for _, diffFile := range diff.Files {
11831184

1184-
gotVendor := false
1185-
gotGenerated := false
1185+
isVendored := optional.None[bool]()
1186+
isGenerated := optional.None[bool]()
11861187
if checker != nil {
11871188
attrs, err := checker.CheckPath(diffFile.Name)
11881189
if err == nil {
1189-
if vendored, has := attrs["linguist-vendored"]; has {
1190-
if vendored == "set" || vendored == "true" {
1191-
diffFile.IsVendored = true
1192-
gotVendor = true
1193-
} else {
1194-
gotVendor = vendored == "false"
1195-
}
1196-
}
1197-
if generated, has := attrs["linguist-generated"]; has {
1198-
if generated == "set" || generated == "true" {
1199-
diffFile.IsGenerated = true
1200-
gotGenerated = true
1201-
} else {
1202-
gotGenerated = generated == "false"
1203-
}
1204-
}
1205-
if language, has := attrs["linguist-language"]; has && language != "unspecified" && language != "" {
1206-
diffFile.Language = language
1207-
} else if language, has := attrs["gitlab-language"]; has && language != "unspecified" && language != "" {
1208-
diffFile.Language = language
1190+
isVendored = git.AttributeToBool(attrs, git.AttributeLinguistVendored)
1191+
isGenerated = git.AttributeToBool(attrs, git.AttributeLinguistGenerated)
1192+
1193+
language := git.TryReadLanguageAttribute(attrs)
1194+
if language.Has() {
1195+
diffFile.Language = language.Value()
12091196
}
12101197
}
12111198
}
12121199

1213-
if !gotVendor {
1214-
diffFile.IsVendored = analyze.IsVendor(diffFile.Name)
1200+
if !isVendored.Has() {
1201+
isVendored = optional.Some(analyze.IsVendor(diffFile.Name))
12151202
}
1216-
if !gotGenerated {
1217-
diffFile.IsGenerated = analyze.IsGenerated(diffFile.Name)
1203+
diffFile.IsVendored = isVendored.Value()
1204+
1205+
if !isGenerated.Has() {
1206+
isGenerated = optional.Some(analyze.IsGenerated(diffFile.Name))
12181207
}
1208+
diffFile.IsGenerated = isGenerated.Value()
12191209

12201210
tailSection := diffFile.GetTailSection(gitRepo, opts.BeforeCommitID, opts.AfterCommitID)
12211211
if tailSection != nil {

services/repository/files/content.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ func TryGetContentLanguage(gitRepo *git.Repository, commitID, treePath string) (
282282

283283
filename2attribute2info, err := gitRepo.CheckAttribute(git.CheckAttributeOpts{
284284
CachedOnly: true,
285-
Attributes: []string{"linguist-language", "gitlab-language"},
285+
Attributes: []string{git.AttributeLinguistLanguage, git.AttributeGitlabLanguage},
286286
Filenames: []string{treePath},
287287
IndexFile: indexFilename,
288288
WorkTree: worktree,
@@ -291,13 +291,7 @@ func TryGetContentLanguage(gitRepo *git.Repository, commitID, treePath string) (
291291
return "", err
292292
}
293293

294-
language := filename2attribute2info[treePath]["linguist-language"]
295-
if language == "" || language == "unspecified" {
296-
language = filename2attribute2info[treePath]["gitlab-language"]
297-
}
298-
if language == "unspecified" {
299-
language = ""
300-
}
294+
language := git.TryReadLanguageAttribute(filename2attribute2info[treePath])
301295

302-
return language, nil
296+
return language.Value(), nil
303297
}

0 commit comments

Comments
 (0)