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.4KB

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