aboutsummaryrefslogtreecommitdiffstats
path: root/routers/web
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2023-01-16 16:00:22 +0800
committerGitHub <noreply@github.com>2023-01-16 16:00:22 +0800
commit2782c1439679402a1f8731a94dc66214781282ba (patch)
tree66739f30beb529119694290bdcdba9e02bdcfabd /routers/web
parentcc1f8cbe96c195aab79761c48bc4ec0bff2b3431 (diff)
downloadgitea-2782c1439679402a1f8731a94dc66214781282ba.tar.gz
gitea-2782c1439679402a1f8731a94dc66214781282ba.zip
Supports wildcard protected branch (#20825)
This PR introduce glob match for protected branch name. The separator is `/` and you can use `*` matching non-separator chars and use `**` across separator. It also supports input an exist or non-exist branch name as matching condition and branch name condition has high priority than glob rule. Should fix #2529 and #15705 screenshots <img width="1160" alt="image" src="https://user-images.githubusercontent.com/81045/205651179-ebb5492a-4ade-4bb4-a13c-965e8c927063.png"> Co-authored-by: zeripath <art27@cantab.net>
Diffstat (limited to 'routers/web')
-rw-r--r--routers/web/repo/branch.go21
-rw-r--r--routers/web/repo/issue.go25
-rw-r--r--routers/web/repo/pull.go22
-rw-r--r--routers/web/repo/setting.go1
-rw-r--r--routers/web/repo/setting_protected_branch.go308
-rw-r--r--routers/web/web.go10
6 files changed, 208 insertions, 179 deletions
diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go
index 8b48d3fb00..b34ccf8538 100644
--- a/routers/web/repo/branch.go
+++ b/routers/web/repo/branch.go
@@ -99,7 +99,7 @@ func DeleteBranchPost(ctx *context.Context) {
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):
+ case errors.Is(err, git_model.ErrBranchIsProtected):
log.Debug("DeleteBranch: Can't delete protected branch '%s'", branchName)
ctx.Flash.Error(ctx.Tr("repo.branch.protected_deletion_failed", branchName))
default:
@@ -189,9 +189,9 @@ func loadBranches(ctx *context.Context, skip, limit int) (*Branch, []*Branch, in
return nil, nil, 0
}
- protectedBranches, err := git_model.GetProtectedBranches(ctx, ctx.Repo.Repository.ID)
+ rules, err := git_model.FindRepoProtectedBranchRules(ctx, ctx.Repo.Repository.ID)
if err != nil {
- ctx.ServerError("GetProtectedBranches", err)
+ ctx.ServerError("FindRepoProtectedBranchRules", err)
return nil, nil, 0
}
@@ -208,7 +208,7 @@ func loadBranches(ctx *context.Context, skip, limit int) (*Branch, []*Branch, in
continue
}
- branch := loadOneBranch(ctx, rawBranches[i], defaultBranch, protectedBranches, repoIDToRepo, repoIDToGitRepo)
+ branch := loadOneBranch(ctx, rawBranches[i], defaultBranch, &rules, repoIDToRepo, repoIDToGitRepo)
if branch == nil {
return nil, nil, 0
}
@@ -220,7 +220,7 @@ func loadBranches(ctx *context.Context, skip, limit int) (*Branch, []*Branch, in
if defaultBranch != nil {
// Always add the default branch
log.Debug("loadOneBranch: load default: '%s'", defaultBranch.Name)
- defaultBranchBranch = loadOneBranch(ctx, defaultBranch, defaultBranch, protectedBranches, repoIDToRepo, repoIDToGitRepo)
+ defaultBranchBranch = loadOneBranch(ctx, defaultBranch, defaultBranch, &rules, repoIDToRepo, repoIDToGitRepo)
branches = append(branches, defaultBranchBranch)
}
@@ -236,7 +236,7 @@ func loadBranches(ctx *context.Context, skip, limit int) (*Branch, []*Branch, in
return defaultBranchBranch, branches, totalNumOfBranches
}
-func loadOneBranch(ctx *context.Context, rawBranch, defaultBranch *git.Branch, protectedBranches []*git_model.ProtectedBranch,
+func loadOneBranch(ctx *context.Context, rawBranch, defaultBranch *git.Branch, protectedBranches *git_model.ProtectedBranchRules,
repoIDToRepo map[int64]*repo_model.Repository,
repoIDToGitRepo map[int64]*git.Repository,
) *Branch {
@@ -249,13 +249,8 @@ func loadOneBranch(ctx *context.Context, rawBranch, defaultBranch *git.Branch, p
}
branchName := rawBranch.Name
- var isProtected bool
- for _, b := range protectedBranches {
- if b.BranchName == branchName {
- isProtected = true
- break
- }
- }
+ p := protectedBranches.GetFirstMatched(branchName)
+ isProtected := p != nil
divergence := &git.DivergeObject{
Ahead: -1,
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index f037c771d4..b081092c57 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -1604,7 +1604,7 @@ func ViewIssue(ctx *context.Context) {
if perm.CanWrite(unit.TypeCode) {
// Check if branch is not protected
if pull.HeadBranch != pull.HeadRepo.DefaultBranch {
- if protected, err := git_model.IsProtectedBranch(ctx, pull.HeadRepo.ID, pull.HeadBranch); err != nil {
+ if protected, err := git_model.IsBranchProtected(ctx, pull.HeadRepo.ID, pull.HeadBranch); err != nil {
log.Error("IsProtectedBranch: %v", err)
} else if !protected {
canDelete = true
@@ -1680,22 +1680,25 @@ func ViewIssue(ctx *context.Context) {
ctx.Data["DefaultSquashMergeMessage"] = defaultSquashMergeMessage
ctx.Data["DefaultSquashMergeBody"] = defaultSquashMergeBody
- if err = pull.LoadProtectedBranch(ctx); err != nil {
+ pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pull.BaseRepoID, pull.BaseBranch)
+ if err != nil {
ctx.ServerError("LoadProtectedBranch", err)
return
}
ctx.Data["ShowMergeInstructions"] = true
- if pull.ProtectedBranch != nil {
+ if pb != nil {
+ pb.Repo = pull.BaseRepo
var showMergeInstructions bool
if ctx.Doer != nil {
- showMergeInstructions = pull.ProtectedBranch.CanUserPush(ctx, ctx.Doer.ID)
- }
- ctx.Data["IsBlockedByApprovals"] = !issues_model.HasEnoughApprovals(ctx, pull.ProtectedBranch, pull)
- ctx.Data["IsBlockedByRejection"] = issues_model.MergeBlockedByRejectedReview(ctx, pull.ProtectedBranch, pull)
- ctx.Data["IsBlockedByOfficialReviewRequests"] = issues_model.MergeBlockedByOfficialReviewRequests(ctx, pull.ProtectedBranch, pull)
- ctx.Data["IsBlockedByOutdatedBranch"] = issues_model.MergeBlockedByOutdatedBranch(pull.ProtectedBranch, pull)
- ctx.Data["GrantedApprovals"] = issues_model.GetGrantedApprovalsCount(ctx, pull.ProtectedBranch, pull)
- ctx.Data["RequireSigned"] = pull.ProtectedBranch.RequireSignedCommits
+ showMergeInstructions = pb.CanUserPush(ctx, ctx.Doer)
+ }
+ ctx.Data["ProtectedBranch"] = pb
+ ctx.Data["IsBlockedByApprovals"] = !issues_model.HasEnoughApprovals(ctx, pb, pull)
+ ctx.Data["IsBlockedByRejection"] = issues_model.MergeBlockedByRejectedReview(ctx, pb, pull)
+ ctx.Data["IsBlockedByOfficialReviewRequests"] = issues_model.MergeBlockedByOfficialReviewRequests(ctx, pb, pull)
+ ctx.Data["IsBlockedByOutdatedBranch"] = issues_model.MergeBlockedByOutdatedBranch(pb, pull)
+ ctx.Data["GrantedApprovals"] = issues_model.GetGrantedApprovalsCount(ctx, pb, pull)
+ ctx.Data["RequireSigned"] = pb.RequireSignedCommits
ctx.Data["ChangedProtectedFiles"] = pull.ChangedProtectedFiles
ctx.Data["IsBlockedByChangedProtectedFiles"] = len(pull.ChangedProtectedFiles) != 0
ctx.Data["ChangedProtectedFilesNum"] = len(pull.ChangedProtectedFiles)
diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go
index c0fab2cead..c2208120fc 100644
--- a/routers/web/repo/pull.go
+++ b/routers/web/repo/pull.go
@@ -440,11 +440,12 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C
setMergeTarget(ctx, pull)
- if err := pull.LoadProtectedBranch(ctx); err != nil {
+ pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, repo.ID, pull.BaseBranch)
+ if err != nil {
ctx.ServerError("LoadProtectedBranch", err)
return nil
}
- ctx.Data["EnableStatusCheck"] = pull.ProtectedBranch != nil && pull.ProtectedBranch.EnableStatusCheck
+ ctx.Data["EnableStatusCheck"] = pb != nil && pb.EnableStatusCheck
var baseGitRepo *git.Repository
if pull.BaseRepoID == ctx.Repo.Repository.ID && ctx.Repo.GitRepo != nil {
@@ -570,16 +571,16 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C
ctx.Data["LatestCommitStatus"] = git_model.CalcCommitStatus(commitStatuses)
}
- if pull.ProtectedBranch != nil && pull.ProtectedBranch.EnableStatusCheck {
+ if pb != nil && pb.EnableStatusCheck {
ctx.Data["is_context_required"] = func(context string) bool {
- for _, c := range pull.ProtectedBranch.StatusCheckContexts {
+ for _, c := range pb.StatusCheckContexts {
if c == context {
return true
}
}
return false
}
- ctx.Data["RequiredStatusCheckState"] = pull_service.MergeRequiredContextsCommitStatus(commitStatuses, pull.ProtectedBranch.StatusCheckContexts)
+ ctx.Data["RequiredStatusCheckState"] = pull_service.MergeRequiredContextsCommitStatus(commitStatuses, pb.StatusCheckContexts)
}
ctx.Data["HeadBranchMovedOn"] = headBranchSha != sha
@@ -752,16 +753,17 @@ func ViewPullFiles(ctx *context.Context) {
return
}
- if err = pull.LoadProtectedBranch(ctx); err != nil {
+ pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pull.BaseRepoID, pull.BaseBranch)
+ if err != nil {
ctx.ServerError("LoadProtectedBranch", err)
return
}
- if pull.ProtectedBranch != nil {
- glob := pull.ProtectedBranch.GetProtectedFilePatterns()
+ if pb != nil {
+ glob := pb.GetProtectedFilePatterns()
if len(glob) != 0 {
for _, file := range diff.Files {
- file.IsProtected = pull.ProtectedBranch.IsProtectedFile(glob, file.Name)
+ file.IsProtected = pb.IsProtectedFile(glob, file.Name)
}
}
}
@@ -1400,7 +1402,7 @@ func deleteBranch(ctx *context.Context, pr *issues_model.PullRequest, gitRepo *g
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):
+ case errors.Is(err, git_model.ErrBranchIsProtected):
ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName))
default:
log.Error("DeleteBranch: %v", err)
diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go
index 913ed6c7cb..43a615abfe 100644
--- a/routers/web/repo/setting.go
+++ b/routers/web/repo/setting.go
@@ -56,7 +56,6 @@ const (
tplGithooks base.TplName = "repo/settings/githooks"
tplGithookEdit base.TplName = "repo/settings/githook_edit"
tplDeployKeys base.TplName = "repo/settings/deploy_keys"
- tplProtectedBranch base.TplName = "repo/settings/protected_branch"
)
// SettingsCtxData is a middleware that sets all the general context data for the
diff --git a/routers/web/repo/setting_protected_branch.go b/routers/web/repo/setting_protected_branch.go
index e0467a23e6..31abde1ef6 100644
--- a/routers/web/repo/setting_protected_branch.go
+++ b/routers/web/repo/setting_protected_branch.go
@@ -19,47 +19,33 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/forms"
pull_service "code.gitea.io/gitea/services/pull"
"code.gitea.io/gitea/services/repository"
)
-// ProtectedBranch render the page to protect the repository
-func ProtectedBranch(ctx *context.Context) {
+const (
+ tplProtectedBranch base.TplName = "repo/settings/protected_branch"
+)
+
+// ProtectedBranchRules render the page to protect the repository
+func ProtectedBranchRules(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.settings")
ctx.Data["PageIsSettingsBranches"] = true
- protectedBranches, err := git_model.GetProtectedBranches(ctx, ctx.Repo.Repository.ID)
+ rules, err := git_model.FindRepoProtectedBranchRules(ctx, ctx.Repo.Repository.ID)
if err != nil {
ctx.ServerError("GetProtectedBranches", err)
return
}
- ctx.Data["ProtectedBranches"] = protectedBranches
-
- branches := ctx.Data["Branches"].([]string)
- leftBranches := make([]string, 0, len(branches)-len(protectedBranches))
- for _, b := range branches {
- var protected bool
- for _, pb := range protectedBranches {
- if b == pb.BranchName {
- protected = true
- break
- }
- }
- if !protected {
- leftBranches = append(leftBranches, b)
- }
- }
-
- ctx.Data["LeftBranches"] = leftBranches
+ ctx.Data["ProtectedBranches"] = rules
ctx.HTML(http.StatusOK, tplBranches)
}
-// ProtectedBranchPost response for protect for a branch of a repository
-func ProtectedBranchPost(ctx *context.Context) {
+// SetDefaultBranchPost set default branch
+func SetDefaultBranchPost(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.settings")
ctx.Data["PageIsSettingsBranches"] = true
@@ -101,41 +87,36 @@ func ProtectedBranchPost(ctx *context.Context) {
// SettingsProtectedBranch renders the protected branch setting page
func SettingsProtectedBranch(c *context.Context) {
- branch := c.Params("*")
- if !c.Repo.GitRepo.IsBranchExist(branch) {
- c.NotFound("IsBranchExist", nil)
- return
- }
-
- c.Data["Title"] = c.Tr("repo.settings.protected_branch") + " - " + branch
- c.Data["PageIsSettingsBranches"] = true
-
- protectBranch, err := git_model.GetProtectedBranchBy(c, c.Repo.Repository.ID, branch)
- if err != nil {
- if !git.IsErrBranchNotExist(err) {
+ ruleName := c.FormString("rule_name")
+ var rule *git_model.ProtectedBranch
+ if ruleName != "" {
+ var err error
+ rule, err = git_model.GetProtectedBranchRuleByName(c, c.Repo.Repository.ID, ruleName)
+ if err != nil {
c.ServerError("GetProtectBranchOfRepoByName", err)
return
}
}
- if protectBranch == nil {
+ if rule == nil {
// No options found, create defaults.
- protectBranch = &git_model.ProtectedBranch{
- BranchName: branch,
- }
+ rule = &git_model.ProtectedBranch{}
}
+ c.Data["PageIsSettingsBranches"] = true
+ c.Data["Title"] = c.Tr("repo.settings.protected_branch") + " - " + rule.RuleName
+
users, err := access_model.GetRepoReaders(c.Repo.Repository)
if err != nil {
c.ServerError("Repo.Repository.GetReaders", err)
return
}
c.Data["Users"] = users
- c.Data["whitelist_users"] = strings.Join(base.Int64sToStrings(protectBranch.WhitelistUserIDs), ",")
- c.Data["merge_whitelist_users"] = strings.Join(base.Int64sToStrings(protectBranch.MergeWhitelistUserIDs), ",")
- c.Data["approvals_whitelist_users"] = strings.Join(base.Int64sToStrings(protectBranch.ApprovalsWhitelistUserIDs), ",")
+ c.Data["whitelist_users"] = strings.Join(base.Int64sToStrings(rule.WhitelistUserIDs), ",")
+ c.Data["merge_whitelist_users"] = strings.Join(base.Int64sToStrings(rule.MergeWhitelistUserIDs), ",")
+ c.Data["approvals_whitelist_users"] = strings.Join(base.Int64sToStrings(rule.ApprovalsWhitelistUserIDs), ",")
contexts, _ := git_model.FindRepoRecentCommitStatusContexts(c, c.Repo.Repository.ID, 7*24*time.Hour) // Find last week status check contexts
- for _, ctx := range protectBranch.StatusCheckContexts {
+ for _, ctx := range rule.StatusCheckContexts {
var found bool
for i := range contexts {
if contexts[i] == ctx {
@@ -150,7 +131,7 @@ func SettingsProtectedBranch(c *context.Context) {
c.Data["branch_status_check_contexts"] = contexts
c.Data["is_context_required"] = func(context string) bool {
- for _, c := range protectBranch.StatusCheckContexts {
+ for _, c := range rule.StatusCheckContexts {
if c == context {
return true
}
@@ -165,130 +146,173 @@ func SettingsProtectedBranch(c *context.Context) {
return
}
c.Data["Teams"] = teams
- c.Data["whitelist_teams"] = strings.Join(base.Int64sToStrings(protectBranch.WhitelistTeamIDs), ",")
- c.Data["merge_whitelist_teams"] = strings.Join(base.Int64sToStrings(protectBranch.MergeWhitelistTeamIDs), ",")
- c.Data["approvals_whitelist_teams"] = strings.Join(base.Int64sToStrings(protectBranch.ApprovalsWhitelistTeamIDs), ",")
+ c.Data["whitelist_teams"] = strings.Join(base.Int64sToStrings(rule.WhitelistTeamIDs), ",")
+ c.Data["merge_whitelist_teams"] = strings.Join(base.Int64sToStrings(rule.MergeWhitelistTeamIDs), ",")
+ c.Data["approvals_whitelist_teams"] = strings.Join(base.Int64sToStrings(rule.ApprovalsWhitelistTeamIDs), ",")
}
- c.Data["Branch"] = protectBranch
+ c.Data["Rule"] = rule
c.HTML(http.StatusOK, tplProtectedBranch)
}
// SettingsProtectedBranchPost updates the protected branch settings
func SettingsProtectedBranchPost(ctx *context.Context) {
f := web.GetForm(ctx).(*forms.ProtectBranchForm)
- branch := ctx.Params("*")
- if !ctx.Repo.GitRepo.IsBranchExist(branch) {
- ctx.NotFound("IsBranchExist", nil)
+ var protectBranch *git_model.ProtectedBranch
+ if f.RuleName == "" {
+ ctx.Flash.Error(ctx.Tr("repo.settings.protected_branch_required_rule_name"))
+ ctx.Redirect(fmt.Sprintf("%s/settings/branches/edit", ctx.Repo.RepoLink))
return
}
- protectBranch, err := git_model.GetProtectedBranchBy(ctx, ctx.Repo.Repository.ID, branch)
+ var err error
+ protectBranch, err = git_model.GetProtectedBranchRuleByName(ctx, ctx.Repo.Repository.ID, f.RuleName)
if err != nil {
- if !git.IsErrBranchNotExist(err) {
- ctx.ServerError("GetProtectBranchOfRepoByName", err)
- return
+ ctx.ServerError("GetProtectBranchOfRepoByName", err)
+ return
+ }
+ if protectBranch == nil {
+ // No options found, create defaults.
+ protectBranch = &git_model.ProtectedBranch{
+ RepoID: ctx.Repo.Repository.ID,
+ RuleName: f.RuleName,
}
}
- if f.Protected {
- if protectBranch == nil {
- // No options found, create defaults.
- protectBranch = &git_model.ProtectedBranch{
- RepoID: ctx.Repo.Repository.ID,
- BranchName: branch,
- }
+ var whitelistUsers, whitelistTeams, mergeWhitelistUsers, mergeWhitelistTeams, approvalsWhitelistUsers, approvalsWhitelistTeams []int64
+ protectBranch.RuleName = f.RuleName
+ if f.RequiredApprovals < 0 {
+ ctx.Flash.Error(ctx.Tr("repo.settings.protected_branch_required_approvals_min"))
+ ctx.Redirect(fmt.Sprintf("%s/settings/branches/edit?rule_name=%s", ctx.Repo.RepoLink, f.RuleName))
+ return
+ }
+
+ switch f.EnablePush {
+ case "all":
+ protectBranch.CanPush = true
+ protectBranch.EnableWhitelist = false
+ protectBranch.WhitelistDeployKeys = false
+ case "whitelist":
+ protectBranch.CanPush = true
+ protectBranch.EnableWhitelist = true
+ protectBranch.WhitelistDeployKeys = f.WhitelistDeployKeys
+ if strings.TrimSpace(f.WhitelistUsers) != "" {
+ whitelistUsers, _ = base.StringsToInt64s(strings.Split(f.WhitelistUsers, ","))
}
- if f.RequiredApprovals < 0 {
- ctx.Flash.Error(ctx.Tr("repo.settings.protected_branch_required_approvals_min"))
- ctx.Redirect(fmt.Sprintf("%s/settings/branches/%s", ctx.Repo.RepoLink, util.PathEscapeSegments(branch)))
+ if strings.TrimSpace(f.WhitelistTeams) != "" {
+ whitelistTeams, _ = base.StringsToInt64s(strings.Split(f.WhitelistTeams, ","))
}
+ default:
+ protectBranch.CanPush = false
+ protectBranch.EnableWhitelist = false
+ protectBranch.WhitelistDeployKeys = false
+ }
- var whitelistUsers, whitelistTeams, mergeWhitelistUsers, mergeWhitelistTeams, approvalsWhitelistUsers, approvalsWhitelistTeams []int64
- switch f.EnablePush {
- case "all":
- protectBranch.CanPush = true
- protectBranch.EnableWhitelist = false
- protectBranch.WhitelistDeployKeys = false
- case "whitelist":
- protectBranch.CanPush = true
- protectBranch.EnableWhitelist = true
- protectBranch.WhitelistDeployKeys = f.WhitelistDeployKeys
- if strings.TrimSpace(f.WhitelistUsers) != "" {
- whitelistUsers, _ = base.StringsToInt64s(strings.Split(f.WhitelistUsers, ","))
- }
- if strings.TrimSpace(f.WhitelistTeams) != "" {
- whitelistTeams, _ = base.StringsToInt64s(strings.Split(f.WhitelistTeams, ","))
- }
- default:
- protectBranch.CanPush = false
- protectBranch.EnableWhitelist = false
- protectBranch.WhitelistDeployKeys = false
+ protectBranch.EnableMergeWhitelist = f.EnableMergeWhitelist
+ if f.EnableMergeWhitelist {
+ if strings.TrimSpace(f.MergeWhitelistUsers) != "" {
+ mergeWhitelistUsers, _ = base.StringsToInt64s(strings.Split(f.MergeWhitelistUsers, ","))
}
-
- protectBranch.EnableMergeWhitelist = f.EnableMergeWhitelist
- if f.EnableMergeWhitelist {
- if strings.TrimSpace(f.MergeWhitelistUsers) != "" {
- mergeWhitelistUsers, _ = base.StringsToInt64s(strings.Split(f.MergeWhitelistUsers, ","))
- }
- if strings.TrimSpace(f.MergeWhitelistTeams) != "" {
- mergeWhitelistTeams, _ = base.StringsToInt64s(strings.Split(f.MergeWhitelistTeams, ","))
- }
+ if strings.TrimSpace(f.MergeWhitelistTeams) != "" {
+ mergeWhitelistTeams, _ = base.StringsToInt64s(strings.Split(f.MergeWhitelistTeams, ","))
}
+ }
- protectBranch.EnableStatusCheck = f.EnableStatusCheck
- if f.EnableStatusCheck {
- protectBranch.StatusCheckContexts = f.StatusCheckContexts
- } else {
- protectBranch.StatusCheckContexts = nil
- }
+ protectBranch.EnableStatusCheck = f.EnableStatusCheck
+ if f.EnableStatusCheck {
+ protectBranch.StatusCheckContexts = f.StatusCheckContexts
+ } else {
+ protectBranch.StatusCheckContexts = nil
+ }
- protectBranch.RequiredApprovals = f.RequiredApprovals
- protectBranch.EnableApprovalsWhitelist = f.EnableApprovalsWhitelist
- if f.EnableApprovalsWhitelist {
- if strings.TrimSpace(f.ApprovalsWhitelistUsers) != "" {
- approvalsWhitelistUsers, _ = base.StringsToInt64s(strings.Split(f.ApprovalsWhitelistUsers, ","))
- }
- if strings.TrimSpace(f.ApprovalsWhitelistTeams) != "" {
- approvalsWhitelistTeams, _ = base.StringsToInt64s(strings.Split(f.ApprovalsWhitelistTeams, ","))
- }
+ protectBranch.RequiredApprovals = f.RequiredApprovals
+ protectBranch.EnableApprovalsWhitelist = f.EnableApprovalsWhitelist
+ if f.EnableApprovalsWhitelist {
+ if strings.TrimSpace(f.ApprovalsWhitelistUsers) != "" {
+ approvalsWhitelistUsers, _ = base.StringsToInt64s(strings.Split(f.ApprovalsWhitelistUsers, ","))
}
- protectBranch.BlockOnRejectedReviews = f.BlockOnRejectedReviews
- protectBranch.BlockOnOfficialReviewRequests = f.BlockOnOfficialReviewRequests
- protectBranch.DismissStaleApprovals = f.DismissStaleApprovals
- protectBranch.RequireSignedCommits = f.RequireSignedCommits
- protectBranch.ProtectedFilePatterns = f.ProtectedFilePatterns
- protectBranch.UnprotectedFilePatterns = f.UnprotectedFilePatterns
- protectBranch.BlockOnOutdatedBranch = f.BlockOnOutdatedBranch
-
- err = git_model.UpdateProtectBranch(ctx, ctx.Repo.Repository, protectBranch, git_model.WhitelistOptions{
- UserIDs: whitelistUsers,
- TeamIDs: whitelistTeams,
- MergeUserIDs: mergeWhitelistUsers,
- MergeTeamIDs: mergeWhitelistTeams,
- ApprovalsUserIDs: approvalsWhitelistUsers,
- ApprovalsTeamIDs: approvalsWhitelistTeams,
- })
- if err != nil {
- ctx.ServerError("UpdateProtectBranch", err)
- return
+ if strings.TrimSpace(f.ApprovalsWhitelistTeams) != "" {
+ approvalsWhitelistTeams, _ = base.StringsToInt64s(strings.Split(f.ApprovalsWhitelistTeams, ","))
}
- if err = pull_service.CheckPrsForBaseBranch(ctx.Repo.Repository, protectBranch.BranchName); err != nil {
- ctx.ServerError("CheckPrsForBaseBranch", err)
+ }
+ protectBranch.BlockOnRejectedReviews = f.BlockOnRejectedReviews
+ protectBranch.BlockOnOfficialReviewRequests = f.BlockOnOfficialReviewRequests
+ protectBranch.DismissStaleApprovals = f.DismissStaleApprovals
+ protectBranch.RequireSignedCommits = f.RequireSignedCommits
+ protectBranch.ProtectedFilePatterns = f.ProtectedFilePatterns
+ protectBranch.UnprotectedFilePatterns = f.UnprotectedFilePatterns
+ protectBranch.BlockOnOutdatedBranch = f.BlockOnOutdatedBranch
+
+ err = git_model.UpdateProtectBranch(ctx, ctx.Repo.Repository, protectBranch, git_model.WhitelistOptions{
+ UserIDs: whitelistUsers,
+ TeamIDs: whitelistTeams,
+ MergeUserIDs: mergeWhitelistUsers,
+ MergeTeamIDs: mergeWhitelistTeams,
+ ApprovalsUserIDs: approvalsWhitelistUsers,
+ ApprovalsTeamIDs: approvalsWhitelistTeams,
+ })
+ if err != nil {
+ ctx.ServerError("UpdateProtectBranch", err)
+ return
+ }
+
+ // FIXME: since we only need to recheck files protected rules, we could improve this
+ matchedBranches, err := git_model.FindAllMatchedBranches(ctx, ctx.Repo.GitRepo, protectBranch.RuleName)
+ if err != nil {
+ ctx.ServerError("FindAllMatchedBranches", err)
+ return
+ }
+ for _, branchName := range matchedBranches {
+ if err = pull_service.CheckPRsForBaseBranch(ctx.Repo.Repository, branchName); err != nil {
+ ctx.ServerError("CheckPRsForBaseBranch", err)
return
}
- ctx.Flash.Success(ctx.Tr("repo.settings.update_protect_branch_success", branch))
- ctx.Redirect(fmt.Sprintf("%s/settings/branches/%s", ctx.Repo.RepoLink, util.PathEscapeSegments(branch)))
- } else {
- if protectBranch != nil {
- if err := git_model.DeleteProtectedBranch(ctx, ctx.Repo.Repository.ID, protectBranch.ID); err != nil {
- ctx.ServerError("DeleteProtectedBranch", err)
- return
- }
- }
- ctx.Flash.Success(ctx.Tr("repo.settings.remove_protected_branch_success", branch))
- ctx.Redirect(fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink))
}
+
+ ctx.Flash.Success(ctx.Tr("repo.settings.update_protect_branch_success", protectBranch.RuleName))
+ ctx.Redirect(fmt.Sprintf("%s/settings/branches?rule_name=%s", ctx.Repo.RepoLink, protectBranch.RuleName))
+}
+
+// DeleteProtectedBranchRulePost delete protected branch rule by id
+func DeleteProtectedBranchRulePost(ctx *context.Context) {
+ ruleID := ctx.ParamsInt64("id")
+ if ruleID <= 0 {
+ ctx.Flash.Error(ctx.Tr("repo.settings.remove_protected_branch_failed", fmt.Sprintf("%d", ruleID)))
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "redirect": fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink),
+ })
+ return
+ }
+
+ rule, err := git_model.GetProtectedBranchRuleByID(ctx, ctx.Repo.Repository.ID, ruleID)
+ if err != nil {
+ ctx.Flash.Error(ctx.Tr("repo.settings.remove_protected_branch_failed", fmt.Sprintf("%d", ruleID)))
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "redirect": fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink),
+ })
+ return
+ }
+
+ if rule == nil {
+ ctx.Flash.Error(ctx.Tr("repo.settings.remove_protected_branch_failed", fmt.Sprintf("%d", ruleID)))
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "redirect": fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink),
+ })
+ return
+ }
+
+ if err := git_model.DeleteProtectedBranch(ctx, ctx.Repo.Repository.ID, ruleID); err != nil {
+ ctx.Flash.Error(ctx.Tr("repo.settings.remove_protected_branch_failed", rule.RuleName))
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "redirect": fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink),
+ })
+ return
+ }
+
+ ctx.Flash.Success(ctx.Tr("repo.settings.remove_protected_branch_success", rule.RuleName))
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "redirect": fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink),
+ })
}
// RenameBranchPost responses for rename a branch
diff --git a/routers/web/web.go b/routers/web/web.go
index 997185974c..f0fedd0715 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -861,10 +861,16 @@ func RegisterRoutes(m *web.Route) {
})
m.Group("/branches", func() {
- m.Combo("").Get(repo.ProtectedBranch).Post(repo.ProtectedBranchPost)
- m.Combo("/*").Get(repo.SettingsProtectedBranch).
+ m.Post("/", repo.SetDefaultBranchPost)
+ }, repo.MustBeNotEmpty)
+
+ m.Group("/branches", func() {
+ m.Get("/", repo.ProtectedBranchRules)
+ m.Combo("/edit").Get(repo.SettingsProtectedBranch).
Post(web.Bind(forms.ProtectBranchForm{}), context.RepoMustNotBeArchived(), repo.SettingsProtectedBranchPost)
+ m.Post("/{id}/delete", repo.DeleteProtectedBranchRulePost)
}, repo.MustBeNotEmpty)
+
m.Post("/rename_branch", web.Bind(forms.RenameBranchForm{}), context.RepoMustNotBeArchived(), repo.RenameBranchPost)
m.Group("/tags", func() {