Skip to content

Commit 1d33329

Browse files
committed
don't make Attributes expose internal map
1 parent ad4af2d commit 1d33329

File tree

8 files changed

+61
-62
lines changed

8 files changed

+61
-62
lines changed

modules/git/attribute/attribute.go

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const (
1919
LinguistLanguage = "linguist-language"
2020
GitlabLanguage = "gitlab-language"
2121
Lockable = "lockable"
22+
Filter = "filter"
2223
)
2324

2425
var LinguistAttributes = []string{
@@ -41,7 +42,7 @@ func (a Attribute) ToString() optional.Option[string] {
4142
return optional.None[string]()
4243
}
4344

44-
// true if "set"/"true", false if "unset"/"false", none otherwise
45+
// ToBool converts the attribute value to optional boolean: true if "set"/"true", false if "unset"/"false", none otherwise
4546
func (a Attribute) ToBool() optional.Option[bool] {
4647
switch a {
4748
case "set", "true":
@@ -52,36 +53,42 @@ func (a Attribute) ToBool() optional.Option[bool] {
5253
return optional.None[bool]()
5354
}
5455

55-
type Attributes map[string]Attribute
56+
type Attributes struct {
57+
m map[string]Attribute
58+
}
59+
60+
func NewAttributes() *Attributes {
61+
return &Attributes{m: make(map[string]Attribute)}
62+
}
5663

57-
func (attrs Attributes) Get(name string) Attribute {
58-
if value, has := attrs[name]; has {
64+
func (attrs *Attributes) Get(name string) Attribute {
65+
if value, has := attrs.m[name]; has {
5966
return value
6067
}
6168
return ""
6269
}
6370

64-
func (attrs Attributes) GetVendored() optional.Option[bool] {
71+
func (attrs *Attributes) GetVendored() optional.Option[bool] {
6572
return attrs.Get(LinguistVendored).ToBool()
6673
}
6774

68-
func (attrs Attributes) GetGenerated() optional.Option[bool] {
75+
func (attrs *Attributes) GetGenerated() optional.Option[bool] {
6976
return attrs.Get(LinguistGenerated).ToBool()
7077
}
7178

72-
func (attrs Attributes) GetDocumentation() optional.Option[bool] {
79+
func (attrs *Attributes) GetDocumentation() optional.Option[bool] {
7380
return attrs.Get(LinguistDocumentation).ToBool()
7481
}
7582

76-
func (attrs Attributes) GetDetectable() optional.Option[bool] {
83+
func (attrs *Attributes) GetDetectable() optional.Option[bool] {
7784
return attrs.Get(LinguistDetectable).ToBool()
7885
}
7986

80-
func (attrs Attributes) GetLinguistLanguage() optional.Option[string] {
87+
func (attrs *Attributes) GetLinguistLanguage() optional.Option[string] {
8188
return attrs.Get(LinguistLanguage).ToString()
8289
}
8390

84-
func (attrs Attributes) GetGitlabLanguage() optional.Option[string] {
91+
func (attrs *Attributes) GetGitlabLanguage() optional.Option[string] {
8592
attrStr := attrs.Get(GitlabLanguage).ToString()
8693
if attrStr.Has() {
8794
raw := attrStr.Value()
@@ -95,7 +102,7 @@ func (attrs Attributes) GetGitlabLanguage() optional.Option[string] {
95102
return attrStr
96103
}
97104

98-
func (attrs Attributes) GetLanguage() optional.Option[string] {
105+
func (attrs *Attributes) GetLanguage() optional.Option[string] {
99106
// prefer linguist-language over gitlab-language
100107
// if linguist-language is not set, use gitlab-language
101108
// if both are not set, return none

modules/git/attribute/attribute_test.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ func Test_Attribute(t *testing.T) {
1616
assert.Equal(t, "Java", Attribute("Java").ToString().Value())
1717

1818
attributes := Attributes{
19-
LinguistGenerated: "true",
20-
LinguistDocumentation: "false",
21-
LinguistDetectable: "set",
22-
LinguistLanguage: "Python",
23-
GitlabLanguage: "Java",
24-
"filter": "unspecified",
25-
"test": "",
19+
m: map[string]Attribute{
20+
LinguistGenerated: "true",
21+
LinguistDocumentation: "false",
22+
LinguistDetectable: "set",
23+
LinguistLanguage: "Python",
24+
GitlabLanguage: "Java",
25+
"filter": "unspecified",
26+
"test": "",
27+
},
2628
}
2729

2830
assert.Empty(t, attributes.Get("test").ToString().Value())

modules/git/attribute/batch.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func NewBatchChecker(repo *git.Repository, treeish string, attributes []string)
9494
}
9595

9696
// CheckPath check attr for given path
97-
func (c *BatchChecker) CheckPath(path string) (rs Attributes, err error) {
97+
func (c *BatchChecker) CheckPath(path string) (rs *Attributes, err error) {
9898
defer func() {
9999
if err != nil && err != c.ctx.Err() {
100100
log.Error("Unexpected error when checking path %s in %s, error: %v", path, filepath.Base(c.repo.Path), err)
@@ -128,7 +128,7 @@ func (c *BatchChecker) CheckPath(path string) (rs Attributes, err error) {
128128
return fmt.Errorf("CheckPath timeout: %s", debugMsg)
129129
}
130130

131-
rs = make(map[string]Attribute)
131+
rs = NewAttributes()
132132
for i := 0; i < c.attributesNum; i++ {
133133
select {
134134
case <-time.After(5 * time.Second):
@@ -138,7 +138,7 @@ func (c *BatchChecker) CheckPath(path string) (rs Attributes, err error) {
138138
if !ok {
139139
return nil, c.ctx.Err()
140140
}
141-
rs[attr.Attribute] = Attribute(attr.Value)
141+
rs.m[attr.Attribute] = Attribute(attr.Value)
142142
case <-c.ctx.Done():
143143
return nil, c.ctx.Err()
144144
}

modules/git/attribute/checker.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ type CheckAttributeOpts struct {
5555

5656
// CheckAttributes return the attributes of the given filenames and attributes in the given treeish.
5757
// If treeish is empty, then it will use current working directory, otherwise it will use the provided treeish on the bare repo
58-
func CheckAttributes(ctx context.Context, gitRepo *git.Repository, treeish string, opts CheckAttributeOpts) (map[string]Attributes, error) {
58+
func CheckAttributes(ctx context.Context, gitRepo *git.Repository, treeish string, opts CheckAttributeOpts) (map[string]*Attributes, error) {
5959
cmd, envs, cancel, err := checkAttrCommand(gitRepo, treeish, opts.Filenames, opts.Attributes)
6060
if err != nil {
6161
return nil, err
@@ -79,17 +79,17 @@ func CheckAttributes(ctx context.Context, gitRepo *git.Repository, treeish strin
7979
return nil, errors.New("wrong number of fields in return from check-attr")
8080
}
8181

82-
attributesMap := make(map[string]Attributes)
82+
attributesMap := make(map[string]*Attributes)
8383
for i := 0; i < (len(fields) / 3); i++ {
8484
filename := string(fields[3*i])
8585
attribute := string(fields[3*i+1])
8686
info := string(fields[3*i+2])
87-
attribute2info := attributesMap[filename]
88-
if attribute2info == nil {
89-
attribute2info = make(Attributes)
87+
attribute2info, ok := attributesMap[filename]
88+
if !ok {
89+
attribute2info = NewAttributes()
90+
attributesMap[filename] = attribute2info
9091
}
91-
attribute2info[attribute] = Attribute(info)
92-
attributesMap[filename] = attribute2info
92+
attribute2info.m[attribute] = Attribute(info)
9393
}
9494

9595
return attributesMap, nil

routers/web/repo/setting/lfs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ func LFSLocks(ctx *context.Context) {
152152
log.Error("Unable to check attributes in %s: %s (%v)", tmpBasePath, lock.Path, err)
153153
continue
154154
}
155-
lockables[i] = attrs["lockable"].ToBool().Value()
155+
lockables[i] = attrs.Get(attribute.Lockable).ToBool().Value()
156156
}
157157
ctx.Data["Lockables"] = lockables
158158

routers/web/repo/view_file.go

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,22 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) {
147147
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_non_text_files")
148148
}
149149

150-
var attrs attribute.Attributes
151-
attributes := []string{attribute.LinguistGenerated, attribute.LinguistVendored}
150+
// read all needed attributes which will be used later
151+
// there should be no performance different between reading 2 or 4 here
152+
attrsMap, err := attribute.CheckAttributes(ctx, ctx.Repo.GitRepo, ctx.Repo.CommitID, attribute.CheckAttributeOpts{
153+
Filenames: []string{ctx.Repo.TreePath},
154+
Attributes: []string{attribute.LinguistGenerated, attribute.LinguistVendored, attribute.LinguistLanguage, attribute.GitlabLanguage},
155+
})
156+
if err != nil {
157+
ctx.ServerError("attribute.CheckAttributes", err)
158+
return
159+
}
160+
attrs := attrsMap[ctx.Repo.TreePath]
161+
if attrs == nil {
162+
// this case shouldn't happe, just in case.
163+
setting.PanicInDevOrTesting("no attributes found for %s", ctx.Repo.TreePath)
164+
attrs = attribute.NewAttributes()
165+
}
152166

153167
switch {
154168
case isRepresentableAsText:
@@ -212,19 +226,7 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) {
212226
ctx.Data["NumLines"] = bytes.Count(buf, []byte{'\n'}) + 1
213227
}
214228

215-
var language string
216-
attributes = append(attributes, attribute.LinguistLanguage, attribute.GitlabLanguage)
217-
attrsMap, err := attribute.CheckAttributes(ctx, ctx.Repo.GitRepo, ctx.Repo.CommitID, attribute.CheckAttributeOpts{
218-
Filenames: []string{ctx.Repo.TreePath},
219-
Attributes: attributes,
220-
})
221-
if err != nil {
222-
log.Error("Unable to get file language for %-v:%s. Error: %v", ctx.Repo.Repository, ctx.Repo.TreePath, err)
223-
} else {
224-
attrs = attrsMap[ctx.Repo.TreePath] // then it will be reused out of the switch block
225-
language = attrs.GetLanguage().Value()
226-
}
227-
229+
language := attrs.GetLanguage().Value()
228230
fileContent, lexerName, err := highlight.File(blob.Name(), language, buf)
229231
ctx.Data["LexerName"] = lexerName
230232
if err != nil {
@@ -294,18 +296,6 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) {
294296
}
295297
}
296298

297-
if attrs == nil {
298-
attrsMap, err := attribute.CheckAttributes(ctx, ctx.Repo.GitRepo, ctx.Repo.CommitID, attribute.CheckAttributeOpts{
299-
Filenames: []string{ctx.Repo.TreePath},
300-
Attributes: attributes,
301-
})
302-
if err != nil {
303-
ctx.ServerError("attribute.CheckAttributes", err)
304-
return
305-
}
306-
attrs = attrsMap[ctx.Repo.TreePath]
307-
}
308-
309299
ctx.Data["IsVendored"], ctx.Data["IsGenerated"] = attrs.GetVendored().Value(), attrs.GetGenerated().Value()
310300

311301
if fInfo.st.IsImage() && !fInfo.st.IsSvgImage() {

services/repository/files/update.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -490,14 +490,14 @@ func CreateOrUpdateFile(ctx context.Context, t *TemporaryUploadRepository, file
490490
if setting.LFS.StartServer && hasOldBranch {
491491
// Check there is no way this can return multiple infos
492492
attributesMap, err := attribute.CheckAttributes(ctx, t.gitRepo, "" /* use temp repo's working dir */, attribute.CheckAttributeOpts{
493-
Attributes: []string{"filter"},
493+
Attributes: []string{attribute.Filter},
494494
Filenames: []string{file.Options.treePath},
495495
})
496496
if err != nil {
497497
return err
498498
}
499499

500-
if attributesMap[file.Options.treePath] != nil && attributesMap[file.Options.treePath]["filter"] == "lfs" {
500+
if attributesMap[file.Options.treePath] != nil && attributesMap[file.Options.treePath].Get(attribute.Filter).ToString().Value() == "lfs" {
501501
// OK so we are supposed to LFS this data!
502502
pointer, err := lfs.GeneratePointer(treeObjectContentReader)
503503
if err != nil {

services/repository/files/upload.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,10 @@ func UploadRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
106106
}
107107
}
108108

109-
var attributesMap map[string]attribute.Attributes
109+
var attributesMap map[string]*attribute.Attributes
110110
if setting.LFS.StartServer {
111111
attributesMap, err = attribute.CheckAttributes(ctx, t.gitRepo, "" /* use temp repo's working dir */, attribute.CheckAttributeOpts{
112-
Attributes: []string{"filter"},
112+
Attributes: []string{attribute.Filter},
113113
Filenames: names,
114114
})
115115
if err != nil {
@@ -176,15 +176,15 @@ func UploadRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
176176
return repo_model.DeleteUploads(ctx, uploads...)
177177
}
178178

179-
func copyUploadedLFSFileIntoRepository(ctx context.Context, info *uploadInfo, attributesMap map[string]attribute.Attributes, t *TemporaryUploadRepository, treePath string) error {
179+
func copyUploadedLFSFileIntoRepository(ctx context.Context, info *uploadInfo, attributesMap map[string]*attribute.Attributes, t *TemporaryUploadRepository, treePath string) error {
180180
file, err := os.Open(info.upload.LocalPath())
181181
if err != nil {
182182
return err
183183
}
184184
defer file.Close()
185185

186186
var objectHash string
187-
if setting.LFS.StartServer && attributesMap[info.upload.Name] != nil && attributesMap[info.upload.Name]["filter"] == "lfs" {
187+
if setting.LFS.StartServer && attributesMap[info.upload.Name] != nil && attributesMap[info.upload.Name].Get(attribute.Filter).ToString().Value() == "lfs" {
188188
// Handle LFS
189189
// FIXME: Inefficient! this should probably happen in models.Upload
190190
pointer, err := lfs.GeneratePointer(file)

0 commit comments

Comments
 (0)