summaryrefslogtreecommitdiffstats
path: root/models/repo_language_stats.go
diff options
context:
space:
mode:
Diffstat (limited to 'models/repo_language_stats.go')
-rw-r--r--models/repo_language_stats.go100
1 files changed, 82 insertions, 18 deletions
diff --git a/models/repo_language_stats.go b/models/repo_language_stats.go
index 5f1aed1f30..d08782eaf8 100644
--- a/models/repo_language_stats.go
+++ b/models/repo_language_stats.go
@@ -20,11 +20,28 @@ type LanguageStat struct {
CommitID string
IsPrimary bool
Language string `xorm:"VARCHAR(30) UNIQUE(s) INDEX NOT NULL"`
- Percentage float32 `xorm:"NUMERIC(5,2) NOT NULL DEFAULT 0"`
+ Percentage float32 `xorm:"-"`
+ Size int64 `xorm:"NOT NULL DEFAULT 0"`
Color string `xorm:"-"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
}
+// specialLanguages defines list of languages that are excluded from the calculation
+// unless they are the only language present in repository. Only languages which under
+// normal circumstances are not considered to be code should be listed here.
+var specialLanguages = map[string]struct{}{
+ "XML": {},
+ "JSON": {},
+ "TOML": {},
+ "YAML": {},
+ "INI": {},
+ "SQL": {},
+ "SVG": {},
+ "Text": {},
+ "Markdown": {},
+ "other": {},
+}
+
// LanguageStatList defines a list of language statistics
type LanguageStatList []*LanguageStat
@@ -34,12 +51,53 @@ func (stats LanguageStatList) loadAttributes() {
}
}
+func (stats LanguageStatList) getLanguagePercentages() map[string]float32 {
+ langPerc := make(map[string]float32)
+ var otherPerc float32 = 100
+ var total int64
+ // Check that repository has at least one non-special language
+ var skipSpecial bool
+ for _, stat := range stats {
+ if _, ok := specialLanguages[stat.Language]; !ok {
+ skipSpecial = true
+ break
+ }
+ }
+ for _, stat := range stats {
+ // Exclude specific languages from percentage calculation
+ if _, ok := specialLanguages[stat.Language]; ok && skipSpecial {
+ continue
+ }
+ total += stat.Size
+ }
+ if total > 0 {
+ for _, stat := range stats {
+ // Exclude specific languages from percentage calculation
+ if _, ok := specialLanguages[stat.Language]; ok && skipSpecial {
+ continue
+ }
+ perc := float32(math.Round(float64(stat.Size)/float64(total)*1000) / 10)
+ if perc <= 0.1 {
+ continue
+ }
+ otherPerc -= perc
+ langPerc[stat.Language] = perc
+ }
+ otherPerc = float32(math.Round(float64(otherPerc)*10) / 10)
+ } else {
+ otherPerc = 100
+ }
+ if otherPerc > 0 {
+ langPerc["other"] = otherPerc
+ }
+ return langPerc
+}
+
func (repo *Repository) getLanguageStats(e Engine) (LanguageStatList, error) {
stats := make(LanguageStatList, 0, 6)
- if err := e.Where("`repo_id` = ?", repo.ID).Desc("`percentage`").Find(&stats); err != nil {
+ if err := e.Where("`repo_id` = ?", repo.ID).Desc("`size`").Find(&stats); err != nil {
return nil, err
}
- stats.loadAttributes()
return stats, nil
}
@@ -54,13 +112,18 @@ func (repo *Repository) GetTopLanguageStats(limit int) (LanguageStatList, error)
if err != nil {
return nil, err
}
+ perc := stats.getLanguagePercentages()
topstats := make(LanguageStatList, 0, limit)
var other float32
for i := range stats {
+ if _, ok := perc[stats[i].Language]; !ok {
+ continue
+ }
if stats[i].Language == "other" || len(topstats) >= limit {
- other += stats[i].Percentage
+ other += perc[stats[i].Language]
continue
}
+ stats[i].Percentage = perc[stats[i].Language]
topstats = append(topstats, stats[i])
}
if other > 0 {
@@ -71,11 +134,12 @@ func (repo *Repository) GetTopLanguageStats(limit int) (LanguageStatList, error)
Percentage: float32(math.Round(float64(other)*10) / 10),
})
}
+ topstats.loadAttributes()
return topstats, nil
}
// UpdateLanguageStats updates the language statistics for repository
-func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]float32) error {
+func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]int64) error {
sess := x.NewSession()
if err := sess.Begin(); err != nil {
return err
@@ -87,15 +151,15 @@ func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]fl
return err
}
var topLang string
- var p float32
- for lang, perc := range stats {
- if perc > p {
- p = perc
+ var s int64
+ for lang, size := range stats {
+ if size > s {
+ s = size
topLang = strings.ToLower(lang)
}
}
- for lang, perc := range stats {
+ for lang, size := range stats {
upd := false
llang := strings.ToLower(lang)
for _, s := range oldstats {
@@ -103,8 +167,8 @@ func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]fl
if strings.ToLower(s.Language) == llang {
s.CommitID = commitID
s.IsPrimary = llang == topLang
- s.Percentage = perc
- if _, err := sess.ID(s.ID).Cols("`commit_id`", "`percentage`", "`is_primary`").Update(s); err != nil {
+ s.Size = size
+ if _, err := sess.ID(s.ID).Cols("`commit_id`", "`size`", "`is_primary`").Update(s); err != nil {
return err
}
upd = true
@@ -114,11 +178,11 @@ func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]fl
// Insert new language
if !upd {
if _, err := sess.Insert(&LanguageStat{
- RepoID: repo.ID,
- CommitID: commitID,
- IsPrimary: llang == topLang,
- Language: lang,
- Percentage: perc,
+ RepoID: repo.ID,
+ CommitID: commitID,
+ IsPrimary: llang == topLang,
+ Language: lang,
+ Size: size,
}); err != nil {
return err
}
@@ -153,7 +217,7 @@ func CopyLanguageStat(originalRepo, destRepo *Repository) error {
return err
}
RepoLang := make(LanguageStatList, 0, 6)
- if err := sess.Where("`repo_id` = ?", originalRepo.ID).Desc("`percentage`").Find(&RepoLang); err != nil {
+ if err := sess.Where("`repo_id` = ?", originalRepo.ID).Desc("`size`").Find(&RepoLang); err != nil {
return err
}
if len(RepoLang) > 0 {