diff --git a/README.md b/README.md index d48c05c25..fa48027db 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language ![Demo](http://gowalker.org/public/gogs_demo.gif) -##### Current version: 0.2.7 Alpha +##### Current version: 0.2.8 Alpha #### Due to testing purpose, data of [try.gogits.org](http://try.gogits.org) has been reset in April 6, 2014 and will reset multiple times after. Please do NOT put your important data on the site. @@ -31,13 +31,12 @@ More importantly, Gogs only needs one binary to setup your own project hosting o - Activity timeline - SSH/HTTP(S) protocol support. - Register/delete/rename account. -- Create/delete/watch/rename/transfer public/private repository. -- Repository viewer. -- Issue tracker. +- Create/migrate/mirror/delete/watch/rename/transfer public/private repository. +- Repository viewer/issue tracker. - Gravatar and cache support. - Mail service(register, issue). - Administration panel. -- Supports MySQL, PostgreSQL and SQLite3(binary release only). +- Supports MySQL, PostgreSQL and SQLite3. ## Installation diff --git a/README_ZH.md b/README_ZH.md index 62996d4df..beb5a1050 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -5,7 +5,7 @@ Gogs(Go Git Service) 是一个由 Go 语言编写的自助 Git 托管服务。 ![Demo](http://gowalker.org/public/gogs_demo.gif) -##### 当前版本:0.2.7 Alpha +##### 当前版本:0.2.8 Alpha ## 开发目的 @@ -25,13 +25,12 @@ Gogs 完全使用 Go 语言来实现对 Git 数据的操作,实现 **零** 依 - 活动时间线 - SSH/HTTP(S) 协议支持 - 注册/删除/重命名用户 -- 创建/删除/关注/重命名/转移 公开/私有 仓库 -- 仓库浏览器 -- Bug 追踪系统 +- 创建/迁移/镜像/删除/关注/重命名/转移 公开/私有 仓库 +- 仓库 浏览器/Bug 追踪 - Gravatar 以及缓存支持 - 邮件服务(注册、Issue) - 管理员面板 -- 支持 MySQL、PostgreSQL 以及 SQLite3(仅限二进制版本) +- 支持 MySQL、PostgreSQL 以及 SQLite3 ## 安装部署 diff --git a/gogs.go b/gogs.go index f726e809a..a42d7225b 100644 --- a/gogs.go +++ b/gogs.go @@ -19,7 +19,7 @@ import ( // Test that go1.2 tag above is included in builds. main.go refers to this definition. const go12tag = true -const APP_VER = "0.2.7.0411 Alpha" +const APP_VER = "0.2.8.0412 Alpha" func init() { base.AppVer = APP_VER diff --git a/models/access.go b/models/access.go index 5bf93f1b1..f20f8fa7c 100644 --- a/models/access.go +++ b/models/access.go @@ -21,7 +21,7 @@ const ( type Access struct { Id int64 UserName string `xorm:"unique(s)"` - RepoName string `xorm:"unique(s)"` + RepoName string `xorm:"unique(s)"` // / Mode int `xorm:"unique(s)"` Created time.Time `xorm:"created"` } diff --git a/models/models.go b/models/models.go index b8374a3d6..f1d43531b 100644 --- a/models/models.go +++ b/models/models.go @@ -32,7 +32,8 @@ var ( func init() { tables = append(tables, new(User), new(PublicKey), new(Repository), new(Watch), - new(Action), new(Access), new(Issue), new(Comment), new(Oauth2), new(Follow)) + new(Action), new(Access), new(Issue), new(Comment), new(Oauth2), new(Follow), + new(Mirror)) } func LoadModelsConfig() { diff --git a/models/repo.go b/models/repo.go index d01a716b5..a2c63a50c 100644 --- a/models/repo.go +++ b/models/repo.go @@ -78,6 +78,7 @@ type Repository struct { NumClosedIssues int NumOpenIssues int `xorm:"-"` IsPrivate bool + IsMirror bool IsBare bool IsGoget bool DefaultBranch string @@ -119,13 +120,92 @@ func IsLegalName(repoName string) bool { return true } +// Mirror represents a mirror information of repository. +type Mirror struct { + Id int64 + RepoId int64 + RepoName string // / + Interval int // Hour. + Updated time.Time `xorm:"UPDATED"` + NextUpdate time.Time +} + +// MirrorRepository creates a mirror repository from source. +func MirrorRepository(repoId int64, userName, repoName, repoPath, url string) error { + _, stderr, err := com.ExecCmd("git", "clone", "--mirror", url, repoPath) + if err != nil { + return err + } else if strings.Contains(stderr, "fatal:") { + return errors.New(stderr) + } + + if _, err = orm.InsertOne(&Mirror{ + RepoId: repoId, + RepoName: strings.ToLower(userName + "/" + repoName), + Interval: 24, + NextUpdate: time.Now().Add(24 * time.Hour), + }); err != nil { + return err + } + + return git.UnpackRefs(repoPath) +} + +// MigrateRepository migrates a existing repository from other project hosting. +func MigrateRepository(user *User, name, desc string, private, mirror bool, url string) (*Repository, error) { + repo, err := CreateRepository(user, name, desc, "", "", private, mirror, false) + if err != nil { + return nil, err + } + + // Clone to temprory path and do the init commit. + tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond())) + os.MkdirAll(tmpDir, os.ModePerm) + + repoPath := RepoPath(user.Name, name) + + repo.IsBare = false + if mirror { + if err = MirrorRepository(repo.Id, user.Name, repo.Name, repoPath, url); err != nil { + return repo, err + } + repo.IsMirror = true + return repo, UpdateRepository(repo) + } + + // Clone from local repository. + _, stderr, err := com.ExecCmd("git", "clone", repoPath, tmpDir) + if err != nil { + return repo, err + } else if strings.Contains(stderr, "fatal:") { + return repo, errors.New("git clone: " + stderr) + } + + // Pull data from source. + _, stderr, err = com.ExecCmdDir(tmpDir, "git", "pull", url) + if err != nil { + return repo, err + } else if strings.Contains(stderr, "fatal:") { + return repo, errors.New("git pull: " + stderr) + } + + // Push data to local repository. + if _, stderr, err = com.ExecCmdDir(tmpDir, "git", "push", "origin", "master"); err != nil { + return repo, err + } else if strings.Contains(stderr, "fatal:") { + return repo, errors.New("git push: " + stderr) + } + + return repo, UpdateRepository(repo) +} + // CreateRepository creates a repository for given user or orgnaziation. -func CreateRepository(user *User, repoName, desc, repoLang, license string, private bool, initReadme bool) (*Repository, error) { - if !IsLegalName(repoName) { +func CreateRepository(user *User, name, desc, lang, license string, private, mirror, initReadme bool) (*Repository, error) { + if !IsLegalName(name) { return nil, ErrRepoNameIllegal } - isExist, err := IsRepositoryExist(user, repoName) + isExist, err := IsRepositoryExist(user, name) if err != nil { return nil, err } else if isExist { @@ -134,13 +214,13 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv repo := &Repository{ OwnerId: user.Id, - Name: repoName, - LowerName: strings.ToLower(repoName), + Name: name, + LowerName: strings.ToLower(name), Description: desc, IsPrivate: private, - IsBare: repoLang == "" && license == "" && !initReadme, + IsBare: lang == "" && license == "" && !initReadme, } - repoPath := RepoPath(user.Name, repoName) + repoPath := RepoPath(user.Name, repo.Name) sess := orm.NewSession() defer sess.Close() @@ -150,23 +230,27 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv if err2 := os.RemoveAll(repoPath); err2 != nil { log.Error("repo.CreateRepository(repo): %v", err) return nil, errors.New(fmt.Sprintf( - "delete repo directory %s/%s failed(1): %v", user.Name, repoName, err2)) + "delete repo directory %s/%s failed(1): %v", user.Name, repo.Name, err2)) } sess.Rollback() return nil, err } + mode := AU_WRITABLE + if mirror { + mode = AU_READABLE + } access := Access{ UserName: user.LowerName, RepoName: strings.ToLower(path.Join(user.Name, repo.Name)), - Mode: AU_WRITABLE, + Mode: mode, } if _, err = sess.Insert(&access); err != nil { sess.Rollback() if err2 := os.RemoveAll(repoPath); err2 != nil { log.Error("repo.CreateRepository(access): %v", err) return nil, errors.New(fmt.Sprintf( - "delete repo directory %s/%s failed(2): %v", user.Name, repoName, err2)) + "delete repo directory %s/%s failed(2): %v", user.Name, repo.Name, err2)) } return nil, err } @@ -177,7 +261,7 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv if err2 := os.RemoveAll(repoPath); err2 != nil { log.Error("repo.CreateRepository(repo count): %v", err) return nil, errors.New(fmt.Sprintf( - "delete repo directory %s/%s failed(3): %v", user.Name, repoName, err2)) + "delete repo directory %s/%s failed(3): %v", user.Name, repo.Name, err2)) } return nil, err } @@ -187,7 +271,7 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv if err2 := os.RemoveAll(repoPath); err2 != nil { log.Error("repo.CreateRepository(commit): %v", err) return nil, errors.New(fmt.Sprintf( - "delete repo directory %s/%s failed(3): %v", user.Name, repoName, err2)) + "delete repo directory %s/%s failed(3): %v", user.Name, repo.Name, err2)) } return nil, err } @@ -202,7 +286,12 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv log.Error("repo.CreateRepository(WatchRepo): %v", err) } - if err = initRepository(repoPath, user, repo, initReadme, repoLang, license); err != nil { + // No need for init for mirror. + if mirror { + return repo, nil + } + + if err = initRepository(repoPath, user, repo, initReadme, lang, license); err != nil { return nil, err } @@ -304,9 +393,13 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond())) os.MkdirAll(tmpDir, os.ModePerm) - if _, _, err := com.ExecCmd("git", "clone", repoPath, tmpDir); err != nil { + _, stderr, err := com.ExecCmd("git", "clone", repoPath, tmpDir) + if err != nil { return err } + if len(stderr) > 0 { + log.Trace("repo.initRepository(git clone): %s", stderr) + } // README if initReadme { @@ -379,6 +472,7 @@ func GetRepos(num, offset int) ([]UserRepo, error) { return urepos, nil } +// RepoPath returns repository path by given user and repository name. func RepoPath(userName, repoName string) string { return filepath.Join(UserPath(userName), strings.ToLower(repoName)+".git") } @@ -519,8 +613,7 @@ func DeleteRepository(userId, repoId int64, userName string) (err error) { sess.Rollback() return err } - rawSql := "UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?" - if _, err = sess.Exec(rawSql, userId); err != nil { + if _, err := sess.Delete(&Action{RepoId: repo.Id}); err != nil { sess.Rollback() return err } @@ -528,6 +621,12 @@ func DeleteRepository(userId, repoId int64, userName string) (err error) { sess.Rollback() return err } + + rawSql := "UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?" + if _, err = sess.Exec(rawSql, userId); err != nil { + sess.Rollback() + return err + } if err = sess.Commit(); err != nil { sess.Rollback() return err diff --git a/modules/auth/auth.go b/modules/auth/auth.go index 4561dd831..7329cbdcd 100644 --- a/modules/auth/auth.go +++ b/modules/auth/auth.go @@ -130,7 +130,9 @@ func validate(errors *binding.Errors, data base.TmplData, form Form) { case binding.MaxSizeError: data["ErrorMsg"] = form.Name(field.Name) + " must contain at most " + getMinMaxSize(field) + " characters" case binding.EmailError: - data["ErrorMsg"] = form.Name(field.Name) + " is not valid" + data["ErrorMsg"] = form.Name(field.Name) + " is not a valid e-mail address" + case binding.UrlError: + data["ErrorMsg"] = form.Name(field.Name) + " is not a valid URL" default: data["ErrorMsg"] = "Unknown error: " + err } diff --git a/modules/auth/repo.go b/modules/auth/repo.go index 1c740bed1..aa94058f9 100644 --- a/modules/auth/repo.go +++ b/modules/auth/repo.go @@ -18,11 +18,11 @@ import ( type CreateRepoForm struct { RepoName string `form:"repo" binding:"Required;AlphaDash"` - Private string `form:"private"` + Private bool `form:"private"` Description string `form:"desc" binding:"MaxSize(100)"` Language string `form:"language"` License string `form:"license"` - InitReadme string `form:"initReadme"` + InitReadme bool `form:"initReadme"` } func (f *CreateRepoForm) Name(field string) string { @@ -51,3 +51,41 @@ func (f *CreateRepoForm) Validate(errors *binding.Errors, req *http.Request, con validate(errors, data, f) } + +type MigrateRepoForm struct { + Url string `form:"url" binding:"Url"` + AuthUserName string `form:"auth_username"` + AuthPasswd string `form:"auth_password"` + RepoName string `form:"repo" binding:"Required;AlphaDash"` + Mirror bool `form:"mirror"` + Private bool `form:"private"` + Description string `form:"desc" binding:"MaxSize(100)"` +} + +func (f *MigrateRepoForm) Name(field string) string { + names := map[string]string{ + "Url": "Migration URL", + "RepoName": "Repository name", + "Description": "Description", + } + return names[field] +} + +func (f *MigrateRepoForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) { + if req.Method == "GET" || errors.Count() == 0 { + return + } + + data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) + data["HasError"] = true + AssignForm(f, data) + + if len(errors.Overall) > 0 { + for _, err := range errors.Overall { + log.Error("MigrateRepoForm.Validate: %v", err) + } + return + } + + validate(errors, data, f) +} diff --git a/modules/middleware/repo.go b/modules/middleware/repo.go index 75d9f999c..2a6d300e4 100644 --- a/modules/middleware/repo.go +++ b/modules/middleware/repo.go @@ -190,27 +190,3 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler { ctx.Data["IsRepositoryWatching"] = ctx.Repo.IsWatching } } - -func WriteAccess() martini.Handler { - return func(ctx *Context) { - if ctx.Repo.Repository.IsPrivate { - ctx.Repo.HasAccess = false - ctx.Data["HasAccess"] = false - if ctx.User == nil { - ctx.Handle(404, "WriteAccess", nil) - return - } - - hasAccess, err := models.HasAccess(ctx.User.Name, ctx.Repo.Owner.Name+"/"+ctx.Repo.Repository.Name, models.AU_WRITABLE) - if err != nil { - ctx.Handle(500, "WriteAccess(HasAccess)", err) - return - } else if !hasAccess { - ctx.Handle(404, "WriteAccess(HasAccess)", nil) - return - } - } - ctx.Repo.HasAccess = true - ctx.Data["HasAccess"] = true - } -} diff --git a/routers/repo/repo.go b/routers/repo/repo.go index 3ffbde1a1..f19ae02ee 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -40,8 +40,8 @@ func CreatePost(ctx *middleware.Context, form auth.CreateRepoForm) { return } - _, err := models.CreateRepository(ctx.User, form.RepoName, form.Description, - form.Language, form.License, form.Private == "on", form.InitReadme == "on") + repo, err := models.CreateRepository(ctx.User, form.RepoName, form.Description, + form.Language, form.License, form.Private, false, form.InitReadme) if err == nil { log.Trace("%s Repository created: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, form.RepoName) ctx.Redirect("/" + ctx.User.Name + "/" + form.RepoName) @@ -53,38 +53,56 @@ func CreatePost(ctx *middleware.Context, form auth.CreateRepoForm) { ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), "repo/create", &form) return } + + if repo != nil { + if errDelete := models.DeleteRepository(ctx.User.Id, repo.Id, ctx.User.Name); errDelete != nil { + log.Error("repo.MigratePost(CreatePost): %v", errDelete) + } + } ctx.Handle(500, "repo.Create", err) } -func Mirror(ctx *middleware.Context) { - ctx.Data["Title"] = "Mirror repository" +func Migrate(ctx *middleware.Context) { + ctx.Data["Title"] = "Migrate repository" ctx.Data["PageIsNewRepo"] = true - ctx.HTML(200, "repo/mirror") + ctx.HTML(200, "repo/migrate") } -func MirrorPost(ctx *middleware.Context, form auth.CreateRepoForm) { - ctx.Data["Title"] = "Mirror repository" +func MigratePost(ctx *middleware.Context, form auth.MigrateRepoForm) { + ctx.Data["Title"] = "Migrate repository" ctx.Data["PageIsNewRepo"] = true if ctx.HasError() { - ctx.HTML(200, "repo/mirror") + ctx.HTML(200, "repo/migrate") return } - _, err := models.CreateRepository(ctx.User, form.RepoName, form.Description, - "", form.License, form.Private == "on", false) + url := strings.Replace(form.Url, "://", fmt.Sprintf("://%s:%s@", form.AuthUserName, form.AuthPasswd), 1) + repo, err := models.MigrateRepository(ctx.User, form.RepoName, form.Description, form.Private, + form.Mirror, url) if err == nil { - log.Trace("%s Repository created: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, form.RepoName) + log.Trace("%s Repository migrated: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, form.RepoName) ctx.Redirect("/" + ctx.User.Name + "/" + form.RepoName) return } else if err == models.ErrRepoAlreadyExist { - ctx.RenderWithErr("Repository name has already been used", "repo/mirror", &form) + ctx.RenderWithErr("Repository name has already been used", "repo/migrate", &form) return } else if err == models.ErrRepoNameIllegal { - ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), "repo/mirror", &form) + ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), "repo/migrate", &form) return } - ctx.Handle(500, "repo.Mirror", err) + + if repo != nil { + if errDelete := models.DeleteRepository(ctx.User.Id, repo.Id, ctx.User.Name); errDelete != nil { + log.Error("repo.MigratePost(DeleteRepository): %v", errDelete) + } + } + + if strings.Contains(err.Error(), "Authentication failed") { + ctx.RenderWithErr(err.Error(), "repo/migrate", &form) + return + } + ctx.Handle(500, "repo.Migrate", err) } func Single(ctx *middleware.Context, params martini.Params) { @@ -425,7 +443,3 @@ func Action(ctx *middleware.Context, params martini.Params) { "ok": true, }) } - -func Import(ctx *middleware.Context, params martini.Params) { - ctx.ResponseWriter.Write([]byte("not done yet")) -} diff --git a/routers/user/user.go b/routers/user/user.go index 8585267a6..e5328173a 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -74,6 +74,20 @@ func Profile(ctx *middleware.Context, params martini.Params) { ctx.HTML(200, "user/profile") } +func Email2User(ctx *middleware.Context) { + u, err := models.GetUserByEmail(ctx.Query("email")) + if err != nil { + if err == models.ErrUserNotExist { + ctx.Handle(404, "user.Email2User", err) + } else { + ctx.Handle(500, "user.Email2User(GetUserByEmail)", err) + } + return + } + + ctx.Redirect("/user/" + u.Name) +} + func SignIn(ctx *middleware.Context) { ctx.Data["Title"] = "Log In" diff --git a/templates/base/navbar.tmpl b/templates/base/navbar.tmpl index 708a39768..cd3f2b83a 100644 --- a/templates/base/navbar.tmpl +++ b/templates/base/navbar.tmpl @@ -28,7 +28,7 @@ diff --git a/templates/repo/commits.tmpl b/templates/repo/commits.tmpl index 68b140358..8125fedaa 100644 --- a/templates/repo/commits.tmpl +++ b/templates/repo/commits.tmpl @@ -31,7 +31,7 @@ {{$r := List .Commits}} {{range $r}} - {{.Author.Name}} + {{.Author.Name}} {{SubStr .Id.String 0 10}} {{.Message}} {{TimeSince .Author.When}} diff --git a/templates/repo/diff.tmpl b/templates/repo/diff.tmpl index 796a8e94c..f3d935aeb 100644 --- a/templates/repo/diff.tmpl +++ b/templates/repo/diff.tmpl @@ -14,7 +14,7 @@

- {{.Commit.Author.Name}} + {{.Commit.Author.Name}} {{TimeSince .Commit.Author.When}}

diff --git a/templates/repo/mirror.tmpl b/templates/repo/migrate.tmpl similarity index 65% rename from templates/repo/mirror.tmpl rename to templates/repo/migrate.tmpl index 0f10d1f54..34a4077ee 100644 --- a/templates/repo/mirror.tmpl +++ b/templates/repo/migrate.tmpl @@ -1,24 +1,26 @@ {{template "base/head" .}} {{template "base/navbar" .}}
-
+ {{.CsrfTokenHtml}} -

Create Repository Mirror

+

Repository Migration

{{template "base/alert" .}} -
+ +
- +
- +
+
Need Authorization @@ -27,13 +29,13 @@
- +
- +
@@ -56,10 +58,26 @@
- +
-

Public

- +
+ +
+
+
+ +
+ +
+
+ +
@@ -72,7 +90,7 @@
- + Cancel
diff --git a/templates/repo/nav.tmpl b/templates/repo/nav.tmpl index f365ab649..f9f74dd19 100644 --- a/templates/repo/nav.tmpl +++ b/templates/repo/nav.tmpl @@ -2,7 +2,7 @@
-

{{.Owner.Name}} / {{.Repository.Name}}{{if .Repository.IsPrivate}} Private {{end}}

+

{{.Owner.Name}} / {{.Repository.Name}} {{if .Repository.IsPrivate}}Private{{else if .Repository.IsMirror}}Mirror{{end}}

{{.Repository.Description}}{{if .Repository.Website}} {{.Repository.Website}}{{end}}

diff --git a/templates/repo/single_bare.tmpl b/templates/repo/single_bare.tmpl index 7d7016e5c..fc0a3bd96 100644 --- a/templates/repo/single_bare.tmpl +++ b/templates/repo/single_bare.tmpl @@ -9,20 +9,6 @@

Quick Guide

- - {{.CsrfTokenHtml}} -

Clone from existing repository

-
- - - - - - - -
- -

Clone this repository

diff --git a/templates/user/dashboard.tmpl b/templates/user/dashboard.tmpl index efa78d880..167ae9abb 100644 --- a/templates/user/dashboard.tmpl +++ b/templates/user/dashboard.tmpl @@ -34,7 +34,7 @@ diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl index 0cbd34891..255eb71cb 100644 --- a/templates/user/profile.tmpl +++ b/templates/user/profile.tmpl @@ -10,7 +10,18 @@
    -
  • + {{if .Owner.Location}} +
  • {{.Owner.Location}}
  • + {{end}} + {{if .Owner.Email}} +
  • {{.Owner.Email}}
  • + {{end}} + {{if .Owner.Website}} +
  • {{.Owner.Website}}
  • + {{end}} +
  • Joined on {{DateFormat .Owner.Created "M d, Y"}}
  • +
    +
  • 123 @@ -22,16 +33,7 @@
  • - {{if .Owner.Location}} -
  • {{.Owner.Location}}
  • - {{end}} - {{if .Owner.Email}} -
  • {{.Owner.Email}}
  • - {{end}} - {{if .Owner.Website}} -
  • {{.Owner.Website}}
  • - {{end}} -
  • Joined on {{DateFormat .Owner.Created "M d, Y"}}
  • +
diff --git a/web.go b/web.go index de8e72505..a17be2a34 100644 --- a/web.go +++ b/web.go @@ -104,6 +104,7 @@ func runWeb(*cli.Context) { m.Group("/user", func(r martini.Router) { r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds) r.Get("/activate", user.Activate) + r.Get("/email2user", user.Email2User) r.Get("/forget_password", user.ForgotPasswd) r.Post("/forget_password", user.ForgotPasswdPost) }) @@ -120,8 +121,8 @@ func runWeb(*cli.Context) { m.Group("/repo", func(r martini.Router) { m.Get("/create", repo.Create) m.Post("/create", bindIgnErr(auth.CreateRepoForm{}), repo.CreatePost) - m.Get("/mirror", repo.Mirror) - m.Post("/mirror", bindIgnErr(auth.CreateRepoForm{}), repo.MirrorPost) + m.Get("/migrate", repo.Migrate) + m.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), repo.MigratePost) }, reqSignIn) adminReq := middleware.Toggle(&middleware.ToggleOptions{SignInRequire: true, AdminRequire: true}) @@ -144,24 +145,21 @@ func runWeb(*cli.Context) { m.Get("/template/**", dev.TemplatePreview) } - writeable := middleware.WriteAccess() - m.Group("/:username/:reponame", func(r martini.Router) { - r.Get("/settings", writeable, repo.Setting) - r.Post("/settings", writeable, repo.SettingPost) + r.Get("/settings", repo.Setting) + r.Post("/settings", repo.SettingPost) r.Get("/action/:action", repo.Action) r.Get("/issues/new", repo.CreateIssue) r.Post("/issues/new", bindIgnErr(auth.CreateIssueForm{}), repo.CreateIssuePost) r.Post("/issues/:index", bindIgnErr(auth.CreateIssueForm{}), repo.UpdateIssue) r.Post("/comment/:action", repo.Comment) - r.Post("/import", writeable, repo.Import) }, reqSignIn, middleware.RepoAssignment(true)) m.Group("/:username/:reponame", func(r martini.Router) { r.Get("/issues", repo.Issues) r.Get("/issues/:index", repo.ViewIssue) r.Get("/releases", repo.Releases) - r.Any("/releases/new", writeable, repo.ReleasesNew) // TODO: + r.Any("/releases/new", repo.ReleasesNew) // TODO: r.Get("/pulls", repo.Pulls) r.Get("/branches", repo.Branches) }, ignSignIn, middleware.RepoAssignment(true))