Skip to content

Commit c75b7a5

Browse files
committed
Implement new endpoint for fetching contributors data
1 parent a4b6666 commit c75b7a5

File tree

7 files changed

+138
-30
lines changed

7 files changed

+138
-30
lines changed

models/contributors/contributors_graph.go

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,15 @@ import (
88
repo_model "code.gitea.io/gitea/models/repo"
99
user_model "code.gitea.io/gitea/models/user"
1010
"code.gitea.io/gitea/modules/git"
11+
api "code.gitea.io/gitea/modules/structs"
1112
util "code.gitea.io/gitea/modules/util"
1213
)
1314

14-
type WeekData struct {
15-
Week int64 `json:"week"`
16-
Additions int `json:"additions"`
17-
Deletions int `json:"deletions"`
18-
Commits int `json:"commits"`
19-
}
20-
21-
// ContributorData represents statistical git commit count data
22-
type ContributorData struct {
23-
Name string `json:"name"`
24-
Login string `json:"login"`
25-
AvatarLink string `json:"avatar_link"`
26-
HomeLink string `json:"home_link"`
27-
TotalCommits int64 `json:"total_commits"`
28-
Weeks []*WeekData `json:"weeks"`
29-
}
30-
31-
func CreateWeeks(sundays []int64) []*WeekData {
32-
var weeks []*WeekData
15+
// CreateWeeks converts list of sundays to list of *api.WeekData
16+
func CreateWeeks(sundays []int64) []*api.WeekData {
17+
var weeks []*api.WeekData
3318
for _, week := range sundays {
34-
weeks = append(weeks, &WeekData{
19+
weeks = append(weeks, &api.WeekData{
3520
Week: week,
3621
Additions: 0,
3722
Deletions: 0,
@@ -42,16 +27,18 @@ func CreateWeeks(sundays []int64) []*WeekData {
4227
return weeks
4328
}
4429

45-
// GetContributorStats returns contributors stats for git commits
46-
func GetContributorStats(ctx context.Context, repo *repo_model.Repository) (map[string]*ContributorData, error) {
30+
// GetContributorStats returns contributors stats for git commits for given revision or default branch
31+
func GetContributorStats(ctx context.Context, repo *repo_model.Repository, revision string) (map[string]*api.ContributorData, error) {
4732
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath())
4833
if err != nil {
4934
return nil, fmt.Errorf("OpenRepository: %w", err)
5035
}
5136
defer closer.Close()
5237

53-
default_branch, _ := gitRepo.GetDefaultBranch()
54-
extended_commit_stats, err := gitRepo.ExtendedCommitStats(default_branch)
38+
if len(revision) == 0 {
39+
revision = repo.DefaultBranch
40+
}
41+
extended_commit_stats, err := gitRepo.ExtendedCommitStats(revision)
5542
if err != nil {
5643
return nil, fmt.Errorf("ExtendedCommitStats: %w", err)
5744
}
@@ -65,8 +52,8 @@ func GetContributorStats(ctx context.Context, repo *repo_model.Repository) (map[
6552
sundays, _ := util.ListSundaysBetween(starting_sunday, ending_sunday)
6653

6754
unknownUserAvatarLink := user_model.NewGhostUser().AvatarLink(ctx)
68-
contributors_commit_stats := make(map[string]*ContributorData)
69-
contributors_commit_stats["Total"] = &ContributorData{
55+
contributors_commit_stats := make(map[string]*api.ContributorData)
56+
contributors_commit_stats["Total"] = &api.ContributorData{
7057
Name: "Total",
7158
AvatarLink: unknownUserAvatarLink,
7259
Weeks: CreateWeeks(sundays),
@@ -80,13 +67,13 @@ func GetContributorStats(ctx context.Context, repo *repo_model.Repository) (map[
8067
if _, ok := contributors_commit_stats[v.Author.Email]; !ok {
8168
u, err := user_model.GetUserByEmail(ctx, v.Author.Email)
8269
if u == nil || user_model.IsErrUserNotExist(err) {
83-
contributors_commit_stats[v.Author.Email] = &ContributorData{
70+
contributors_commit_stats[v.Author.Email] = &api.ContributorData{
8471
Name: v.Author.Name,
8572
AvatarLink: unknownUserAvatarLink,
8673
Weeks: CreateWeeks(sundays),
8774
}
8875
} else {
89-
contributors_commit_stats[v.Author.Email] = &ContributorData{
76+
contributors_commit_stats[v.Author.Email] = &api.ContributorData{
9077
Name: u.DisplayName(),
9178
Login: u.LowerName,
9279
AvatarLink: u.AvatarLink(ctx),

modules/structs/repo_collaborator.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,20 @@ type RepoCollaboratorPermission struct {
1414
RoleName string `json:"role_name"`
1515
User *User `json:"user"`
1616
}
17+
18+
type WeekData struct {
19+
Week int64 `json:"week"`
20+
Additions int `json:"additions"`
21+
Deletions int `json:"deletions"`
22+
Commits int `json:"commits"`
23+
}
24+
25+
// ContributorData represents statistical git commit count data
26+
type ContributorData struct {
27+
Name string `json:"name"`
28+
Login string `json:"login"`
29+
AvatarLink string `json:"avatar_link"`
30+
HomeLink string `json:"home_link"`
31+
TotalCommits int64 `json:"total_commits"`
32+
Weeks []*WeekData `json:"weeks"`
33+
}

routers/api/v1/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,7 @@ func Routes() *web.Route {
10961096
m.Get("/statuses", repo.GetCommitStatusesByRef)
10971097
}, context.ReferencesGitRepo())
10981098
}, reqRepoReader(unit.TypeCode))
1099+
m.Get("/contributors", context.ReferencesGitRepo(), reqRepoReader(unit.TypeCode), repo.GetAllContributorsStats)
10991100
m.Group("/git", func() {
11001101
m.Group("/commits", func() {
11011102
m.Get("/{sha}", repo.GetSingleCommit)

routers/api/v1/repo/collaborators.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ import (
99
"net/http"
1010

1111
"code.gitea.io/gitea/models"
12+
contributors_model "code.gitea.io/gitea/models/contributors"
1213
"code.gitea.io/gitea/models/perm"
1314
access_model "code.gitea.io/gitea/models/perm/access"
1415
repo_model "code.gitea.io/gitea/models/repo"
1516
user_model "code.gitea.io/gitea/models/user"
1617
"code.gitea.io/gitea/modules/context"
1718
repo_module "code.gitea.io/gitea/modules/repository"
19+
"code.gitea.io/gitea/modules/setting"
1820
api "code.gitea.io/gitea/modules/structs"
1921
"code.gitea.io/gitea/modules/web"
2022
"code.gitea.io/gitea/routers/api/v1/utils"
@@ -349,3 +351,54 @@ func GetAssignees(ctx *context.APIContext) {
349351
}
350352
ctx.JSON(http.StatusOK, convert.ToUsers(ctx, ctx.Doer, assignees))
351353
}
354+
355+
// GetAllContributorsStats retrieves a map of contributors along with their weekly commit statistics
356+
func GetAllContributorsStats(ctx *context.APIContext) {
357+
// swagger:operation GET /repos/{owner}/{repo}/contributors repository repoGetAllContributorsStats
358+
// ---
359+
// summary: Get a map of all contributors along with their weekly commit statistics from a repository
360+
// produces:
361+
// - application/json
362+
// parameters:
363+
// - name: owner
364+
// in: path
365+
// description: owner of the repo
366+
// type: string
367+
// required: true
368+
// - name: repo
369+
// in: path
370+
// description: name of the repo
371+
// type: string
372+
// required: true
373+
// - name: sha
374+
// in: query
375+
// description: SHA or branch to start listing commits from (usually 'master')
376+
// type: string
377+
// responses:
378+
// "200":
379+
// "$ref": "#/responses/ContributorDataMap"
380+
// "404":
381+
// "$ref": "#/responses/notFound"
382+
// "409":
383+
// "$ref": "#/responses/EmptyRepository"
384+
385+
if ctx.Repo.Repository.IsEmpty {
386+
ctx.JSON(http.StatusConflict, api.APIError{
387+
Message: "Git Repository is empty.",
388+
URL: setting.API.SwaggerURL,
389+
})
390+
return
391+
}
392+
393+
sha := ctx.FormString("sha")
394+
395+
if len(sha) == 0 {
396+
sha = ctx.Repo.Repository.DefaultBranch
397+
}
398+
399+
if contributor_stats, err := contributors_model.GetContributorStats(ctx, ctx.Repo.Repository, sha); err != nil {
400+
ctx.Error(http.StatusInternalServerError, "GetContributorStats", err)
401+
} else {
402+
ctx.JSON(http.StatusOK, &contributor_stats)
403+
}
404+
}

routers/api/v1/swagger/repo.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,11 @@ type swaggerCommitList struct {
253253
Body []api.Commit `json:"body"`
254254
}
255255

256+
type swaggerContributorDataMap struct {
257+
// in: body
258+
Body map[string]*api.ContributorData `json:"body"`
259+
}
260+
256261
// ChangedFileList
257262
// swagger:response ChangedFileList
258263
type swaggerChangedFileList struct {

routers/web/repo/contributors.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func Contributors(ctx *context.Context) {
2626

2727
ctx.Data["ContributionTypeText"] = ctx.Tr("repo.contributors.contribution_type." + ctx.Data["ContributionType"].(string))
2828

29-
if contributor_stats, err := contributors_model.GetContributorStats(ctx, ctx.Repo.Repository); err != nil {
29+
if contributor_stats, err := contributors_model.GetContributorStats(ctx, ctx.Repo.Repository, ""); err != nil {
3030
ctx.ServerError("GetContributorStats", err)
3131
return
3232
} else {

templates/swagger/v1_json.tmpl

Lines changed: 46 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)