]> source.dussan.org Git - gitea.git/commitdiff
Performance improvement for list pull requests (#15447)
authorLunny Xiao <xiaolunwen@gmail.com>
Thu, 15 Apr 2021 17:34:43 +0000 (01:34 +0800)
committerGitHub <noreply@github.com>
Thu, 15 Apr 2021 17:34:43 +0000 (19:34 +0200)
models/issue_list.go
routers/repo/issue.go
routers/user/home.go
services/pull/pull.go
templates/shared/issuelist.tmpl

index 0ac25fc690e04dae110e0f94b97cfdfaf13f566b..87ad318dcf2d6c17823f652cfa570184a3d827a7 100644 (file)
@@ -53,6 +53,9 @@ func (issues IssueList) loadRepositories(e Engine) ([]*Repository, error) {
 
        for _, issue := range issues {
                issue.Repo = repoMaps[issue.RepoID]
+               if issue.PullRequest != nil {
+                       issue.PullRequest.BaseRepo = issue.Repo
+               }
        }
        return valuesRepository(repoMaps), nil
 }
@@ -516,6 +519,11 @@ func (issues IssueList) LoadDiscussComments() error {
        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
 // FIXME: only returns official counts due to double counting of non-official approvals
 func (issues IssueList) GetApprovalCounts() (map[int64][]*ReviewCount, error) {
index da3772ef5a693c7a6fd2a1996749641e674aaffc..7471bb65a4ef0c57694222cbc1d72d99b90995cd 100644 (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 {
                ctx.ServerError("ApprovalCounts", err)
                return
        }
 
-       var commitStatus = make(map[int64]*models.CommitStatus, len(issues))
-
        // Get posters.
        for i := range issues {
                // Check read status
@@ -256,16 +255,12 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
                        ctx.ServerError("GetIsRead", err)
                        return
                }
+       }
 
-               if issues[i].IsPull {
-                       if err := issues[i].LoadPullRequest(); err != nil {
-                               ctx.ServerError("LoadPullRequest", err)
-                               return
-                       }
-
-                       var statuses, _ = pull_service.GetLastCommitStatus(issues[i].PullRequest)
-                       commitStatus[issues[i].PullRequest.ID] = models.CalcCommitStatus(statuses)
-               }
+       commitStatus, err := pull_service.GetIssuesLastCommitStatus(issues)
+       if err != nil {
+               ctx.ServerError("GetIssuesLastCommitStatus", err)
+               return
        }
 
        ctx.Data["Issues"] = issues
index 431ffdde8e5276525016ddd077306b190774425d..584bc019fab740d5685e8bd3204fb729e02d656c 100644 (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.
-       var commitStatus = make(map[int64]*models.CommitStatus, len(issues))
        for _, issue := range issues {
                issue.Repo = showReposMap[issue.RepoID]
+       }
 
-               if isPullList {
-                       var statuses, _ = pull_service.GetLastCommitStatus(issue.PullRequest)
-                       commitStatus[issue.PullRequest.ID] = models.CalcCommitStatus(statuses)
-               }
+       commitStatus, err := pull_service.GetIssuesLastCommitStatus(issues)
+       if err != nil {
+               ctx.ServerError("GetIssuesLastCommitStatus", err)
+               return
        }
 
        // -------------------------------
index 331ef46d3d34cfa888e854cf3d18623a25fa18cf..153a75094d7393bd5079b8b30bc975efc2471755 100644 (file)
@@ -8,7 +8,6 @@ import (
        "bufio"
        "bytes"
        "context"
-       "errors"
        "fmt"
        "strings"
        "time"
@@ -643,33 +642,74 @@ func GetSquashMergeCommitMessages(pr *models.PullRequest) string {
        return stringBuilder.String()
 }
 
+// GetIssuesLastCommitStatus returns a map
+func GetIssuesLastCommitStatus(issues models.IssueList) (map[int64]*models.CommitStatus, error) {
+       if err := issues.LoadPullRequests(); err != nil {
+               return nil, err
+       }
+       if _, err := issues.LoadRepositories(); err != nil {
+               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) {
+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())
        if err != nil {
                return nil, err
        }
        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 {
                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{})
        if err != nil {
                return nil, err
        }
-       return statusList, nil
+       return models.CalcCommitStatus(statusList), nil
 }
 
 // IsHeadEqualWithBranch returns if the commits of branchName are available in pull request head
index d6cd60cbd245beb02b1e3c204f10ade0e45fca31..d07295aa671017b9cc9a203227161b464859afc1 100644 (file)
                                                {{$.i18n.Tr .GetLastEventLabelFake $timeStr (.Poster.GetDisplayName | Escape) | Safe}}
                                        {{end}}
                                        {{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}}
                                                </a>
                                        {{end}}
                                        {{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}}
                                                </a>
                                        {{end}}