Add a migrate service type switch page (#12697)
* Add a migrat service type switch page * Improve translations * remove images * Fix images * remove extra create repo button on dashboard * Follow reviewers' opinions * Fix frontend lint * Remove wrong submit file * Fix tests * Adjust the size of image * Apply suggestions from code review Co-authored-by: 赵智超 <1012112796@qq.com> * Remove username and password from migration of github/gitlab * Improve docs * Improve interface docs Co-authored-by: 赵智超 <1012112796@qq.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
parent
6483dbc8ec
commit
e153cf07c3
21 changed files with 481 additions and 209 deletions
173
routers/repo/migrate.go
Normal file
173
routers/repo/migrate.go
Normal file
|
@ -0,0 +1,173 @@
|
|||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2020 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 repo
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/auth"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/migrations"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/task"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
const (
|
||||
tplMigrate base.TplName = "repo/migrate/migrate"
|
||||
)
|
||||
|
||||
// Migrate render migration of repository page
|
||||
func Migrate(ctx *context.Context) {
|
||||
ctx.Data["Services"] = append([]structs.GitServiceType{structs.PlainGitService}, structs.SupportedFullGitService...)
|
||||
serviceType := ctx.QueryInt("service_type")
|
||||
if serviceType == 0 {
|
||||
ctx.HTML(200, tplMigrate)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Title"] = ctx.Tr("new_migrate")
|
||||
ctx.Data["private"] = getRepoPrivate(ctx)
|
||||
ctx.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate
|
||||
ctx.Data["DisableMirrors"] = setting.Repository.DisableMirrors
|
||||
ctx.Data["mirror"] = ctx.Query("mirror") == "1"
|
||||
ctx.Data["wiki"] = ctx.Query("wiki") == "1"
|
||||
ctx.Data["milestones"] = ctx.Query("milestones") == "1"
|
||||
ctx.Data["labels"] = ctx.Query("labels") == "1"
|
||||
ctx.Data["issues"] = ctx.Query("issues") == "1"
|
||||
ctx.Data["pull_requests"] = ctx.Query("pull_requests") == "1"
|
||||
ctx.Data["releases"] = ctx.Query("releases") == "1"
|
||||
ctx.Data["LFSActive"] = setting.LFS.StartServer
|
||||
// Plain git should be first
|
||||
ctx.Data["service"] = structs.GitServiceType(serviceType)
|
||||
|
||||
ctxUser := checkContextUser(ctx, ctx.QueryInt64("org"))
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
ctx.Data["ContextUser"] = ctxUser
|
||||
|
||||
ctx.HTML(200, base.TplName("repo/migrate/"+structs.GitServiceType(serviceType).Name()))
|
||||
}
|
||||
|
||||
func handleMigrateError(ctx *context.Context, owner *models.User, err error, name string, tpl base.TplName, form *auth.MigrateRepoForm) {
|
||||
switch {
|
||||
case migrations.IsRateLimitError(err):
|
||||
ctx.RenderWithErr(ctx.Tr("form.visit_rate_limit"), tpl, form)
|
||||
case migrations.IsTwoFactorAuthError(err):
|
||||
ctx.RenderWithErr(ctx.Tr("form.2fa_auth_required"), tpl, form)
|
||||
case models.IsErrReachLimitOfRepo(err):
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.reach_limit_of_creation", owner.MaxCreationLimit()), tpl, form)
|
||||
case models.IsErrRepoAlreadyExist(err):
|
||||
ctx.Data["Err_RepoName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), tpl, form)
|
||||
case models.IsErrNameReserved(err):
|
||||
ctx.Data["Err_RepoName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), tpl, form)
|
||||
case models.IsErrNamePatternNotAllowed(err):
|
||||
ctx.Data["Err_RepoName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tpl, form)
|
||||
default:
|
||||
remoteAddr, _ := form.ParseRemoteAddr(owner)
|
||||
err = util.URLSanitizedError(err, remoteAddr)
|
||||
if strings.Contains(err.Error(), "Authentication failed") ||
|
||||
strings.Contains(err.Error(), "Bad credentials") ||
|
||||
strings.Contains(err.Error(), "could not read Username") {
|
||||
ctx.Data["Err_Auth"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.auth_failed", err.Error()), tpl, form)
|
||||
} else if strings.Contains(err.Error(), "fatal:") {
|
||||
ctx.Data["Err_CloneAddr"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.failed", err.Error()), tpl, form)
|
||||
} else {
|
||||
ctx.ServerError(name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MigratePost response for migrating from external git repository
|
||||
func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) {
|
||||
ctx.Data["Title"] = ctx.Tr("new_migrate")
|
||||
// Plain git should be first
|
||||
ctx.Data["service"] = form.Service
|
||||
ctx.Data["Services"] = append([]structs.GitServiceType{structs.PlainGitService}, structs.SupportedFullGitService...)
|
||||
|
||||
ctxUser := checkContextUser(ctx, form.UID)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
ctx.Data["ContextUser"] = ctxUser
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.HTML(200, tplMigrate)
|
||||
return
|
||||
}
|
||||
|
||||
remoteAddr, err := form.ParseRemoteAddr(ctx.User)
|
||||
if err != nil {
|
||||
if models.IsErrInvalidCloneAddr(err) {
|
||||
ctx.Data["Err_CloneAddr"] = true
|
||||
addrErr := err.(models.ErrInvalidCloneAddr)
|
||||
switch {
|
||||
case addrErr.IsURLError:
|
||||
ctx.RenderWithErr(ctx.Tr("form.url_error"), tplMigrate, &form)
|
||||
case addrErr.IsPermissionDenied:
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied"), tplMigrate, &form)
|
||||
case addrErr.IsInvalidPath:
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_local_path"), tplMigrate, &form)
|
||||
default:
|
||||
ctx.ServerError("Unknown error", err)
|
||||
}
|
||||
} else {
|
||||
ctx.ServerError("ParseRemoteAddr", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var opts = migrations.MigrateOptions{
|
||||
OriginalURL: form.CloneAddr,
|
||||
GitServiceType: structs.GitServiceType(form.Service),
|
||||
CloneAddr: remoteAddr,
|
||||
RepoName: form.RepoName,
|
||||
Description: form.Description,
|
||||
Private: form.Private || setting.Repository.ForcePrivate,
|
||||
Mirror: form.Mirror && !setting.Repository.DisableMirrors,
|
||||
AuthUsername: form.AuthUsername,
|
||||
AuthPassword: form.AuthPassword,
|
||||
AuthToken: form.AuthToken,
|
||||
Wiki: form.Wiki,
|
||||
Issues: form.Issues,
|
||||
Milestones: form.Milestones,
|
||||
Labels: form.Labels,
|
||||
Comments: form.Issues || form.PullRequests,
|
||||
PullRequests: form.PullRequests,
|
||||
Releases: form.Releases,
|
||||
}
|
||||
if opts.Mirror {
|
||||
opts.Issues = false
|
||||
opts.Milestones = false
|
||||
opts.Labels = false
|
||||
opts.Comments = false
|
||||
opts.PullRequests = false
|
||||
opts.Releases = false
|
||||
}
|
||||
|
||||
err = models.CheckCreateRepository(ctx.User, ctxUser, opts.RepoName)
|
||||
if err != nil {
|
||||
handleMigrateError(ctx, ctxUser, err, "MigratePost", tplMigrate, &form)
|
||||
return
|
||||
}
|
||||
|
||||
err = task.MigrateRepository(ctx.User, ctxUser, opts)
|
||||
if err == nil {
|
||||
ctx.Redirect(setting.AppSubURL + "/" + ctxUser.Name + "/" + opts.RepoName)
|
||||
return
|
||||
}
|
||||
|
||||
handleMigrateError(ctx, ctxUser, err, "MigratePost", tplMigrate, &form)
|
||||
}
|
|
@ -17,19 +17,14 @@ import (
|
|||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/migrations"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/task"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
|
||||
"github.com/unknwon/com"
|
||||
)
|
||||
|
||||
const (
|
||||
tplCreate base.TplName = "repo/create"
|
||||
tplMigrate base.TplName = "repo/migrate"
|
||||
tplCreate base.TplName = "repo/create"
|
||||
)
|
||||
|
||||
// MustBeNotEmpty render when a repo is a empty git dir
|
||||
|
@ -254,149 +249,6 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) {
|
|||
handleCreateError(ctx, ctxUser, err, "CreatePost", tplCreate, &form)
|
||||
}
|
||||
|
||||
// Migrate render migration of repository page
|
||||
func Migrate(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("new_migrate")
|
||||
ctx.Data["private"] = getRepoPrivate(ctx)
|
||||
ctx.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate
|
||||
ctx.Data["DisableMirrors"] = setting.Repository.DisableMirrors
|
||||
ctx.Data["mirror"] = ctx.Query("mirror") == "1"
|
||||
ctx.Data["wiki"] = ctx.Query("wiki") == "1"
|
||||
ctx.Data["milestones"] = ctx.Query("milestones") == "1"
|
||||
ctx.Data["labels"] = ctx.Query("labels") == "1"
|
||||
ctx.Data["issues"] = ctx.Query("issues") == "1"
|
||||
ctx.Data["pull_requests"] = ctx.Query("pull_requests") == "1"
|
||||
ctx.Data["releases"] = ctx.Query("releases") == "1"
|
||||
ctx.Data["LFSActive"] = setting.LFS.StartServer
|
||||
// Plain git should be first
|
||||
ctx.Data["service"] = structs.PlainGitService
|
||||
ctx.Data["Services"] = append([]structs.GitServiceType{structs.PlainGitService}, structs.SupportedFullGitService...)
|
||||
|
||||
ctxUser := checkContextUser(ctx, ctx.QueryInt64("org"))
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
ctx.Data["ContextUser"] = ctxUser
|
||||
|
||||
ctx.HTML(200, tplMigrate)
|
||||
}
|
||||
|
||||
func handleMigrateError(ctx *context.Context, owner *models.User, err error, name string, tpl base.TplName, form *auth.MigrateRepoForm) {
|
||||
switch {
|
||||
case migrations.IsRateLimitError(err):
|
||||
ctx.RenderWithErr(ctx.Tr("form.visit_rate_limit"), tpl, form)
|
||||
case migrations.IsTwoFactorAuthError(err):
|
||||
ctx.RenderWithErr(ctx.Tr("form.2fa_auth_required"), tpl, form)
|
||||
case models.IsErrReachLimitOfRepo(err):
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.reach_limit_of_creation", owner.MaxCreationLimit()), tpl, form)
|
||||
case models.IsErrRepoAlreadyExist(err):
|
||||
ctx.Data["Err_RepoName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), tpl, form)
|
||||
case models.IsErrNameReserved(err):
|
||||
ctx.Data["Err_RepoName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), tpl, form)
|
||||
case models.IsErrNamePatternNotAllowed(err):
|
||||
ctx.Data["Err_RepoName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tpl, form)
|
||||
default:
|
||||
remoteAddr, _ := form.ParseRemoteAddr(owner)
|
||||
err = util.URLSanitizedError(err, remoteAddr)
|
||||
if strings.Contains(err.Error(), "Authentication failed") ||
|
||||
strings.Contains(err.Error(), "Bad credentials") ||
|
||||
strings.Contains(err.Error(), "could not read Username") {
|
||||
ctx.Data["Err_Auth"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.auth_failed", err.Error()), tpl, form)
|
||||
} else if strings.Contains(err.Error(), "fatal:") {
|
||||
ctx.Data["Err_CloneAddr"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.failed", err.Error()), tpl, form)
|
||||
} else {
|
||||
ctx.ServerError(name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MigratePost response for migrating from external git repository
|
||||
func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) {
|
||||
ctx.Data["Title"] = ctx.Tr("new_migrate")
|
||||
// Plain git should be first
|
||||
ctx.Data["service"] = structs.PlainGitService
|
||||
ctx.Data["Services"] = append([]structs.GitServiceType{structs.PlainGitService}, structs.SupportedFullGitService...)
|
||||
|
||||
ctxUser := checkContextUser(ctx, form.UID)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
ctx.Data["ContextUser"] = ctxUser
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.HTML(200, tplMigrate)
|
||||
return
|
||||
}
|
||||
|
||||
remoteAddr, err := form.ParseRemoteAddr(ctx.User)
|
||||
if err != nil {
|
||||
if models.IsErrInvalidCloneAddr(err) {
|
||||
ctx.Data["Err_CloneAddr"] = true
|
||||
addrErr := err.(models.ErrInvalidCloneAddr)
|
||||
switch {
|
||||
case addrErr.IsURLError:
|
||||
ctx.RenderWithErr(ctx.Tr("form.url_error"), tplMigrate, &form)
|
||||
case addrErr.IsPermissionDenied:
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied"), tplMigrate, &form)
|
||||
case addrErr.IsInvalidPath:
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_local_path"), tplMigrate, &form)
|
||||
default:
|
||||
ctx.ServerError("Unknown error", err)
|
||||
}
|
||||
} else {
|
||||
ctx.ServerError("ParseRemoteAddr", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var opts = migrations.MigrateOptions{
|
||||
OriginalURL: form.CloneAddr,
|
||||
GitServiceType: structs.GitServiceType(form.Service),
|
||||
CloneAddr: remoteAddr,
|
||||
RepoName: form.RepoName,
|
||||
Description: form.Description,
|
||||
Private: form.Private || setting.Repository.ForcePrivate,
|
||||
Mirror: form.Mirror && !setting.Repository.DisableMirrors,
|
||||
AuthUsername: form.AuthUsername,
|
||||
AuthPassword: form.AuthPassword,
|
||||
AuthToken: form.AuthToken,
|
||||
Wiki: form.Wiki,
|
||||
Issues: form.Issues,
|
||||
Milestones: form.Milestones,
|
||||
Labels: form.Labels,
|
||||
Comments: true,
|
||||
PullRequests: form.PullRequests,
|
||||
Releases: form.Releases,
|
||||
}
|
||||
if opts.Mirror {
|
||||
opts.Issues = false
|
||||
opts.Milestones = false
|
||||
opts.Labels = false
|
||||
opts.Comments = false
|
||||
opts.PullRequests = false
|
||||
opts.Releases = false
|
||||
}
|
||||
|
||||
err = models.CheckCreateRepository(ctx.User, ctxUser, opts.RepoName)
|
||||
if err != nil {
|
||||
handleMigrateError(ctx, ctxUser, err, "MigratePost", tplMigrate, &form)
|
||||
return
|
||||
}
|
||||
|
||||
err = task.MigrateRepository(ctx.User, ctxUser, opts)
|
||||
if err == nil {
|
||||
ctx.Redirect(setting.AppSubURL + "/" + ctxUser.Name + "/" + opts.RepoName)
|
||||
return
|
||||
}
|
||||
|
||||
handleMigrateError(ctx, ctxUser, err, "MigratePost", tplMigrate, &form)
|
||||
}
|
||||
|
||||
// Action response for actions to a repository
|
||||
func Action(ctx *context.Context) {
|
||||
var err error
|
||||
|
|
|
@ -34,7 +34,7 @@ const (
|
|||
tplRepoHome base.TplName = "repo/home"
|
||||
tplWatchers base.TplName = "repo/watchers"
|
||||
tplForks base.TplName = "repo/forks"
|
||||
tplMigrating base.TplName = "repo/migrating"
|
||||
tplMigrating base.TplName = "repo/migrate/migrating"
|
||||
)
|
||||
|
||||
type namedBlob struct {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue