mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-03 21:08:25 +00:00 
			
		
		
		
	Move all checks into DeleteBranch and PushUpdate
This commit is contained in:
		@@ -133,11 +133,6 @@ func DeleteBranch(ctx *context.APIContext) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	branchName := ctx.PathParam("*")
 | 
						branchName := ctx.PathParam("*")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.Repo.Repository.IsEmpty {
 | 
					 | 
				
			||||||
		ctx.Error(http.StatusForbidden, "", "Git Repository is empty.")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// check whether branches of this repository has been synced
 | 
						// check whether branches of this repository has been synced
 | 
				
			||||||
	totalNumOfBranches, err := db.Count[git_model.Branch](ctx, git_model.FindBranchOptions{
 | 
						totalNumOfBranches, err := db.Count[git_model.Branch](ctx, git_model.FindBranchOptions{
 | 
				
			||||||
		RepoID:          ctx.Repo.Repository.ID,
 | 
							RepoID:          ctx.Repo.Repository.ID,
 | 
				
			||||||
@@ -155,12 +150,7 @@ func DeleteBranch(ctx *context.APIContext) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.Repo.Repository.IsMirror {
 | 
						if err := repo_service.DeleteBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName, nil); err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusForbidden, "IsMirrored", fmt.Errorf("can not delete branch of an mirror repository"))
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err := repo_service.DeleteBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil {
 | 
					 | 
				
			||||||
		switch {
 | 
							switch {
 | 
				
			||||||
		case git.IsErrBranchNotExist(err):
 | 
							case git.IsErrBranchNotExist(err):
 | 
				
			||||||
			ctx.NotFound(err)
 | 
								ctx.NotFound(err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1046,17 +1046,6 @@ func MergePullRequest(ctx *context.APIContext) {
 | 
				
			|||||||
	log.Trace("Pull request merged: %d", pr.ID)
 | 
						log.Trace("Pull request merged: %d", pr.ID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if form.DeleteBranchAfterMerge {
 | 
						if form.DeleteBranchAfterMerge {
 | 
				
			||||||
		// Don't cleanup when there are other PR's that use this branch as head branch.
 | 
					 | 
				
			||||||
		exist, err := issues_model.HasUnmergedPullRequestsByHeadInfo(ctx, pr.HeadRepoID, pr.HeadBranch)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			ctx.ServerError("HasUnmergedPullRequestsByHeadInfo", err)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if exist {
 | 
					 | 
				
			||||||
			ctx.Status(http.StatusOK)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		var headRepo *git.Repository
 | 
							var headRepo *git.Repository
 | 
				
			||||||
		if ctx.Repo != nil && ctx.Repo.Repository != nil && ctx.Repo.Repository.ID == pr.HeadRepoID && ctx.Repo.GitRepo != nil {
 | 
							if ctx.Repo != nil && ctx.Repo.Repository != nil && ctx.Repo.Repository.ID == pr.HeadRepoID && ctx.Repo.GitRepo != nil {
 | 
				
			||||||
			headRepo = ctx.Repo.GitRepo
 | 
								headRepo = ctx.Repo.GitRepo
 | 
				
			||||||
@@ -1068,11 +1057,7 @@ func MergePullRequest(ctx *context.APIContext) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			defer headRepo.Close()
 | 
								defer headRepo.Close()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err := pull_service.RetargetChildrenOnMerge(ctx, ctx.Doer, pr); err != nil {
 | 
							if err := repo_service.DeleteBranch(ctx, ctx.Doer, pr.HeadRepo, headRepo, pr.HeadBranch, pr); err != nil {
 | 
				
			||||||
			ctx.Error(http.StatusInternalServerError, "RetargetChildrenOnMerge", err)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if err := repo_service.DeleteBranch(ctx, ctx.Doer, pr.HeadRepo, headRepo, pr.HeadBranch); err != nil {
 | 
					 | 
				
			||||||
			switch {
 | 
								switch {
 | 
				
			||||||
			case git.IsErrBranchNotExist(err):
 | 
								case git.IsErrBranchNotExist(err):
 | 
				
			||||||
				ctx.NotFound(err)
 | 
									ctx.NotFound(err)
 | 
				
			||||||
@@ -1085,10 +1070,6 @@ func MergePullRequest(ctx *context.APIContext) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err := issues_model.AddDeletePRBranchComment(ctx, ctx.Doer, pr.BaseRepo, pr.Issue.ID, pr.HeadBranch); err != nil {
 | 
					 | 
				
			||||||
			// Do not fail here as branch has already been deleted
 | 
					 | 
				
			||||||
			log.Error("DeleteBranch: %v", err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.Status(http.StatusOK)
 | 
						ctx.Status(http.StatusOK)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -98,7 +98,7 @@ func DeleteBranchPost(ctx *context.Context) {
 | 
				
			|||||||
	defer redirect(ctx)
 | 
						defer redirect(ctx)
 | 
				
			||||||
	branchName := ctx.FormString("name")
 | 
						branchName := ctx.FormString("name")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := repo_service.DeleteBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil {
 | 
						if err := repo_service.DeleteBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName, nil); err != nil {
 | 
				
			||||||
		switch {
 | 
							switch {
 | 
				
			||||||
		case git.IsErrBranchNotExist(err):
 | 
							case git.IsErrBranchNotExist(err):
 | 
				
			||||||
			log.Debug("DeleteBranch: Can't delete non existing branch '%s'", branchName)
 | 
								log.Debug("DeleteBranch: Can't delete non existing branch '%s'", branchName)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1493,12 +1493,7 @@ func CleanUpPullRequest(ctx *context.Context) {
 | 
				
			|||||||
func deleteBranch(ctx *context.Context, pr *issues_model.PullRequest, gitRepo *git.Repository) {
 | 
					func deleteBranch(ctx *context.Context, pr *issues_model.PullRequest, gitRepo *git.Repository) {
 | 
				
			||||||
	fullBranchName := pr.HeadRepo.FullName() + ":" + pr.HeadBranch
 | 
						fullBranchName := pr.HeadRepo.FullName() + ":" + pr.HeadBranch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := pull_service.RetargetChildrenOnMerge(ctx, ctx.Doer, pr); err != nil {
 | 
						if err := repo_service.DeleteBranch(ctx, ctx.Doer, pr.HeadRepo, gitRepo, pr.HeadBranch, pr); err != nil {
 | 
				
			||||||
		ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName))
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err := repo_service.DeleteBranch(ctx, ctx.Doer, pr.HeadRepo, gitRepo, pr.HeadBranch); err != nil {
 | 
					 | 
				
			||||||
		switch {
 | 
							switch {
 | 
				
			||||||
		case git.IsErrBranchNotExist(err):
 | 
							case git.IsErrBranchNotExist(err):
 | 
				
			||||||
			ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName))
 | 
								ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName))
 | 
				
			||||||
@@ -1513,11 +1508,6 @@ func deleteBranch(ctx *context.Context, pr *issues_model.PullRequest, gitRepo *g
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := issues_model.AddDeletePRBranchComment(ctx, ctx.Doer, pr.BaseRepo, pr.IssueID, pr.HeadBranch); err != nil {
 | 
					 | 
				
			||||||
		// Do not fail here as branch has already been deleted
 | 
					 | 
				
			||||||
		log.Error("DeleteBranch: %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ctx.Flash.Success(ctx.Tr("repo.branch.deletion_success", fullBranchName))
 | 
						ctx.Flash.Success(ctx.Tr("repo.branch.deletion_success", fullBranchName))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -306,7 +306,7 @@ func handlePullRequestAutoMerge(pullID int64, sha string) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if pr.Flow == issues_model.PullRequestFlowGithub && scheduledPRM.DeleteBranchAfterMerge {
 | 
						if pr.Flow == issues_model.PullRequestFlowGithub && scheduledPRM.DeleteBranchAfterMerge {
 | 
				
			||||||
		if err := repo_service.DeletePullRequestHeadBranch(ctx, pr, doer, headGitRepo); err != nil {
 | 
							if err := repo_service.DeleteBranch(ctx, doer, pr.HeadRepo, headGitRepo, pr.HeadBranch, pr); err != nil {
 | 
				
			||||||
			log.Error("DeletePullRequestHeadBranch: %v", err)
 | 
								log.Error("DeletePullRequestHeadBranch: %v", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -606,17 +606,9 @@ func (errs errlist) Error() string {
 | 
				
			|||||||
	return ""
 | 
						return ""
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RetargetChildrenOnMerge retarget children pull requests on merge if possible
 | 
					 | 
				
			||||||
func RetargetChildrenOnMerge(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) error {
 | 
					 | 
				
			||||||
	if setting.Repository.PullRequest.RetargetChildrenOnMerge && pr.BaseRepoID == pr.HeadRepoID {
 | 
					 | 
				
			||||||
		return RetargetBranchPulls(ctx, doer, pr.HeadRepoID, pr.HeadBranch, pr.BaseBranch)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// RetargetBranchPulls change target branch for all pull requests whose base branch is the branch
 | 
					// RetargetBranchPulls change target branch for all pull requests whose base branch is the branch
 | 
				
			||||||
// Both branch and targetBranch must be in the same repo (for security reasons)
 | 
					// Both branch and targetBranch must be in the same repo (for security reasons)
 | 
				
			||||||
func RetargetBranchPulls(ctx context.Context, doer *user_model.User, repoID int64, branch, targetBranch string) error {
 | 
					func RetargetBranchPulls(ctx context.Context, doer *user_model.User, repoID int64, branch string, targetBranch string) error {
 | 
				
			||||||
	prs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(ctx, repoID, branch)
 | 
						prs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(ctx, repoID, branch)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@@ -650,12 +642,14 @@ func CloseBranchPulls(ctx context.Context, doer *user_model.User, repoID int64,
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !setting.Repository.PullRequest.RetargetChildrenOnMerge {
 | 
				
			||||||
		prs2, err := issues_model.GetUnmergedPullRequestsByBaseInfo(ctx, repoID, branch)
 | 
							prs2, err := issues_model.GetUnmergedPullRequestsByBaseInfo(ctx, repoID, branch)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		prs = append(prs, prs2...)
 | 
							prs = append(prs, prs2...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := issues_model.PullRequestList(prs).LoadAttributes(ctx); err != nil {
 | 
						if err := issues_model.PullRequestList(prs).LoadAttributes(ctx); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,7 +31,6 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/util"
 | 
						"code.gitea.io/gitea/modules/util"
 | 
				
			||||||
	webhook_module "code.gitea.io/gitea/modules/webhook"
 | 
						webhook_module "code.gitea.io/gitea/modules/webhook"
 | 
				
			||||||
	notify_service "code.gitea.io/gitea/services/notify"
 | 
						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"
 | 
						files_service "code.gitea.io/gitea/services/repository/files"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"xorm.io/builder"
 | 
						"xorm.io/builder"
 | 
				
			||||||
@@ -468,7 +467,7 @@ var (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteBranch delete branch
 | 
					// DeleteBranch delete branch
 | 
				
			||||||
func DeleteBranch(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, gitRepo *git.Repository, branchName string) error {
 | 
					func DeleteBranch(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, gitRepo *git.Repository, branchName string, pr *issues_model.PullRequest) error {
 | 
				
			||||||
	perm, err := access_model.GetUserRepoPermission(ctx, repo, doer)
 | 
						perm, err := access_model.GetUserRepoPermission(ctx, repo, doer)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@@ -515,6 +514,12 @@ func DeleteBranch(ctx context.Context, doer *user_model.User, repo *repo_model.R
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if pr != nil {
 | 
				
			||||||
 | 
								if err := issues_model.AddDeletePRBranchComment(ctx, doer, pr.BaseRepo, pr.Issue.ID, pr.HeadBranch); err != nil {
 | 
				
			||||||
 | 
									return fmt.Errorf("DeleteBranch: %v", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return gitRepo.DeleteBranch(branchName, git.DeleteBranchOptions{
 | 
							return gitRepo.DeleteBranch(branchName, git.DeleteBranchOptions{
 | 
				
			||||||
			Force: true,
 | 
								Force: true,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
@@ -541,23 +546,6 @@ func DeleteBranch(ctx context.Context, doer *user_model.User, repo *repo_model.R
 | 
				
			|||||||
	return nil
 | 
						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 {
 | 
					type BranchSyncOptions struct {
 | 
				
			||||||
	RepoID int64
 | 
						RepoID int64
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -275,6 +275,13 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				notify_service.DeleteRef(ctx, pusher, repo, opts.RefFullName)
 | 
									notify_service.DeleteRef(ctx, pusher, repo, opts.RefFullName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if setting.Repository.PullRequest.RetargetChildrenOnMerge {
 | 
				
			||||||
 | 
										if err := pull_service.RetargetBranchPulls(ctx, pusher, repo.ID, branch, repo.DefaultBranch); err != nil {
 | 
				
			||||||
 | 
											return err
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if err = pull_service.CloseBranchPulls(ctx, pusher, repo.ID, branch); err != nil {
 | 
									if err = pull_service.CloseBranchPulls(ctx, pusher, repo.ID, branch); err != nil {
 | 
				
			||||||
					// close all related pulls
 | 
										// close all related pulls
 | 
				
			||||||
					log.Error("close related pull request failed: %v", err)
 | 
										log.Error("close related pull request failed: %v", err)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user