mirror of
				https://gitcode.com/gitea/gitea.git
				synced 2025-10-26 05:04:27 +08:00 
			
		
		
		
	Performance improvement for list pull requests (#15447)
This commit is contained in:
		| @ -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) { | ||||||
|  | |||||||
| @ -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,18 +255,14 @@ 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 | ||||||
| 	ctx.Data["CommitStatus"] = commitStatus | 	ctx.Data["CommitStatus"] = commitStatus | ||||||
|  |  | ||||||
|  | |||||||
| @ -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 { |  | ||||||
| 			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 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// ------------------------------- | 	// ------------------------------- | ||||||
|  | |||||||
| @ -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 | ||||||
|  | |||||||
| @ -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}} | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Lunny Xiao
					Lunny Xiao