code.gitea.io/gitea@v1.21.7/routers/api/v1/repo/tag.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package repo 5 6 import ( 7 "errors" 8 "fmt" 9 "net/http" 10 11 "code.gitea.io/gitea/models" 12 repo_model "code.gitea.io/gitea/models/repo" 13 "code.gitea.io/gitea/modules/context" 14 api "code.gitea.io/gitea/modules/structs" 15 "code.gitea.io/gitea/modules/web" 16 "code.gitea.io/gitea/routers/api/v1/utils" 17 "code.gitea.io/gitea/services/convert" 18 releaseservice "code.gitea.io/gitea/services/release" 19 ) 20 21 // ListTags list all the tags of a repository 22 func ListTags(ctx *context.APIContext) { 23 // swagger:operation GET /repos/{owner}/{repo}/tags repository repoListTags 24 // --- 25 // summary: List a repository's tags 26 // produces: 27 // - application/json 28 // parameters: 29 // - name: owner 30 // in: path 31 // description: owner of the repo 32 // type: string 33 // required: true 34 // - name: repo 35 // in: path 36 // description: name of the repo 37 // type: string 38 // required: true 39 // - name: page 40 // in: query 41 // description: page number of results to return (1-based) 42 // type: integer 43 // - name: limit 44 // in: query 45 // description: page size of results, default maximum page size is 50 46 // type: integer 47 // responses: 48 // "200": 49 // "$ref": "#/responses/TagList" 50 // "404": 51 // "$ref": "#/responses/notFound" 52 53 listOpts := utils.GetListOptions(ctx) 54 55 tags, total, err := ctx.Repo.GitRepo.GetTagInfos(listOpts.Page, listOpts.PageSize) 56 if err != nil { 57 ctx.Error(http.StatusInternalServerError, "GetTags", err) 58 return 59 } 60 61 apiTags := make([]*api.Tag, len(tags)) 62 for i := range tags { 63 apiTags[i] = convert.ToTag(ctx.Repo.Repository, tags[i]) 64 } 65 66 ctx.SetTotalCountHeader(int64(total)) 67 ctx.JSON(http.StatusOK, &apiTags) 68 } 69 70 // GetAnnotatedTag get the tag of a repository. 71 func GetAnnotatedTag(ctx *context.APIContext) { 72 // swagger:operation GET /repos/{owner}/{repo}/git/tags/{sha} repository GetAnnotatedTag 73 // --- 74 // summary: Gets the tag object of an annotated tag (not lightweight tags) 75 // produces: 76 // - application/json 77 // parameters: 78 // - name: owner 79 // in: path 80 // description: owner of the repo 81 // type: string 82 // required: true 83 // - name: repo 84 // in: path 85 // description: name of the repo 86 // type: string 87 // required: true 88 // - name: sha 89 // in: path 90 // description: sha of the tag. The Git tags API only supports annotated tag objects, not lightweight tags. 91 // type: string 92 // required: true 93 // responses: 94 // "200": 95 // "$ref": "#/responses/AnnotatedTag" 96 // "400": 97 // "$ref": "#/responses/error" 98 // "404": 99 // "$ref": "#/responses/notFound" 100 101 sha := ctx.Params("sha") 102 if len(sha) == 0 { 103 ctx.Error(http.StatusBadRequest, "", "SHA not provided") 104 return 105 } 106 107 if tag, err := ctx.Repo.GitRepo.GetAnnotatedTag(sha); err != nil { 108 ctx.Error(http.StatusBadRequest, "GetAnnotatedTag", err) 109 } else { 110 commit, err := tag.Commit(ctx.Repo.GitRepo) 111 if err != nil { 112 ctx.Error(http.StatusBadRequest, "GetAnnotatedTag", err) 113 } 114 ctx.JSON(http.StatusOK, convert.ToAnnotatedTag(ctx, ctx.Repo.Repository, tag, commit)) 115 } 116 } 117 118 // GetTag get the tag of a repository 119 func GetTag(ctx *context.APIContext) { 120 // swagger:operation GET /repos/{owner}/{repo}/tags/{tag} repository repoGetTag 121 // --- 122 // summary: Get the tag of a repository by tag name 123 // produces: 124 // - application/json 125 // parameters: 126 // - name: owner 127 // in: path 128 // description: owner of the repo 129 // type: string 130 // required: true 131 // - name: repo 132 // in: path 133 // description: name of the repo 134 // type: string 135 // required: true 136 // - name: tag 137 // in: path 138 // description: name of tag 139 // type: string 140 // required: true 141 // responses: 142 // "200": 143 // "$ref": "#/responses/Tag" 144 // "404": 145 // "$ref": "#/responses/notFound" 146 tagName := ctx.Params("*") 147 148 tag, err := ctx.Repo.GitRepo.GetTag(tagName) 149 if err != nil { 150 ctx.NotFound(tagName) 151 return 152 } 153 ctx.JSON(http.StatusOK, convert.ToTag(ctx.Repo.Repository, tag)) 154 } 155 156 // CreateTag create a new git tag in a repository 157 func CreateTag(ctx *context.APIContext) { 158 // swagger:operation POST /repos/{owner}/{repo}/tags repository repoCreateTag 159 // --- 160 // summary: Create a new git tag in a repository 161 // produces: 162 // - application/json 163 // parameters: 164 // - name: owner 165 // in: path 166 // description: owner of the repo 167 // type: string 168 // required: true 169 // - name: repo 170 // in: path 171 // description: name of the repo 172 // type: string 173 // required: true 174 // - name: body 175 // in: body 176 // schema: 177 // "$ref": "#/definitions/CreateTagOption" 178 // responses: 179 // "200": 180 // "$ref": "#/responses/Tag" 181 // "404": 182 // "$ref": "#/responses/notFound" 183 // "405": 184 // "$ref": "#/responses/empty" 185 // "409": 186 // "$ref": "#/responses/conflict" 187 form := web.GetForm(ctx).(*api.CreateTagOption) 188 189 // If target is not provided use default branch 190 if len(form.Target) == 0 { 191 form.Target = ctx.Repo.Repository.DefaultBranch 192 } 193 194 commit, err := ctx.Repo.GitRepo.GetCommit(form.Target) 195 if err != nil { 196 ctx.Error(http.StatusNotFound, "target not found", fmt.Errorf("target not found: %w", err)) 197 return 198 } 199 200 if err := releaseservice.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, commit.ID.String(), form.TagName, form.Message); err != nil { 201 if models.IsErrTagAlreadyExists(err) { 202 ctx.Error(http.StatusConflict, "tag exist", err) 203 return 204 } 205 if models.IsErrProtectedTagName(err) { 206 ctx.Error(http.StatusMethodNotAllowed, "CreateNewTag", "user not allowed to create protected tag") 207 return 208 } 209 210 ctx.InternalServerError(err) 211 return 212 } 213 214 tag, err := ctx.Repo.GitRepo.GetTag(form.TagName) 215 if err != nil { 216 ctx.InternalServerError(err) 217 return 218 } 219 ctx.JSON(http.StatusCreated, convert.ToTag(ctx.Repo.Repository, tag)) 220 } 221 222 // DeleteTag delete a specific tag of in a repository by name 223 func DeleteTag(ctx *context.APIContext) { 224 // swagger:operation DELETE /repos/{owner}/{repo}/tags/{tag} repository repoDeleteTag 225 // --- 226 // summary: Delete a repository's tag by name 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: tag 241 // in: path 242 // description: name of tag to delete 243 // type: string 244 // required: true 245 // responses: 246 // "204": 247 // "$ref": "#/responses/empty" 248 // "404": 249 // "$ref": "#/responses/notFound" 250 // "405": 251 // "$ref": "#/responses/empty" 252 // "409": 253 // "$ref": "#/responses/conflict" 254 tagName := ctx.Params("*") 255 256 tag, err := repo_model.GetRelease(ctx, ctx.Repo.Repository.ID, tagName) 257 if err != nil { 258 if repo_model.IsErrReleaseNotExist(err) { 259 ctx.NotFound() 260 return 261 } 262 ctx.Error(http.StatusInternalServerError, "GetRelease", err) 263 return 264 } 265 266 if !tag.IsTag { 267 ctx.Error(http.StatusConflict, "IsTag", errors.New("a tag attached to a release cannot be deleted directly")) 268 return 269 } 270 271 if err = releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, tag, ctx.Doer, true); err != nil { 272 if models.IsErrProtectedTagName(err) { 273 ctx.Error(http.StatusMethodNotAllowed, "delTag", "user not allowed to delete protected tag") 274 return 275 } 276 ctx.Error(http.StatusInternalServerError, "DeleteReleaseByID", err) 277 return 278 } 279 280 ctx.Status(http.StatusNoContent) 281 }