@@ -20,11 +20,28 @@ type LanguageStat struct {
20
20
CommitID string
21
21
IsPrimary bool
22
22
Language string `xorm:"VARCHAR(30) UNIQUE(s) INDEX NOT NULL"`
23
- Percentage float32 `xorm:"NUMERIC(5,2) NOT NULL DEFAULT 0"`
23
+ Percentage float32 `xorm:"-"`
24
+ Size int64 `xorm:"NOT NULL DEFAULT 0"`
24
25
Color string `xorm:"-"`
25
26
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
26
27
}
27
28
29
+ // specialLanguages defines list of languages that are excluded from the calculation
30
+ // unless they are the only language present in repository. Only languages which under
31
+ // normal circumstances are not considered to be code should be listed here.
32
+ var specialLanguages = map [string ]struct {}{
33
+ "XML" : {},
34
+ "JSON" : {},
35
+ "TOML" : {},
36
+ "YAML" : {},
37
+ "INI" : {},
38
+ "SQL" : {},
39
+ "SVG" : {},
40
+ "Text" : {},
41
+ "Markdown" : {},
42
+ "other" : {},
43
+ }
44
+
28
45
// LanguageStatList defines a list of language statistics
29
46
type LanguageStatList []* LanguageStat
30
47
@@ -34,12 +51,53 @@ func (stats LanguageStatList) loadAttributes() {
34
51
}
35
52
}
36
53
54
+ func (stats LanguageStatList ) getLanguagePercentages () map [string ]float32 {
55
+ langPerc := make (map [string ]float32 )
56
+ var otherPerc float32 = 100
57
+ var total int64
58
+ // Check that repository has at least one non-special language
59
+ var skipSpecial bool
60
+ for _ , stat := range stats {
61
+ if _ , ok := specialLanguages [stat .Language ]; ! ok {
62
+ skipSpecial = true
63
+ break
64
+ }
65
+ }
66
+ for _ , stat := range stats {
67
+ // Exclude specific languages from percentage calculation
68
+ if _ , ok := specialLanguages [stat .Language ]; ok && skipSpecial {
69
+ continue
70
+ }
71
+ total += stat .Size
72
+ }
73
+ if total > 0 {
74
+ for _ , stat := range stats {
75
+ // Exclude specific languages from percentage calculation
76
+ if _ , ok := specialLanguages [stat .Language ]; ok && skipSpecial {
77
+ continue
78
+ }
79
+ perc := float32 (math .Round (float64 (stat .Size )/ float64 (total )* 1000 ) / 10 )
80
+ if perc <= 0.1 {
81
+ continue
82
+ }
83
+ otherPerc -= perc
84
+ langPerc [stat .Language ] = perc
85
+ }
86
+ otherPerc = float32 (math .Round (float64 (otherPerc )* 10 ) / 10 )
87
+ } else {
88
+ otherPerc = 100
89
+ }
90
+ if otherPerc > 0 {
91
+ langPerc ["other" ] = otherPerc
92
+ }
93
+ return langPerc
94
+ }
95
+
37
96
func (repo * Repository ) getLanguageStats (e Engine ) (LanguageStatList , error ) {
38
97
stats := make (LanguageStatList , 0 , 6 )
39
- if err := e .Where ("`repo_id` = ?" , repo .ID ).Desc ("`percentage `" ).Find (& stats ); err != nil {
98
+ if err := e .Where ("`repo_id` = ?" , repo .ID ).Desc ("`size `" ).Find (& stats ); err != nil {
40
99
return nil , err
41
100
}
42
- stats .loadAttributes ()
43
101
return stats , nil
44
102
}
45
103
@@ -54,13 +112,18 @@ func (repo *Repository) GetTopLanguageStats(limit int) (LanguageStatList, error)
54
112
if err != nil {
55
113
return nil , err
56
114
}
115
+ perc := stats .getLanguagePercentages ()
57
116
topstats := make (LanguageStatList , 0 , limit )
58
117
var other float32
59
118
for i := range stats {
119
+ if _ , ok := perc [stats [i ].Language ]; ! ok {
120
+ continue
121
+ }
60
122
if stats [i ].Language == "other" || len (topstats ) >= limit {
61
- other += stats [i ].Percentage
123
+ other += perc [ stats [i ].Language ]
62
124
continue
63
125
}
126
+ stats [i ].Percentage = perc [stats [i ].Language ]
64
127
topstats = append (topstats , stats [i ])
65
128
}
66
129
if other > 0 {
@@ -71,11 +134,12 @@ func (repo *Repository) GetTopLanguageStats(limit int) (LanguageStatList, error)
71
134
Percentage : float32 (math .Round (float64 (other )* 10 ) / 10 ),
72
135
})
73
136
}
137
+ topstats .loadAttributes ()
74
138
return topstats , nil
75
139
}
76
140
77
141
// UpdateLanguageStats updates the language statistics for repository
78
- func (repo * Repository ) UpdateLanguageStats (commitID string , stats map [string ]float32 ) error {
142
+ func (repo * Repository ) UpdateLanguageStats (commitID string , stats map [string ]int64 ) error {
79
143
sess := x .NewSession ()
80
144
if err := sess .Begin (); err != nil {
81
145
return err
@@ -87,24 +151,24 @@ func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]fl
87
151
return err
88
152
}
89
153
var topLang string
90
- var p float32
91
- for lang , perc := range stats {
92
- if perc > p {
93
- p = perc
154
+ var s int64
155
+ for lang , size := range stats {
156
+ if size > s {
157
+ s = size
94
158
topLang = strings .ToLower (lang )
95
159
}
96
160
}
97
161
98
- for lang , perc := range stats {
162
+ for lang , size := range stats {
99
163
upd := false
100
164
llang := strings .ToLower (lang )
101
165
for _ , s := range oldstats {
102
166
// Update already existing language
103
167
if strings .ToLower (s .Language ) == llang {
104
168
s .CommitID = commitID
105
169
s .IsPrimary = llang == topLang
106
- s .Percentage = perc
107
- if _ , err := sess .ID (s .ID ).Cols ("`commit_id`" , "`percentage `" , "`is_primary`" ).Update (s ); err != nil {
170
+ s .Size = size
171
+ if _ , err := sess .ID (s .ID ).Cols ("`commit_id`" , "`size `" , "`is_primary`" ).Update (s ); err != nil {
108
172
return err
109
173
}
110
174
upd = true
@@ -114,11 +178,11 @@ func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]fl
114
178
// Insert new language
115
179
if ! upd {
116
180
if _ , err := sess .Insert (& LanguageStat {
117
- RepoID : repo .ID ,
118
- CommitID : commitID ,
119
- IsPrimary : llang == topLang ,
120
- Language : lang ,
121
- Percentage : perc ,
181
+ RepoID : repo .ID ,
182
+ CommitID : commitID ,
183
+ IsPrimary : llang == topLang ,
184
+ Language : lang ,
185
+ Size : size ,
122
186
}); err != nil {
123
187
return err
124
188
}
@@ -153,7 +217,7 @@ func CopyLanguageStat(originalRepo, destRepo *Repository) error {
153
217
return err
154
218
}
155
219
RepoLang := make (LanguageStatList , 0 , 6 )
156
- if err := sess .Where ("`repo_id` = ?" , originalRepo .ID ).Desc ("`percentage `" ).Find (& RepoLang ); err != nil {
220
+ if err := sess .Where ("`repo_id` = ?" , originalRepo .ID ).Desc ("`size `" ).Find (& RepoLang ); err != nil {
157
221
return err
158
222
}
159
223
if len (RepoLang ) > 0 {
0 commit comments