You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
4.0 KiB

  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package convert
  5. import (
  6. "fmt"
  7. "code.gitea.io/gitea/models"
  8. "code.gitea.io/gitea/modules/git"
  9. "code.gitea.io/gitea/modules/log"
  10. repo_module "code.gitea.io/gitea/modules/repository"
  11. api "code.gitea.io/gitea/modules/structs"
  12. )
  13. // ToAPIPullRequest assumes following fields have been assigned with valid values:
  14. // Required - Issue
  15. // Optional - Merger
  16. func ToAPIPullRequest(pr *models.PullRequest) *api.PullRequest {
  17. var (
  18. baseBranch *git.Branch
  19. headBranch *git.Branch
  20. baseCommit *git.Commit
  21. err error
  22. )
  23. if err = pr.Issue.LoadRepo(); err != nil {
  24. log.Error("pr.Issue.LoadRepo[%d]: %v", pr.ID, err)
  25. return nil
  26. }
  27. apiIssue := ToAPIIssue(pr.Issue)
  28. if err := pr.LoadBaseRepo(); err != nil {
  29. log.Error("GetRepositoryById[%d]: %v", pr.ID, err)
  30. return nil
  31. }
  32. if err := pr.LoadHeadRepo(); err != nil {
  33. log.Error("GetRepositoryById[%d]: %v", pr.ID, err)
  34. return nil
  35. }
  36. apiPullRequest := &api.PullRequest{
  37. ID: pr.ID,
  38. URL: pr.Issue.HTMLURL(),
  39. Index: pr.Index,
  40. Poster: apiIssue.Poster,
  41. Title: apiIssue.Title,
  42. Body: apiIssue.Body,
  43. Labels: apiIssue.Labels,
  44. Milestone: apiIssue.Milestone,
  45. Assignee: apiIssue.Assignee,
  46. Assignees: apiIssue.Assignees,
  47. State: apiIssue.State,
  48. IsLocked: apiIssue.IsLocked,
  49. Comments: apiIssue.Comments,
  50. HTMLURL: pr.Issue.HTMLURL(),
  51. DiffURL: pr.Issue.DiffURL(),
  52. PatchURL: pr.Issue.PatchURL(),
  53. HasMerged: pr.HasMerged,
  54. MergeBase: pr.MergeBase,
  55. Deadline: apiIssue.Deadline,
  56. Created: pr.Issue.CreatedUnix.AsTimePtr(),
  57. Updated: pr.Issue.UpdatedUnix.AsTimePtr(),
  58. Base: &api.PRBranchInfo{
  59. Name: pr.BaseBranch,
  60. Ref: pr.BaseBranch,
  61. RepoID: pr.BaseRepoID,
  62. Repository: pr.BaseRepo.APIFormat(models.AccessModeNone),
  63. },
  64. Head: &api.PRBranchInfo{
  65. Name: pr.HeadBranch,
  66. Ref: fmt.Sprintf("refs/pull/%d/head", pr.Index),
  67. RepoID: -1,
  68. },
  69. }
  70. baseBranch, err = repo_module.GetBranch(pr.BaseRepo, pr.BaseBranch)
  71. if err != nil && !git.IsErrBranchNotExist(err) {
  72. log.Error("GetBranch[%s]: %v", pr.BaseBranch, err)
  73. return nil
  74. }
  75. if err == nil {
  76. baseCommit, err = baseBranch.GetCommit()
  77. if err != nil && !git.IsErrNotExist(err) {
  78. log.Error("GetCommit[%s]: %v", baseBranch.Name, err)
  79. return nil
  80. }
  81. if err == nil {
  82. apiPullRequest.Base.Sha = baseCommit.ID.String()
  83. }
  84. }
  85. if pr.HeadRepo != nil {
  86. apiPullRequest.Head.RepoID = pr.HeadRepo.ID
  87. apiPullRequest.Head.Repository = pr.HeadRepo.APIFormat(models.AccessModeNone)
  88. headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
  89. if err != nil {
  90. log.Error("OpenRepository[%s]: %v", pr.HeadRepo.RepoPath(), err)
  91. return nil
  92. }
  93. defer headGitRepo.Close()
  94. headBranch, err = headGitRepo.GetBranch(pr.HeadBranch)
  95. if err != nil && !git.IsErrBranchNotExist(err) {
  96. log.Error("GetBranch[%s]: %v", pr.HeadBranch, err)
  97. return nil
  98. }
  99. if git.IsErrBranchNotExist(err) {
  100. headCommitID, err := headGitRepo.GetRefCommitID(apiPullRequest.Head.Ref)
  101. if err != nil && !git.IsErrNotExist(err) {
  102. log.Error("GetCommit[%s]: %v", pr.HeadBranch, err)
  103. return nil
  104. }
  105. if err == nil {
  106. apiPullRequest.Head.Sha = headCommitID
  107. }
  108. } else {
  109. commit, err := headBranch.GetCommit()
  110. if err != nil && !git.IsErrNotExist(err) {
  111. log.Error("GetCommit[%s]: %v", headBranch.Name, err)
  112. return nil
  113. }
  114. if err == nil {
  115. apiPullRequest.Head.Ref = pr.HeadBranch
  116. apiPullRequest.Head.Sha = commit.ID.String()
  117. }
  118. }
  119. }
  120. if pr.Status != models.PullRequestStatusChecking {
  121. mergeable := !(pr.Status == models.PullRequestStatusConflict || pr.Status == models.PullRequestStatusError) && !pr.IsWorkInProgress()
  122. apiPullRequest.Mergeable = mergeable
  123. }
  124. if pr.HasMerged {
  125. apiPullRequest.Merged = pr.MergedUnix.AsTimePtr()
  126. apiPullRequest.MergedCommitID = &pr.MergedCommitID
  127. apiPullRequest.MergedBy = pr.Merger.APIFormat()
  128. }
  129. return apiPullRequest
  130. }