From 037c9895a7406b42f88991295382db18f98dbef9 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 21 Jul 2023 12:32:47 +0800 Subject: [PATCH] Support copy protected branch from template repository (#25889) Fix #14303 --- modules/repository/generate.go | 24 +++++++++++++----------- modules/structs/repo.go | 2 ++ routers/api/v1/repo/repo.go | 21 +++++++++++---------- routers/web/repo/repo.go | 19 ++++++++++--------- services/forms/repo_form.go | 17 +++++++++-------- services/repository/template.go | 29 +++++++++++++++++++++++++++++ templates/repo/create.tmpl | 7 +++++++ templates/swagger/v1_json.tmpl | 5 +++++ 8 files changed, 86 insertions(+), 38 deletions(-) diff --git a/modules/repository/generate.go b/modules/repository/generate.go index cb25daa10b3..2e0b7600a59 100644 --- a/modules/repository/generate.go +++ b/modules/repository/generate.go @@ -303,21 +303,23 @@ func GenerateGitContent(ctx context.Context, templateRepo, generateRepo *repo_mo // GenerateRepoOptions contains the template units to generate type GenerateRepoOptions struct { - Name string - DefaultBranch string - Description string - Private bool - GitContent bool - Topics bool - GitHooks bool - Webhooks bool - Avatar bool - IssueLabels bool + Name string + DefaultBranch string + Description string + Private bool + GitContent bool + Topics bool + GitHooks bool + Webhooks bool + Avatar bool + IssueLabels bool + ProtectedBranch bool } // IsValid checks whether at least one option is chosen for generation 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 diff --git a/modules/structs/repo.go b/modules/structs/repo.go index af439ad7309..6a2ba4836bb 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -238,6 +238,8 @@ type GenerateRepoOption struct { Avatar bool `json:"avatar"` // include labels in template repo Labels bool `json:"labels"` + // include protected branches in template repo + ProtectedBranch bool `json:"protected_branch"` } // CreateBranchRepoOption options when creating a branch in a repository diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index d9424d9e769..7b0c954a73b 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -355,16 +355,17 @@ func Generate(ctx *context.APIContext) { } opts := repo_module.GenerateRepoOptions{ - Name: form.Name, - DefaultBranch: form.DefaultBranch, - Description: form.Description, - Private: form.Private, - GitContent: form.GitContent, - Topics: form.Topics, - GitHooks: form.GitHooks, - Webhooks: form.Webhooks, - Avatar: form.Avatar, - IssueLabels: form.Labels, + Name: form.Name, + DefaultBranch: form.DefaultBranch, + Description: form.Description, + Private: form.Private, + GitContent: form.GitContent, + Topics: form.Topics, + GitHooks: form.GitHooks, + Webhooks: form.Webhooks, + Avatar: form.Avatar, + IssueLabels: form.Labels, + ProtectedBranch: form.ProtectedBranch, } if !opts.IsValid() { diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go index d1ccb011bb1..0a2b334eb90 100644 --- a/routers/web/repo/repo.go +++ b/routers/web/repo/repo.go @@ -241,15 +241,16 @@ func CreatePost(ctx *context.Context) { var err error if form.RepoTemplate > 0 { opts := repo_module.GenerateRepoOptions{ - Name: form.RepoName, - Description: form.Description, - Private: form.Private, - GitContent: form.GitContent, - Topics: form.Topics, - GitHooks: form.GitHooks, - Webhooks: form.Webhooks, - Avatar: form.Avatar, - IssueLabels: form.Labels, + Name: form.RepoName, + Description: form.Description, + Private: form.Private, + GitContent: form.GitContent, + Topics: form.Topics, + GitHooks: form.GitHooks, + Webhooks: form.Webhooks, + Avatar: form.Avatar, + IssueLabels: form.Labels, + ProtectedBranch: form.ProtectedBranch, } if !opts.IsValid() { diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index 8108a55f7a3..a26a2d89c5d 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -42,14 +42,15 @@ type CreateRepoForm struct { Readme string Template bool - RepoTemplate int64 - GitContent bool - Topics bool - GitHooks bool - Webhooks bool - Avatar bool - Labels bool - TrustModel string + RepoTemplate int64 + GitContent bool + Topics bool + GitHooks bool + Webhooks bool + Avatar bool + Labels bool + ProtectedBranch bool + TrustModel string } // Validate validates the fields diff --git a/services/repository/template.go b/services/repository/template.go index 42174d095b0..9a69360aff6 100644 --- a/services/repository/template.go +++ b/services/repository/template.go @@ -7,6 +7,7 @@ import ( "context" "code.gitea.io/gitea/models/db" + git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" 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) } +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 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() { @@ -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 }); err != nil { return nil, err diff --git a/templates/repo/create.tmpl b/templates/repo/create.tmpl index 1ec67827e52..ce909fbbf7b 100644 --- a/templates/repo/create.tmpl +++ b/templates/repo/create.tmpl @@ -107,6 +107,13 @@ +
+ +
+ + +
+
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 0dfbc9c6959..7b3a616740c 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -18906,6 +18906,11 @@ "type": "boolean", "x-go-name": "Private" }, + "protected_branch": { + "description": "include protected branches in template repo", + "type": "boolean", + "x-go-name": "ProtectedBranch" + }, "topics": { "description": "include topics in template repo", "type": "boolean",