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.

205 lines
5.1 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. "strings"
  7. "code.gitea.io/gitea/models"
  8. api "code.gitea.io/gitea/modules/structs"
  9. )
  10. // ToAPIIssue converts an Issue to API format
  11. // it assumes some fields assigned with values:
  12. // Required - Poster, Labels,
  13. // Optional - Milestone, Assignee, PullRequest
  14. func ToAPIIssue(issue *models.Issue) *api.Issue {
  15. if err := issue.LoadLabels(); err != nil {
  16. return &api.Issue{}
  17. }
  18. if err := issue.LoadPoster(); err != nil {
  19. return &api.Issue{}
  20. }
  21. if err := issue.LoadRepo(); err != nil {
  22. return &api.Issue{}
  23. }
  24. apiIssue := &api.Issue{
  25. ID: issue.ID,
  26. URL: issue.APIURL(),
  27. HTMLURL: issue.HTMLURL(),
  28. Index: issue.Index,
  29. Poster: issue.Poster.APIFormat(),
  30. Title: issue.Title,
  31. Body: issue.Content,
  32. Labels: ToLabelList(issue.Labels),
  33. State: issue.State(),
  34. IsLocked: issue.IsLocked,
  35. Comments: issue.NumComments,
  36. Created: issue.CreatedUnix.AsTime(),
  37. Updated: issue.UpdatedUnix.AsTime(),
  38. }
  39. apiIssue.Repo = &api.RepositoryMeta{
  40. ID: issue.Repo.ID,
  41. Name: issue.Repo.Name,
  42. Owner: issue.Repo.OwnerName,
  43. FullName: issue.Repo.FullName(),
  44. }
  45. if issue.ClosedUnix != 0 {
  46. apiIssue.Closed = issue.ClosedUnix.AsTimePtr()
  47. }
  48. if err := issue.LoadMilestone(); err != nil {
  49. return &api.Issue{}
  50. }
  51. if issue.Milestone != nil {
  52. apiIssue.Milestone = ToAPIMilestone(issue.Milestone)
  53. }
  54. if err := issue.LoadAssignees(); err != nil {
  55. return &api.Issue{}
  56. }
  57. if len(issue.Assignees) > 0 {
  58. for _, assignee := range issue.Assignees {
  59. apiIssue.Assignees = append(apiIssue.Assignees, assignee.APIFormat())
  60. }
  61. apiIssue.Assignee = issue.Assignees[0].APIFormat() // For compatibility, we're keeping the first assignee as `apiIssue.Assignee`
  62. }
  63. if issue.IsPull {
  64. if err := issue.LoadPullRequest(); err != nil {
  65. return &api.Issue{}
  66. }
  67. apiIssue.PullRequest = &api.PullRequestMeta{
  68. HasMerged: issue.PullRequest.HasMerged,
  69. }
  70. if issue.PullRequest.HasMerged {
  71. apiIssue.PullRequest.Merged = issue.PullRequest.MergedUnix.AsTimePtr()
  72. }
  73. }
  74. if issue.DeadlineUnix != 0 {
  75. apiIssue.Deadline = issue.DeadlineUnix.AsTimePtr()
  76. }
  77. return apiIssue
  78. }
  79. // ToAPIIssueList converts an IssueList to API format
  80. func ToAPIIssueList(il models.IssueList) []*api.Issue {
  81. result := make([]*api.Issue, len(il))
  82. for i := range il {
  83. result[i] = ToAPIIssue(il[i])
  84. }
  85. return result
  86. }
  87. // ToTrackedTime converts TrackedTime to API format
  88. func ToTrackedTime(t *models.TrackedTime) (apiT *api.TrackedTime) {
  89. apiT = &api.TrackedTime{
  90. ID: t.ID,
  91. IssueID: t.IssueID,
  92. UserID: t.UserID,
  93. UserName: t.User.Name,
  94. Time: t.Time,
  95. Created: t.Created,
  96. }
  97. if t.Issue != nil {
  98. apiT.Issue = ToAPIIssue(t.Issue)
  99. }
  100. if t.User != nil {
  101. apiT.UserName = t.User.Name
  102. }
  103. return
  104. }
  105. // ToStopWatches convert Stopwatch list to api.StopWatches
  106. func ToStopWatches(sws []*models.Stopwatch) (api.StopWatches, error) {
  107. result := api.StopWatches(make([]api.StopWatch, 0, len(sws)))
  108. issueCache := make(map[int64]*models.Issue)
  109. repoCache := make(map[int64]*models.Repository)
  110. var (
  111. issue *models.Issue
  112. repo *models.Repository
  113. ok bool
  114. err error
  115. )
  116. for _, sw := range sws {
  117. issue, ok = issueCache[sw.IssueID]
  118. if !ok {
  119. issue, err = models.GetIssueByID(sw.IssueID)
  120. if err != nil {
  121. return nil, err
  122. }
  123. }
  124. repo, ok = repoCache[issue.RepoID]
  125. if !ok {
  126. repo, err = models.GetRepositoryByID(issue.RepoID)
  127. if err != nil {
  128. return nil, err
  129. }
  130. }
  131. result = append(result, api.StopWatch{
  132. Created: sw.CreatedUnix.AsTime(),
  133. IssueIndex: issue.Index,
  134. IssueTitle: issue.Title,
  135. RepoOwnerName: repo.OwnerName,
  136. RepoName: repo.Name,
  137. })
  138. }
  139. return result, nil
  140. }
  141. // ToTrackedTimeList converts TrackedTimeList to API format
  142. func ToTrackedTimeList(tl models.TrackedTimeList) api.TrackedTimeList {
  143. result := make([]*api.TrackedTime, 0, len(tl))
  144. for _, t := range tl {
  145. result = append(result, ToTrackedTime(t))
  146. }
  147. return result
  148. }
  149. // ToLabel converts Label to API format
  150. func ToLabel(label *models.Label) *api.Label {
  151. return &api.Label{
  152. ID: label.ID,
  153. Name: label.Name,
  154. Color: strings.TrimLeft(label.Color, "#"),
  155. Description: label.Description,
  156. }
  157. }
  158. // ToLabelList converts list of Label to API format
  159. func ToLabelList(labels []*models.Label) []*api.Label {
  160. result := make([]*api.Label, len(labels))
  161. for i := range labels {
  162. result[i] = ToLabel(labels[i])
  163. }
  164. return result
  165. }
  166. // ToAPIMilestone converts Milestone into API Format
  167. func ToAPIMilestone(m *models.Milestone) *api.Milestone {
  168. apiMilestone := &api.Milestone{
  169. ID: m.ID,
  170. State: m.State(),
  171. Title: m.Name,
  172. Description: m.Content,
  173. OpenIssues: m.NumOpenIssues,
  174. ClosedIssues: m.NumClosedIssues,
  175. Created: m.CreatedUnix.AsTime(),
  176. Updated: m.UpdatedUnix.AsTimePtr(),
  177. }
  178. if m.IsClosed {
  179. apiMilestone.Closed = m.ClosedDateUnix.AsTimePtr()
  180. }
  181. if m.DeadlineUnix.Year() < 9999 {
  182. apiMilestone.Deadline = m.DeadlineUnix.AsTimePtr()
  183. }
  184. return apiMilestone
  185. }