mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-27 18:30:34 +00:00
Merge all deleteBranch as one function and also fix bug when delete branch don't close related PRs (#16067)
* Fix bug when delete branch don't close related PRs * Merge all deletebranch as one method * Add missed branch.go * fix comment Co-authored-by: Lauris BH <lauris@nix.lv>
This commit is contained in:
parent
3607f79d78
commit
0909695204
4 changed files with 111 additions and 146 deletions
|
@ -6,6 +6,7 @@
|
||||||
package repo
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -13,7 +14,6 @@ import (
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/convert"
|
"code.gitea.io/gitea/modules/convert"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
|
@ -117,62 +117,20 @@ func DeleteBranch(ctx *context.APIContext) {
|
||||||
|
|
||||||
branchName := ctx.Params("*")
|
branchName := ctx.Params("*")
|
||||||
|
|
||||||
if ctx.Repo.Repository.DefaultBranch == branchName {
|
if err := repo_service.DeleteBranch(ctx.User, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil {
|
||||||
ctx.Error(http.StatusForbidden, "DefaultBranch", fmt.Errorf("can not delete default branch"))
|
switch {
|
||||||
return
|
case git.IsErrBranchNotExist(err):
|
||||||
}
|
|
||||||
|
|
||||||
isProtected, err := ctx.Repo.Repository.IsProtectedBranch(branchName, ctx.User)
|
|
||||||
if err != nil {
|
|
||||||
ctx.InternalServerError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if isProtected {
|
|
||||||
ctx.Error(http.StatusForbidden, "IsProtectedBranch", fmt.Errorf("branch protected"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
branch, err := repo_module.GetBranch(ctx.Repo.Repository, branchName)
|
|
||||||
if err != nil {
|
|
||||||
if git.IsErrBranchNotExist(err) {
|
|
||||||
ctx.NotFound(err)
|
ctx.NotFound(err)
|
||||||
} else {
|
case errors.Is(err, repo_service.ErrBranchIsDefault):
|
||||||
ctx.Error(http.StatusInternalServerError, "GetBranch", err)
|
ctx.Error(http.StatusForbidden, "DefaultBranch", fmt.Errorf("can not delete default branch"))
|
||||||
|
case errors.Is(err, repo_service.ErrBranchIsProtected):
|
||||||
|
ctx.Error(http.StatusForbidden, "IsProtectedBranch", fmt.Errorf("branch protected"))
|
||||||
|
default:
|
||||||
|
ctx.Error(http.StatusInternalServerError, "DeleteBranch", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := branch.GetCommit()
|
|
||||||
if err != nil {
|
|
||||||
ctx.Error(http.StatusInternalServerError, "GetCommit", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ctx.Repo.GitRepo.DeleteBranch(branchName, git.DeleteBranchOptions{
|
|
||||||
Force: true,
|
|
||||||
}); err != nil {
|
|
||||||
ctx.Error(http.StatusInternalServerError, "DeleteBranch", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't return error below this
|
|
||||||
if err := repo_service.PushUpdate(
|
|
||||||
&repo_module.PushUpdateOptions{
|
|
||||||
RefFullName: git.BranchPrefix + branchName,
|
|
||||||
OldCommitID: c.ID.String(),
|
|
||||||
NewCommitID: git.EmptySHA,
|
|
||||||
PusherID: ctx.User.ID,
|
|
||||||
PusherName: ctx.User.Name,
|
|
||||||
RepoUserName: ctx.Repo.Owner.Name,
|
|
||||||
RepoName: ctx.Repo.Repository.Name,
|
|
||||||
}); err != nil {
|
|
||||||
log.Error("Update: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ctx.Repo.Repository.AddDeletedBranch(branchName, c.ID.String(), ctx.User.ID); err != nil {
|
|
||||||
log.Warn("AddDeletedBranch: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.Status(http.StatusNoContent)
|
ctx.Status(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
package repo
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -83,34 +84,23 @@ func Branches(ctx *context.Context) {
|
||||||
func DeleteBranchPost(ctx *context.Context) {
|
func DeleteBranchPost(ctx *context.Context) {
|
||||||
defer redirect(ctx)
|
defer redirect(ctx)
|
||||||
branchName := ctx.Query("name")
|
branchName := ctx.Query("name")
|
||||||
if branchName == ctx.Repo.Repository.DefaultBranch {
|
|
||||||
log.Debug("DeleteBranch: Can't delete default branch '%s'", branchName)
|
|
||||||
ctx.Flash.Error(ctx.Tr("repo.branch.default_deletion_failed", branchName))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
isProtected, err := ctx.Repo.Repository.IsProtectedBranch(branchName, ctx.User)
|
if err := repo_service.DeleteBranch(ctx.User, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil {
|
||||||
if err != nil {
|
switch {
|
||||||
log.Error("DeleteBranch: %v", err)
|
case git.IsErrBranchNotExist(err):
|
||||||
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", branchName))
|
log.Debug("DeleteBranch: Can't delete non existing branch '%s'", branchName)
|
||||||
return
|
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", branchName))
|
||||||
}
|
case errors.Is(err, repo_service.ErrBranchIsDefault):
|
||||||
|
log.Debug("DeleteBranch: Can't delete default branch '%s'", branchName)
|
||||||
|
ctx.Flash.Error(ctx.Tr("repo.branch.default_deletion_failed", branchName))
|
||||||
|
case errors.Is(err, repo_service.ErrBranchIsProtected):
|
||||||
|
log.Debug("DeleteBranch: Can't delete protected branch '%s'", branchName)
|
||||||
|
ctx.Flash.Error(ctx.Tr("repo.branch.protected_deletion_failed", branchName))
|
||||||
|
default:
|
||||||
|
log.Error("DeleteBranch: %v", err)
|
||||||
|
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", branchName))
|
||||||
|
}
|
||||||
|
|
||||||
if isProtected {
|
|
||||||
log.Debug("DeleteBranch: Can't delete protected branch '%s'", branchName)
|
|
||||||
ctx.Flash.Error(ctx.Tr("repo.branch.protected_deletion_failed", branchName))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !ctx.Repo.GitRepo.IsBranchExist(branchName) {
|
|
||||||
log.Debug("DeleteBranch: Can't delete non existing branch '%s'", branchName)
|
|
||||||
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", branchName))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := deleteBranch(ctx, branchName); err != nil {
|
|
||||||
log.Error("DeleteBranch: %v", err)
|
|
||||||
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", branchName))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,41 +159,6 @@ func redirect(ctx *context.Context) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteBranch(ctx *context.Context, branchName string) error {
|
|
||||||
commit, err := ctx.Repo.GitRepo.GetBranchCommit(branchName)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("GetBranchCommit: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ctx.Repo.GitRepo.DeleteBranch(branchName, git.DeleteBranchOptions{
|
|
||||||
Force: true,
|
|
||||||
}); err != nil {
|
|
||||||
log.Error("DeleteBranch: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't return error below this
|
|
||||||
if err := repo_service.PushUpdate(
|
|
||||||
&repo_module.PushUpdateOptions{
|
|
||||||
RefFullName: git.BranchPrefix + branchName,
|
|
||||||
OldCommitID: commit.ID.String(),
|
|
||||||
NewCommitID: git.EmptySHA,
|
|
||||||
PusherID: ctx.User.ID,
|
|
||||||
PusherName: ctx.User.Name,
|
|
||||||
RepoUserName: ctx.Repo.Owner.Name,
|
|
||||||
RepoName: ctx.Repo.Repository.Name,
|
|
||||||
}); err != nil {
|
|
||||||
log.Error("Update: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ctx.Repo.Repository.AddDeletedBranch(branchName, commit.ID.String(), ctx.User.ID); err != nil {
|
|
||||||
log.Warn("AddDeletedBranch: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// loadBranches loads branches from the repository limited by page & pageSize.
|
// loadBranches loads branches from the repository limited by page & pageSize.
|
||||||
// NOTE: May write to context on error.
|
// NOTE: May write to context on error.
|
||||||
func loadBranches(ctx *context.Context, skip, limit int) ([]*Branch, int) {
|
func loadBranches(ctx *context.Context, skip, limit int) ([]*Branch, int) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ package repo
|
||||||
import (
|
import (
|
||||||
"container/list"
|
"container/list"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
|
@ -21,7 +22,6 @@ import (
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/notification"
|
"code.gitea.io/gitea/modules/notification"
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/upload"
|
"code.gitea.io/gitea/modules/upload"
|
||||||
|
@ -1186,20 +1186,6 @@ func CleanUpPullRequest(ctx *context.Context) {
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if pr.HeadBranch == pr.HeadRepo.DefaultBranch || !gitRepo.IsBranchExist(pr.HeadBranch) {
|
|
||||||
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if branch is not protected
|
|
||||||
if protected, err := pr.HeadRepo.IsProtectedBranch(pr.HeadBranch, ctx.User); err != nil || protected {
|
|
||||||
if err != nil {
|
|
||||||
log.Error("HeadRepo.IsProtectedBranch: %v", err)
|
|
||||||
}
|
|
||||||
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if branch has no new commits
|
// Check if branch has no new commits
|
||||||
headCommitID, err := gitBaseRepo.GetRefCommitID(pr.GetGitRefName())
|
headCommitID, err := gitBaseRepo.GetRefCommitID(pr.GetGitRefName())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1218,27 +1204,21 @@ func CleanUpPullRequest(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := gitRepo.DeleteBranch(pr.HeadBranch, git.DeleteBranchOptions{
|
if err := repo_service.DeleteBranch(ctx.User, pr.HeadRepo, gitRepo, pr.HeadBranch); err != nil {
|
||||||
Force: true,
|
switch {
|
||||||
}); err != nil {
|
case git.IsErrBranchNotExist(err):
|
||||||
log.Error("DeleteBranch: %v", err)
|
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName))
|
||||||
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName))
|
case errors.Is(err, repo_service.ErrBranchIsDefault):
|
||||||
|
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName))
|
||||||
|
case errors.Is(err, repo_service.ErrBranchIsProtected):
|
||||||
|
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName))
|
||||||
|
default:
|
||||||
|
log.Error("DeleteBranch: %v", err)
|
||||||
|
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName))
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := repo_service.PushUpdate(
|
|
||||||
&repo_module.PushUpdateOptions{
|
|
||||||
RefFullName: git.BranchPrefix + pr.HeadBranch,
|
|
||||||
OldCommitID: branchCommitID,
|
|
||||||
NewCommitID: git.EmptySHA,
|
|
||||||
PusherID: ctx.User.ID,
|
|
||||||
PusherName: ctx.User.Name,
|
|
||||||
RepoUserName: pr.HeadRepo.Owner.Name,
|
|
||||||
RepoName: pr.HeadRepo.Name,
|
|
||||||
}); err != nil {
|
|
||||||
log.Error("Update: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := models.AddDeletePRBranchComment(ctx.User, pr.BaseRepo, issue.ID, pr.HeadBranch); err != nil {
|
if err := models.AddDeletePRBranchComment(ctx.User, pr.BaseRepo, issue.ID, pr.HeadBranch); err != nil {
|
||||||
// Do not fail here as branch has already been deleted
|
// Do not fail here as branch has already been deleted
|
||||||
log.Error("DeleteBranch: %v", err)
|
log.Error("DeleteBranch: %v", err)
|
||||||
|
|
72
services/repository/branch.go
Normal file
72
services/repository/branch.go
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package repository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
|
pull_service "code.gitea.io/gitea/services/pull"
|
||||||
|
)
|
||||||
|
|
||||||
|
// enmuerates all branch related errors
|
||||||
|
var (
|
||||||
|
ErrBranchIsDefault = errors.New("branch is default")
|
||||||
|
ErrBranchIsProtected = errors.New("branch is protected")
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeleteBranch delete branch
|
||||||
|
func DeleteBranch(doer *models.User, repo *models.Repository, gitRepo *git.Repository, branchName string) error {
|
||||||
|
if branchName == repo.DefaultBranch {
|
||||||
|
return ErrBranchIsDefault
|
||||||
|
}
|
||||||
|
|
||||||
|
isProtected, err := repo.IsProtectedBranch(branchName, doer)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if isProtected {
|
||||||
|
return ErrBranchIsProtected
|
||||||
|
}
|
||||||
|
|
||||||
|
commit, err := gitRepo.GetBranchCommit(branchName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := gitRepo.DeleteBranch(branchName, git.DeleteBranchOptions{
|
||||||
|
Force: true,
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := pull_service.CloseBranchPulls(doer, repo.ID, branchName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't return error below this
|
||||||
|
if err := PushUpdate(
|
||||||
|
&repo_module.PushUpdateOptions{
|
||||||
|
RefFullName: git.BranchPrefix + branchName,
|
||||||
|
OldCommitID: commit.ID.String(),
|
||||||
|
NewCommitID: git.EmptySHA,
|
||||||
|
PusherID: doer.ID,
|
||||||
|
PusherName: doer.Name,
|
||||||
|
RepoUserName: repo.OwnerName,
|
||||||
|
RepoName: repo.Name,
|
||||||
|
}); err != nil {
|
||||||
|
log.Error("Update: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := repo.AddDeletedBranch(branchName, commit.ID.String(), doer.ID); err != nil {
|
||||||
|
log.Warn("AddDeletedBranch: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in a new issue