package repository import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/redis/redis_client" "code.gitea.io/gitea/modules/redis/redis_key" "encoding/json" "github.com/patrickmn/go-cache" "time" ) var repoContributorCache = cache.New(5*time.Minute, 1*time.Minute) type ContributorCacheVal struct { Contributors []*models.ContributorInfo Total int } func GetRepoTopNContributors(repo *models.Repository, N int) ([]*models.ContributorInfo, int) { val, _ := redis_client.Get(redis_key.RepoTopNContributors(repo.ID, N)) if val != "" { log.Debug("Get RepoTopNContributors from redis,repo.ID = %d value = %v", repo.ID, val) temp := &ContributorCacheVal{} json.Unmarshal([]byte(val), temp) return temp.Contributors, temp.Total } contributorInfos, total := getRepoTopNContributorsFromDisk(repo, N) log.Debug("Get RepoTopNContributors from disk,repo.ID = %d ", repo.ID) jsonVal, err := json.Marshal(&ContributorCacheVal{Contributors: contributorInfos, Total: total}) if err == nil { redis_client.Setex(redis_key.RepoTopNContributors(repo.ID, N), string(jsonVal), 2*time.Minute) } return contributorInfos, total } func getRepoTopNContributorsFromDisk(repo *models.Repository, N int) ([]*models.ContributorInfo, int) { contributorInfos := make([]*models.ContributorInfo, 0) branchName := GetDefaultBranchName(repo) if branchName == "" { return contributorInfos, 0 } contributors, err := git.GetContributors(repo.RepoPath(), branchName) if err == nil && contributors != nil { contributorInfoHash := make(map[string]*models.ContributorInfo) for _, c := range contributors { if len(contributorInfos) >= N { break } if c.Email == "" { continue } // get user info from committer email user, err := models.GetUserByActivateEmail(c.Email) if err == nil { // committer is system user, get info through user's primary email if existedContributorInfo, ok := contributorInfoHash[user.Email]; ok { // existed: same primary email, different committer name existedContributorInfo.CommitCnt += c.CommitCnt } else { // new committer info var newContributor = &models.ContributorInfo{ user.RelAvatarLink(), user.Name, user.Email, c.CommitCnt, } contributorInfos = append(contributorInfos, newContributor) contributorInfoHash[user.Email] = newContributor } } else { // committer is not system user if existedContributorInfo, ok := contributorInfoHash[c.Email]; ok { // existed: same primary email, different committer name existedContributorInfo.CommitCnt += c.CommitCnt } else { var newContributor = &models.ContributorInfo{ "", "", c.Email, c.CommitCnt, } contributorInfos = append(contributorInfos, newContributor) contributorInfoHash[c.Email] = newContributor } } } } return contributorInfos, len(contributors) }