@@ -37,14 +37,14 @@ import (
3737 "xorm.io/builder"
3838)
3939
40- // CreateNewBranch creates a new repository branch
41- func CreateNewBranch (ctx context.Context , doer * user_model.User , repo * repo_model.Repository , oldBranchName , branchName string ) (err error ) {
40+ // CreateUpdateBranch creates a new repository branch
41+ func CreateUpdateBranch (ctx context.Context , doer * user_model.User , repo * repo_model.Repository , oldBranchName , branchName , sha string ) (err error ) {
4242 branch , err := git_model .GetBranch (ctx , repo .ID , oldBranchName )
4343 if err != nil {
4444 return err
4545 }
4646
47- return CreateNewBranchFromCommit (ctx , doer , repo , branch .CommitID , branchName )
47+ return CreateUpdateBranchFromCommit (ctx , doer , repo , branch .CommitID , branchName , sha )
4848}
4949
5050// Branch contains the branch information
@@ -255,6 +255,22 @@ func loadOneBranch(ctx context.Context, repo *repo_model.Repository, dbBranch *g
255255 }, nil
256256}
257257
258+ func checkBranchSha (ctx context.Context , repo * repo_model.Repository , name , sha string ) error {
259+ branch , err := git_model .GetBranch (ctx , repo .ID , name )
260+ if err != nil {
261+ return err
262+ }
263+
264+ if branch .CommitID != sha {
265+ return git_model.ErrBranchShaMismatch {
266+ BranchName : name ,
267+ Expected : sha ,
268+ Actual : branch .CommitID ,
269+ }
270+ }
271+ return nil
272+ }
273+
258274// checkBranchName validates branch name with existing repository branches
259275func checkBranchName (ctx context.Context , repo * repo_model.Repository , name string ) error {
260276 _ , err := gitrepo .WalkReferences (ctx , repo , func (_ , refName string ) error {
@@ -373,20 +389,27 @@ func SyncBranchesToDB(ctx context.Context, repoID, pusherID int64, branchNames,
373389 })
374390}
375391
376- // CreateNewBranchFromCommit creates a new repository branch
377- func CreateNewBranchFromCommit (ctx context.Context , doer * user_model.User , repo * repo_model.Repository , commitID , branchName string ) (err error ) {
392+ // CreateUpdateBranchFromCommit creates a new repository branch
393+ func CreateUpdateBranchFromCommit (ctx context.Context , doer * user_model.User , repo * repo_model.Repository , commitID , branchName , sha string ) (err error ) {
378394 err = repo .MustNotBeArchived ()
379395 if err != nil {
380396 return err
381397 }
382398
383- // Check if branch name can be used
384- if err := checkBranchName (ctx , repo , branchName ); err != nil {
385- return err
399+ if sha != "" {
400+ if err := checkBranchSha (ctx , repo , branchName , sha ); err != nil {
401+ return err
402+ }
403+ } else {
404+ // Check if branch name can be used
405+ if err := checkBranchName (ctx , repo , branchName ); err != nil {
406+ return err
407+ }
386408 }
387409
388410 if err := git .Push (ctx , repo .RepoPath (), git.PushOptions {
389411 Remote : repo .RepoPath (),
412+ Force : sha != "" ,
390413 Branch : fmt .Sprintf ("%s:%s%s" , commitID , git .BranchPrefix , branchName ),
391414 Env : repo_module .PushingEnvironment (doer , repo ),
392415 }); err != nil {
0 commit comments