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.tokarchuk/v1.17
parent
d2163df6a0
commit
42ea0023a3
@ -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"} |
||||||
|
} |
After Width: | Height: | Size: 1.9 KiB |
@ -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" .}} |
After Width: | Height: | Size: 2.2 KiB |
Loading…
Reference in new issue