mirror of
https://github.com/go-gitea/gitea.git
synced 2025-09-06 18:51:53 +00:00
Rename UpdateBranch API to RenameBranch API (#35374)
Discussed in #35368, originally implemented in #32433
This commit is contained in:
@@ -282,9 +282,9 @@ type CreateBranchRepoOption struct {
|
|||||||
OldRefName string `json:"old_ref_name" binding:"GitRefName;MaxSize(100)"`
|
OldRefName string `json:"old_ref_name" binding:"GitRefName;MaxSize(100)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateBranchRepoOption options when updating a branch in a repository
|
// RenameBranchRepoOption options when renaming a branch in a repository
|
||||||
// swagger:model
|
// swagger:model
|
||||||
type UpdateBranchRepoOption struct {
|
type RenameBranchRepoOption struct {
|
||||||
// New branch name
|
// New branch name
|
||||||
//
|
//
|
||||||
// required: true
|
// required: true
|
||||||
|
@@ -1256,7 +1256,7 @@ func Routes() *web.Router {
|
|||||||
m.Get("/*", repo.GetBranch)
|
m.Get("/*", repo.GetBranch)
|
||||||
m.Delete("/*", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, repo.DeleteBranch)
|
m.Delete("/*", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, repo.DeleteBranch)
|
||||||
m.Post("", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, bind(api.CreateBranchRepoOption{}), repo.CreateBranch)
|
m.Post("", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, bind(api.CreateBranchRepoOption{}), repo.CreateBranch)
|
||||||
m.Patch("/*", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, bind(api.UpdateBranchRepoOption{}), repo.UpdateBranch)
|
m.Patch("/*", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, bind(api.RenameBranchRepoOption{}), repo.RenameBranch)
|
||||||
}, context.ReferencesGitRepo(), reqRepoReader(unit.TypeCode))
|
}, context.ReferencesGitRepo(), reqRepoReader(unit.TypeCode))
|
||||||
m.Group("/branch_protections", func() {
|
m.Group("/branch_protections", func() {
|
||||||
m.Get("", repo.ListBranchProtections)
|
m.Get("", repo.ListBranchProtections)
|
||||||
|
@@ -380,11 +380,11 @@ func ListBranches(ctx *context.APIContext) {
|
|||||||
ctx.JSON(http.StatusOK, apiBranches)
|
ctx.JSON(http.StatusOK, apiBranches)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateBranch updates a repository's branch.
|
// RenameBranch renames a repository's branch.
|
||||||
func UpdateBranch(ctx *context.APIContext) {
|
func RenameBranch(ctx *context.APIContext) {
|
||||||
// swagger:operation PATCH /repos/{owner}/{repo}/branches/{branch} repository repoUpdateBranch
|
// swagger:operation PATCH /repos/{owner}/{repo}/branches/{branch} repository repoRenameBranch
|
||||||
// ---
|
// ---
|
||||||
// summary: Update a branch
|
// summary: Rename a branch
|
||||||
// consumes:
|
// consumes:
|
||||||
// - application/json
|
// - application/json
|
||||||
// produces:
|
// produces:
|
||||||
@@ -408,7 +408,7 @@ func UpdateBranch(ctx *context.APIContext) {
|
|||||||
// - name: body
|
// - name: body
|
||||||
// in: body
|
// in: body
|
||||||
// schema:
|
// schema:
|
||||||
// "$ref": "#/definitions/UpdateBranchRepoOption"
|
// "$ref": "#/definitions/RenameBranchRepoOption"
|
||||||
// responses:
|
// responses:
|
||||||
// "204":
|
// "204":
|
||||||
// "$ref": "#/responses/empty"
|
// "$ref": "#/responses/empty"
|
||||||
@@ -419,7 +419,7 @@ func UpdateBranch(ctx *context.APIContext) {
|
|||||||
// "422":
|
// "422":
|
||||||
// "$ref": "#/responses/validationError"
|
// "$ref": "#/responses/validationError"
|
||||||
|
|
||||||
opt := web.GetForm(ctx).(*api.UpdateBranchRepoOption)
|
opt := web.GetForm(ctx).(*api.RenameBranchRepoOption)
|
||||||
|
|
||||||
oldName := ctx.PathParam("*")
|
oldName := ctx.PathParam("*")
|
||||||
repo := ctx.Repo.Repository
|
repo := ctx.Repo.Repository
|
||||||
|
@@ -90,7 +90,7 @@ type swaggerParameterBodies struct {
|
|||||||
// in:body
|
// in:body
|
||||||
EditRepoOption api.EditRepoOption
|
EditRepoOption api.EditRepoOption
|
||||||
// in:body
|
// in:body
|
||||||
UpdateBranchRepoOption api.UpdateBranchRepoOption
|
RenameBranchRepoOption api.RenameBranchRepoOption
|
||||||
// in:body
|
// in:body
|
||||||
TransferRepoOption api.TransferRepoOption
|
TransferRepoOption api.TransferRepoOption
|
||||||
// in:body
|
// in:body
|
||||||
|
38
templates/swagger/v1_json.tmpl
generated
38
templates/swagger/v1_json.tmpl
generated
@@ -6807,8 +6807,8 @@
|
|||||||
"tags": [
|
"tags": [
|
||||||
"repository"
|
"repository"
|
||||||
],
|
],
|
||||||
"summary": "Update a branch",
|
"summary": "Rename a branch",
|
||||||
"operationId": "repoUpdateBranch",
|
"operationId": "repoRenameBranch",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -6835,7 +6835,7 @@
|
|||||||
"name": "body",
|
"name": "body",
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/UpdateBranchRepoOption"
|
"$ref": "#/definitions/RenameBranchRepoOption"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -27163,6 +27163,22 @@
|
|||||||
},
|
},
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
},
|
},
|
||||||
|
"RenameBranchRepoOption": {
|
||||||
|
"description": "RenameBranchRepoOption options when renaming a branch in a repository",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "New branch name",
|
||||||
|
"type": "string",
|
||||||
|
"uniqueItems": true,
|
||||||
|
"x-go-name": "Name"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
|
},
|
||||||
"RenameOrgOption": {
|
"RenameOrgOption": {
|
||||||
"description": "RenameOrgOption options when renaming an organization",
|
"description": "RenameOrgOption options when renaming an organization",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@@ -28093,22 +28109,6 @@
|
|||||||
},
|
},
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
},
|
},
|
||||||
"UpdateBranchRepoOption": {
|
|
||||||
"description": "UpdateBranchRepoOption options when updating a branch in a repository",
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"name"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"name": {
|
|
||||||
"description": "New branch name",
|
|
||||||
"type": "string",
|
|
||||||
"uniqueItems": true,
|
|
||||||
"x-go-name": "Name"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
|
||||||
},
|
|
||||||
"UpdateFileOptions": {
|
"UpdateFileOptions": {
|
||||||
"description": "UpdateFileOptions options for updating files\nNote: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)",
|
"description": "UpdateFileOptions options for updating files\nNote: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@@ -187,26 +187,26 @@ func testAPICreateBranch(t testing.TB, session *TestSession, user, repo, oldBran
|
|||||||
return resp.Result().StatusCode == status
|
return resp.Result().StatusCode == status
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAPIUpdateBranch(t *testing.T) {
|
func TestAPIRenameBranch(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, _ *url.URL) {
|
onGiteaRun(t, func(t *testing.T, _ *url.URL) {
|
||||||
t.Run("UpdateBranchWithEmptyRepo", func(t *testing.T) {
|
t.Run("RenameBranchWithEmptyRepo", func(t *testing.T) {
|
||||||
testAPIUpdateBranch(t, "user10", "user10", "repo6", "master", "test", http.StatusNotFound)
|
testAPIRenameBranch(t, "user10", "user10", "repo6", "master", "test", http.StatusNotFound)
|
||||||
})
|
})
|
||||||
t.Run("UpdateBranchWithSameBranchNames", func(t *testing.T) {
|
t.Run("RenameBranchWithSameBranchNames", func(t *testing.T) {
|
||||||
resp := testAPIUpdateBranch(t, "user2", "user2", "repo1", "master", "master", http.StatusUnprocessableEntity)
|
resp := testAPIRenameBranch(t, "user2", "user2", "repo1", "master", "master", http.StatusUnprocessableEntity)
|
||||||
assert.Contains(t, resp.Body.String(), "Cannot rename a branch using the same name or rename to a branch that already exists.")
|
assert.Contains(t, resp.Body.String(), "Cannot rename a branch using the same name or rename to a branch that already exists.")
|
||||||
})
|
})
|
||||||
t.Run("UpdateBranchThatAlreadyExists", func(t *testing.T) {
|
t.Run("RenameBranchThatAlreadyExists", func(t *testing.T) {
|
||||||
resp := testAPIUpdateBranch(t, "user2", "user2", "repo1", "master", "branch2", http.StatusUnprocessableEntity)
|
resp := testAPIRenameBranch(t, "user2", "user2", "repo1", "master", "branch2", http.StatusUnprocessableEntity)
|
||||||
assert.Contains(t, resp.Body.String(), "Cannot rename a branch using the same name or rename to a branch that already exists.")
|
assert.Contains(t, resp.Body.String(), "Cannot rename a branch using the same name or rename to a branch that already exists.")
|
||||||
})
|
})
|
||||||
t.Run("UpdateBranchWithNonExistentBranch", func(t *testing.T) {
|
t.Run("RenameBranchWithNonExistentBranch", func(t *testing.T) {
|
||||||
resp := testAPIUpdateBranch(t, "user2", "user2", "repo1", "i-dont-exist", "new-branch-name", http.StatusNotFound)
|
resp := testAPIRenameBranch(t, "user2", "user2", "repo1", "i-dont-exist", "new-branch-name", http.StatusNotFound)
|
||||||
assert.Contains(t, resp.Body.String(), "Branch doesn't exist.")
|
assert.Contains(t, resp.Body.String(), "Branch doesn't exist.")
|
||||||
})
|
})
|
||||||
t.Run("UpdateBranchWithNonAdminDoer", func(t *testing.T) {
|
t.Run("RenameBranchWithNonAdminDoer", func(t *testing.T) {
|
||||||
// don't allow default branch renaming
|
// don't allow default branch renaming
|
||||||
resp := testAPIUpdateBranch(t, "user40", "user2", "repo1", "master", "new-branch-name", http.StatusForbidden)
|
resp := testAPIRenameBranch(t, "user40", "user2", "repo1", "master", "new-branch-name", http.StatusForbidden)
|
||||||
assert.Contains(t, resp.Body.String(), "User must be a repo or site admin to rename default or protected branches.")
|
assert.Contains(t, resp.Body.String(), "User must be a repo or site admin to rename default or protected branches.")
|
||||||
|
|
||||||
// don't allow protected branch renaming
|
// don't allow protected branch renaming
|
||||||
@@ -216,10 +216,10 @@ func TestAPIUpdateBranch(t *testing.T) {
|
|||||||
}).AddTokenAuth(token)
|
}).AddTokenAuth(token)
|
||||||
MakeRequest(t, req, http.StatusCreated)
|
MakeRequest(t, req, http.StatusCreated)
|
||||||
testAPICreateBranchProtection(t, "protected-branch", 1, http.StatusCreated)
|
testAPICreateBranchProtection(t, "protected-branch", 1, http.StatusCreated)
|
||||||
resp = testAPIUpdateBranch(t, "user40", "user2", "repo1", "protected-branch", "new-branch-name", http.StatusForbidden)
|
resp = testAPIRenameBranch(t, "user40", "user2", "repo1", "protected-branch", "new-branch-name", http.StatusForbidden)
|
||||||
assert.Contains(t, resp.Body.String(), "User must be a repo or site admin to rename default or protected branches.")
|
assert.Contains(t, resp.Body.String(), "User must be a repo or site admin to rename default or protected branches.")
|
||||||
})
|
})
|
||||||
t.Run("UpdateBranchWithGlobedBasedProtectionRulesAndAdminAccess", func(t *testing.T) {
|
t.Run("RenameBranchWithGlobedBasedProtectionRulesAndAdminAccess", func(t *testing.T) {
|
||||||
// don't allow branch that falls under glob-based protection rules to be renamed
|
// don't allow branch that falls under glob-based protection rules to be renamed
|
||||||
token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteRepository)
|
token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/branch_protections", &api.BranchProtection{
|
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/branch_protections", &api.BranchProtection{
|
||||||
@@ -234,18 +234,18 @@ func TestAPIUpdateBranch(t *testing.T) {
|
|||||||
}).AddTokenAuth(token)
|
}).AddTokenAuth(token)
|
||||||
MakeRequest(t, req, http.StatusCreated)
|
MakeRequest(t, req, http.StatusCreated)
|
||||||
|
|
||||||
resp := testAPIUpdateBranch(t, "user2", "user2", "repo1", from, "new-branch-name", http.StatusForbidden)
|
resp := testAPIRenameBranch(t, "user2", "user2", "repo1", from, "new-branch-name", http.StatusForbidden)
|
||||||
assert.Contains(t, resp.Body.String(), "Branch is protected by glob-based protection rules.")
|
assert.Contains(t, resp.Body.String(), "Branch is protected by glob-based protection rules.")
|
||||||
})
|
})
|
||||||
t.Run("UpdateBranchNormalScenario", func(t *testing.T) {
|
t.Run("RenameBranchNormalScenario", func(t *testing.T) {
|
||||||
testAPIUpdateBranch(t, "user2", "user2", "repo1", "branch2", "new-branch-name", http.StatusNoContent)
|
testAPIRenameBranch(t, "user2", "user2", "repo1", "branch2", "new-branch-name", http.StatusNoContent)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAPIUpdateBranch(t *testing.T, doerName, ownerName, repoName, from, to string, expectedHTTPStatus int) *httptest.ResponseRecorder {
|
func testAPIRenameBranch(t *testing.T, doerName, ownerName, repoName, from, to string, expectedHTTPStatus int) *httptest.ResponseRecorder {
|
||||||
token := getUserToken(t, doerName, auth_model.AccessTokenScopeWriteRepository)
|
token := getUserToken(t, doerName, auth_model.AccessTokenScopeWriteRepository)
|
||||||
req := NewRequestWithJSON(t, "PATCH", "api/v1/repos/"+ownerName+"/"+repoName+"/branches/"+from, &api.UpdateBranchRepoOption{
|
req := NewRequestWithJSON(t, "PATCH", "api/v1/repos/"+ownerName+"/"+repoName+"/branches/"+from, &api.RenameBranchRepoOption{
|
||||||
Name: to,
|
Name: to,
|
||||||
}).AddTokenAuth(token)
|
}).AddTokenAuth(token)
|
||||||
return MakeRequest(t, req, expectedHTTPStatus)
|
return MakeRequest(t, req, expectedHTTPStatus)
|
||||||
|
Reference in New Issue
Block a user