summaryrefslogtreecommitdiffstats
path: root/modules/migrations/migrate.go
diff options
context:
space:
mode:
Diffstat (limited to 'modules/migrations/migrate.go')
-rw-r--r--modules/migrations/migrate.go205
1 files changed, 205 insertions, 0 deletions
diff --git a/modules/migrations/migrate.go b/modules/migrations/migrate.go
new file mode 100644
index 0000000000..d72c869626
--- /dev/null
+++ b/modules/migrations/migrate.go
@@ -0,0 +1,205 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Copyright 2018 Jonas Franz. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package migrations
+
+import (
+ "fmt"
+
+ "code.gitea.io/gitea/models"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/migrations/base"
+)
+
+// MigrateOptions is equal to base.MigrateOptions
+type MigrateOptions = base.MigrateOptions
+
+var (
+ factories []base.DownloaderFactory
+)
+
+// RegisterDownloaderFactory registers a downloader factory
+func RegisterDownloaderFactory(factory base.DownloaderFactory) {
+ factories = append(factories, factory)
+}
+
+// MigrateRepository migrate repository according MigrateOptions
+func MigrateRepository(doer *models.User, ownerName string, opts base.MigrateOptions) (*models.Repository, error) {
+ var (
+ downloader base.Downloader
+ uploader = NewGiteaLocalUploader(doer, ownerName, opts.Name)
+ )
+
+ for _, factory := range factories {
+ if match, err := factory.Match(opts); err != nil {
+ return nil, err
+ } else if match {
+ downloader, err = factory.New(opts)
+ if err != nil {
+ return nil, err
+ }
+ break
+ }
+ }
+
+ if downloader == nil {
+ opts.Wiki = true
+ opts.Milestones = false
+ opts.Labels = false
+ opts.Releases = false
+ opts.Comments = false
+ opts.Issues = false
+ opts.PullRequests = false
+ downloader = NewPlainGitDownloader(ownerName, opts.Name, opts.RemoteURL)
+ log.Trace("Will migrate from git: %s", opts.RemoteURL)
+ }
+
+ if err := migrateRepository(downloader, uploader, opts); err != nil {
+ if err1 := uploader.Rollback(); err1 != nil {
+ log.Error("rollback failed: %v", err1)
+ }
+ return nil, err
+ }
+
+ return uploader.repo, nil
+}
+
+// migrateRepository will download informations and upload to Uploader, this is a simple
+// process for small repository. For a big repository, save all the data to disk
+// before upload is better
+func migrateRepository(downloader base.Downloader, uploader base.Uploader, opts base.MigrateOptions) error {
+ repo, err := downloader.GetRepoInfo()
+ if err != nil {
+ return err
+ }
+ repo.IsPrivate = opts.Private
+ repo.IsMirror = opts.Mirror
+ log.Trace("migrating git data")
+ if err := uploader.CreateRepo(repo, opts.Wiki); err != nil {
+ return err
+ }
+
+ if opts.Milestones {
+ log.Trace("migrating milestones")
+ milestones, err := downloader.GetMilestones()
+ if err != nil {
+ return err
+ }
+
+ for _, milestone := range milestones {
+ if err := uploader.CreateMilestone(milestone); err != nil {
+ return err
+ }
+ }
+ }
+
+ if opts.Labels {
+ log.Trace("migrating labels")
+ labels, err := downloader.GetLabels()
+ if err != nil {
+ return err
+ }
+
+ for _, label := range labels {
+ if err := uploader.CreateLabel(label); err != nil {
+ return err
+ }
+ }
+ }
+
+ if opts.Releases {
+ log.Trace("migrating releases")
+ releases, err := downloader.GetReleases()
+ if err != nil {
+ return err
+ }
+
+ for _, release := range releases {
+ if err := uploader.CreateRelease(release); err != nil {
+ return err
+ }
+ }
+ }
+
+ if opts.Issues {
+ log.Trace("migrating issues and comments")
+ for {
+ issues, err := downloader.GetIssues(0, 100)
+ if err != nil {
+ return err
+ }
+ for _, issue := range issues {
+ if !opts.IgnoreIssueAuthor {
+ issue.Content = fmt.Sprintf("Author: @%s \n\n%s", issue.PosterName, issue.Content)
+ }
+
+ if err := uploader.CreateIssue(issue); err != nil {
+ return err
+ }
+
+ if !opts.Comments {
+ continue
+ }
+
+ comments, err := downloader.GetComments(issue.Number)
+ if err != nil {
+ return err
+ }
+ for _, comment := range comments {
+ if !opts.IgnoreIssueAuthor {
+ comment.Content = fmt.Sprintf("Author: @%s \n\n%s", comment.PosterName, comment.Content)
+ }
+ if err := uploader.CreateComment(issue.Number, comment); err != nil {
+ return err
+ }
+ }
+ }
+
+ if len(issues) < 100 {
+ break
+ }
+ }
+ }
+
+ if opts.PullRequests {
+ log.Trace("migrating pull requests and comments")
+ for {
+ prs, err := downloader.GetPullRequests(0, 100)
+ if err != nil {
+ return err
+ }
+
+ for _, pr := range prs {
+ if !opts.IgnoreIssueAuthor {
+ pr.Content = fmt.Sprintf("Author: @%s \n\n%s", pr.PosterName, pr.Content)
+ }
+ if err := uploader.CreatePullRequest(pr); err != nil {
+ return err
+ }
+ if !opts.Comments {
+ continue
+ }
+
+ comments, err := downloader.GetComments(pr.Number)
+ if err != nil {
+ return err
+ }
+ for _, comment := range comments {
+ if !opts.IgnoreIssueAuthor {
+ comment.Content = fmt.Sprintf("Author: @%s \n\n%s", comment.PosterName, comment.Content)
+ }
+ if err := uploader.CreateComment(pr.Number, comment); err != nil {
+ return err
+ }
+ }
+ }
+ if len(prs) < 100 {
+ break
+ }
+ }
+ }
+
+ return nil
+}