Performance improvement for list pull requests (#15447)

This commit is contained in:
Lunny Xiao 2021-04-16 01:34:43 +08:00 committed by GitHub
parent f44543a1bb
commit 8202dd1311
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 73 additions and 30 deletions

View file

@ -53,6 +53,9 @@ func (issues IssueList) loadRepositories(e Engine) ([]*Repository, error) {
for _, issue := range issues { for _, issue := range issues {
issue.Repo = repoMaps[issue.RepoID] issue.Repo = repoMaps[issue.RepoID]
if issue.PullRequest != nil {
issue.PullRequest.BaseRepo = issue.Repo
}
} }
return valuesRepository(repoMaps), nil return valuesRepository(repoMaps), nil
} }
@ -516,6 +519,11 @@ func (issues IssueList) LoadDiscussComments() error {
return issues.loadComments(x, builder.Eq{"comment.type": CommentTypeComment}) return issues.loadComments(x, builder.Eq{"comment.type": CommentTypeComment})
} }
// LoadPullRequests loads pull requests
func (issues IssueList) LoadPullRequests() error {
return issues.loadPullRequests(x)
}
// GetApprovalCounts returns a map of issue ID to slice of approval counts // GetApprovalCounts returns a map of issue ID to slice of approval counts
// FIXME: only returns official counts due to double counting of non-official approvals // FIXME: only returns official counts due to double counting of non-official approvals
func (issues IssueList) GetApprovalCounts() (map[int64][]*ReviewCount, error) { func (issues IssueList) GetApprovalCounts() (map[int64][]*ReviewCount, error) {

View file

@ -239,14 +239,13 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
} }
} }
approvalCounts, err := models.IssueList(issues).GetApprovalCounts() var issueList = models.IssueList(issues)
approvalCounts, err := issueList.GetApprovalCounts()
if err != nil { if err != nil {
ctx.ServerError("ApprovalCounts", err) ctx.ServerError("ApprovalCounts", err)
return return
} }
var commitStatus = make(map[int64]*models.CommitStatus, len(issues))
// Get posters. // Get posters.
for i := range issues { for i := range issues {
// Check read status // Check read status
@ -256,16 +255,12 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
ctx.ServerError("GetIsRead", err) ctx.ServerError("GetIsRead", err)
return return
} }
}
if issues[i].IsPull { commitStatus, err := pull_service.GetIssuesLastCommitStatus(issues)
if err := issues[i].LoadPullRequest(); err != nil { if err != nil {
ctx.ServerError("LoadPullRequest", err) ctx.ServerError("GetIssuesLastCommitStatus", err)
return return
}
var statuses, _ = pull_service.GetLastCommitStatus(issues[i].PullRequest)
commitStatus[issues[i].PullRequest.ID] = models.CalcCommitStatus(statuses)
}
} }
ctx.Data["Issues"] = issues ctx.Data["Issues"] = issues

View file

@ -550,14 +550,14 @@ func buildIssueOverview(ctx *context.Context, unitType models.UnitType) {
} }
// maps pull request IDs to their CommitStatus. Will be posted to ctx.Data. // maps pull request IDs to their CommitStatus. Will be posted to ctx.Data.
var commitStatus = make(map[int64]*models.CommitStatus, len(issues))
for _, issue := range issues { for _, issue := range issues {
issue.Repo = showReposMap[issue.RepoID] issue.Repo = showReposMap[issue.RepoID]
}
if isPullList { commitStatus, err := pull_service.GetIssuesLastCommitStatus(issues)
var statuses, _ = pull_service.GetLastCommitStatus(issue.PullRequest) if err != nil {
commitStatus[issue.PullRequest.ID] = models.CalcCommitStatus(statuses) ctx.ServerError("GetIssuesLastCommitStatus", err)
} return
} }
// ------------------------------- // -------------------------------

View file

@ -8,7 +8,6 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"context" "context"
"errors"
"fmt" "fmt"
"strings" "strings"
"time" "time"
@ -643,33 +642,74 @@ func GetSquashMergeCommitMessages(pr *models.PullRequest) string {
return stringBuilder.String() return stringBuilder.String()
} }
// GetLastCommitStatus returns list of commit statuses for latest commit on this pull request. // GetIssuesLastCommitStatus returns a map
func GetLastCommitStatus(pr *models.PullRequest) (status []*models.CommitStatus, err error) { func GetIssuesLastCommitStatus(issues models.IssueList) (map[int64]*models.CommitStatus, error) {
if err = pr.LoadBaseRepo(); err != nil { if err := issues.LoadPullRequests(); err != nil {
return nil, err
}
if _, err := issues.LoadRepositories(); err != nil {
return nil, err return nil, err
} }
var (
gitRepos = make(map[int64]*git.Repository)
res = make(map[int64]*models.CommitStatus)
err error
)
defer func() {
for _, gitRepo := range gitRepos {
gitRepo.Close()
}
}()
for _, issue := range issues {
if !issue.IsPull {
continue
}
gitRepo, ok := gitRepos[issue.RepoID]
if !ok {
gitRepo, err = git.OpenRepository(issue.Repo.RepoPath())
if err != nil {
return nil, err
}
gitRepos[issue.RepoID] = gitRepo
}
status, err := getLastCommitStatus(gitRepo, issue.PullRequest)
if err != nil {
return nil, err
}
res[issue.PullRequest.ID] = status
}
return res, nil
}
// GetLastCommitStatus returns list of commit statuses for latest commit on this pull request.
func GetLastCommitStatus(pr *models.PullRequest) (status *models.CommitStatus, err error) {
if err = pr.LoadBaseRepo(); err != nil {
return nil, err
}
gitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath()) gitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath())
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer gitRepo.Close() defer gitRepo.Close()
compareInfo, err := gitRepo.GetCompareInfo(pr.BaseRepo.RepoPath(), pr.MergeBase, pr.GetGitRefName()) return getLastCommitStatus(gitRepo, pr)
}
// getLastCommitStatus get pr's last commit status. PR's last commit status is the head commit id's last commit status
func getLastCommitStatus(gitRepo *git.Repository, pr *models.PullRequest) (status *models.CommitStatus, err error) {
sha, err := gitRepo.GetRefCommitID(pr.GetGitRefName())
if err != nil { if err != nil {
return nil, err return nil, err
} }
if compareInfo.Commits.Len() == 0 {
return nil, errors.New("pull request has no commits")
}
sha := compareInfo.Commits.Front().Value.(*git.Commit).ID.String()
statusList, err := models.GetLatestCommitStatus(pr.BaseRepo.ID, sha, models.ListOptions{}) statusList, err := models.GetLatestCommitStatus(pr.BaseRepo.ID, sha, models.ListOptions{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
return statusList, nil return models.CalcCommitStatus(statusList), nil
} }
// IsHeadEqualWithBranch returns if the commits of branchName are available in pull request head // IsHeadEqualWithBranch returns if the commits of branchName are available in pull request head

View file

@ -62,12 +62,12 @@
{{$.i18n.Tr .GetLastEventLabelFake $timeStr (.Poster.GetDisplayName | Escape) | Safe}} {{$.i18n.Tr .GetLastEventLabelFake $timeStr (.Poster.GetDisplayName | Escape) | Safe}}
{{end}} {{end}}
{{if and .Milestone (ne $.listType "milestone")}} {{if and .Milestone (ne $.listType "milestone")}}
<a class="milestone" {{if $.RepoLink}}href="{{$.RepoLink}}/milestone/{{.Milestone.ID}}"{{else}}href="{{AppSubUrl}}/{{.Repo.Owner.Name}}/{{.Repo.Name}}/milestone/{{.Milestone.ID}}"{{end}}> <a class="milestone" {{if $.RepoLink}}href="{{$.RepoLink}}/milestone/{{.Milestone.ID}}"{{else}}href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/milestone/{{.Milestone.ID}}"{{end}}>
{{svg "octicon-milestone" 14 "mr-2"}}{{.Milestone.Name}} {{svg "octicon-milestone" 14 "mr-2"}}{{.Milestone.Name}}
</a> </a>
{{end}} {{end}}
{{if .Ref}} {{if .Ref}}
<a class="ref" {{if $.RepoLink}}href="{{$.RepoLink}}{{index $.IssueRefURLs .ID}}"{{else}}href="{{AppSubUrl}}/{{.Repo.Owner.Name}}/{{.Repo.Name}}{{index $.IssueRefURLs .ID}}"{{end}}> <a class="ref" {{if $.RepoLink}}href="{{$.RepoLink}}{{index $.IssueRefURLs .ID}}"{{else}}href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{index $.IssueRefURLs .ID}}"{{end}}>
{{svg "octicon-git-branch" 14 "mr-2"}}{{index $.IssueRefEndNames .ID}} {{svg "octicon-git-branch" 14 "mr-2"}}{{index $.IssueRefEndNames .ID}}
</a> </a>
{{end}} {{end}}