diff --git a/services/automerge/automerge.go b/services/automerge/automerge.go index d0310fc52be..94ceac3f26c 100644 --- a/services/automerge/automerge.go +++ b/services/automerge/automerge.go @@ -15,7 +15,6 @@ import ( access_model "code.gitea.io/gitea/models/perm/access" pull_model "code.gitea.io/gitea/models/pull" repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitrepo" @@ -307,16 +306,8 @@ func handlePullRequestAutoMerge(pullID int64, sha string) { } if pr.Flow == issues_model.PullRequestFlowGithub && scheduledPRM.DeleteBranchAfterMerge { - perm, err := access_model.GetUserRepoPermission(ctx, pr.HeadRepo, doer) - if err != nil { - log.Error("GetUserRepoPermission %-v: %v", pr.HeadRepo, err) - return - } - - if perm.CanWrite(unit.TypeCode) { // default branch and branch protection will be checked in DeleteBranch - if err := repo_service.DeleteBranch(ctx, doer, pr.HeadRepo, headGitRepo, pr.HeadBranch); err != nil { - log.Error("deleteBranch after automerge for pull[%d] failed: %v", pr.ID, err) - } + if err := repo_service.DeletePullRequestHeadBranch(ctx, pr, doer, headGitRepo); err != nil { + log.Error("DeletePullRequestHeadBranch: %v", err) } } } diff --git a/services/repository/branch.go b/services/repository/branch.go index 600ba96e92e..f3d388357ba 100644 --- a/services/repository/branch.go +++ b/services/repository/branch.go @@ -14,7 +14,9 @@ import ( "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" + access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" @@ -29,6 +31,7 @@ import ( "code.gitea.io/gitea/modules/util" webhook_module "code.gitea.io/gitea/modules/webhook" notify_service "code.gitea.io/gitea/services/notify" + pull_service "code.gitea.io/gitea/services/pull" files_service "code.gitea.io/gitea/services/repository/files" "xorm.io/builder" @@ -460,12 +463,22 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, doer *user_m // enmuerates all branch related errors var ( - ErrBranchIsDefault = errors.New("branch is default") + ErrBranchIsDefault = errors.New("branch is default") + ErrInsufficientAccess = errors.New("insufficient access") ) // DeleteBranch delete branch func DeleteBranch(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, gitRepo *git.Repository, branchName string) error { - err := repo.MustNotBeArchived() + perm, err := access_model.GetUserRepoPermission(ctx, repo, doer) + if err != nil { + return err + } + + if !perm.CanWrite(unit.TypeCode) { + return ErrInsufficientAccess + } + + err = repo.MustNotBeArchived() if err != nil { return err } @@ -528,6 +541,23 @@ func DeleteBranch(ctx context.Context, doer *user_model.User, repo *repo_model.R return nil } +func DeletePullRequestHeadBranch(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User, headGitRepo *git.Repository) error { + if err := pull_service.RetargetChildrenOnMerge(ctx, doer, pr); err != nil { + return err + } + + if err := DeleteBranch(ctx, doer, pr.HeadRepo, headGitRepo, pr.HeadBranch); err != nil { + return err + } + + if err := issues_model.AddDeletePRBranchComment(ctx, doer, pr.BaseRepo, pr.IssueID, pr.HeadBranch); err != nil { + // Do not fail here as branch has already been deleted + log.Error("AddDeletePRBranchComment: %v", err) + } + + return nil +} + type BranchSyncOptions struct { RepoID int64 }