|
|
|
@ -1057,49 +1057,54 @@ func MergePullRequest(ctx *context.APIContext) {
|
|
|
|
|
}
|
|
|
|
|
log.Trace("Pull request merged: %d", pr.ID)
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
if ctx.Repo != nil && ctx.Repo.Repository != nil && ctx.Repo.Repository.ID == pr.HeadRepoID && ctx.Repo.GitRepo != nil {
|
|
|
|
|
headRepo = ctx.Repo.GitRepo
|
|
|
|
|
} else {
|
|
|
|
|
headRepo, err = gitrepo.OpenRepository(ctx, pr.HeadRepo)
|
|
|
|
|
// for agit flow, we should not delete the agit reference after merge
|
|
|
|
|
if form.DeleteBranchAfterMerge && pr.Flow == issues_model.PullRequestFlowGithub {
|
|
|
|
|
// check permission even it has been checked in repo_service.DeleteBranch so that we don't need to
|
|
|
|
|
// do RetargetChildrenOnMerge
|
|
|
|
|
if err := repo_service.CanDeleteBranch(ctx, pr.HeadRepo, pr.HeadBranch, ctx.Doer); err == nil {
|
|
|
|
|
// 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(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.FullName()), err)
|
|
|
|
|
ctx.ServerError("HasUnmergedPullRequestsByHeadInfo", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
defer headRepo.Close()
|
|
|
|
|
}
|
|
|
|
|
if err := pull_service.RetargetChildrenOnMerge(ctx, ctx.Doer, 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 {
|
|
|
|
|
case git.IsErrBranchNotExist(err):
|
|
|
|
|
ctx.NotFound(err)
|
|
|
|
|
case errors.Is(err, repo_service.ErrBranchIsDefault):
|
|
|
|
|
ctx.Error(http.StatusForbidden, "DefaultBranch", fmt.Errorf("can not delete default branch"))
|
|
|
|
|
case errors.Is(err, git_model.ErrBranchIsProtected):
|
|
|
|
|
ctx.Error(http.StatusForbidden, "IsProtectedBranch", fmt.Errorf("branch protected"))
|
|
|
|
|
default:
|
|
|
|
|
ctx.Error(http.StatusInternalServerError, "DeleteBranch", err)
|
|
|
|
|
if exist {
|
|
|
|
|
ctx.Status(http.StatusOK)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var headRepo *git.Repository
|
|
|
|
|
if ctx.Repo != nil && ctx.Repo.Repository != nil && ctx.Repo.Repository.ID == pr.HeadRepoID && ctx.Repo.GitRepo != nil {
|
|
|
|
|
headRepo = ctx.Repo.GitRepo
|
|
|
|
|
} else {
|
|
|
|
|
headRepo, err = gitrepo.OpenRepository(ctx, pr.HeadRepo)
|
|
|
|
|
if err != nil {
|
|
|
|
|
ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.FullName()), err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
defer headRepo.Close()
|
|
|
|
|
}
|
|
|
|
|
if err := pull_service.RetargetChildrenOnMerge(ctx, ctx.Doer, 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 {
|
|
|
|
|
case git.IsErrBranchNotExist(err):
|
|
|
|
|
ctx.NotFound(err)
|
|
|
|
|
case errors.Is(err, repo_service.ErrBranchIsDefault):
|
|
|
|
|
ctx.Error(http.StatusForbidden, "DefaultBranch", fmt.Errorf("can not delete default branch"))
|
|
|
|
|
case errors.Is(err, git_model.ErrBranchIsProtected):
|
|
|
|
|
ctx.Error(http.StatusForbidden, "IsProtectedBranch", fmt.Errorf("branch protected"))
|
|
|
|
|
default:
|
|
|
|
|
ctx.Error(http.StatusInternalServerError, "DeleteBranch", err)
|
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|