| @@ -1,13 +1,115 @@ | |||
| package models | |||
| import "code.gitea.io/gitea/modules/git" | |||
| import ( | |||
| "fmt" | |||
| "strings" | |||
| "time" | |||
| "code.gitea.io/gitea/modules/git" | |||
| ) | |||
| func GetRepoKPIStats(repo *Repository) (*git.RepoKPIStats, error) { | |||
| wikiPath := "" | |||
| if repo.HasWiki() { | |||
| wikiPath = repo.WikiPath() | |||
| } | |||
| return git.GetRepoKPIStats(repo.RepoPath(), wikiPath) | |||
| return getRepoKPIStats(repo.RepoPath(), wikiPath) | |||
| } | |||
| func getRepoKPIStats(repoPath string, wikiPath string) (*git.RepoKPIStats, error) { | |||
| stats := &git.RepoKPIStats{} | |||
| contributors, err := git.GetContributors(repoPath) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| timeUntil := time.Now() | |||
| fourMonthAgo := timeUntil.AddDate(0, -4, 0) | |||
| recentlyContributors, err := git.GetContributorsDetail(repoPath, fourMonthAgo) | |||
| newContributersDict := make(map[string]struct{}) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| if contributors != nil { | |||
| contributorDistinctDict := make(map[string]int, 0) | |||
| keyContributorsDict := make(map[string]struct{}, 0) | |||
| for _, contributor := range contributors { | |||
| if strings.Compare(contributor.Email, "") == 0 { | |||
| continue | |||
| } | |||
| user, err := GetUserByActivateEmail(contributor.Email) | |||
| if err == nil { | |||
| value, ok := contributorDistinctDict[user.Email] | |||
| if !ok { | |||
| contributorDistinctDict[user.Email] = contributor.CommitCnt | |||
| } else { | |||
| contributorDistinctDict[user.Email] = value + contributor.CommitCnt | |||
| } | |||
| setKeyContributerDict(contributorDistinctDict, user.Email, keyContributorsDict) | |||
| } else { | |||
| value, ok := contributorDistinctDict[contributor.Email] | |||
| if !ok { | |||
| contributorDistinctDict[contributor.Email] = contributor.CommitCnt | |||
| } else { | |||
| contributorDistinctDict[contributor.Email] = value + contributor.CommitCnt | |||
| } | |||
| setKeyContributerDict(contributorDistinctDict, contributor.Email, keyContributorsDict) | |||
| } | |||
| } | |||
| if recentlyContributors != nil { | |||
| for _, recentlyContributor := range recentlyContributors { | |||
| user, err := GetUserByActivateEmail(recentlyContributor.Email) | |||
| var ok bool | |||
| if err == nil { | |||
| _, ok = contributorDistinctDict[user.Email] | |||
| } else { | |||
| _, ok = contributorDistinctDict[recentlyContributor.Email] | |||
| } | |||
| if !ok { | |||
| stats.ContributorsAdded++ | |||
| newContributersDict[recentlyContributor.Email] = struct{}{} | |||
| } | |||
| } | |||
| } | |||
| stats.Contributors = int64(len(contributorDistinctDict)) | |||
| stats.KeyContributors = int64(len(keyContributorsDict)) | |||
| } | |||
| err = git.SetDevelopAge(repoPath, stats) | |||
| if err != nil { | |||
| return nil, fmt.Errorf("FillFromGit: %v", err) | |||
| } | |||
| err = git.SetRepoKPIStats(repoPath, fourMonthAgo, stats, newContributersDict) | |||
| if err != nil { | |||
| return nil, fmt.Errorf("FillFromGit: %v", err) | |||
| } | |||
| git.SetWikiPages(wikiPath, stats) | |||
| return stats, nil | |||
| } | |||
| func setKeyContributerDict(contributorDistinctDict map[string]int, email string, keyContributorsDict map[string]struct{}) { | |||
| if contributorDistinctDict[email] >= 3 { | |||
| _, ok := keyContributorsDict[email] | |||
| if !ok { | |||
| keyContributorsDict[email] = struct{}{} | |||
| } | |||
| } | |||
| } | |||
| func GetAllUserKPIStats() (map[string]*git.UserKPIStats, error) { | |||
| @@ -35,58 +35,7 @@ type UserKPITypeStats struct { | |||
| isNewContributor bool //是否是4个月内的新增贡献者 | |||
| } | |||
| func GetRepoKPIStats(repoPath string, wikiPath string) (*RepoKPIStats, error) { | |||
| stats := &RepoKPIStats{} | |||
| contributors, err := GetContributors(repoPath) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| timeUntil := time.Now() | |||
| fourMonthAgo := timeUntil.AddDate(0, -4, 0) | |||
| recentlyContributors, err := getContributors(repoPath, fourMonthAgo) | |||
| newContributersDict := make(map[string]struct{}) | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| if contributors != nil { | |||
| stats.Contributors = int64(len(contributors)) | |||
| for _, contributor := range contributors { | |||
| if contributor.CommitCnt >= 3 { | |||
| stats.KeyContributors++ | |||
| } | |||
| if recentlyContributors != nil { | |||
| for _, recentlyContributor := range recentlyContributors { | |||
| if recentlyContributor.Email == contributor.Email && recentlyContributor.CommitCnt == contributor.CommitCnt { | |||
| stats.ContributorsAdded++ | |||
| newContributersDict[recentlyContributor.Email] = struct{}{} | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| err = setDevelopAge(repoPath, stats) | |||
| if err != nil { | |||
| return nil, fmt.Errorf("FillFromGit: %v", err) | |||
| } | |||
| err = setRepoKPIStats(repoPath, fourMonthAgo, stats, newContributersDict) | |||
| if err != nil { | |||
| return nil, fmt.Errorf("FillFromGit: %v", err) | |||
| } | |||
| setWikiPages(wikiPath, stats) | |||
| return stats, nil | |||
| } | |||
| func setDevelopAge(repoPath string, stats *RepoKPIStats) error { | |||
| func SetDevelopAge(repoPath string, stats *RepoKPIStats) error { | |||
| args := []string{"log", "--no-merges", "--branches=*", "--format=%cd", "--date=short"} | |||
| stdout, err := NewCommand(args...).RunInDirBytes(repoPath) | |||
| if err != nil { | |||
| @@ -173,7 +122,7 @@ func GetUserKPIStats(repoPath string) (map[string]*UserKPIStats, error) { | |||
| } | |||
| func setRepoKPIStats(repoPath string, fromTime time.Time, stats *RepoKPIStats, newContributers map[string]struct{}) error { | |||
| func SetRepoKPIStats(repoPath string, fromTime time.Time, stats *RepoKPIStats, newContributers map[string]struct{}) error { | |||
| since := fromTime.Format(time.RFC3339) | |||
| args := []string{"log", "--numstat", "--no-merges", "--branches=*", "--pretty=format:---%n%h%n%an%n%ae%n", "--date=iso", fmt.Sprintf("--since='%s'", since)} | |||
| @@ -259,7 +208,7 @@ func setRepoKPIStats(repoPath string, fromTime time.Time, stats *RepoKPIStats, n | |||
| } | |||
| func getContributors(repoPath string, fromTime time.Time) ([]Contributor, error) { | |||
| func GetContributorsDetail(repoPath string, fromTime time.Time) ([]Contributor, error) { | |||
| since := fromTime.Format(time.RFC3339) | |||
| cmd := NewCommand("shortlog", "-sne", "--all", fmt.Sprintf("--since='%s'", since)) | |||
| stdout, err := cmd.RunInDir(repoPath) | |||
| @@ -289,7 +238,7 @@ func getContributors(repoPath string, fromTime time.Time) ([]Contributor, error) | |||
| return nil, nil | |||
| } | |||
| func setWikiPages(wikiPath string, stats *RepoKPIStats) { | |||
| func SetWikiPages(wikiPath string, stats *RepoKPIStats) { | |||
| wikiPages := 0 | |||
| if wikiPath == "" { | |||