mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Add migration from GitBucket (#16767)
This PR adds [GitBucket](https://gitbucket.github.io/) as migration source. Supported: - Milestones - Issues - Pull Requests - Comments - Reviews - Labels There is no public usable instance so no integration tests added.
This commit is contained in:
		@@ -35,6 +35,8 @@ func ToGitServiceType(value string) structs.GitServiceType {
 | 
				
			|||||||
		return structs.GogsService
 | 
							return structs.GogsService
 | 
				
			||||||
	case "onedev":
 | 
						case "onedev":
 | 
				
			||||||
		return structs.OneDevService
 | 
							return structs.OneDevService
 | 
				
			||||||
 | 
						case "gitbucket":
 | 
				
			||||||
 | 
							return structs.GitBucketService
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return structs.PlainGitService
 | 
							return structs.PlainGitService
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										72
									
								
								modules/migrations/gitbucket.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								modules/migrations/gitbucket.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 The Gitea Authors. 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 (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"net/url"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/migrations/base"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						_ base.Downloader        = &GitBucketDownloader{}
 | 
				
			||||||
 | 
						_ base.DownloaderFactory = &GitBucketDownloaderFactory{}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						RegisterDownloaderFactory(&GitBucketDownloaderFactory{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GitBucketDownloaderFactory defines a GitBucket downloader factory
 | 
				
			||||||
 | 
					type GitBucketDownloaderFactory struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// New returns a Downloader related to this factory according MigrateOptions
 | 
				
			||||||
 | 
					func (f *GitBucketDownloaderFactory) New(ctx context.Context, opts base.MigrateOptions) (base.Downloader, error) {
 | 
				
			||||||
 | 
						u, err := url.Parse(opts.CloneAddr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						baseURL := u.Scheme + "://" + u.Host
 | 
				
			||||||
 | 
						fields := strings.Split(u.Path, "/")
 | 
				
			||||||
 | 
						oldOwner := fields[1]
 | 
				
			||||||
 | 
						oldName := strings.TrimSuffix(fields[2], ".git")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NewGitBucketDownloader(ctx, baseURL, opts.AuthUsername, opts.AuthPassword, opts.AuthToken, oldOwner, oldName), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GitServiceType returns the type of git service
 | 
				
			||||||
 | 
					func (f *GitBucketDownloaderFactory) GitServiceType() structs.GitServiceType {
 | 
				
			||||||
 | 
						return structs.GitBucketService
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GitBucketDownloader implements a Downloader interface to get repository information
 | 
				
			||||||
 | 
					// from GitBucket via GithubDownloader
 | 
				
			||||||
 | 
					type GitBucketDownloader struct {
 | 
				
			||||||
 | 
						*GithubDownloaderV3
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewGitBucketDownloader creates a GitBucket downloader
 | 
				
			||||||
 | 
					func NewGitBucketDownloader(ctx context.Context, baseURL, userName, password, token, repoOwner, repoName string) *GitBucketDownloader {
 | 
				
			||||||
 | 
						githubDownloader := NewGithubDownloaderV3(ctx, baseURL, userName, password, token, repoOwner, repoName)
 | 
				
			||||||
 | 
						githubDownloader.SkipReactions = true
 | 
				
			||||||
 | 
						return &GitBucketDownloader{
 | 
				
			||||||
 | 
							githubDownloader,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SupportGetRepoComments return true if it supports get repo comments
 | 
				
			||||||
 | 
					func (g *GitBucketDownloader) SupportGetRepoComments() bool {
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetReviews is not supported
 | 
				
			||||||
 | 
					func (g *GitBucketDownloader) GetReviews(context base.IssueContext) ([]*base.Review, error) {
 | 
				
			||||||
 | 
						return nil, &base.ErrNotSupported{Entity: "Reviews"}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -68,15 +68,16 @@ func (f *GithubDownloaderV3Factory) GitServiceType() structs.GitServiceType {
 | 
				
			|||||||
// from github via APIv3
 | 
					// from github via APIv3
 | 
				
			||||||
type GithubDownloaderV3 struct {
 | 
					type GithubDownloaderV3 struct {
 | 
				
			||||||
	base.NullDownloader
 | 
						base.NullDownloader
 | 
				
			||||||
	ctx          context.Context
 | 
						ctx           context.Context
 | 
				
			||||||
	clients      []*github.Client
 | 
						clients       []*github.Client
 | 
				
			||||||
	repoOwner    string
 | 
						repoOwner     string
 | 
				
			||||||
	repoName     string
 | 
						repoName      string
 | 
				
			||||||
	userName     string
 | 
						userName      string
 | 
				
			||||||
	password     string
 | 
						password      string
 | 
				
			||||||
	rates        []*github.Rate
 | 
						rates         []*github.Rate
 | 
				
			||||||
	curClientIdx int
 | 
						curClientIdx  int
 | 
				
			||||||
	maxPerPage   int
 | 
						maxPerPage    int
 | 
				
			||||||
 | 
						SkipReactions bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewGithubDownloaderV3 creates a github Downloader via github v3 API
 | 
					// NewGithubDownloaderV3 creates a github Downloader via github v3 API
 | 
				
			||||||
@@ -428,25 +429,27 @@ func (g *GithubDownloaderV3) GetIssues(page, perPage int) ([]*base.Issue, bool,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		// get reactions
 | 
							// get reactions
 | 
				
			||||||
		var reactions []*base.Reaction
 | 
							var reactions []*base.Reaction
 | 
				
			||||||
		for i := 1; ; i++ {
 | 
							if !g.SkipReactions {
 | 
				
			||||||
			g.waitAndPickClient()
 | 
								for i := 1; ; i++ {
 | 
				
			||||||
			res, resp, err := g.getClient().Reactions.ListIssueReactions(g.ctx, g.repoOwner, g.repoName, issue.GetNumber(), &github.ListOptions{
 | 
									g.waitAndPickClient()
 | 
				
			||||||
				Page:    i,
 | 
									res, resp, err := g.getClient().Reactions.ListIssueReactions(g.ctx, g.repoOwner, g.repoName, issue.GetNumber(), &github.ListOptions{
 | 
				
			||||||
				PerPage: perPage,
 | 
										Page:    i,
 | 
				
			||||||
			})
 | 
										PerPage: perPage,
 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return nil, false, err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			g.setRate(&resp.Rate)
 | 
					 | 
				
			||||||
			if len(res) == 0 {
 | 
					 | 
				
			||||||
				break
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			for _, reaction := range res {
 | 
					 | 
				
			||||||
				reactions = append(reactions, &base.Reaction{
 | 
					 | 
				
			||||||
					UserID:   reaction.User.GetID(),
 | 
					 | 
				
			||||||
					UserName: reaction.User.GetLogin(),
 | 
					 | 
				
			||||||
					Content:  reaction.GetContent(),
 | 
					 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return nil, false, err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									g.setRate(&resp.Rate)
 | 
				
			||||||
 | 
									if len(res) == 0 {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									for _, reaction := range res {
 | 
				
			||||||
 | 
										reactions = append(reactions, &base.Reaction{
 | 
				
			||||||
 | 
											UserID:   reaction.User.GetID(),
 | 
				
			||||||
 | 
											UserName: reaction.User.GetLogin(),
 | 
				
			||||||
 | 
											Content:  reaction.GetContent(),
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -516,25 +519,27 @@ func (g *GithubDownloaderV3) getComments(issueContext base.IssueContext) ([]*bas
 | 
				
			|||||||
		for _, comment := range comments {
 | 
							for _, comment := range comments {
 | 
				
			||||||
			// get reactions
 | 
								// get reactions
 | 
				
			||||||
			var reactions []*base.Reaction
 | 
								var reactions []*base.Reaction
 | 
				
			||||||
			for i := 1; ; i++ {
 | 
								if !g.SkipReactions {
 | 
				
			||||||
				g.waitAndPickClient()
 | 
									for i := 1; ; i++ {
 | 
				
			||||||
				res, resp, err := g.getClient().Reactions.ListIssueCommentReactions(g.ctx, g.repoOwner, g.repoName, comment.GetID(), &github.ListOptions{
 | 
										g.waitAndPickClient()
 | 
				
			||||||
					Page:    i,
 | 
										res, resp, err := g.getClient().Reactions.ListIssueCommentReactions(g.ctx, g.repoOwner, g.repoName, comment.GetID(), &github.ListOptions{
 | 
				
			||||||
					PerPage: g.maxPerPage,
 | 
											Page:    i,
 | 
				
			||||||
				})
 | 
											PerPage: g.maxPerPage,
 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					return nil, err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				g.setRate(&resp.Rate)
 | 
					 | 
				
			||||||
				if len(res) == 0 {
 | 
					 | 
				
			||||||
					break
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				for _, reaction := range res {
 | 
					 | 
				
			||||||
					reactions = append(reactions, &base.Reaction{
 | 
					 | 
				
			||||||
						UserID:   reaction.User.GetID(),
 | 
					 | 
				
			||||||
						UserName: reaction.User.GetLogin(),
 | 
					 | 
				
			||||||
						Content:  reaction.GetContent(),
 | 
					 | 
				
			||||||
					})
 | 
										})
 | 
				
			||||||
 | 
										if err != nil {
 | 
				
			||||||
 | 
											return nil, err
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										g.setRate(&resp.Rate)
 | 
				
			||||||
 | 
										if len(res) == 0 {
 | 
				
			||||||
 | 
											break
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										for _, reaction := range res {
 | 
				
			||||||
 | 
											reactions = append(reactions, &base.Reaction{
 | 
				
			||||||
 | 
												UserID:   reaction.User.GetID(),
 | 
				
			||||||
 | 
												UserName: reaction.User.GetLogin(),
 | 
				
			||||||
 | 
												Content:  reaction.GetContent(),
 | 
				
			||||||
 | 
											})
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -588,25 +593,27 @@ func (g *GithubDownloaderV3) GetAllComments(page, perPage int) ([]*base.Comment,
 | 
				
			|||||||
	for _, comment := range comments {
 | 
						for _, comment := range comments {
 | 
				
			||||||
		// get reactions
 | 
							// get reactions
 | 
				
			||||||
		var reactions []*base.Reaction
 | 
							var reactions []*base.Reaction
 | 
				
			||||||
		for i := 1; ; i++ {
 | 
							if !g.SkipReactions {
 | 
				
			||||||
			g.waitAndPickClient()
 | 
								for i := 1; ; i++ {
 | 
				
			||||||
			res, resp, err := g.getClient().Reactions.ListIssueCommentReactions(g.ctx, g.repoOwner, g.repoName, comment.GetID(), &github.ListOptions{
 | 
									g.waitAndPickClient()
 | 
				
			||||||
				Page:    i,
 | 
									res, resp, err := g.getClient().Reactions.ListIssueCommentReactions(g.ctx, g.repoOwner, g.repoName, comment.GetID(), &github.ListOptions{
 | 
				
			||||||
				PerPage: g.maxPerPage,
 | 
										Page:    i,
 | 
				
			||||||
			})
 | 
										PerPage: g.maxPerPage,
 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return nil, false, err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			g.setRate(&resp.Rate)
 | 
					 | 
				
			||||||
			if len(res) == 0 {
 | 
					 | 
				
			||||||
				break
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			for _, reaction := range res {
 | 
					 | 
				
			||||||
				reactions = append(reactions, &base.Reaction{
 | 
					 | 
				
			||||||
					UserID:   reaction.User.GetID(),
 | 
					 | 
				
			||||||
					UserName: reaction.User.GetLogin(),
 | 
					 | 
				
			||||||
					Content:  reaction.GetContent(),
 | 
					 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return nil, false, err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									g.setRate(&resp.Rate)
 | 
				
			||||||
 | 
									if len(res) == 0 {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									for _, reaction := range res {
 | 
				
			||||||
 | 
										reactions = append(reactions, &base.Reaction{
 | 
				
			||||||
 | 
											UserID:   reaction.User.GetID(),
 | 
				
			||||||
 | 
											UserName: reaction.User.GetLogin(),
 | 
				
			||||||
 | 
											Content:  reaction.GetContent(),
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		idx := strings.LastIndex(*comment.IssueURL, "/")
 | 
							idx := strings.LastIndex(*comment.IssueURL, "/")
 | 
				
			||||||
@@ -656,25 +663,27 @@ func (g *GithubDownloaderV3) GetPullRequests(page, perPage int) ([]*base.PullReq
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		// get reactions
 | 
							// get reactions
 | 
				
			||||||
		var reactions []*base.Reaction
 | 
							var reactions []*base.Reaction
 | 
				
			||||||
		for i := 1; ; i++ {
 | 
							if !g.SkipReactions {
 | 
				
			||||||
			g.waitAndPickClient()
 | 
								for i := 1; ; i++ {
 | 
				
			||||||
			res, resp, err := g.getClient().Reactions.ListIssueReactions(g.ctx, g.repoOwner, g.repoName, pr.GetNumber(), &github.ListOptions{
 | 
									g.waitAndPickClient()
 | 
				
			||||||
				Page:    i,
 | 
									res, resp, err := g.getClient().Reactions.ListIssueReactions(g.ctx, g.repoOwner, g.repoName, pr.GetNumber(), &github.ListOptions{
 | 
				
			||||||
				PerPage: perPage,
 | 
										Page:    i,
 | 
				
			||||||
			})
 | 
										PerPage: perPage,
 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return nil, false, err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			g.setRate(&resp.Rate)
 | 
					 | 
				
			||||||
			if len(res) == 0 {
 | 
					 | 
				
			||||||
				break
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			for _, reaction := range res {
 | 
					 | 
				
			||||||
				reactions = append(reactions, &base.Reaction{
 | 
					 | 
				
			||||||
					UserID:   reaction.User.GetID(),
 | 
					 | 
				
			||||||
					UserName: reaction.User.GetLogin(),
 | 
					 | 
				
			||||||
					Content:  reaction.GetContent(),
 | 
					 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return nil, false, err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									g.setRate(&resp.Rate)
 | 
				
			||||||
 | 
									if len(res) == 0 {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									for _, reaction := range res {
 | 
				
			||||||
 | 
										reactions = append(reactions, &base.Reaction{
 | 
				
			||||||
 | 
											UserID:   reaction.User.GetID(),
 | 
				
			||||||
 | 
											UserName: reaction.User.GetLogin(),
 | 
				
			||||||
 | 
											Content:  reaction.GetContent(),
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -737,25 +746,27 @@ func (g *GithubDownloaderV3) convertGithubReviewComments(cs []*github.PullReques
 | 
				
			|||||||
	for _, c := range cs {
 | 
						for _, c := range cs {
 | 
				
			||||||
		// get reactions
 | 
							// get reactions
 | 
				
			||||||
		var reactions []*base.Reaction
 | 
							var reactions []*base.Reaction
 | 
				
			||||||
		for i := 1; ; i++ {
 | 
							if !g.SkipReactions {
 | 
				
			||||||
			g.waitAndPickClient()
 | 
								for i := 1; ; i++ {
 | 
				
			||||||
			res, resp, err := g.getClient().Reactions.ListPullRequestCommentReactions(g.ctx, g.repoOwner, g.repoName, c.GetID(), &github.ListOptions{
 | 
									g.waitAndPickClient()
 | 
				
			||||||
				Page:    i,
 | 
									res, resp, err := g.getClient().Reactions.ListPullRequestCommentReactions(g.ctx, g.repoOwner, g.repoName, c.GetID(), &github.ListOptions{
 | 
				
			||||||
				PerPage: g.maxPerPage,
 | 
										Page:    i,
 | 
				
			||||||
			})
 | 
										PerPage: g.maxPerPage,
 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return nil, err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			g.setRate(&resp.Rate)
 | 
					 | 
				
			||||||
			if len(res) == 0 {
 | 
					 | 
				
			||||||
				break
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			for _, reaction := range res {
 | 
					 | 
				
			||||||
				reactions = append(reactions, &base.Reaction{
 | 
					 | 
				
			||||||
					UserID:   reaction.User.GetID(),
 | 
					 | 
				
			||||||
					UserName: reaction.User.GetLogin(),
 | 
					 | 
				
			||||||
					Content:  reaction.GetContent(),
 | 
					 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return nil, err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									g.setRate(&resp.Rate)
 | 
				
			||||||
 | 
									if len(res) == 0 {
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									for _, reaction := range res {
 | 
				
			||||||
 | 
										reactions = append(reactions, &base.Reaction{
 | 
				
			||||||
 | 
											UserID:   reaction.User.GetID(),
 | 
				
			||||||
 | 
											UserName: reaction.User.GetLogin(),
 | 
				
			||||||
 | 
											Content:  reaction.GetContent(),
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -242,13 +242,14 @@ type GitServiceType int
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// enumerate all GitServiceType
 | 
					// enumerate all GitServiceType
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	NotMigrated     GitServiceType = iota // 0 not migrated from external sites
 | 
						NotMigrated      GitServiceType = iota // 0 not migrated from external sites
 | 
				
			||||||
	PlainGitService                       // 1 plain git service
 | 
						PlainGitService                        // 1 plain git service
 | 
				
			||||||
	GithubService                         // 2 github.com
 | 
						GithubService                          // 2 github.com
 | 
				
			||||||
	GiteaService                          // 3 gitea service
 | 
						GiteaService                           // 3 gitea service
 | 
				
			||||||
	GitlabService                         // 4 gitlab service
 | 
						GitlabService                          // 4 gitlab service
 | 
				
			||||||
	GogsService                           // 5 gogs service
 | 
						GogsService                            // 5 gogs service
 | 
				
			||||||
	OneDevService                         // 6 onedev service
 | 
						OneDevService                          // 6 onedev service
 | 
				
			||||||
 | 
						GitBucketService                       // 7 gitbucket service
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Name represents the service type's name
 | 
					// Name represents the service type's name
 | 
				
			||||||
@@ -270,6 +271,8 @@ func (gt GitServiceType) Title() string {
 | 
				
			|||||||
		return "Gogs"
 | 
							return "Gogs"
 | 
				
			||||||
	case OneDevService:
 | 
						case OneDevService:
 | 
				
			||||||
		return "OneDev"
 | 
							return "OneDev"
 | 
				
			||||||
 | 
						case GitBucketService:
 | 
				
			||||||
 | 
							return "GitBucket"
 | 
				
			||||||
	case PlainGitService:
 | 
						case PlainGitService:
 | 
				
			||||||
		return "Git"
 | 
							return "Git"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -326,5 +329,6 @@ var (
 | 
				
			|||||||
		GiteaService,
 | 
							GiteaService,
 | 
				
			||||||
		GogsService,
 | 
							GogsService,
 | 
				
			||||||
		OneDevService,
 | 
							OneDevService,
 | 
				
			||||||
 | 
							GitBucketService,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -911,6 +911,7 @@ migrate.gitlab.description = Migrate data from gitlab.com or other GitLab instan
 | 
				
			|||||||
migrate.gitea.description = Migrate data from gitea.com or other Gitea instances.
 | 
					migrate.gitea.description = Migrate data from gitea.com or other Gitea instances.
 | 
				
			||||||
migrate.gogs.description = Migrate data from notabug.org or other Gogs instances.
 | 
					migrate.gogs.description = Migrate data from notabug.org or other Gogs instances.
 | 
				
			||||||
migrate.onedev.description = Migrate data from code.onedev.io or other OneDev instances.
 | 
					migrate.onedev.description = Migrate data from code.onedev.io or other OneDev instances.
 | 
				
			||||||
 | 
					migrate.gitbucket.description = Migrating data from GitBucket instances.
 | 
				
			||||||
migrate.migrating_git = Migrating Git Data
 | 
					migrate.migrating_git = Migrating Git Data
 | 
				
			||||||
migrate.migrating_topics = Migrating Topics
 | 
					migrate.migrating_topics = Migrating Topics
 | 
				
			||||||
migrate.migrating_milestones = Migrating Milestones
 | 
					migrate.migrating_milestones = Migrating Milestones
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								public/img/svg/gitea-gitbucket.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								public/img/svg/gitea-gitbucket.svg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg version="1.0" viewBox="0 0 316 329" class="svg gitea-gitbucket" width="16" height="16" aria-hidden="true"><g fill="#303030"><path d="M123 21.1c-44.8 2.8-84 12.8-97.1 24.6-5 4.5-5 7.1 0 11.6C41.7 71.5 96.6 82.9 150 83h10.6l5.4-5.6c11.8-12.1 21.3-12.4 32.6-1.2l5.2 5 13.3-1.7c33.8-4.2 61.5-12.7 71.8-22 5.3-4.8 5.3-7.2 0-12-10.1-9.1-39.1-18.1-70.4-21.9-28.3-3.4-65.6-4.4-95.5-2.5zM23.2 80.6c.4 1.6 7 42.9 14.8 91.9 7.9 49 14.7 89.5 15.2 90.2 1.7 2.1 25.8 11.4 41.6 15.9 13 3.7 35.1 8.4 40 8.4.6 0 1.2-.6 1.2-1.3 0-.6-17.4-18.5-38.6-39.7C57.9 206.6 55 203.2 55 196c0-7.2 3-10.7 38.3-45.9 30.1-30 34.8-34.3 36.6-33.5 1.1.5 8.7 7.4 17 15.2l15.1 14.4v5.9c0 7.3 2.4 12.4 7.7 16.7l3.8 3v61.8l-3.8 3.4c-10.2 8.9-10.2 22.9-.1 30.7 3.1 2.3 4.9 2.8 10.8 3.1 8.2.4 11.5-1.1 16.2-7.3 2.2-3 2.9-5.1 3.2-10 .4-6.5-.2-8.3-5.3-15.4l-2.5-3.4v-26.6c0-26.7.3-31.1 2.3-31.1.5 0 5.4 4.4 10.9 9.7 9.6 9.5 9.9 10 10.8 15.7 1.7 10.3 8.9 16.6 19 16.6 7.6 0 13.5-3.9 17.4-11.7 3.2-6.4 1.6-14.3-4.3-20.6-4.1-4.4-7.3-5.7-14.9-5.7h-6.8l-12.7-12.1c-10.7-10.1-12.7-12.6-13.2-15.7-1.2-7.2-1.6-8.2-4.7-11.7-3.9-4.5-7.7-6.5-12.2-6.5-1.9 0-4.5-.4-5.8-.9-1.3-.5-9.9-8.2-19.3-17l-17-16-7.1-.1c-10.6 0-36-2.7-52.4-5.5-22.8-4-38.5-8.6-57.9-17.2-1.1-.5-1.3 0-.9 2.3zM278.5 83.6c-8.6 3.6-28 8.8-42.5 11.4-6.9 1.2-12.9 2.6-13.5 3.1-.6.6 9.3 11.2 27.5 29.4 15.6 15.6 28.5 28.3 28.7 28.1.2-.2 1.9-15.8 3.8-34.7 1.9-18.9 3.7-35.6 4-37.2.6-3.4-.2-3.4-8-.1zM255.2 259.3c-7.8 7.8-14.2 14.6-14.2 15 0 .4.7.7 1.6.7 2.2 0 23-8.9 24.2-10.3.9-1.1 3.5-18.7 2.9-19.3-.2-.2-6.7 6.1-14.5 13.9zM56 283.5c0 3.4 4 9.5 8.4 12.9 6.1 4.6 19.7 10.4 31.7 13.5 16.9 4.3 32.1 6.2 53.4 6.8l19 .5-7-7.1c-6.8-6.9-7.1-7.1-12-7.1-18.9 0-55.1-7.9-80.6-17.6C62.5 283 57 281 56.6 281c-.3 0-.6 1.1-.6 2.5zM262 283.4c-5.3 2.8-25 9.7-36 12.6l-11.4 2.9-7.8 7.8c-4.2 4.2-7.6 7.9-7.4 8.1.9.8 24.4-4.1 33.4-6.9 16.4-5.3 26.7-11.4 30.8-18.5 2.4-4 3.1-7.4 1.7-7.4-.5.1-1.9.7-3.3 1.4z"/></g></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1.9 KiB  | 
							
								
								
									
										129
									
								
								templates/repo/migrate/gitbucket.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								templates/repo/migrate/gitbucket.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,129 @@
 | 
				
			|||||||
 | 
					{{template "base/head" .}}
 | 
				
			||||||
 | 
					<div class="page-content repository new migrate">
 | 
				
			||||||
 | 
						<div class="ui middle very relaxed page grid">
 | 
				
			||||||
 | 
							<div class="column">
 | 
				
			||||||
 | 
								<form class="ui form" action="{{.Link}}" method="post">
 | 
				
			||||||
 | 
									{{.CsrfTokenHtml}}
 | 
				
			||||||
 | 
									<h3 class="ui top attached header">
 | 
				
			||||||
 | 
										{{.i18n.Tr "repo.migrate.migrate" .service.Title}}
 | 
				
			||||||
 | 
										<input id="service_type" type="hidden" name="service" value="{{.service}}">
 | 
				
			||||||
 | 
									</h3>
 | 
				
			||||||
 | 
									<div class="ui attached segment">
 | 
				
			||||||
 | 
										{{template "base/alert" .}}
 | 
				
			||||||
 | 
										<div class="inline required field {{if .Err_CloneAddr}}error{{end}}">
 | 
				
			||||||
 | 
											<label for="clone_addr">{{.i18n.Tr "repo.migrate.clone_address"}}</label>
 | 
				
			||||||
 | 
											<input id="clone_addr" name="clone_addr" value="{{.clone_addr}}" autofocus required>
 | 
				
			||||||
 | 
											<span class="help">
 | 
				
			||||||
 | 
											{{.i18n.Tr "repo.migrate.clone_address_desc"}}{{if .ContextUser.CanImportLocal}} {{.i18n.Tr "repo.migrate.clone_local_path"}}{{end}}
 | 
				
			||||||
 | 
											</span>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<div class="inline field {{if .Err_Auth}}error{{end}}">
 | 
				
			||||||
 | 
											<label for="auth_username">{{.i18n.Tr "username"}}</label>
 | 
				
			||||||
 | 
											<input id="auth_username" name="auth_username" value="{{.auth_username}}" {{if not .auth_username}}data-need-clear="true"{{end}}>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
										<input class="fake" type="password">
 | 
				
			||||||
 | 
										<div class="inline field {{if .Err_Auth}}error{{end}}">
 | 
				
			||||||
 | 
											<label for="auth_password">{{.i18n.Tr "password"}}</label>
 | 
				
			||||||
 | 
											<input id="auth_password" name="auth_password" type="password" value="{{.auth_password}}">
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										{{template "repo/migrate/options" .}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<span class="help">{{.i18n.Tr "repo.migrate.migrate_items_options"}}</span>
 | 
				
			||||||
 | 
										<div id="migrate_items">
 | 
				
			||||||
 | 
											<div class="inline field">
 | 
				
			||||||
 | 
												<label>{{.i18n.Tr "repo.migrate_items"}}</label>
 | 
				
			||||||
 | 
												<div class="ui checkbox">
 | 
				
			||||||
 | 
													<input name="wiki" type="checkbox" {{if .wiki}}checked{{end}}>
 | 
				
			||||||
 | 
													<label>{{.i18n.Tr "repo.migrate_items_wiki" | Safe}}</label>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div class="ui checkbox">
 | 
				
			||||||
 | 
													<input name="milestones" type="checkbox" {{if .milestones}}checked{{end}}>
 | 
				
			||||||
 | 
													<label>{{.i18n.Tr "repo.migrate_items_milestones" | Safe}}</label>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<div class="inline field">
 | 
				
			||||||
 | 
												<label></label>
 | 
				
			||||||
 | 
												<div class="ui checkbox">
 | 
				
			||||||
 | 
													<input name="labels" type="checkbox" {{if .labels}}checked{{end}}>
 | 
				
			||||||
 | 
													<label>{{.i18n.Tr "repo.migrate_items_labels" | Safe}}</label>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div class="ui checkbox">
 | 
				
			||||||
 | 
													<input name="issues" type="checkbox" {{if .issues}}checked{{end}}>
 | 
				
			||||||
 | 
													<label>{{.i18n.Tr "repo.migrate_items_issues" | Safe}}</label>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<div class="inline field">
 | 
				
			||||||
 | 
												<label></label>
 | 
				
			||||||
 | 
												<div class="ui checkbox">
 | 
				
			||||||
 | 
													<input name="pull_requests" type="checkbox" {{if .pull_requests}}checked{{end}}>
 | 
				
			||||||
 | 
													<label>{{.i18n.Tr "repo.migrate_items_pullrequests" | Safe}}</label>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div class="ui checkbox">
 | 
				
			||||||
 | 
													<input name="releases" type="checkbox" {{if .releases}}checked{{end}}>
 | 
				
			||||||
 | 
													<label>{{.i18n.Tr "repo.migrate_items_releases" | Safe}}</label>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<div class="ui divider"></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<div class="inline required field {{if .Err_Owner}}error{{end}}">
 | 
				
			||||||
 | 
											<label>{{.i18n.Tr "repo.owner"}}</label>
 | 
				
			||||||
 | 
											<div class="ui selection owner dropdown">
 | 
				
			||||||
 | 
												<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required>
 | 
				
			||||||
 | 
												<span class="text truncated-item-container" title="{{.ContextUser.Name}}">
 | 
				
			||||||
 | 
													{{avatar .ContextUser 28 "mini"}}
 | 
				
			||||||
 | 
													<span class="truncated-item-name">{{.ContextUser.ShortName 40}}</span>
 | 
				
			||||||
 | 
												</span>
 | 
				
			||||||
 | 
												{{svg "octicon-triangle-down" 14 "dropdown icon"}}
 | 
				
			||||||
 | 
												<div class="menu" title="{{.SignedUser.Name}}">
 | 
				
			||||||
 | 
													<div class="item truncated-item-container" data-value="{{.SignedUser.ID}}">
 | 
				
			||||||
 | 
														{{avatar .SignedUser 28 "mini"}}
 | 
				
			||||||
 | 
														<span class="truncated-item-name">{{.SignedUser.ShortName 40}}</span>
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
													{{range .Orgs}}
 | 
				
			||||||
 | 
														<div class="item truncated-item-container" data-value="{{.ID}}" title="{{.Name}}">
 | 
				
			||||||
 | 
															{{avatar . 28 "mini"}}
 | 
				
			||||||
 | 
															<span class="truncated-item-name">{{.ShortName 40}}</span>
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
													{{end}}
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<div class="inline required field {{if .Err_RepoName}}error{{end}}">
 | 
				
			||||||
 | 
											<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label>
 | 
				
			||||||
 | 
											<input id="repo_name" name="repo_name" value="{{.repo_name}}" required>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
										<div class="inline field">
 | 
				
			||||||
 | 
											<label>{{.i18n.Tr "repo.visibility"}}</label>
 | 
				
			||||||
 | 
											<div class="ui checkbox">
 | 
				
			||||||
 | 
												{{if .IsForcedPrivate}}
 | 
				
			||||||
 | 
													<input name="private" type="checkbox" checked readonly>
 | 
				
			||||||
 | 
													<label>{{.i18n.Tr "repo.visibility_helper_forced" | Safe}}</label>
 | 
				
			||||||
 | 
												{{else}}
 | 
				
			||||||
 | 
													<input name="private" type="checkbox" {{if .private}}checked{{end}}>
 | 
				
			||||||
 | 
													<label>{{.i18n.Tr "repo.visibility_helper" | Safe}}</label>
 | 
				
			||||||
 | 
												{{end}}
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
										<div class="inline field {{if .Err_Description}}error{{end}}">
 | 
				
			||||||
 | 
											<label for="description">{{.i18n.Tr "repo.repo_desc"}}</label>
 | 
				
			||||||
 | 
											<textarea id="description" name="description">{{.description}}</textarea>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<div class="inline field">
 | 
				
			||||||
 | 
											<label></label>
 | 
				
			||||||
 | 
											<button class="ui green button">
 | 
				
			||||||
 | 
												{{.i18n.Tr "repo.migrate_repo"}}
 | 
				
			||||||
 | 
											</button>
 | 
				
			||||||
 | 
											<a class="ui button" href="{{AppSubUrl}}/">{{.i18n.Tr "cancel"}}</a>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</form>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{{template "base/footer" .}}
 | 
				
			||||||
							
								
								
									
										39
									
								
								web_src/svg/gitea-gitbucket.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								web_src/svg/gitea-gitbucket.svg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" standalone="no"?>
 | 
				
			||||||
 | 
					<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
 | 
				
			||||||
 | 
					 "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
 | 
				
			||||||
 | 
					<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					 width="316.000000pt" height="329.000000pt" viewBox="0 0 316.000000 329.000000"
 | 
				
			||||||
 | 
					 preserveAspectRatio="xMidYMid meet">
 | 
				
			||||||
 | 
					<metadata>
 | 
				
			||||||
 | 
					Created by potrace 1.14, written by Peter Selinger 2001-2017
 | 
				
			||||||
 | 
					</metadata>
 | 
				
			||||||
 | 
					<g transform="translate(0.000000,329.000000) scale(0.100000,-0.100000)"
 | 
				
			||||||
 | 
					fill="#303030" stroke="none">
 | 
				
			||||||
 | 
					<path d="M1230 3079 c-448 -28 -840 -128 -971 -246 -50 -45 -50 -71 0 -116
 | 
				
			||||||
 | 
					158 -142 707 -256 1241 -257 l106 0 54 56 c118 121 213 124 326 12 l52 -50
 | 
				
			||||||
 | 
					133 17 c338 42 615 127 718 220 53 48 53 72 0 120 -101 91 -391 181 -704 219
 | 
				
			||||||
 | 
					-283 34 -656 44 -955 25z"/>
 | 
				
			||||||
 | 
					<path d="M232 2484 c4 -16 70 -429 148 -919 79 -490 147 -895 152 -902 17 -21
 | 
				
			||||||
 | 
					258 -114 416 -159 130 -37 351 -84 400 -84 6 0 12 6 12 13 0 6 -174 185 -386
 | 
				
			||||||
 | 
					397 -395 394 -424 428 -424 500 0 72 30 107 383 459 301 300 348 343 366 335
 | 
				
			||||||
 | 
					11 -5 87 -74 170 -152 l151 -144 0 -59 c0 -73 24 -124 77 -167 l38 -30 0 -309
 | 
				
			||||||
 | 
					0 -309 -38 -34 c-102 -89 -102 -229 -1 -307 31 -23 49 -28 108 -31 82 -4 115
 | 
				
			||||||
 | 
					11 162 73 22 30 29 51 32 100 4 65 -2 83 -53 154 l-25 34 0 266 c0 267 3 311
 | 
				
			||||||
 | 
					23 311 5 0 54 -44 109 -97 96 -95 99 -100 108 -157 17 -103 89 -166 190 -166
 | 
				
			||||||
 | 
					76 0 135 39 174 117 32 64 16 143 -43 206 -41 44 -73 57 -149 57 l-68 0 -127
 | 
				
			||||||
 | 
					121 c-107 101 -127 126 -132 157 -12 72 -16 82 -47 117 -39 45 -77 65 -122 65
 | 
				
			||||||
 | 
					-19 0 -45 4 -58 9 -13 5 -99 82 -193 170 l-170 160 -71 1 c-106 0 -360 27
 | 
				
			||||||
 | 
					-524 55 -228 40 -385 86 -579 172 -11 5 -13 0 -9 -23z"/>
 | 
				
			||||||
 | 
					<path d="M2785 2454 c-86 -36 -280 -88 -425 -114 -69 -12 -129 -26 -135 -31
 | 
				
			||||||
 | 
					-6 -6 93 -112 275 -294 156 -156 285 -283 287 -281 2 2 19 158 38 347 19 189
 | 
				
			||||||
 | 
					37 356 40 372 6 34 -2 34 -80 1z"/>
 | 
				
			||||||
 | 
					<path d="M2552 697 c-78 -78 -142 -146 -142 -150 0 -4 7 -7 16 -7 22 0 230 89
 | 
				
			||||||
 | 
					242 103 9 11 35 187 29 193 -2 2 -67 -61 -145 -139z"/>
 | 
				
			||||||
 | 
					<path d="M560 455 c0 -34 40 -95 84 -129 61 -46 197 -104 317 -135 169 -43
 | 
				
			||||||
 | 
					321 -62 534 -68 l190 -5 -70 71 c-68 69 -71 71 -120 71 -189 0 -551 79 -806
 | 
				
			||||||
 | 
					176 -64 24 -119 44 -123 44 -3 0 -6 -11 -6 -25z"/>
 | 
				
			||||||
 | 
					<path d="M2620 456 c-53 -28 -250 -97 -360 -126 l-114 -29 -78 -78 c-42 -42
 | 
				
			||||||
 | 
					-76 -79 -74 -81 9 -8 244 41 334 69 164 53 267 114 308 185 24 40 31 74 17 74
 | 
				
			||||||
 | 
					-5 -1 -19 -7 -33 -14z"/>
 | 
				
			||||||
 | 
					</g>
 | 
				
			||||||
 | 
					</svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 2.2 KiB  | 
		Reference in New Issue
	
	Block a user