diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 411a585c81..92ca5be8d3 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2152,6 +2152,7 @@ settings.choose_branch = Choose a branch… settings.no_protected_branch = There are no protected branches. settings.edit_protected_branch = Edit settings.protected_branch_required_rule_name = Required rule name +settings.protected_branch_duplicate_rule_name = Duplicate rule name settings.protected_branch_required_approvals_min = Required approvals cannot be negative. settings.tags = Tags settings.tags.protection = Tag Protection diff --git a/routers/web/repo/setting_protected_branch.go b/routers/web/repo/setting_protected_branch.go index a54565c1f1..0a8c39fef0 100644 --- a/routers/web/repo/setting_protected_branch.go +++ b/routers/web/repo/setting_protected_branch.go @@ -166,10 +166,36 @@ func SettingsProtectedBranchPost(ctx *context.Context) { } var err error - protectBranch, err = git_model.GetProtectedBranchRuleByName(ctx, ctx.Repo.Repository.ID, f.RuleName) - if err != nil { - ctx.ServerError("GetProtectBranchOfRepoByName", err) - return + if f.RuleID > 0 { + // If the RuleID isn't 0, it must be an edit operation. So we get rule by id. + protectBranch, err = git_model.GetProtectedBranchRuleByID(ctx, ctx.Repo.Repository.ID, f.RuleID) + if err != nil { + ctx.ServerError("GetProtectBranchOfRepoByID", err) + return + } + if protectBranch != nil && protectBranch.RuleName != f.RuleName { + // RuleName changed. We need to check if there is a rule with the same name. + // If a rule with the same name exists, an error should be returned. + sameNameProtectBranch, err := git_model.GetProtectedBranchRuleByName(ctx, ctx.Repo.Repository.ID, f.RuleName) + if err != nil { + ctx.ServerError("GetProtectBranchOfRepoByName", err) + return + } + if sameNameProtectBranch != nil { + ctx.Flash.Error(ctx.Tr("repo.settings.protected_branch_duplicate_rule_name")) + ctx.Redirect(fmt.Sprintf("%s/settings/branches/edit?rule_name=%s", ctx.Repo.RepoLink, protectBranch.RuleName)) + return + } + } + } else { + // FIXME: If a new ProtectBranch has a duplicate RuleName, an error should be returned. + // Currently, if a new ProtectBranch with a duplicate RuleName is created, the existing ProtectBranch will be updated. + // But we cannot modify this logic now because many unit tests rely on it. + protectBranch, err = git_model.GetProtectedBranchRuleByName(ctx, ctx.Repo.Repository.ID, f.RuleName) + if err != nil { + ctx.ServerError("GetProtectBranchOfRepoByName", err) + return + } } if protectBranch == nil { // No options found, create defaults. diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index ff0916f8e1..374ae0ac5c 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -190,6 +190,7 @@ func (f *RepoSettingForm) Validate(req *http.Request, errs binding.Errors) bindi // ProtectBranchForm form for changing protected branch settings type ProtectBranchForm struct { RuleName string `binding:"Required"` + RuleID int64 EnablePush string WhitelistUsers string WhitelistTeams string