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.8KB

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