You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

repo_generate.go 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package models
  5. import (
  6. "bufio"
  7. "bytes"
  8. "strconv"
  9. "strings"
  10. "code.gitea.io/gitea/modules/git"
  11. "code.gitea.io/gitea/modules/log"
  12. "code.gitea.io/gitea/modules/storage"
  13. "github.com/gobwas/glob"
  14. )
  15. // GenerateRepoOptions contains the template units to generate
  16. type GenerateRepoOptions struct {
  17. Name string
  18. Description string
  19. Private bool
  20. GitContent bool
  21. Topics bool
  22. GitHooks bool
  23. Webhooks bool
  24. Avatar bool
  25. IssueLabels bool
  26. }
  27. // IsValid checks whether at least one option is chosen for generation
  28. func (gro GenerateRepoOptions) IsValid() bool {
  29. return gro.GitContent || gro.Topics || gro.GitHooks || gro.Webhooks || gro.Avatar || gro.IssueLabels // or other items as they are added
  30. }
  31. // GiteaTemplate holds information about a .gitea/template file
  32. type GiteaTemplate struct {
  33. Path string
  34. Content []byte
  35. globs []glob.Glob
  36. }
  37. // Globs parses the .gitea/template globs or returns them if they were already parsed
  38. func (gt GiteaTemplate) Globs() []glob.Glob {
  39. if gt.globs != nil {
  40. return gt.globs
  41. }
  42. gt.globs = make([]glob.Glob, 0)
  43. scanner := bufio.NewScanner(bytes.NewReader(gt.Content))
  44. for scanner.Scan() {
  45. line := strings.TrimSpace(scanner.Text())
  46. if line == "" || strings.HasPrefix(line, "#") {
  47. continue
  48. }
  49. g, err := glob.Compile(line, '/')
  50. if err != nil {
  51. log.Info("Invalid glob expression '%s' (skipped): %v", line, err)
  52. continue
  53. }
  54. gt.globs = append(gt.globs, g)
  55. }
  56. return gt.globs
  57. }
  58. // GenerateTopics generates topics from a template repository
  59. func GenerateTopics(ctx DBContext, templateRepo, generateRepo *Repository) error {
  60. for _, topic := range templateRepo.Topics {
  61. if _, err := addTopicByNameToRepo(ctx.e, generateRepo.ID, topic); err != nil {
  62. return err
  63. }
  64. }
  65. return nil
  66. }
  67. // GenerateGitHooks generates git hooks from a template repository
  68. func GenerateGitHooks(ctx DBContext, templateRepo, generateRepo *Repository) error {
  69. generateGitRepo, err := git.OpenRepository(generateRepo.RepoPath())
  70. if err != nil {
  71. return err
  72. }
  73. defer generateGitRepo.Close()
  74. templateGitRepo, err := git.OpenRepository(templateRepo.RepoPath())
  75. if err != nil {
  76. return err
  77. }
  78. defer templateGitRepo.Close()
  79. templateHooks, err := templateGitRepo.Hooks()
  80. if err != nil {
  81. return err
  82. }
  83. for _, templateHook := range templateHooks {
  84. generateHook, err := generateGitRepo.GetHook(templateHook.Name())
  85. if err != nil {
  86. return err
  87. }
  88. generateHook.Content = templateHook.Content
  89. if err := generateHook.Update(); err != nil {
  90. return err
  91. }
  92. }
  93. return nil
  94. }
  95. // GenerateWebhooks generates webhooks from a template repository
  96. func GenerateWebhooks(ctx DBContext, templateRepo, generateRepo *Repository) error {
  97. templateWebhooks, err := ListWebhooksByOpts(&ListWebhookOptions{RepoID: templateRepo.ID})
  98. if err != nil {
  99. return err
  100. }
  101. for _, templateWebhook := range templateWebhooks {
  102. generateWebhook := &Webhook{
  103. RepoID: generateRepo.ID,
  104. URL: templateWebhook.URL,
  105. HTTPMethod: templateWebhook.HTTPMethod,
  106. ContentType: templateWebhook.ContentType,
  107. Secret: templateWebhook.Secret,
  108. HookEvent: templateWebhook.HookEvent,
  109. IsActive: templateWebhook.IsActive,
  110. Type: templateWebhook.Type,
  111. OrgID: templateWebhook.OrgID,
  112. Events: templateWebhook.Events,
  113. Meta: templateWebhook.Meta,
  114. }
  115. if err := createWebhook(ctx.e, generateWebhook); err != nil {
  116. return err
  117. }
  118. }
  119. return nil
  120. }
  121. // GenerateAvatar generates the avatar from a template repository
  122. func GenerateAvatar(ctx DBContext, templateRepo, generateRepo *Repository) error {
  123. generateRepo.Avatar = strings.Replace(templateRepo.Avatar, strconv.FormatInt(templateRepo.ID, 10), strconv.FormatInt(generateRepo.ID, 10), 1)
  124. if _, err := storage.Copy(storage.RepoAvatars, generateRepo.CustomAvatarRelativePath(), storage.RepoAvatars, templateRepo.CustomAvatarRelativePath()); err != nil {
  125. return err
  126. }
  127. return updateRepositoryCols(ctx.e, generateRepo, "avatar")
  128. }
  129. // GenerateIssueLabels generates issue labels from a template repository
  130. func GenerateIssueLabels(ctx DBContext, templateRepo, generateRepo *Repository) error {
  131. templateLabels, err := getLabelsByRepoID(ctx.e, templateRepo.ID, "", ListOptions{})
  132. if err != nil {
  133. return err
  134. }
  135. for _, templateLabel := range templateLabels {
  136. generateLabel := &Label{
  137. RepoID: generateRepo.ID,
  138. Name: templateLabel.Name,
  139. Description: templateLabel.Description,
  140. Color: templateLabel.Color,
  141. }
  142. if err := newLabel(ctx.e, generateLabel); err != nil {
  143. return err
  144. }
  145. }
  146. return nil
  147. }