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.

status.go 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // Copyright 2017 Gitea. 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 repo
  5. import (
  6. "fmt"
  7. "net/http"
  8. "code.gitea.io/gitea/models"
  9. "code.gitea.io/gitea/modules/context"
  10. "code.gitea.io/gitea/modules/convert"
  11. "code.gitea.io/gitea/modules/repofiles"
  12. api "code.gitea.io/gitea/modules/structs"
  13. "code.gitea.io/gitea/routers/api/v1/utils"
  14. )
  15. // NewCommitStatus creates a new CommitStatus
  16. func NewCommitStatus(ctx *context.APIContext, form api.CreateStatusOption) {
  17. // swagger:operation POST /repos/{owner}/{repo}/statuses/{sha} repository repoCreateStatus
  18. // ---
  19. // summary: Create a commit status
  20. // produces:
  21. // - application/json
  22. // parameters:
  23. // - name: owner
  24. // in: path
  25. // description: owner of the repo
  26. // type: string
  27. // required: true
  28. // - name: repo
  29. // in: path
  30. // description: name of the repo
  31. // type: string
  32. // required: true
  33. // - name: sha
  34. // in: path
  35. // description: sha of the commit
  36. // type: string
  37. // required: true
  38. // - name: body
  39. // in: body
  40. // schema:
  41. // "$ref": "#/definitions/CreateStatusOption"
  42. // responses:
  43. // "201":
  44. // "$ref": "#/responses/Status"
  45. // "400":
  46. // "$ref": "#/responses/error"
  47. sha := ctx.Params("sha")
  48. if len(sha) == 0 {
  49. ctx.Error(http.StatusBadRequest, "sha not given", nil)
  50. return
  51. }
  52. status := &models.CommitStatus{
  53. State: api.CommitStatusState(form.State),
  54. TargetURL: form.TargetURL,
  55. Description: form.Description,
  56. Context: form.Context,
  57. }
  58. if err := repofiles.CreateCommitStatus(ctx.Repo.Repository, ctx.User, sha, status); err != nil {
  59. ctx.Error(http.StatusInternalServerError, "CreateCommitStatus", err)
  60. return
  61. }
  62. ctx.JSON(http.StatusCreated, convert.ToCommitStatus(status))
  63. }
  64. // GetCommitStatuses returns all statuses for any given commit hash
  65. func GetCommitStatuses(ctx *context.APIContext) {
  66. // swagger:operation GET /repos/{owner}/{repo}/statuses/{sha} repository repoListStatuses
  67. // ---
  68. // summary: Get a commit's statuses
  69. // produces:
  70. // - application/json
  71. // parameters:
  72. // - name: owner
  73. // in: path
  74. // description: owner of the repo
  75. // type: string
  76. // required: true
  77. // - name: repo
  78. // in: path
  79. // description: name of the repo
  80. // type: string
  81. // required: true
  82. // - name: sha
  83. // in: path
  84. // description: sha of the commit
  85. // type: string
  86. // required: true
  87. // - name: sort
  88. // in: query
  89. // description: type of sort
  90. // type: string
  91. // enum: [oldest, recentupdate, leastupdate, leastindex, highestindex]
  92. // required: false
  93. // - name: state
  94. // in: query
  95. // description: type of state
  96. // type: string
  97. // enum: [pending, success, error, failure, warning]
  98. // required: false
  99. // - name: page
  100. // in: query
  101. // description: page number of results to return (1-based)
  102. // type: integer
  103. // - name: limit
  104. // in: query
  105. // description: page size of results
  106. // type: integer
  107. // responses:
  108. // "200":
  109. // "$ref": "#/responses/StatusList"
  110. // "400":
  111. // "$ref": "#/responses/error"
  112. getCommitStatuses(ctx, ctx.Params("sha"))
  113. }
  114. // GetCommitStatusesByRef returns all statuses for any given commit ref
  115. func GetCommitStatusesByRef(ctx *context.APIContext) {
  116. // swagger:operation GET /repos/{owner}/{repo}/commits/{ref}/statuses repository repoListStatusesByRef
  117. // ---
  118. // summary: Get a commit's statuses, by branch/tag/commit reference
  119. // produces:
  120. // - application/json
  121. // parameters:
  122. // - name: owner
  123. // in: path
  124. // description: owner of the repo
  125. // type: string
  126. // required: true
  127. // - name: repo
  128. // in: path
  129. // description: name of the repo
  130. // type: string
  131. // required: true
  132. // - name: ref
  133. // in: path
  134. // description: name of branch/tag/commit
  135. // type: string
  136. // required: true
  137. // - name: sort
  138. // in: query
  139. // description: type of sort
  140. // type: string
  141. // enum: [oldest, recentupdate, leastupdate, leastindex, highestindex]
  142. // required: false
  143. // - name: state
  144. // in: query
  145. // description: type of state
  146. // type: string
  147. // enum: [pending, success, error, failure, warning]
  148. // required: false
  149. // - name: page
  150. // in: query
  151. // description: page number of results to return (1-based)
  152. // type: integer
  153. // - name: limit
  154. // in: query
  155. // description: page size of results
  156. // type: integer
  157. // responses:
  158. // "200":
  159. // "$ref": "#/responses/StatusList"
  160. // "400":
  161. // "$ref": "#/responses/error"
  162. filter := ctx.Params("ref")
  163. if len(filter) == 0 {
  164. ctx.Error(http.StatusBadRequest, "ref not given", nil)
  165. return
  166. }
  167. for _, reftype := range []string{"heads", "tags"} { //Search branches and tags
  168. refSHA, lastMethodName, err := searchRefCommitByType(ctx, reftype, filter)
  169. if err != nil {
  170. ctx.Error(http.StatusInternalServerError, lastMethodName, err)
  171. return
  172. }
  173. if refSHA != "" {
  174. filter = refSHA
  175. break
  176. }
  177. }
  178. getCommitStatuses(ctx, filter) //By default filter is maybe the raw SHA
  179. }
  180. func searchRefCommitByType(ctx *context.APIContext, refType, filter string) (string, string, error) {
  181. refs, lastMethodName, err := getGitRefs(ctx, refType+"/"+filter) //Search by type
  182. if err != nil {
  183. return "", lastMethodName, err
  184. }
  185. if len(refs) > 0 {
  186. return refs[0].Object.String(), "", nil //Return found SHA
  187. }
  188. return "", "", nil
  189. }
  190. func getCommitStatuses(ctx *context.APIContext, sha string) {
  191. if len(sha) == 0 {
  192. ctx.Error(http.StatusBadRequest, "ref/sha not given", nil)
  193. return
  194. }
  195. repo := ctx.Repo.Repository
  196. listOptions := utils.GetListOptions(ctx)
  197. statuses, maxResults, err := models.GetCommitStatuses(repo, sha, &models.CommitStatusOptions{
  198. ListOptions: listOptions,
  199. SortType: ctx.QueryTrim("sort"),
  200. State: ctx.QueryTrim("state"),
  201. })
  202. if err != nil {
  203. ctx.Error(http.StatusInternalServerError, "GetCommitStatuses", fmt.Errorf("GetCommitStatuses[%s, %s, %d]: %v", repo.FullName(), sha, ctx.QueryInt("page"), err))
  204. return
  205. }
  206. apiStatuses := make([]*api.Status, 0, len(statuses))
  207. for _, status := range statuses {
  208. apiStatuses = append(apiStatuses, convert.ToCommitStatus(status))
  209. }
  210. ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
  211. ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", maxResults))
  212. ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
  213. ctx.JSON(http.StatusOK, apiStatuses)
  214. }
  215. type combinedCommitStatus struct {
  216. State api.CommitStatusState `json:"state"`
  217. SHA string `json:"sha"`
  218. TotalCount int `json:"total_count"`
  219. Statuses []*api.Status `json:"statuses"`
  220. Repo *api.Repository `json:"repository"`
  221. CommitURL string `json:"commit_url"`
  222. URL string `json:"url"`
  223. }
  224. // GetCombinedCommitStatusByRef returns the combined status for any given commit hash
  225. func GetCombinedCommitStatusByRef(ctx *context.APIContext) {
  226. // swagger:operation GET /repos/{owner}/{repo}/commits/{ref}/statuses repository repoGetCombinedStatusByRef
  227. // ---
  228. // summary: Get a commit's combined status, by branch/tag/commit reference
  229. // produces:
  230. // - application/json
  231. // parameters:
  232. // - name: owner
  233. // in: path
  234. // description: owner of the repo
  235. // type: string
  236. // required: true
  237. // - name: repo
  238. // in: path
  239. // description: name of the repo
  240. // type: string
  241. // required: true
  242. // - name: ref
  243. // in: path
  244. // description: name of branch/tag/commit
  245. // type: string
  246. // required: true
  247. // - name: page
  248. // in: query
  249. // description: page number of results
  250. // type: integer
  251. // required: false
  252. // responses:
  253. // "200":
  254. // "$ref": "#/responses/Status"
  255. // "400":
  256. // "$ref": "#/responses/error"
  257. sha := ctx.Params("ref")
  258. if len(sha) == 0 {
  259. ctx.Error(http.StatusBadRequest, "ref/sha not given", nil)
  260. return
  261. }
  262. repo := ctx.Repo.Repository
  263. page := ctx.QueryInt("page")
  264. statuses, err := models.GetLatestCommitStatus(repo, sha, page)
  265. if err != nil {
  266. ctx.Error(http.StatusInternalServerError, "GetLatestCommitStatus", fmt.Errorf("GetLatestCommitStatus[%s, %s, %d]: %v", repo.FullName(), sha, page, err))
  267. return
  268. }
  269. if len(statuses) == 0 {
  270. ctx.Status(http.StatusOK)
  271. return
  272. }
  273. retStatus := &combinedCommitStatus{
  274. SHA: sha,
  275. TotalCount: len(statuses),
  276. Repo: repo.APIFormat(ctx.Repo.AccessMode),
  277. URL: "",
  278. }
  279. retStatus.Statuses = make([]*api.Status, 0, len(statuses))
  280. for _, status := range statuses {
  281. retStatus.Statuses = append(retStatus.Statuses, convert.ToCommitStatus(status))
  282. if status.State.NoBetterThan(retStatus.State) {
  283. retStatus.State = status.State
  284. }
  285. }
  286. ctx.JSON(http.StatusOK, retStatus)
  287. }