routers: able to migrate repo from local path
- modules/middleware/context.go: add HandleAPI method
This commit is contained in:
parent
c753fdceaf
commit
059338139c
7 changed files with 74 additions and 53 deletions
|
@ -79,7 +79,7 @@ func checkVersion() {
|
||||||
// Check dependency version.
|
// Check dependency version.
|
||||||
checkers := []VerChecker{
|
checkers := []VerChecker{
|
||||||
{"github.com/Unknwon/macaron", macaron.Version, "0.5.1"},
|
{"github.com/Unknwon/macaron", macaron.Version, "0.5.1"},
|
||||||
{"github.com/macaron-contrib/binding", binding.Version, "0.0.4"},
|
{"github.com/macaron-contrib/binding", binding.Version, "0.0.5"},
|
||||||
{"github.com/macaron-contrib/cache", cache.Version, "0.0.7"},
|
{"github.com/macaron-contrib/cache", cache.Version, "0.0.7"},
|
||||||
{"github.com/macaron-contrib/csrf", csrf.Version, "0.0.3"},
|
{"github.com/macaron-contrib/csrf", csrf.Version, "0.0.3"},
|
||||||
{"github.com/macaron-contrib/i18n", i18n.Version, "0.0.5"},
|
{"github.com/macaron-contrib/i18n", i18n.Version, "0.0.5"},
|
||||||
|
@ -229,7 +229,7 @@ func runWeb(ctx *cli.Context) {
|
||||||
})
|
})
|
||||||
|
|
||||||
m.Any("/*", func(ctx *middleware.Context) {
|
m.Any("/*", func(ctx *middleware.Context) {
|
||||||
ctx.JSON(404, &base.ApiJsonErr{"Not Found", base.DOC_URL})
|
ctx.HandleAPI(404, "Page not found")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -286,6 +286,8 @@ need_auth = Need Authorization
|
||||||
migrate_type = Migration Type
|
migrate_type = Migration Type
|
||||||
migrate_type_helper = This repository will be a <span class="label label-blue label-radius">Mirror</span>
|
migrate_type_helper = This repository will be a <span class="label label-blue label-radius">Mirror</span>
|
||||||
migrate_repo = Migrate Repository
|
migrate_repo = Migrate Repository
|
||||||
|
migrate.clone_address = Clone Address
|
||||||
|
migrate.invalid_local_path = Invalid local path, it does not exist or not a directory.
|
||||||
|
|
||||||
copy_link = Copy
|
copy_link = Copy
|
||||||
click_to_copy = Copy to clipboard
|
click_to_copy = Copy to clipboard
|
||||||
|
|
|
@ -31,7 +31,7 @@ func (f *CreateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) bin
|
||||||
}
|
}
|
||||||
|
|
||||||
type MigrateRepoForm struct {
|
type MigrateRepoForm struct {
|
||||||
HttpsUrl string `form:"url" binding:"Required;Url"`
|
CloneAddr string `binding:"Required"`
|
||||||
AuthUserName string `form:"auth_username"`
|
AuthUserName string `form:"auth_username"`
|
||||||
AuthPasswd string `form:"auth_password"`
|
AuthPasswd string `form:"auth_password"`
|
||||||
Uid int64 `form:"uid" binding:"Required"`
|
Uid int64 `form:"uid" binding:"Required"`
|
||||||
|
|
|
@ -130,6 +130,18 @@ func (ctx *Context) Handle(status int, title string, err error) {
|
||||||
ctx.HTML(status, base.TplName(fmt.Sprintf("status/%d", status)))
|
ctx.HTML(status, base.TplName(fmt.Sprintf("status/%d", status)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ctx *Context) HandleAPI(status int, obj interface{}) {
|
||||||
|
var message string
|
||||||
|
if err, ok := obj.(error); ok {
|
||||||
|
message = err.Error()
|
||||||
|
} else {
|
||||||
|
message = obj.(string)
|
||||||
|
}
|
||||||
|
ctx.JSON(status, map[string]string{
|
||||||
|
"message": message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) {
|
func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) {
|
||||||
modtime := time.Now()
|
modtime := time.Now()
|
||||||
for _, p := range params {
|
for _, p := range params {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -156,17 +156,15 @@ func CreateOrgRepo(ctx *middleware.Context, opt api.CreateRepoOption) {
|
||||||
func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) {
|
func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) {
|
||||||
u, err := models.GetUserByName(ctx.Query("username"))
|
u, err := models.GetUserByName(ctx.Query("username"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.JSON(500, map[string]interface{}{
|
if err == models.ErrUserNotExist {
|
||||||
"ok": false,
|
ctx.HandleAPI(422, err)
|
||||||
"error": err.Error(),
|
} else {
|
||||||
})
|
ctx.HandleAPI(500, err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !u.ValidtePassword(ctx.Query("password")) {
|
if !u.ValidtePassword(ctx.Query("password")) {
|
||||||
ctx.JSON(500, map[string]interface{}{
|
ctx.HandleAPI(422, "Username or password is not correct.")
|
||||||
"ok": false,
|
|
||||||
"error": "username or password is not correct",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,56 +173,59 @@ func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) {
|
||||||
if form.Uid != u.Id {
|
if form.Uid != u.Id {
|
||||||
org, err := models.GetUserById(form.Uid)
|
org, err := models.GetUserById(form.Uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(4, "GetUserById: %v", err)
|
if err == models.ErrUserNotExist {
|
||||||
ctx.Error(500)
|
ctx.HandleAPI(422, err)
|
||||||
|
} else {
|
||||||
|
ctx.HandleAPI(500, err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctxUser = org
|
ctxUser = org
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.HasError() {
|
if ctx.HasError() {
|
||||||
ctx.JSON(422, map[string]interface{}{
|
ctx.HandleAPI(422, ctx.GetErrMsg())
|
||||||
"ok": false,
|
|
||||||
"error": ctx.GetErrMsg(),
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctxUser.IsOrganization() {
|
if ctxUser.IsOrganization() {
|
||||||
// Check ownership of organization.
|
// Check ownership of organization.
|
||||||
if !ctxUser.IsOwnedBy(u.Id) {
|
if !ctxUser.IsOwnedBy(u.Id) {
|
||||||
ctx.JSON(403, map[string]interface{}{
|
ctx.HandleAPI(403, "Given user is not owner of organization.")
|
||||||
"ok": false,
|
|
||||||
"error": "given user is not owner of organization",
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
authStr := strings.Replace(fmt.Sprintf("://%s:%s",
|
// Remote address can be HTTPS URL or local path.
|
||||||
form.AuthUserName, form.AuthPasswd), "@", "%40", -1)
|
remoteAddr := form.CloneAddr
|
||||||
url := strings.Replace(form.HttpsUrl, "://", authStr+"@", 1)
|
if strings.HasPrefix(form.CloneAddr, "http") {
|
||||||
repo, err := models.MigrateRepository(ctxUser, form.RepoName, form.Description, form.Private,
|
u, err := url.Parse(form.CloneAddr)
|
||||||
form.Mirror, url)
|
if err != nil {
|
||||||
if err == nil {
|
ctx.HandleAPI(422, err)
|
||||||
log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName)
|
return
|
||||||
ctx.JSON(200, map[string]interface{}{
|
}
|
||||||
"ok": true,
|
if len(form.AuthUserName) > 0 || len(form.AuthPasswd) > 0 {
|
||||||
"data": "/" + ctxUser.Name + "/" + form.RepoName,
|
u.User = url.UserPassword(form.AuthUserName, form.AuthPasswd)
|
||||||
})
|
}
|
||||||
|
remoteAddr = u.String()
|
||||||
|
} else if !com.IsDir(remoteAddr) {
|
||||||
|
ctx.HandleAPI(422, "Invalid local path, it does not exist or not a directory.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if repo != nil {
|
repo, err := models.MigrateRepository(ctxUser, form.RepoName, form.Description, form.Private, form.Mirror, remoteAddr)
|
||||||
if errDelete := models.DeleteRepository(ctxUser.Id, repo.Id, ctxUser.Name); errDelete != nil {
|
if err != nil {
|
||||||
log.Error(4, "DeleteRepository: %v", errDelete)
|
if repo != nil {
|
||||||
|
if errDelete := models.DeleteRepository(ctxUser.Id, repo.Id, ctxUser.Name); errDelete != nil {
|
||||||
|
log.Error(4, "DeleteRepository: %v", errDelete)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ctx.HandleAPI(500, err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.JSON(500, map[string]interface{}{
|
log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName)
|
||||||
"ok": false,
|
ctx.WriteHeader(200)
|
||||||
"error": err.Error(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET /user/repos
|
// GET /user/repos
|
||||||
|
|
|
@ -181,20 +181,26 @@ func MigratePost(ctx *middleware.Context, form auth.MigrateRepoForm) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := url.Parse(form.HttpsUrl)
|
// Remote address can be HTTPS URL or local path.
|
||||||
|
remoteAddr := form.CloneAddr
|
||||||
if err != nil || u.Scheme != "https" {
|
if strings.HasPrefix(form.CloneAddr, "http") {
|
||||||
ctx.Data["Err_HttpsUrl"] = true
|
u, err := url.Parse(form.CloneAddr)
|
||||||
ctx.RenderWithErr(ctx.Tr("form.url_error"), MIGRATE, &form)
|
if err != nil {
|
||||||
|
ctx.Data["Err_CloneAddr"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("form.url_error"), MIGRATE, &form)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(form.AuthUserName) > 0 || len(form.AuthPasswd) > 0 {
|
||||||
|
u.User = url.UserPassword(form.AuthUserName, form.AuthPasswd)
|
||||||
|
}
|
||||||
|
remoteAddr = u.String()
|
||||||
|
} else if !com.IsDir(remoteAddr) {
|
||||||
|
ctx.Data["Err_CloneAddr"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_local_path"), MIGRATE, &form)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(form.AuthUserName) > 0 || len(form.AuthPasswd) > 0 {
|
repo, err := models.MigrateRepository(ctxUser, form.RepoName, form.Description, form.Private, form.Mirror, remoteAddr)
|
||||||
u.User = url.UserPassword(form.AuthUserName, form.AuthPasswd)
|
|
||||||
}
|
|
||||||
|
|
||||||
repo, err := models.MigrateRepository(ctxUser, form.RepoName, form.Description, form.Private,
|
|
||||||
form.Mirror, u.String())
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName)
|
log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName)
|
||||||
ctx.Redirect(setting.AppSubUrl + "/" + ctxUser.Name + "/" + form.RepoName)
|
ctx.Redirect(setting.AppSubUrl + "/" + ctxUser.Name + "/" + form.RepoName)
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
<div class="panel-content">
|
<div class="panel-content">
|
||||||
{{template "ng/base/alert" .}}
|
{{template "ng/base/alert" .}}
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="req" for="url">HTTPS URL</label>
|
<label class="req" for="clone_addr">{{.i18n.Tr "repo.migrate.clone_address"}}</label>
|
||||||
<input class="ipt ipt-large ipt-radius {{if .Err_HttpsUrl}}ipt-error{{end}}" id="url" name="url" type="text" value="{{.url}}" required />
|
<input class="ipt ipt-large ipt-radius {{if .Err_CloneAddr}}ipt-error{{end}}" id="clone_addr" name="clone_addr" type="text" value="{{.clone_addr}}" required />
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<span class="form-label"></span>
|
<span class="form-label"></span>
|
||||||
|
|
Reference in a new issue