diff options
author | Lauris BH <lauris@nix.lv> | 2019-05-04 15:39:03 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-04 15:39:03 +0300 |
commit | 1fa96629461ac4229932b0a4526fc2f60c88ec51 (patch) | |
tree | caa3906758c6998bb6450932393336ac57c3db19 /models/repo_activity.go | |
parent | 2933ae4e88bb954af76c4e1e67c7ab1e4892e4a4 (diff) | |
download | gitea-1fa96629461ac4229932b0a4526fc2f60c88ec51.tar.gz gitea-1fa96629461ac4229932b0a4526fc2f60c88ec51.zip |
Git statistics in Activity tab (#4724)
* Initial implementation for git statistics in Activity tab
* Create top user by commit count endpoint
* Add UI and update src-d/go-git dependency
* Add coloring
* Fix typo
* Move git activity stats data extraction to git module
* Fix message
* Add git code stats test
Diffstat (limited to 'models/repo_activity.go')
-rw-r--r-- | models/repo_activity.go | 88 |
1 files changed, 82 insertions, 6 deletions
diff --git a/models/repo_activity.go b/models/repo_activity.go index c3017e8e39..fb1385a54b 100644 --- a/models/repo_activity.go +++ b/models/repo_activity.go @@ -6,11 +6,22 @@ package models import ( "fmt" + "sort" "time" + "code.gitea.io/gitea/modules/git" + "github.com/go-xorm/xorm" ) +// ActivityAuthorData represents statistical git commit count data +type ActivityAuthorData struct { + Name string `json:"name"` + Login string `json:"login"` + AvatarLink string `json:"avatar_link"` + Commits int64 `json:"commits"` +} + // ActivityStats represets issue and pull request information. type ActivityStats struct { OpenedPRs PullRequestList @@ -24,32 +35,97 @@ type ActivityStats struct { UnresolvedIssues IssueList PublishedReleases []*Release PublishedReleaseAuthorCount int64 + Code *git.CodeActivityStats } // GetActivityStats return stats for repository at given time range -func GetActivityStats(repoID int64, timeFrom time.Time, releases, issues, prs bool) (*ActivityStats, error) { - stats := &ActivityStats{} +func GetActivityStats(repo *Repository, timeFrom time.Time, releases, issues, prs, code bool) (*ActivityStats, error) { + stats := &ActivityStats{Code: &git.CodeActivityStats{}} if releases { - if err := stats.FillReleases(repoID, timeFrom); err != nil { + if err := stats.FillReleases(repo.ID, timeFrom); err != nil { return nil, fmt.Errorf("FillReleases: %v", err) } } if prs { - if err := stats.FillPullRequests(repoID, timeFrom); err != nil { + if err := stats.FillPullRequests(repo.ID, timeFrom); err != nil { return nil, fmt.Errorf("FillPullRequests: %v", err) } } if issues { - if err := stats.FillIssues(repoID, timeFrom); err != nil { + if err := stats.FillIssues(repo.ID, timeFrom); err != nil { return nil, fmt.Errorf("FillIssues: %v", err) } } - if err := stats.FillUnresolvedIssues(repoID, timeFrom, issues, prs); err != nil { + if err := stats.FillUnresolvedIssues(repo.ID, timeFrom, issues, prs); err != nil { return nil, fmt.Errorf("FillUnresolvedIssues: %v", err) } + if code { + gitRepo, err := git.OpenRepository(repo.RepoPath()) + if err != nil { + return nil, fmt.Errorf("OpenRepository: %v", err) + } + code, err := gitRepo.GetCodeActivityStats(timeFrom, repo.DefaultBranch) + if err != nil { + return nil, fmt.Errorf("FillFromGit: %v", err) + } + stats.Code = code + } return stats, nil } +// GetActivityStatsTopAuthors returns top author stats for git commits for all branches +func GetActivityStatsTopAuthors(repo *Repository, timeFrom time.Time, count int) ([]*ActivityAuthorData, error) { + gitRepo, err := git.OpenRepository(repo.RepoPath()) + if err != nil { + return nil, fmt.Errorf("OpenRepository: %v", err) + } + code, err := gitRepo.GetCodeActivityStats(timeFrom, "") + if err != nil { + return nil, fmt.Errorf("FillFromGit: %v", err) + } + if code.Authors == nil { + return nil, nil + } + users := make(map[int64]*ActivityAuthorData) + for k, v := range code.Authors { + if len(k) == 0 { + continue + } + u, err := GetUserByEmail(k) + if u == nil || IsErrUserNotExist(err) { + continue + } + if err != nil { + return nil, err + } + if user, ok := users[u.ID]; !ok { + users[u.ID] = &ActivityAuthorData{ + Name: u.DisplayName(), + Login: u.LowerName, + AvatarLink: u.AvatarLink(), + Commits: v, + } + } else { + user.Commits += v + } + } + v := make([]*ActivityAuthorData, 0) + for _, u := range users { + v = append(v, u) + } + + sort.Slice(v[:], func(i, j int) bool { + return v[i].Commits < v[j].Commits + }) + + cnt := count + if cnt > len(v) { + cnt = len(v) + } + + return v[:cnt], nil +} + // ActivePRCount returns total active pull request count func (stats *ActivityStats) ActivePRCount() int { return stats.OpenedPRCount() + stats.MergedPRCount() |