mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-06-23 09:30:50 +00:00
Change language statistics to save size instead of percentage (#11681)
* Change language statistics to save size instead of percentage in database Co-Authored-By: Cirno the Strongest <1447794+CirnoT@users.noreply.github.com> * Do not exclude if only language * Fix edge cases with special langauges Co-authored-by: Cirno the Strongest <1447794+CirnoT@users.noreply.github.com>
This commit is contained in:
parent
4395c607ed
commit
ea4c139cd2
5 changed files with 150 additions and 38 deletions
|
@ -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 stats[i].Language == "other" || len(topstats) >= limit {
|
||||
other += stats[i].Percentage
|
||||
if _, ok := perc[stats[i].Language]; !ok {
|
||||
continue
|
||||
}
|
||||
if stats[i].Language == "other" || len(topstats) >= limit {
|
||||
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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue