mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	[API] Milestone endpoints accept names too (#12649)
* API: Milestone endpoints accept names too * add test * rename Co-authored-by: Lauris BH <lauris@nix.lv>
This commit is contained in:
		@@ -61,6 +61,11 @@ func TestAPIIssuesMilestone(t *testing.T) {
 | 
			
		||||
	DecodeJSON(t, resp, &apiMilestones)
 | 
			
		||||
	assert.Len(t, apiMilestones, 4)
 | 
			
		||||
 | 
			
		||||
	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/milestones/%s?token=%s", owner.Name, repo.Name, apiMilestones[2].Title, token))
 | 
			
		||||
	resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
	DecodeJSON(t, resp, &apiMilestone)
 | 
			
		||||
	assert.EqualValues(t, apiMilestones[2], apiMilestone)
 | 
			
		||||
 | 
			
		||||
	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/milestones?state=%s&name=%s&token=%s", owner.Name, repo.Name, "all", "milestone2", token))
 | 
			
		||||
	resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
	DecodeJSON(t, resp, &apiMilestones)
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ package repo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
@@ -73,7 +74,7 @@ func ListMilestones(ctx *context.APIContext) {
 | 
			
		||||
	ctx.JSON(http.StatusOK, &apiMilestones)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetMilestone get a milestone for a repository
 | 
			
		||||
// GetMilestone get a milestone for a repository by ID and if not available by name
 | 
			
		||||
func GetMilestone(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation GET /repos/{owner}/{repo}/milestones/{id} issue issueGetMilestone
 | 
			
		||||
	// ---
 | 
			
		||||
@@ -93,23 +94,18 @@ func GetMilestone(ctx *context.APIContext) {
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: id
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: id of the milestone
 | 
			
		||||
	//   type: integer
 | 
			
		||||
	//   format: int64
 | 
			
		||||
	//   description: the milestone to get, identified by ID and if not available by name
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// responses:
 | 
			
		||||
	//   "200":
 | 
			
		||||
	//     "$ref": "#/responses/Milestone"
 | 
			
		||||
 | 
			
		||||
	milestone, err := models.GetMilestoneByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if models.IsErrMilestoneNotExist(err) {
 | 
			
		||||
			ctx.NotFound()
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.Error(http.StatusInternalServerError, "GetMilestoneByRepoID", err)
 | 
			
		||||
		}
 | 
			
		||||
	milestone := getMilestoneByIDOrName(ctx)
 | 
			
		||||
	if ctx.Written() {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.JSON(http.StatusOK, convert.ToAPIMilestone(milestone))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -165,7 +161,7 @@ func CreateMilestone(ctx *context.APIContext, form api.CreateMilestoneOption) {
 | 
			
		||||
	ctx.JSON(http.StatusCreated, convert.ToAPIMilestone(milestone))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EditMilestone modify a milestone for a repository
 | 
			
		||||
// EditMilestone modify a milestone for a repository by ID and if not available by name
 | 
			
		||||
func EditMilestone(ctx *context.APIContext, form api.EditMilestoneOption) {
 | 
			
		||||
	// swagger:operation PATCH /repos/{owner}/{repo}/milestones/{id} issue issueEditMilestone
 | 
			
		||||
	// ---
 | 
			
		||||
@@ -187,9 +183,8 @@ func EditMilestone(ctx *context.APIContext, form api.EditMilestoneOption) {
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: id
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: id of the milestone
 | 
			
		||||
	//   type: integer
 | 
			
		||||
	//   format: int64
 | 
			
		||||
	//   description: the milestone to edit, identified by ID and if not available by name
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: body
 | 
			
		||||
	//   in: body
 | 
			
		||||
@@ -199,13 +194,8 @@ func EditMilestone(ctx *context.APIContext, form api.EditMilestoneOption) {
 | 
			
		||||
	//   "200":
 | 
			
		||||
	//     "$ref": "#/responses/Milestone"
 | 
			
		||||
 | 
			
		||||
	milestone, err := models.GetMilestoneByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if models.IsErrMilestoneNotExist(err) {
 | 
			
		||||
			ctx.NotFound()
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.Error(http.StatusInternalServerError, "GetMilestoneByRepoID", err)
 | 
			
		||||
		}
 | 
			
		||||
	milestone := getMilestoneByIDOrName(ctx)
 | 
			
		||||
	if ctx.Written() {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -231,7 +221,7 @@ func EditMilestone(ctx *context.APIContext, form api.EditMilestoneOption) {
 | 
			
		||||
	ctx.JSON(http.StatusOK, convert.ToAPIMilestone(milestone))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteMilestone delete a milestone for a repository
 | 
			
		||||
// DeleteMilestone delete a milestone for a repository by ID and if not available by name
 | 
			
		||||
func DeleteMilestone(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation DELETE /repos/{owner}/{repo}/milestones/{id} issue issueDeleteMilestone
 | 
			
		||||
	// ---
 | 
			
		||||
@@ -249,17 +239,49 @@ func DeleteMilestone(ctx *context.APIContext) {
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: id
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: id of the milestone to delete
 | 
			
		||||
	//   type: integer
 | 
			
		||||
	//   format: int64
 | 
			
		||||
	//   description: the milestone to delete, identified by ID and if not available by name
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// responses:
 | 
			
		||||
	//   "204":
 | 
			
		||||
	//     "$ref": "#/responses/empty"
 | 
			
		||||
 | 
			
		||||
	if err := models.DeleteMilestoneByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")); err != nil {
 | 
			
		||||
	m := getMilestoneByIDOrName(ctx)
 | 
			
		||||
	if ctx.Written() {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := models.DeleteMilestoneByRepoID(ctx.Repo.Repository.ID, m.ID); err != nil {
 | 
			
		||||
		ctx.Error(http.StatusInternalServerError, "DeleteMilestoneByRepoID", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Status(http.StatusNoContent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getMilestoneByIDOrName get milestone by ID and if not available by name
 | 
			
		||||
func getMilestoneByIDOrName(ctx *context.APIContext) *models.Milestone {
 | 
			
		||||
	mile := ctx.Params(":id")
 | 
			
		||||
	mileID, _ := strconv.ParseInt(mile, 0, 64)
 | 
			
		||||
 | 
			
		||||
	if mileID != 0 {
 | 
			
		||||
		milestone, err := models.GetMilestoneByRepoID(ctx.Repo.Repository.ID, mileID)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			return milestone
 | 
			
		||||
		} else if !models.IsErrMilestoneNotExist(err) {
 | 
			
		||||
			ctx.Error(http.StatusInternalServerError, "GetMilestoneByRepoID", err)
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	milestone, err := models.GetMilestoneByRepoIDANDName(ctx.Repo.Repository.ID, mile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if models.IsErrMilestoneNotExist(err) {
 | 
			
		||||
			ctx.NotFound()
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		ctx.Error(http.StatusInternalServerError, "GetMilestoneByRepoID", err)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return milestone
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6353,9 +6353,8 @@
 | 
			
		||||
            "required": true
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            "type": "integer",
 | 
			
		||||
            "format": "int64",
 | 
			
		||||
            "description": "id of the milestone",
 | 
			
		||||
            "type": "string",
 | 
			
		||||
            "description": "the milestone to get, identified by ID and if not available by name",
 | 
			
		||||
            "name": "id",
 | 
			
		||||
            "in": "path",
 | 
			
		||||
            "required": true
 | 
			
		||||
@@ -6389,9 +6388,8 @@
 | 
			
		||||
            "required": true
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            "type": "integer",
 | 
			
		||||
            "format": "int64",
 | 
			
		||||
            "description": "id of the milestone to delete",
 | 
			
		||||
            "type": "string",
 | 
			
		||||
            "description": "the milestone to delete, identified by ID and if not available by name",
 | 
			
		||||
            "name": "id",
 | 
			
		||||
            "in": "path",
 | 
			
		||||
            "required": true
 | 
			
		||||
@@ -6431,9 +6429,8 @@
 | 
			
		||||
            "required": true
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            "type": "integer",
 | 
			
		||||
            "format": "int64",
 | 
			
		||||
            "description": "id of the milestone",
 | 
			
		||||
            "type": "string",
 | 
			
		||||
            "description": "the milestone to edit, identified by ID and if not available by name",
 | 
			
		||||
            "name": "id",
 | 
			
		||||
            "in": "path",
 | 
			
		||||
            "required": true
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user