diff --git a/models/status.go b/models/status.go index 3146f8d30..0684f7de2 100644 --- a/models/status.go +++ b/models/status.go @@ -6,6 +6,7 @@ package models import ( "container/list" + "errors" "fmt" "strings" @@ -15,6 +16,7 @@ import ( "code.gitea.io/gitea/modules/util" api "code.gitea.io/sdk/gitea" + "github.com/go-xorm/builder" "github.com/go-xorm/xorm" ) @@ -157,6 +159,59 @@ func GetLatestCommitStatus(repo *Repository, sha string, page int) ([]*CommitSta return statuses, x.In("id", ids).Find(&statuses) } +// GetLatestCommitStatuses returns all statuses with given repoIDs and shas +func GetLatestCommitStatuses(repoIDs []int64, shas []string) ([][]*CommitStatus, error) { + if len(repoIDs) != len(shas) { + return nil, errors.New("parameter repoIDs should have the same size of shas") + } + + var results = make([]struct { + ID int64 + RepoID int64 + }, 0, 10*len(repoIDs)) + + var cond = builder.NewCond() + for i := 0; i < len(repoIDs); i++ { + cond = cond.Or(builder.Eq{ + "repo_id": repoIDs[i], + "sha": shas[i], + }) + } + + err := x.Table(&CommitStatus{}). + Where(cond). + Select("max( id ) as id, repo_id"). + GroupBy("context").OrderBy("max( id ) desc").Find(&results) + if err != nil { + return nil, err + } + + var returns = make([][]*CommitStatus, len(repoIDs)) + if len(results) == 0 { + return returns, nil + } + + var ids = make([]int64, 0, len(results)) + var repoIDsMap = make(map[int64][]int64, len(repoIDs)) + for _, res := range results { + ids = append(ids, res.ID) + repoIDsMap[res.RepoID] = append(repoIDsMap[res.RepoID], res.ID) + } + + statuses := make(map[int64]*CommitStatus, len(ids)) + err = x.In("id", ids).Find(&statuses) + if err != nil { + return nil, err + } + + for i := 0; i < len(repoIDs); i++ { + for _, id := range repoIDsMap[repoIDs[i]] { + returns[i] = append(returns[i], statuses[id]) + } + } + return returns, nil +} + // GetCommitStatus populates a given status for a given commit. // NOTE: If ID or Index isn't given, and only Context, TargetURL and/or Description // is given, the CommitStatus created _last_ will be returned. diff --git a/routers/repo/issue.go b/routers/repo/issue.go index 1f5c4c62e..52f5ca0ec 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -209,7 +209,9 @@ func Issues(ctx *context.Context) { } } - var issuesStates = make([]*models.CommitStatus, 0, len(issues)) + var repoIDs = make([]int64, 0, len(issues)) + var shas = make([]string, 0, len(issues)) + var pullIDs = make([]int64, 0, len(issues)) // Get posters. for i, issue := range issues { // Check read status @@ -221,15 +223,28 @@ func Issues(ctx *context.Context) { } if issue.IsPull { - issue.LoadAttributes() - statuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository, issue.PullRequest.MergeBase, 0) - if err != nil { - log.Error(3, "GetLatestCommitStatus: %v", err) + if err := issue.LoadAttributes(); err != nil { + ctx.ServerError("LoadAttributes", err) + return } - issuesStates = append(issuesStates, models.CalcCommitStatus(statuses)) + repoIDs = append(repoIDs, ctx.Repo.Repository.ID) + shas = append(shas, issue.PullRequest.MergeBase) + pullIDs = append(pullIDs, issue.ID) } } + + commitStatuses, err := models.GetLatestCommitStatuses(repoIDs, shas) + if err != nil { + ctx.ServerError("GetLatestCommitStatuses", err) + return + } + + var issuesStates = make(map[int64]*models.CommitStatus, len(issues)) + for i, statuses := range commitStatuses { + issuesStates[pullIDs[i]] = models.CalcCommitStatus(statuses) + } + ctx.Data["Issues"] = issues ctx.Data["IssuesStates"] = issuesStates diff --git a/routers/user/home.go b/routers/user/home.go index 762c7712d..6694509d0 100644 --- a/routers/user/home.go +++ b/routers/user/home.go @@ -12,7 +12,6 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" @@ -292,21 +291,37 @@ func Issues(ctx *context.Context) { return } - var issuesStates = make([]*models.CommitStatus, 0, len(issues)) + var repoIDs = make([]int64, 0, len(issues)) + var shas = make([]string, 0, len(issues)) + var pullIDs = make([]int64, 0, len(issues)) for _, issue := range issues { issue.Repo = showReposMap[issue.RepoID] if issue.IsPull { - issue.LoadAttributes() - statuses, err := models.GetLatestCommitStatus(issue.Repo, issue.PullRequest.MergeBase, 0) - if err != nil { - log.Error(3, "GetLatestCommitStatus: %v", err) + if err := issue.LoadAttributes(); err != nil { + ctx.ServerError("LoadAttributes", fmt.Errorf("%v", err)) + return } - issuesStates = append(issuesStates, models.CalcCommitStatus(statuses)) + repoIDs = append(repoIDs, issue.Repo.ID) + shas = append(shas, issue.PullRequest.MergeBase) + pullIDs = append(pullIDs, issue.ID) } } + commitStatuses, err := models.GetLatestCommitStatuses(repoIDs, shas) + if err != nil { + ctx.ServerError("GetLatestCommitStatuses", err) + return + } + + var issuesStates = make(map[int64]*models.CommitStatus, len(issues)) + for i, statuses := range commitStatuses { + issuesStates[pullIDs[i]] = models.CalcCommitStatus(statuses) + } + + ctx.Data["IssuesStates"] = issuesStates + issueStats, err := models.GetUserIssueStats(models.UserIssueStatsOptions{ UserID: ctxUser.ID, RepoID: repoID, diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl index 21902bed6..4c253257a 100644 --- a/templates/repo/issue/list.tmpl +++ b/templates/repo/issue/list.tmpl @@ -187,7 +187,7 @@
#{{$issue.Index}}
{{$issue.Title}} {{if $issue.IsPull}} - {{template "repo/commit_status" (index $.IssuesStates $index)}} + {{template "repo/commit_status" (index $.IssuesStates $issue.ID)}} {{end}} {{if $issue.Ref}} {{$issue.Ref}} diff --git a/templates/user/dashboard/issues.tmpl b/templates/user/dashboard/issues.tmpl index eb359ca37..3e245597f 100644 --- a/templates/user/dashboard/issues.tmpl +++ b/templates/user/dashboard/issues.tmpl @@ -63,7 +63,9 @@
  • {{if not $.RepoID}}{{$issue.Repo.FullName}}{{end}}#{{$issue.Index}}
    {{$issue.Title}} - + {{if $issue.IsPull}} + {{template "repo/commit_status" (index $.IssuesStates $issue.ID)}} + {{end}} {{with $issue.Labels}} {{/* If we have any labels, we should show them with a 2.5 line height, this way they don't look