0
0
mirror of https://github.com/go-gitea/gitea.git synced 2025-12-08 11:25:21 +01:00

Add UpdateBranch API (#35368).

This is CreateBranch for branches that already exist making it possible
to reset branch to an arbitrary commit.

Consistent with CreateFile/UpdateFile new branches are created by POST
and existing branches updated by PUT.
This commit is contained in:
Michal Suchanek 2025-12-06 12:16:57 +01:00
parent 124d0d4ec4
commit b8597b76b2
14 changed files with 301 additions and 32 deletions

View File

@ -749,6 +749,11 @@
"path": "github.com/jhillyerd/enmime/LICENSE",
"licenseText": "The MIT License (MIT)\n\nCopyright (c) 2012-2016 James Hillyerd, All Rights Reserved\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
},
{
"name": "github.com/jinzhu/copier",
"path": "github.com/jinzhu/copier/License",
"licenseText": "The MIT License (MIT)\n\nCopyright (c) 2015 Jinzhu\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
},
{
"name": "github.com/josharian/intern",
"path": "github.com/josharian/intern/license.md",

1
go.mod
View File

@ -77,6 +77,7 @@ require (
github.com/huandu/xstrings v1.5.0
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056
github.com/jhillyerd/enmime v1.3.0
github.com/jinzhu/copier v0.4.0
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/klauspost/compress v1.18.0
github.com/klauspost/cpuid/v2 v2.3.0

2
go.sum
View File

@ -510,6 +510,8 @@ github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZ
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/jhillyerd/enmime v1.3.0 h1:LV5kzfLidiOr8qRGIpYYmUZCnhrPbcFAnAFUnWn99rw=
github.com/jhillyerd/enmime v1.3.0/go.mod h1:6c6jg5HdRRV2FtvVL69LjiX1M8oE0xDX9VEhV3oy4gs=
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=

View File

@ -292,6 +292,30 @@ type RenameBranchRepoOption struct {
Name string `json:"name" binding:"Required;GitRefName;MaxSize(100)"`
}
// UpdateBranchRepoOption options when updating a branch reference in a repository
// swagger:model
type UpdateBranchRepoOption struct {
// Name of the branch to update
//
// required: true
// unique: true
BranchName string `json:"new_branch_name" binding:"Required;GitRefName;MaxSize(100)"`
// the commit ID (SHA) for the branch that already exists to update
SHA string `json:"sha" binding:"Required"`
// Deprecated: true
// Name of the old branch to reset to
//
// unique: true
OldBranchName string `json:"old_branch_name" binding:"GitRefName;MaxSize(100)"`
// Name of the old branch/tag/commit to reset to
//
// unique: true
OldRefName string `json:"old_ref_name" binding:"GitRefName;MaxSize(100)"`
}
// TransferRepoOption options when transfer a repository's ownership
// swagger:model
type TransferRepoOption struct {

View File

@ -1242,6 +1242,7 @@ func Routes() *web.Router {
m.Get("/*", repo.GetBranch)
m.Delete("/*", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, repo.DeleteBranch)
m.Post("", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, bind(api.CreateBranchRepoOption{}), repo.CreateBranch)
m.Put("", 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))
m.Group("/branch_protections", func() {

View File

@ -6,6 +6,7 @@ package repo
import (
"errors"
"fmt"
"net/http"
"code.gitea.io/gitea/models/db"
@ -26,6 +27,8 @@ import (
pull_service "code.gitea.io/gitea/services/pull"
release_service "code.gitea.io/gitea/services/release"
repo_service "code.gitea.io/gitea/services/repository"
"github.com/jinzhu/copier"
)
// GetBranch get a branch of a repository
@ -203,6 +206,62 @@ func CreateBranch(ctx *context.APIContext) {
// "423":
// "$ref": "#/responses/repoArchivedError"
optCreate := web.GetForm(ctx).(*api.CreateBranchRepoOption)
opt := api.UpdateBranchRepoOption{}
err := copier.Copy(&opt, optCreate)
if err != nil {
ctx.APIError(http.StatusInternalServerError, fmt.Sprintf("Error processing request %s.", err))
return
}
CreateUpdateRepoBranch(ctx, &opt)
}
// UpdateBranch update (reset) a branch in a user's repository
func UpdateBranch(ctx *context.APIContext) {
// swagger:operation PUT /repos/{owner}/{repo}/branches repository repoUpdateBranch
// ---
// summary: Update a branch
// consumes:
// - application/json
// 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: body
// in: body
// schema:
// "$ref": "#/definitions/UpdateBranchRepoOption"
// responses:
// "201":
// "$ref": "#/responses/Branch"
// "403":
// description: The branch is archived or a mirror.
// "404":
// description: The branch does not exist.
// "409":
// description: The branch SHA does not match.
// "423":
// "$ref": "#/responses/repoArchivedError"
opt := web.GetForm(ctx).(*api.UpdateBranchRepoOption)
CreateUpdateRepoBranch(ctx, opt)
}
func CreateUpdateRepoBranch(ctx *context.APIContext, opt *api.UpdateBranchRepoOption) {
var oldCommit *git.Commit
var err error
if ctx.Repo.Repository.IsEmpty {
ctx.APIError(http.StatusNotFound, "Git Repository is empty.")
return
@ -213,11 +272,6 @@ func CreateBranch(ctx *context.APIContext) {
return
}
opt := web.GetForm(ctx).(*api.CreateBranchRepoOption)
var oldCommit *git.Commit
var err error
if len(opt.OldRefName) > 0 {
oldCommit, err = ctx.Repo.GitRepo.GetCommit(opt.OldRefName)
if err != nil {
@ -243,14 +297,16 @@ func CreateBranch(ctx *context.APIContext) {
}
}
err = repo_service.CreateNewBranchFromCommit(ctx, ctx.Doer, ctx.Repo.Repository, oldCommit.ID.String(), opt.BranchName)
err = repo_service.CreateUpdateBranchFromCommit(ctx, ctx.Doer, ctx.Repo.Repository, oldCommit.ID.String(), opt.BranchName, opt.SHA)
if err != nil {
if git_model.IsErrBranchNotExist(err) {
ctx.APIError(http.StatusNotFound, "The old branch does not exist")
} else if release_service.IsErrTagAlreadyExists(err) {
ctx.APIError(http.StatusConflict, "The branch with the same tag already exists.")
} else if git_model.IsErrBranchAlreadyExists(err) || git.IsErrPushOutOfDate(err) {
} else if git_model.IsErrBranchAlreadyExists(err) {
ctx.APIError(http.StatusConflict, "The branch already exists.")
} else if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) {
ctx.APIError(http.StatusConflict, "The branch SHA does not match.")
} else if git_model.IsErrBranchNameConflict(err) {
ctx.APIError(http.StatusConflict, "The branch with the same name already exists.")
} else {

View File

@ -148,6 +148,9 @@ type swaggerParameterBodies struct {
// in:body
CreateBranchRepoOption api.CreateBranchRepoOption
// in:body
UpdateBranchRepoOption api.UpdateBranchRepoOption
// in:body
CreateBranchProtectionOption api.CreateBranchProtectionOption

View File

@ -194,9 +194,9 @@ func CreateBranch(ctx *context.Context) {
}
err = release_service.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, target, form.NewBranchName, "")
} else if ctx.Repo.RefFullName.IsBranch() {
err = repo_service.CreateNewBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName)
err = repo_service.CreateUpdateBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName, "")
} else {
err = repo_service.CreateNewBranchFromCommit(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.CommitID, form.NewBranchName)
err = repo_service.CreateUpdateBranchFromCommit(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.CommitID, form.NewBranchName, "")
}
if err != nil {
if release_service.IsErrProtectedTagName(err) {

View File

@ -37,14 +37,14 @@ import (
"xorm.io/builder"
)
// CreateNewBranch creates a new repository branch
func CreateNewBranch(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldBranchName, branchName string) (err error) {
// CreateUpdateBranch creates or updates a repository branch
func CreateUpdateBranch(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldBranchName, branchName, sha string) (err error) {
branch, err := git_model.GetBranch(ctx, repo.ID, oldBranchName)
if err != nil {
return err
}
return CreateNewBranchFromCommit(ctx, doer, repo, branch.CommitID, branchName)
return CreateUpdateBranchFromCommit(ctx, doer, repo, branch.CommitID, branchName, sha)
}
// Branch contains the branch information
@ -373,23 +373,36 @@ func SyncBranchesToDB(ctx context.Context, repoID, pusherID int64, branchNames,
})
}
// CreateNewBranchFromCommit creates a new repository branch
func CreateNewBranchFromCommit(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, commitID, branchName string) (err error) {
// CreateUpdateBranchFromCommit creates or updates a repository branch
func CreateUpdateBranchFromCommit(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, commitID, branchName, sha string) (err error) {
err = repo.MustNotBeArchived()
if err != nil {
return err
}
// Check if branch name can be used
if err := checkBranchName(ctx, repo, branchName); err != nil {
return err
if sha != "" {
_, err := git_model.GetBranch(ctx, repo.ID, branchName)
if err != nil {
return err
}
} else {
// Check if branch name can be used
if err := checkBranchName(ctx, repo, branchName); err != nil {
return err
}
}
if err := git.Push(ctx, repo.RepoPath(), git.PushOptions{
pushOpts := git.PushOptions{
Remote: repo.RepoPath(),
Branch: fmt.Sprintf("%s:%s%s", commitID, git.BranchPrefix, branchName),
Env: repo_module.PushingEnvironment(doer, repo),
}); err != nil {
}
if sha != "" {
pushOpts.ForceWithLease = fmt.Sprintf("%s:%s", git.BranchPrefix+branchName, sha)
}
if err := git.Push(ctx, repo.RepoPath(), pushOpts); err != nil {
if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) {
return err
}

View File

@ -6654,6 +6654,59 @@
}
}
},
"put": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Update a branch",
"operationId": "repoUpdateBranch",
"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
},
{
"name": "body",
"in": "body",
"schema": {
"$ref": "#/definitions/UpdateBranchRepoOption"
}
}
],
"responses": {
"201": {
"$ref": "#/responses/Branch"
},
"403": {
"description": "The branch is archived or a mirror."
},
"404": {
"description": "The branch does not exist."
},
"409": {
"description": "The branch SHA does not match."
},
"423": {
"$ref": "#/responses/repoArchivedError"
}
}
},
"post": {
"consumes": [
"application/json"
@ -28702,6 +28755,39 @@
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"UpdateBranchRepoOption": {
"description": "UpdateBranchRepoOption options when updating a branch reference in a repository",
"type": "object",
"required": [
"new_branch_name"
],
"properties": {
"new_branch_name": {
"description": "Name of the branch to update",
"type": "string",
"uniqueItems": true,
"x-go-name": "BranchName"
},
"old_branch_name": {
"description": "Deprecated: true\nName of the old branch to reset to",
"type": "string",
"uniqueItems": true,
"x-go-name": "OldBranchName"
},
"old_ref_name": {
"description": "Name of the old branch/tag/commit to reset to",
"type": "string",
"uniqueItems": true,
"x-go-name": "OldRefName"
},
"sha": {
"description": "the commit ID (SHA) for the branch that already exists to update",
"type": "string",
"x-go-name": "SHA"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"UpdateFileOptions": {
"description": "UpdateFileOptions options for updating or creating a file\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",

View File

@ -412,7 +412,7 @@ jobs:
assert.NoError(t, err)
// create a branch
err = repo_service.CreateNewBranchFromCommit(t.Context(), user2, repo, branch.CommitID, "test-create-branch")
err = repo_service.CreateUpdateBranchFromCommit(t.Context(), user2, repo, branch.CommitID, "test-create-branch", "")
assert.NoError(t, err)
run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
Title: "add workflow",
@ -530,7 +530,7 @@ jobs:
// create a new branch
testBranch := "test-branch"
err = repo_service.CreateNewBranch(t.Context(), user2, repo, "main", testBranch)
err = repo_service.CreateUpdateBranch(t.Context(), user2, repo, "main", testBranch, "")
assert.NoError(t, err)
// create Pull
@ -1509,7 +1509,7 @@ jobs:
assert.NoError(t, err)
// create a branch
err = repo_service.CreateNewBranchFromCommit(t.Context(), user2, repo, branch.CommitID, "test-action-run-name-with-variables")
err = repo_service.CreateUpdateBranchFromCommit(t.Context(), user2, repo, branch.CommitID, "test-action-run-name-with-variables", "")
assert.NoError(t, err)
run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
Title: user2.LoginName + " is running this workflow",
@ -1583,7 +1583,7 @@ jobs:
assert.NoError(t, err)
// create a branch
err = repo_service.CreateNewBranchFromCommit(t.Context(), user2, repo, branch.CommitID, "test-action-run-name")
err = repo_service.CreateUpdateBranchFromCommit(t.Context(), user2, repo, branch.CommitID, "test-action-run-name", "")
assert.NoError(t, err)
run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
Title: "run name without variables",

View File

@ -4,6 +4,7 @@
package integration
import (
"encoding/base64"
"net/http"
"net/http/httptest"
"net/url"
@ -18,14 +19,14 @@ import (
"github.com/stretchr/testify/assert"
)
func testAPIGetBranch(t *testing.T, branchName string, exists bool) {
token := getUserToken(t, "user2", auth_model.AccessTokenScopeReadRepository)
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/branches/%s", branchName).
func testAPIGetBranch(t *testing.T, user, repo, branchName string, exists bool) string {
token := getUserToken(t, user, auth_model.AccessTokenScopeReadRepository)
req := NewRequestf(t, "GET", "/api/v1/repos/"+user+"/"+repo+"/branches/%s", branchName).
AddTokenAuth(token)
resp := MakeRequest(t, req, NoExpectedStatus)
if !exists {
assert.Equal(t, http.StatusNotFound, resp.Code)
return
return ""
}
assert.Equal(t, http.StatusOK, resp.Code)
var branch api.Branch
@ -33,6 +34,7 @@ func testAPIGetBranch(t *testing.T, branchName string, exists bool) {
assert.Equal(t, branchName, branch.Name)
assert.True(t, branch.UserCanPush)
assert.True(t, branch.UserCanMerge)
return branch.Commit.ID
}
func testAPIGetBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) *api.BranchProtection {
@ -103,7 +105,7 @@ func TestAPIGetBranch(t *testing.T) {
{"feature/1", true},
{"feature/1/doesnotexist", false},
} {
testAPIGetBranch(t, test.BranchName, test.Exists)
testAPIGetBranch(t, "user2", "repo1", test.BranchName, test.Exists)
}
}
@ -113,7 +115,8 @@ func TestAPICreateBranch(t *testing.T) {
func testAPICreateBranches(t *testing.T, giteaURL *url.URL) {
username := "user2"
ctx := NewAPITestContext(t, username, "my-noo-repo", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
reponame := "my-noo-repo"
ctx := NewAPITestContext(t, username, reponame, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
giteaURL.Path = ctx.GitPath()
t.Run("CreateRepo", doAPICreateRepository(ctx, false))
@ -164,7 +167,7 @@ func testAPICreateBranches(t *testing.T, giteaURL *url.URL) {
for _, test := range testCases {
session := ctx.Session
t.Run(test.NewBranch, func(t *testing.T) {
testAPICreateBranch(t, session, "user2", "my-noo-repo", test.OldBranch, test.NewBranch, test.ExpectedHTTPStatus)
testAPICreateBranch(t, session, username, reponame, test.OldBranch, test.NewBranch, test.ExpectedHTTPStatus)
})
}
}
@ -251,6 +254,81 @@ func testAPIRenameBranch(t *testing.T, doerName, ownerName, repoName, from, to s
return MakeRequest(t, req, expectedHTTPStatus)
}
func TestAPIUpdateBranch(t *testing.T) {
onGiteaRun(t, testAPIUpdateBranches)
}
func testAPIUpdateBranches(t *testing.T, giteaURL *url.URL) {
username := "user2"
reponame := "my-nuu-repo"
branchname := "new-branch"
ctx := NewAPITestContext(t, username, reponame, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
giteaURL.Path = ctx.GitPath()
session := ctx.Session
t.Run("CreateRepo", doAPICreateRepository(ctx, false))
t.Run("create branch", func(t *testing.T) {
testAPICreateBranch(t, session, username, reponame, "", branchname, http.StatusCreated)
})
oldCommit := ""
t.Run("get commit ID", func(t *testing.T) {
oldCommit = testAPIGetBranch(t, username, reponame, branchname, true)
})
t.Run("advance branch", func(t *testing.T) {
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/"+username+"/"+reponame+"/contents/a new file",
&api.CreateFileOptions{
FileOptions: api.FileOptions{
BranchName: branchname,
},
ContentBase64: base64.StdEncoding.EncodeToString([]byte("foo")),
}).AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusCreated)
assert.Equal(t, http.StatusCreated, resp.Result().StatusCode)
})
newCommit := ""
t.Run("get new commit ID", func(t *testing.T) {
newCommit = testAPIGetBranch(t, username, reponame, branchname, true)
})
t.Run("fail update nonexistent branch", func(t *testing.T) {
testAPIUpdateBranch(t, session, username, reponame, oldCommit, "no-branch-here", oldCommit, http.StatusNotFound)
})
t.Run("fail update on sha mismatch", func(t *testing.T) {
testAPIUpdateBranch(t, session, username, reponame, oldCommit, branchname, oldCommit, http.StatusConflict)
assert.Equal(t, newCommit, testAPIGetBranch(t, username, reponame, branchname, true))
})
t.Run("reset to old commit", func(t *testing.T) {
testAPIUpdateBranch(t, session, username, reponame, oldCommit, branchname, newCommit, http.StatusCreated)
assert.Equal(t, oldCommit, testAPIGetBranch(t, username, reponame, branchname, true))
})
t.Run("reset to new commit", func(t *testing.T) {
testAPIUpdateBranch(t, session, username, reponame, newCommit, branchname, oldCommit, http.StatusCreated)
assert.Equal(t, newCommit, testAPIGetBranch(t, username, reponame, branchname, true))
})
}
func testAPIUpdateBranch(t testing.TB, session *TestSession, user, repo, oldBranch, newBranch, sha string, status int) bool {
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
req := NewRequestWithJSON(t, "PUT", "/api/v1/repos/"+user+"/"+repo+"/branches", &api.UpdateBranchRepoOption{
BranchName: newBranch,
OldRefName: oldBranch,
SHA: sha,
}).AddTokenAuth(token)
resp := MakeRequest(t, req, status)
var branch api.Branch
DecodeJSON(t, resp, &branch)
if resp.Result().StatusCode == http.StatusCreated {
assert.Equal(t, newBranch, branch.Name)
}
return resp.Result().StatusCode == status
}
func TestAPIBranchProtection(t *testing.T) {
defer tests.PrepareTestEnv(t)()

View File

@ -80,7 +80,7 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) {
// Make a new branch in repo1
newBranch := "test_branch"
err = repo_service.CreateNewBranch(t.Context(), user2, repo1, repo1.DefaultBranch, newBranch)
err = repo_service.CreateUpdateBranch(t.Context(), user2, repo1, repo1.DefaultBranch, newBranch, "")
assert.NoError(t, err)
commitID, _ := gitRepo.GetBranchCommitID(repo1.DefaultBranch)

View File

@ -85,7 +85,7 @@ func testAPIGetContents(t *testing.T, u *url.URL) {
// Make a new branch in repo1
newBranch := "test_branch"
err = repo_service.CreateNewBranch(t.Context(), user2, repo1, repo1.DefaultBranch, newBranch)
err = repo_service.CreateUpdateBranch(t.Context(), user2, repo1, repo1.DefaultBranch, newBranch, "")
require.NoError(t, err)
commitID, err := gitRepo.GetBranchCommitID(repo1.DefaultBranch)