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.

205 lines
4.7 KiB

  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // Copyright 2018 Jonas Franz. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package migrations
  6. import (
  7. "fmt"
  8. "code.gitea.io/gitea/models"
  9. "code.gitea.io/gitea/modules/log"
  10. "code.gitea.io/gitea/modules/migrations/base"
  11. )
  12. // MigrateOptions is equal to base.MigrateOptions
  13. type MigrateOptions = base.MigrateOptions
  14. var (
  15. factories []base.DownloaderFactory
  16. )
  17. // RegisterDownloaderFactory registers a downloader factory
  18. func RegisterDownloaderFactory(factory base.DownloaderFactory) {
  19. factories = append(factories, factory)
  20. }
  21. // MigrateRepository migrate repository according MigrateOptions
  22. func MigrateRepository(doer *models.User, ownerName string, opts base.MigrateOptions) (*models.Repository, error) {
  23. var (
  24. downloader base.Downloader
  25. uploader = NewGiteaLocalUploader(doer, ownerName, opts.Name)
  26. )
  27. for _, factory := range factories {
  28. if match, err := factory.Match(opts); err != nil {
  29. return nil, err
  30. } else if match {
  31. downloader, err = factory.New(opts)
  32. if err != nil {
  33. return nil, err
  34. }
  35. break
  36. }
  37. }
  38. if downloader == nil {
  39. opts.Wiki = true
  40. opts.Milestones = false
  41. opts.Labels = false
  42. opts.Releases = false
  43. opts.Comments = false
  44. opts.Issues = false
  45. opts.PullRequests = false
  46. downloader = NewPlainGitDownloader(ownerName, opts.Name, opts.RemoteURL)
  47. log.Trace("Will migrate from git: %s", opts.RemoteURL)
  48. }
  49. if err := migrateRepository(downloader, uploader, opts); err != nil {
  50. if err1 := uploader.Rollback(); err1 != nil {
  51. log.Error("rollback failed: %v", err1)
  52. }
  53. return nil, err
  54. }
  55. return uploader.repo, nil
  56. }
  57. // migrateRepository will download informations and upload to Uploader, this is a simple
  58. // process for small repository. For a big repository, save all the data to disk
  59. // before upload is better
  60. func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts base.MigrateOptions) error {
  61. repo, err := downloader.GetRepoInfo()
  62. if err != nil {
  63. return err
  64. }
  65. repo.IsPrivate = opts.Private
  66. repo.IsMirror = opts.Mirror
  67. log.Trace("migrating git data")
  68. if err := uploader.CreateRepo(repo, opts.Wiki); err != nil {
  69. return err
  70. }
  71. if opts.Milestones {
  72. log.Trace("migrating milestones")
  73. milestones, err := downloader.GetMilestones()
  74. if err != nil {
  75. return err
  76. }
  77. for _, milestone := range milestones {
  78. if err := uploader.CreateMilestone(milestone); err != nil {
  79. return err
  80. }
  81. }
  82. }
  83. if opts.Labels {
  84. log.Trace("migrating labels")
  85. labels, err := downloader.GetLabels()
  86. if err != nil {
  87. return err
  88. }
  89. for _, label := range labels {
  90. if err := uploader.CreateLabel(label); err != nil {
  91. return err
  92. }
  93. }
  94. }
  95. if opts.Releases {
  96. log.Trace("migrating releases")
  97. releases, err := downloader.GetReleases()
  98. if err != nil {
  99. return err
  100. }
  101. for _, release := range releases {
  102. if err := uploader.CreateRelease(release); err != nil {
  103. return err
  104. }
  105. }
  106. }
  107. if opts.Issues {
  108. log.Trace("migrating issues and comments")
  109. for {
  110. issues, err := downloader.GetIssues(0, 100)
  111. if err != nil {
  112. return err
  113. }
  114. for _, issue := range issues {
  115. if !opts.IgnoreIssueAuthor {
  116. issue.Content = fmt.Sprintf("Author: @%s \n\n%s", issue.PosterName, issue.Content)
  117. }
  118. if err := uploader.CreateIssue(issue); err != nil {
  119. return err
  120. }
  121. if !opts.Comments {
  122. continue
  123. }
  124. comments, err := downloader.GetComments(issue.Number)
  125. if err != nil {
  126. return err
  127. }
  128. for _, comment := range comments {
  129. if !opts.IgnoreIssueAuthor {
  130. comment.Content = fmt.Sprintf("Author: @%s \n\n%s", comment.PosterName, comment.Content)
  131. }
  132. if err := uploader.CreateComment(issue.Number, comment); err != nil {
  133. return err
  134. }
  135. }
  136. }
  137. if len(issues) < 100 {
  138. break
  139. }
  140. }
  141. }
  142. if opts.PullRequests {
  143. log.Trace("migrating pull requests and comments")
  144. for {
  145. prs, err := downloader.GetPullRequests(0, 100)
  146. if err != nil {
  147. return err
  148. }
  149. for _, pr := range prs {
  150. if !opts.IgnoreIssueAuthor {
  151. pr.Content = fmt.Sprintf("Author: @%s \n\n%s", pr.PosterName, pr.Content)
  152. }
  153. if err := uploader.CreatePullRequest(pr); err != nil {
  154. return err
  155. }
  156. if !opts.Comments {
  157. continue
  158. }
  159. comments, err := downloader.GetComments(pr.Number)
  160. if err != nil {
  161. return err
  162. }
  163. for _, comment := range comments {
  164. if !opts.IgnoreIssueAuthor {
  165. comment.Content = fmt.Sprintf("Author: @%s \n\n%s", comment.PosterName, comment.Content)
  166. }
  167. if err := uploader.CreateComment(pr.Number, comment); err != nil {
  168. return err
  169. }
  170. }
  171. }
  172. if len(prs) < 100 {
  173. break
  174. }
  175. }
  176. }
  177. return nil
  178. }