package models import ( "fmt" "sort" "strings" "time" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/git" ) type ContributorWithUserId struct { git.Contributor UserId int64 IsAdmin bool RelAvatarLink string } func GetRepoKPIStats(repo *Repository) (*git.RepoKPIStats, error) { wikiPath := "" if repo.HasWiki() { wikiPath = repo.WikiPath() } repoCreated := time.Unix(int64(repo.CreatedUnix), 0) return getRepoKPIStats(repo.RepoPath(), repoCreated, wikiPath) } func getRepoKPIStats(repoPath string, repoCreated time.Time, wikiPath string) (*git.RepoKPIStats, error) { stats := &git.RepoKPIStats{} contributors, err := git.GetContributorsDetail(repoPath, repoCreated) if err != nil { return nil, err } timeUntil := time.Now() fourMonthAgo := timeUntil.AddDate(0, -4, 0) if fourMonthAgo.Before(repoCreated) { fourMonthAgo = repoCreated } 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) var commitsCount int64 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) } commitsCount += int64(contributor.CommitCnt) } if recentlyContributors != nil { resentlyContributorDistinctDict := make(map[string]int, 0) for _, recentlyContributor := range recentlyContributors { user, err := GetUserByActivateEmail(recentlyContributor.Email) if err == nil { value, ok := resentlyContributorDistinctDict[user.Email] if !ok { resentlyContributorDistinctDict[user.Email] = recentlyContributor.CommitCnt } else { resentlyContributorDistinctDict[user.Email] = value + recentlyContributor.CommitCnt } } else { value, ok := resentlyContributorDistinctDict[recentlyContributor.Email] if !ok { resentlyContributorDistinctDict[recentlyContributor.Email] = recentlyContributor.CommitCnt } else { resentlyContributorDistinctDict[recentlyContributor.Email] = value + recentlyContributor.CommitCnt } } } for k, v := range resentlyContributorDistinctDict { count, ok := contributorDistinctDict[k] if ok && count == v { stats.ContributorsAdded++ } } } stats.Contributors = int64(len(contributorDistinctDict)) stats.KeyContributors = int64(len(keyContributorsDict)) stats.Commits = int64(commitsCount) } err = git.SetDevelopAge(repoPath, stats, repoCreated) 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 GetTop10Contributor(repoPath string) ([]*ContributorWithUserId, error) { contributors, err := git.GetContributors(repoPath) if err != nil { return make([]*ContributorWithUserId, 0), err } contributorDistinctDict := make(map[string]*ContributorWithUserId, 0) if contributors != nil { 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] = &ContributorWithUserId{ git.Contributor{ contributor.CommitCnt, user.Name, user.Email, }, user.ID, user.IsAdmin, user.RelAvatarLink(), } } else { value.CommitCnt += contributor.CommitCnt } } else { value, ok := contributorDistinctDict[contributor.Email] if !ok { contributorDistinctDict[contributor.Email] = &ContributorWithUserId{ contributor, -1, false, "", } } else { value.CommitCnt += contributor.CommitCnt } } } v := make([]*ContributorWithUserId, 0, len(contributorDistinctDict)) for _, value := range contributorDistinctDict { v = append(v, value) } sort.Slice(v, func(i, j int) bool { return v[i].CommitCnt > v[j].CommitCnt }) if len(v) <= 10 { return v, nil } else { return v[0:10], nil } } return make([]*ContributorWithUserId, 0), 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 GetAllUserPublicRepoKPIStats(startTime time.Time, endTime time.Time) (map[string]*git.UserKPIStats, error) { authors := make(map[string]*git.UserKPIStats) repositorys, err := GetAllRepositoriesByFilterCols("owner_name", "name", "is_private") if err != nil { return nil, err } for _, repository := range repositorys { if repository.IsPrivate { continue } authorsOneRepo, err1 := git.GetUserKPIStats(repository.RepoPath(), startTime, endTime) if err1 != nil { log.Warn("get user kpi status err:"+repository.RepoPath(), err1.Error()) continue } for key, value := range authorsOneRepo { if _, ok := authors[key]; !ok { authors[key] = &git.UserKPIStats{ Name: value.Name, Email: value.Email, Commits: 0, CommitLines: 0, } } if value.Email == "1250125907@qq.com" || value.Email == "peiyongyu-34@163.com" { log.Info("repo path=" + repository.RepoPath()) } authors[key].Commits += value.Commits authors[key].CommitLines += value.CommitLines } } return authors, nil } func GetAllUserKPIStats(startTime time.Time, endTime time.Time) (map[string]*git.UserKPIStats, error) { authors := make(map[string]*git.UserKPIStats) repositorys, err := GetAllRepositoriesByFilterCols("owner_name", "name") if err != nil { return nil, err } for _, repository := range repositorys { authorsOneRepo, err1 := git.GetUserKPIStats(repository.RepoPath(), startTime, endTime) if err1 != nil { log.Warn("get user kpi status err:"+repository.RepoPath(), err1.Error()) continue } // if repository.Name == "yolov5" { // log.Info("repoName=" + repository.Name + " owner=" + repository.RepoPath()) // authorsOneRepoJson, _ := json.Marshal(authorsOneRepo) // log.Info("authorsOneRepoJson=" + string(authorsOneRepoJson)) // } for key, value := range authorsOneRepo { if _, ok := authors[key]; !ok { authors[key] = &git.UserKPIStats{ Name: value.Name, Email: value.Email, Commits: 0, CommitLines: 0, } } authors[key].Commits += value.Commits authors[key].CommitLines += value.CommitLines } } return authors, nil }