1
0
Fork 0
mirror of https://codeberg.org/forgejo/forgejo.git synced 2024-12-22 12:54:53 -05:00

Support copy protected branch from template repository (#25889)

Fix #14303
This commit is contained in:
Lunny Xiao 2023-07-21 12:32:47 +08:00 committed by GitHub
parent 2b6f224336
commit 037c9895a7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 86 additions and 38 deletions

View file

@ -303,21 +303,23 @@ func GenerateGitContent(ctx context.Context, templateRepo, generateRepo *repo_mo
// GenerateRepoOptions contains the template units to generate // GenerateRepoOptions contains the template units to generate
type GenerateRepoOptions struct { type GenerateRepoOptions struct {
Name string Name string
DefaultBranch string DefaultBranch string
Description string Description string
Private bool Private bool
GitContent bool GitContent bool
Topics bool Topics bool
GitHooks bool GitHooks bool
Webhooks bool Webhooks bool
Avatar bool Avatar bool
IssueLabels bool IssueLabels bool
ProtectedBranch bool
} }
// IsValid checks whether at least one option is chosen for generation // IsValid checks whether at least one option is chosen for generation
func (gro GenerateRepoOptions) IsValid() bool { func (gro GenerateRepoOptions) IsValid() bool {
return gro.GitContent || gro.Topics || gro.GitHooks || gro.Webhooks || gro.Avatar || gro.IssueLabels // or other items as they are added return gro.GitContent || gro.Topics || gro.GitHooks || gro.Webhooks || gro.Avatar ||
gro.IssueLabels || gro.ProtectedBranch // or other items as they are added
} }
// GenerateRepository generates a repository from a template // GenerateRepository generates a repository from a template

View file

@ -238,6 +238,8 @@ type GenerateRepoOption struct {
Avatar bool `json:"avatar"` Avatar bool `json:"avatar"`
// include labels in template repo // include labels in template repo
Labels bool `json:"labels"` Labels bool `json:"labels"`
// include protected branches in template repo
ProtectedBranch bool `json:"protected_branch"`
} }
// CreateBranchRepoOption options when creating a branch in a repository // CreateBranchRepoOption options when creating a branch in a repository

View file

@ -355,16 +355,17 @@ func Generate(ctx *context.APIContext) {
} }
opts := repo_module.GenerateRepoOptions{ opts := repo_module.GenerateRepoOptions{
Name: form.Name, Name: form.Name,
DefaultBranch: form.DefaultBranch, DefaultBranch: form.DefaultBranch,
Description: form.Description, Description: form.Description,
Private: form.Private, Private: form.Private,
GitContent: form.GitContent, GitContent: form.GitContent,
Topics: form.Topics, Topics: form.Topics,
GitHooks: form.GitHooks, GitHooks: form.GitHooks,
Webhooks: form.Webhooks, Webhooks: form.Webhooks,
Avatar: form.Avatar, Avatar: form.Avatar,
IssueLabels: form.Labels, IssueLabels: form.Labels,
ProtectedBranch: form.ProtectedBranch,
} }
if !opts.IsValid() { if !opts.IsValid() {

View file

@ -241,15 +241,16 @@ func CreatePost(ctx *context.Context) {
var err error var err error
if form.RepoTemplate > 0 { if form.RepoTemplate > 0 {
opts := repo_module.GenerateRepoOptions{ opts := repo_module.GenerateRepoOptions{
Name: form.RepoName, Name: form.RepoName,
Description: form.Description, Description: form.Description,
Private: form.Private, Private: form.Private,
GitContent: form.GitContent, GitContent: form.GitContent,
Topics: form.Topics, Topics: form.Topics,
GitHooks: form.GitHooks, GitHooks: form.GitHooks,
Webhooks: form.Webhooks, Webhooks: form.Webhooks,
Avatar: form.Avatar, Avatar: form.Avatar,
IssueLabels: form.Labels, IssueLabels: form.Labels,
ProtectedBranch: form.ProtectedBranch,
} }
if !opts.IsValid() { if !opts.IsValid() {

View file

@ -42,14 +42,15 @@ type CreateRepoForm struct {
Readme string Readme string
Template bool Template bool
RepoTemplate int64 RepoTemplate int64
GitContent bool GitContent bool
Topics bool Topics bool
GitHooks bool GitHooks bool
Webhooks bool Webhooks bool
Avatar bool Avatar bool
Labels bool Labels bool
TrustModel string ProtectedBranch bool
TrustModel string
} }
// Validate validates the fields // Validate validates the fields

View file

@ -7,6 +7,7 @@ import (
"context" "context"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
@ -39,6 +40,28 @@ func GenerateIssueLabels(ctx context.Context, templateRepo, generateRepo *repo_m
return db.Insert(ctx, newLabels) return db.Insert(ctx, newLabels)
} }
func GenerateProtectedBranch(ctx context.Context, templateRepo, generateRepo *repo_model.Repository) error {
templateBranches, err := git_model.FindRepoProtectedBranchRules(ctx, templateRepo.ID)
if err != nil {
return err
}
// Prevent insert being called with an empty slice which would result in
// err "no element on slice when insert".
if len(templateBranches) == 0 {
return nil
}
newBranches := make([]*git_model.ProtectedBranch, 0, len(templateBranches))
for _, templateBranch := range templateBranches {
templateBranch.ID = 0
templateBranch.RepoID = generateRepo.ID
templateBranch.UpdatedUnix = 0
templateBranch.CreatedUnix = 0
newBranches = append(newBranches, templateBranch)
}
return db.Insert(ctx, newBranches)
}
// GenerateRepository generates a repository from a template // GenerateRepository generates a repository from a template
func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templateRepo *repo_model.Repository, opts repo_module.GenerateRepoOptions) (_ *repo_model.Repository, err error) { func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templateRepo *repo_model.Repository, opts repo_module.GenerateRepoOptions) (_ *repo_model.Repository, err error) {
if !doer.IsAdmin && !owner.CanCreateRepo() { if !doer.IsAdmin && !owner.CanCreateRepo() {
@ -96,6 +119,12 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ
} }
} }
if opts.ProtectedBranch {
if err = GenerateProtectedBranch(ctx, templateRepo, generateRepo); err != nil {
return err
}
}
return nil return nil
}); err != nil { }); err != nil {
return nil, err return nil, err

View file

@ -107,6 +107,13 @@
<label>{{.locale.Tr "repo.template.issue_labels"}}</label> <label>{{.locale.Tr "repo.template.issue_labels"}}</label>
</div> </div>
</div> </div>
<div class="inline field">
<label></label>
<div class="ui checkbox">
<input name="protected_branch" type="checkbox" tabindex="0" {{if .protected_branch}}checked{{end}}>
<label>{{.locale.Tr "repo.settings.protected_branch"}}</label>
</div>
</div>
</div> </div>
<div id="non_template"> <div id="non_template">

View file

@ -18906,6 +18906,11 @@
"type": "boolean", "type": "boolean",
"x-go-name": "Private" "x-go-name": "Private"
}, },
"protected_branch": {
"description": "include protected branches in template repo",
"type": "boolean",
"x-go-name": "ProtectedBranch"
},
"topics": { "topics": {
"description": "include topics in template repo", "description": "include topics in template repo",
"type": "boolean", "type": "boolean",