summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--integrations/api_releases_test.go20
-rw-r--r--integrations/api_repo_git_tags_test.go24
-rw-r--r--routers/api/v1/api.go5
-rw-r--r--routers/api/v1/repo/release_tags.go29
-rw-r--r--routers/api/v1/repo/tag.go56
-rw-r--r--templates/swagger/v1_json.tmpl59
6 files changed, 157 insertions, 36 deletions
diff --git a/integrations/api_releases_test.go b/integrations/api_releases_test.go
index 2b310d11e0..26bf752cca 100644
--- a/integrations/api_releases_test.go
+++ b/integrations/api_releases_test.go
@@ -154,7 +154,7 @@ func TestAPIGetReleaseByTag(t *testing.T) {
assert.EqualValues(t, "Not Found", err.Message)
}
-func TestAPIDeleteTagByName(t *testing.T) {
+func TestAPIDeleteReleaseByTagName(t *testing.T) {
defer prepareTestEnv(t)()
repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
@@ -162,17 +162,17 @@ func TestAPIDeleteTagByName(t *testing.T) {
session := loginUser(t, owner.LowerName)
token := getTokenForLoggedInUser(t, session)
- urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/delete-tag?token=%s",
- owner.Name, repo.Name, token)
+ createNewReleaseUsingAPI(t, session, token, owner, repo, "release-tag", "", "Release Tag", "test")
- req := NewRequestf(t, http.MethodDelete, urlStr)
+ // delete release
+ req := NewRequestf(t, http.MethodDelete, fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/release-tag?token=%s", owner.Name, repo.Name, token))
_ = session.MakeRequest(t, req, http.StatusNoContent)
- // Make sure that actual releases can't be deleted outright
- createNewReleaseUsingAPI(t, session, token, owner, repo, "release-tag", "", "Release Tag", "test")
- urlStr = fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/release-tag?token=%s",
- owner.Name, repo.Name, token)
+ // make sure release is deleted
+ req = NewRequestf(t, http.MethodDelete, fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/release-tag?token=%s", owner.Name, repo.Name, token))
+ _ = session.MakeRequest(t, req, http.StatusNotFound)
- req = NewRequestf(t, http.MethodDelete, urlStr)
- _ = session.MakeRequest(t, req, http.StatusConflict)
+ // delete release tag too
+ req = NewRequestf(t, http.MethodDelete, fmt.Sprintf("/api/v1/repos/%s/%s/tags/release-tag?token=%s", owner.Name, repo.Name, token))
+ _ = session.MakeRequest(t, req, http.StatusNoContent)
}
diff --git a/integrations/api_repo_git_tags_test.go b/integrations/api_repo_git_tags_test.go
index ad710a4520..bf6fc7c858 100644
--- a/integrations/api_repo_git_tags_test.go
+++ b/integrations/api_repo_git_tags_test.go
@@ -5,6 +5,7 @@
package integrations
import (
+ "fmt"
"net/http"
"testing"
@@ -59,3 +60,26 @@ func TestAPIGitTags(t *testing.T) {
badReq := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/git/tags/%s?token=%s", user.Name, repo.Name, commit.ID.String(), token)
session.MakeRequest(t, badReq, http.StatusBadRequest)
}
+
+func TestAPIDeleteTagByName(t *testing.T) {
+ defer prepareTestEnv(t)()
+
+ repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
+ owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
+ session := loginUser(t, owner.LowerName)
+ token := getTokenForLoggedInUser(t, session)
+
+ urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/tags/delete-tag?token=%s",
+ owner.Name, repo.Name, token)
+
+ req := NewRequestf(t, http.MethodDelete, urlStr)
+ _ = session.MakeRequest(t, req, http.StatusNoContent)
+
+ // Make sure that actual releases can't be deleted outright
+ createNewReleaseUsingAPI(t, session, token, owner, repo, "release-tag", "", "Release Tag", "test")
+ urlStr = fmt.Sprintf("/api/v1/repos/%s/%s/tags/release-tag?token=%s",
+ owner.Name, repo.Name, token)
+
+ req = NewRequestf(t, http.MethodDelete, urlStr)
+ _ = session.MakeRequest(t, req, http.StatusConflict)
+}
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 42b52db936..9c21107a28 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -754,6 +754,7 @@ func Routes() *web.Route {
}, reqToken(), reqAdmin())
m.Group("/tags", func() {
m.Get("", repo.ListTags)
+ m.Delete("/{tag}", repo.DeleteTag)
}, reqRepoReader(models.UnitTypeCode), context.ReferencesGitRepo(true))
m.Group("/keys", func() {
m.Combo("").Get(repo.ListDeployKeys).
@@ -862,8 +863,8 @@ func Routes() *web.Route {
})
m.Group("/tags", func() {
m.Combo("/{tag}").
- Get(repo.GetReleaseTag).
- Delete(reqToken(), reqRepoWriter(models.UnitTypeReleases), repo.DeleteReleaseTag)
+ Get(repo.GetReleaseByTag).
+ Delete(reqToken(), reqRepoWriter(models.UnitTypeReleases), repo.DeleteReleaseByTag)
})
}, reqRepoReader(models.UnitTypeReleases))
m.Post("/mirror-sync", reqToken(), reqRepoWriter(models.UnitTypeCode), repo.MirrorSync)
diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go
index 70011a6a8e..4b853d44bb 100644
--- a/routers/api/v1/repo/release_tags.go
+++ b/routers/api/v1/repo/release_tags.go
@@ -5,7 +5,6 @@
package repo
import (
- "errors"
"net/http"
"code.gitea.io/gitea/models"
@@ -14,9 +13,9 @@ import (
releaseservice "code.gitea.io/gitea/services/release"
)
-// GetReleaseTag get a single release of a repository by its tagname
-func GetReleaseTag(ctx *context.APIContext) {
- // swagger:operation GET /repos/{owner}/{repo}/releases/tags/{tag} repository repoGetReleaseTag
+// GetReleaseByTag get a single release of a repository by tag name
+func GetReleaseByTag(ctx *context.APIContext) {
+ // swagger:operation GET /repos/{owner}/{repo}/releases/tags/{tag} repository repoGetReleaseByTag
// ---
// summary: Get a release by tag name
// produces:
@@ -34,7 +33,7 @@ func GetReleaseTag(ctx *context.APIContext) {
// required: true
// - name: tag
// in: path
- // description: tagname of the release to get
+ // description: tag name of the release to get
// type: string
// required: true
// responses:
@@ -67,11 +66,11 @@ func GetReleaseTag(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, convert.ToRelease(release))
}
-// DeleteReleaseTag delete a tag from a repository
-func DeleteReleaseTag(ctx *context.APIContext) {
- // swagger:operation DELETE /repos/{owner}/{repo}/releases/tags/{tag} repository repoDeleteReleaseTag
+// DeleteReleaseByTag delete a release from a repository by tag name
+func DeleteReleaseByTag(ctx *context.APIContext) {
+ // swagger:operation DELETE /repos/{owner}/{repo}/releases/tags/{tag} repository repoDeleteReleaseByTag
// ---
- // summary: Delete a release tag
+ // summary: Delete a release by tag name
// parameters:
// - name: owner
// in: path
@@ -85,7 +84,7 @@ func DeleteReleaseTag(ctx *context.APIContext) {
// required: true
// - name: tag
// in: path
- // description: name of the tag to delete
+ // description: tag name of the release to delete
// type: string
// required: true
// responses:
@@ -93,27 +92,25 @@ func DeleteReleaseTag(ctx *context.APIContext) {
// "$ref": "#/responses/empty"
// "404":
// "$ref": "#/responses/notFound"
- // "409":
- // "$ref": "#/responses/conflict"
tag := ctx.Params(":tag")
release, err := models.GetRelease(ctx.Repo.Repository.ID, tag)
if err != nil {
if models.IsErrReleaseNotExist(err) {
- ctx.Error(http.StatusNotFound, "GetRelease", err)
+ ctx.NotFound()
return
}
ctx.Error(http.StatusInternalServerError, "GetRelease", err)
return
}
- if !release.IsTag {
- ctx.Error(http.StatusConflict, "IsTag", errors.New("a tag attached to a release cannot be deleted directly"))
+ if release.IsTag {
+ ctx.NotFound()
return
}
- if err := releaseservice.DeleteReleaseByID(release.ID, ctx.User, true); err != nil {
+ if err = releaseservice.DeleteReleaseByID(release.ID, ctx.User, false); err != nil {
ctx.Error(http.StatusInternalServerError, "DeleteReleaseByID", err)
}
diff --git a/routers/api/v1/repo/tag.go b/routers/api/v1/repo/tag.go
index 76c612bea4..ec9b541bd4 100644
--- a/routers/api/v1/repo/tag.go
+++ b/routers/api/v1/repo/tag.go
@@ -5,12 +5,15 @@
package repo
import (
+ "errors"
"net/http"
+ "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/convert"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/v1/utils"
+ releaseservice "code.gitea.io/gitea/services/release"
)
// ListTags list all the tags of a repository
@@ -104,3 +107,56 @@ func GetTag(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, convert.ToAnnotatedTag(ctx.Repo.Repository, tag, commit))
}
}
+
+// DeleteTag delete a specific tag of in a repository by name
+func DeleteTag(ctx *context.APIContext) {
+ // swagger:operation DELETE /repos/{owner}/{repo}/tags/{tag} repository repoDeleteTag
+ // ---
+ // summary: Delete a repository's tag by name
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: owner
+ // in: path
+ // description: owner of the repo
+ // type: string
+ // required: true
+ // - name: repo
+ // in: path
+ // description: name of the repo
+ // type: string
+ // required: true
+ // - name: tag
+ // in: path
+ // description: name of tag to delete
+ // type: string
+ // required: true
+ // responses:
+ // "204":
+ // "$ref": "#/responses/empty"
+ // "404":
+ // "$ref": "#/responses/notFound"
+ // "409":
+ // "$ref": "#/responses/conflict"
+
+ tag, err := models.GetRelease(ctx.Repo.Repository.ID, ctx.Params("tag"))
+ if err != nil {
+ if models.IsErrReleaseNotExist(err) {
+ ctx.NotFound()
+ return
+ }
+ ctx.Error(http.StatusInternalServerError, "GetRelease", err)
+ return
+ }
+
+ if !tag.IsTag {
+ ctx.Error(http.StatusConflict, "IsTag", errors.New("a tag attached to a release cannot be deleted directly"))
+ return
+ }
+
+ if err = releaseservice.DeleteReleaseByID(tag.ID, ctx.User, true); err != nil {
+ ctx.Error(http.StatusInternalServerError, "DeleteReleaseByID", err)
+ }
+
+ ctx.Status(http.StatusNoContent)
+}
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index 5a3be37b4a..45f396f283 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -7964,7 +7964,7 @@
"repository"
],
"summary": "Get a release by tag name",
- "operationId": "repoGetReleaseTag",
+ "operationId": "repoGetReleaseByTag",
"parameters": [
{
"type": "string",
@@ -7982,7 +7982,7 @@
},
{
"type": "string",
- "description": "tagname of the release to get",
+ "description": "tag name of the release to get",
"name": "tag",
"in": "path",
"required": true
@@ -8001,8 +8001,8 @@
"tags": [
"repository"
],
- "summary": "Delete a release tag",
- "operationId": "repoDeleteReleaseTag",
+ "summary": "Delete a release by tag name",
+ "operationId": "repoDeleteReleaseByTag",
"parameters": [
{
"type": "string",
@@ -8020,7 +8020,7 @@
},
{
"type": "string",
- "description": "name of the tag to delete",
+ "description": "tag name of the release to delete",
"name": "tag",
"in": "path",
"required": true
@@ -8032,9 +8032,6 @@
},
"404": {
"$ref": "#/responses/notFound"
- },
- "409": {
- "$ref": "#/responses/conflict"
}
}
}
@@ -8815,6 +8812,52 @@
}
}
},
+ "/repos/{owner}/{repo}/tags/{tag}": {
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a repository's tag by name",
+ "operationId": "repoDeleteTag",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of tag to delete",
+ "name": "tag",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "409": {
+ "$ref": "#/responses/conflict"
+ }
+ }
+ }
+ },
"/repos/{owner}/{repo}/teams": {
"get": {
"produces": [