Skip to content

Commit cdab85e

Browse files
committed
Now a path support multiple types of attributes
1 parent 61672d2 commit cdab85e

File tree

2 files changed

+82
-44
lines changed

2 files changed

+82
-44
lines changed

utils.go

Lines changed: 74 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"path/filepath"
1111
"regexp"
1212
"strings"
13+
14+
"gopkg.in/src-d/enry.v1/data"
1315
)
1416

1517
var (
@@ -28,10 +30,20 @@ var (
2830
"XML": true, "JSON": true, "TOML": true, "YAML": true, "INI": true, "SQL": true,
2931
}
3032

31-
gitattributes = map[string]bool{}
32-
languageGitattributes = map[*regexp.Regexp]string{}
33+
vendorGitattributes = map[string]bool{}
34+
documentationGitattributes = map[string]bool{}
35+
languageGitattributes = map[*regexp.Regexp]string{}
3336
)
3437

38+
type OverrideError struct {
39+
attribute string
40+
path string
41+
}
42+
43+
func (e *OverrideError) Error() string {
44+
return fmt.Sprintf(".gitattributes: You are overriding a %s attribute of one of your previous lines %s\n", e.attribute, e.path)
45+
}
46+
3547
// IsAuxiliaryLanguage returns whether or not lang is an auxiliary language.
3648
func IsAuxiliaryLanguage(lang string) bool {
3749
_, ok := auxiliaryLanguages[lang]
@@ -52,20 +64,20 @@ func IsDotFile(path string) bool {
5264

5365
// IsVendor returns whether or not path is a vendor path.
5466
func IsVendor(path string) bool {
55-
if val, ok := gitattributes[path]; ok {
67+
if val, ok := vendorGitattributes[path]; ok {
5668
return val
5769
}
5870

59-
return vendorMatchers.Match(path)
71+
return data.VendorMatchers.Match(path)
6072
}
6173

6274
// IsDocumentation returns whether or not path is a documentation path.
6375
func IsDocumentation(path string) bool {
64-
if val, ok := gitattributes[path]; ok {
76+
if val, ok := documentationGitattributes[path]; ok {
6577
return val
6678
}
6779

68-
return documentationMatchers.Match(path)
80+
return data.DocumentationMatchers.Match(path)
6981
}
7082

7183
const sniffLen = 8000
@@ -92,8 +104,8 @@ func LoadGitattributes() {
92104
}
93105
}
94106

95-
func loadRawGitattributes(name string) (map[string]string, error) {
96-
gitattributes := map[string]string{}
107+
func loadRawGitattributes(name string) (map[string][]string, error) {
108+
gitattributes := map[string][]string{}
97109
data, err := ioutil.ReadFile(name)
98110
if err != nil {
99111
if err != os.ErrNotExist {
@@ -113,54 +125,80 @@ func loadRawGitattributes(name string) (map[string]string, error) {
113125
return gitattributes, nil
114126
}
115127

116-
func loadLine(line string, gitattributes map[string]string) error {
128+
func loadLine(line string, gitattributes map[string][]string) error {
117129
tokens := strings.Fields(line)
118130
if len(tokens) == 2 {
119-
var err error
120-
if isInside(tokens[0], gitattributes) {
121-
err = errors.New(fmt.Sprintf(".gitattributes: You are overriding one of your previous lines %s\n", tokens[0]))
122-
log.Printf(err.Error())
123-
}
124131

125-
gitattributes[tokens[0]] = tokens[1]
126-
return err
127-
} else {
132+
gitattributes[tokens[0]] = append(gitattributes[tokens[0]], tokens[1])
133+
return nil
134+
} else if len(tokens) != 0 {
128135
err := errors.New(".gitattributes: Each line only can have a pair of elements E.g. path/to/file attribute")
129136
log.Println(err.Error())
130-
131137
return err
132138
}
139+
return nil
133140
}
134141

135-
func parseAttributes(attributes map[string]string) []error {
136-
var errArray []error
137-
for key, val := range attributes {
138-
switch {
139-
case val == "linguist-vendored" || val == "linguist-documentation":
140-
gitattributes[key] = true
141-
case val == "linguist-vendored=false" || val == "linguist-documentation=false":
142-
gitattributes[key] = false
143-
case strings.Contains(val, "linguist-language="):
144-
err := processLanguageAttr(key, val)
142+
func parseAttributes(attributes map[string][]string) []error {
143+
errArray := []error{}
144+
for key, values := range attributes {
145+
for _, val := range values {
146+
err := parseAttribute(key, val)
145147
if err != nil {
146148
errArray = append(errArray, err)
147149
}
148-
default:
149-
err := errors.New(fmt.Sprintf("gitattributes: The matcher %s doesn't exists\n", val))
150-
errArray = append(errArray, err)
151-
log.Printf(err.Error())
152150
}
153151
}
154152

155153
return errArray
156154
}
157155

158-
func isInside(key string, gitattributes map[string]string) bool {
159-
if _, ok := gitattributes[key]; ok {
160-
return ok
156+
func parseAttribute(key string, attribute string) error {
157+
var err error
158+
switch {
159+
case strings.Contains(attribute, "linguist-vendored"):
160+
err = processVendorAttr(key, attribute)
161+
case strings.Contains(attribute, "linguist-documentation"):
162+
err = processDocumentationAttr(key, attribute)
163+
case strings.Contains(attribute, "linguist-language="):
164+
err = processLanguageAttr(key, attribute)
165+
default:
166+
err = errors.New(fmt.Sprintf("gitattributes: The matcher %s doesn't exists\n", attribute))
167+
log.Printf(err.Error())
168+
}
169+
return err
170+
}
171+
172+
func processVendorAttr(key string, attribute string) error {
173+
var err error
174+
if _, ok := vendorGitattributes[key]; ok {
175+
err = &OverrideError{attribute: "vendor", path: key}
176+
}
177+
178+
switch {
179+
case attribute == "linguist-vendored":
180+
vendorGitattributes[key] = true
181+
case attribute == "linguist-vendored=false":
182+
vendorGitattributes[key] = false
183+
}
184+
185+
return err
186+
}
187+
188+
func processDocumentationAttr(key string, attribute string) error {
189+
var err error
190+
if _, ok := documentationGitattributes[key]; ok {
191+
err = &OverrideError{attribute: "documentation", path: key}
192+
}
193+
194+
switch {
195+
case attribute == "linguist-documentation":
196+
documentationGitattributes[key] = true
197+
case attribute == "linguist-documentation=false":
198+
documentationGitattributes[key] = false
161199
}
162200

163-
return false
201+
return err
164202
}
165203

166204
func processLanguageAttr(regExpString string, attribute string) error {

utils_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,13 @@ func (s *EnryTestSuite) TestLoadLine() {
8888
line string
8989
expected error
9090
}{
91-
{name: "TestLoadLine_1", line: "test/path/foo.file foo_attribute", expected: nil},
91+
{name: "TestLoadLine_1", line: "test/path/foo.file linguist-vendored", expected: nil},
9292
{name: "TestLoadLine_2", line: "test/path/foo.json foo_attribute foo_attribute2", expected: errors.New(".gitattributes: Each line only can have a pair of elements E.g. path/to/file attribute")},
93-
{name: "TestLoadLine_3", line: "test/path/ foo_attribute", expected: nil},
94-
{name: "TestLoadLine_4", line: "test/path/foo.file foo_attribute2", expected: errors.New(".gitattributes: You are overriding one of your previous lines test/path/foo.file\n")},
93+
{name: "TestLoadLine_3", line: "test/path/ linguist-documentation", expected: nil},
94+
{name: "TestLoadLine_4", line: "test/path/foo.file linguist-vendored=false", expected: nil},
9595
}
9696

97-
foo := map[string]string{}
97+
foo := map[string][]string{}
9898
for _, test := range tests {
9999
err := loadLine(test.line, foo)
100100
assert.Equal(s.T(), err, test.expected, fmt.Sprintf("%v: is = %v, expected: %v", test.name, err, test.expected))
@@ -104,12 +104,12 @@ func (s *EnryTestSuite) TestLoadLine() {
104104
func (s *EnryTestSuite) TestParseAttributes() {
105105
tests := []struct {
106106
name string
107-
attributes map[string]string
107+
attributes map[string][]string
108108
expected int
109109
}{
110-
{name: "TestParseAttributes_1", attributes: map[string]string{"test/path": "linguist-vendored", "test/hello": "linguist-documentation=false", ".*\\.java": "linguist-language=java"}, expected: 0},
111-
{name: "TestParseAttributes_2", attributes: map[string]string{"test/path": "linguist-fooAttribute"}, expected: 1},
112-
{name: "TestParseAttributes_3", attributes: map[string]string{"test/path/foo": "linguist-language=this=contains=equals"}, expected: 0},
110+
{name: "TestParseAttributes_1", attributes: map[string][]string{"test/path": []string{"linguist-vendored"}, "test/hello": []string{"linguist-documentation=false"}, ".*\\.java": []string{"linguist-language=java"}}, expected: 0},
111+
{name: "TestParseAttributes_2", attributes: map[string][]string{"test/path/duplicate": []string{"linguist-vendored", "linguist-vendored=false"}}, expected: 1},
112+
{name: "TestParseAttributes_3", attributes: map[string][]string{"test/path/foo": []string{"linguist-language=this=contains=equals"}}, expected: 0},
113113
}
114114

115115
for _, test := range tests {

0 commit comments

Comments
 (0)