Add repo mirror and import
This commit is contained in:
parent
23bba7633b
commit
90f6aa8cd1
20 changed files with 271 additions and 125 deletions
|
@ -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)
|
![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.
|
#### 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
|
- Activity timeline
|
||||||
- SSH/HTTP(S) protocol support.
|
- SSH/HTTP(S) protocol support.
|
||||||
- Register/delete/rename account.
|
- Register/delete/rename account.
|
||||||
- Create/delete/watch/rename/transfer public/private repository.
|
- Create/migrate/mirror/delete/watch/rename/transfer public/private repository.
|
||||||
- Repository viewer.
|
- Repository viewer/issue tracker.
|
||||||
- Issue tracker.
|
|
||||||
- Gravatar and cache support.
|
- Gravatar and cache support.
|
||||||
- Mail service(register, issue).
|
- Mail service(register, issue).
|
||||||
- Administration panel.
|
- Administration panel.
|
||||||
- Supports MySQL, PostgreSQL and SQLite3(binary release only).
|
- Supports MySQL, PostgreSQL and SQLite3.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ Gogs(Go Git Service) 是一个由 Go 语言编写的自助 Git 托管服务。
|
||||||
|
|
||||||
![Demo](http://gowalker.org/public/gogs_demo.gif)
|
![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) 协议支持
|
- SSH/HTTP(S) 协议支持
|
||||||
- 注册/删除/重命名用户
|
- 注册/删除/重命名用户
|
||||||
- 创建/删除/关注/重命名/转移 公开/私有 仓库
|
- 创建/迁移/镜像/删除/关注/重命名/转移 公开/私有 仓库
|
||||||
- 仓库浏览器
|
- 仓库 浏览器/Bug 追踪
|
||||||
- Bug 追踪系统
|
|
||||||
- Gravatar 以及缓存支持
|
- Gravatar 以及缓存支持
|
||||||
- 邮件服务(注册、Issue)
|
- 邮件服务(注册、Issue)
|
||||||
- 管理员面板
|
- 管理员面板
|
||||||
- 支持 MySQL、PostgreSQL 以及 SQLite3(仅限二进制版本)
|
- 支持 MySQL、PostgreSQL 以及 SQLite3
|
||||||
|
|
||||||
## 安装部署
|
## 安装部署
|
||||||
|
|
||||||
|
|
2
gogs.go
2
gogs.go
|
@ -19,7 +19,7 @@ import (
|
||||||
// Test that go1.2 tag above is included in builds. main.go refers to this definition.
|
// Test that go1.2 tag above is included in builds. main.go refers to this definition.
|
||||||
const go12tag = true
|
const go12tag = true
|
||||||
|
|
||||||
const APP_VER = "0.2.7.0411 Alpha"
|
const APP_VER = "0.2.8.0412 Alpha"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
base.AppVer = APP_VER
|
base.AppVer = APP_VER
|
||||||
|
|
|
@ -21,7 +21,7 @@ const (
|
||||||
type Access struct {
|
type Access struct {
|
||||||
Id int64
|
Id int64
|
||||||
UserName string `xorm:"unique(s)"`
|
UserName string `xorm:"unique(s)"`
|
||||||
RepoName string `xorm:"unique(s)"`
|
RepoName string `xorm:"unique(s)"` // <user name>/<repo name>
|
||||||
Mode int `xorm:"unique(s)"`
|
Mode int `xorm:"unique(s)"`
|
||||||
Created time.Time `xorm:"created"`
|
Created time.Time `xorm:"created"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,8 @@ var (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
tables = append(tables, new(User), new(PublicKey), new(Repository), new(Watch),
|
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() {
|
func LoadModelsConfig() {
|
||||||
|
|
131
models/repo.go
131
models/repo.go
|
@ -78,6 +78,7 @@ type Repository struct {
|
||||||
NumClosedIssues int
|
NumClosedIssues int
|
||||||
NumOpenIssues int `xorm:"-"`
|
NumOpenIssues int `xorm:"-"`
|
||||||
IsPrivate bool
|
IsPrivate bool
|
||||||
|
IsMirror bool
|
||||||
IsBare bool
|
IsBare bool
|
||||||
IsGoget bool
|
IsGoget bool
|
||||||
DefaultBranch string
|
DefaultBranch string
|
||||||
|
@ -119,13 +120,92 @@ func IsLegalName(repoName string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mirror represents a mirror information of repository.
|
||||||
|
type Mirror struct {
|
||||||
|
Id int64
|
||||||
|
RepoId int64
|
||||||
|
RepoName string // <user name>/<repo name>
|
||||||
|
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.
|
// CreateRepository creates a repository for given user or orgnaziation.
|
||||||
func CreateRepository(user *User, repoName, desc, repoLang, license string, private bool, initReadme bool) (*Repository, error) {
|
func CreateRepository(user *User, name, desc, lang, license string, private, mirror, initReadme bool) (*Repository, error) {
|
||||||
if !IsLegalName(repoName) {
|
if !IsLegalName(name) {
|
||||||
return nil, ErrRepoNameIllegal
|
return nil, ErrRepoNameIllegal
|
||||||
}
|
}
|
||||||
|
|
||||||
isExist, err := IsRepositoryExist(user, repoName)
|
isExist, err := IsRepositoryExist(user, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if isExist {
|
} else if isExist {
|
||||||
|
@ -134,13 +214,13 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv
|
||||||
|
|
||||||
repo := &Repository{
|
repo := &Repository{
|
||||||
OwnerId: user.Id,
|
OwnerId: user.Id,
|
||||||
Name: repoName,
|
Name: name,
|
||||||
LowerName: strings.ToLower(repoName),
|
LowerName: strings.ToLower(name),
|
||||||
Description: desc,
|
Description: desc,
|
||||||
IsPrivate: private,
|
IsPrivate: private,
|
||||||
IsBare: repoLang == "" && license == "" && !initReadme,
|
IsBare: lang == "" && license == "" && !initReadme,
|
||||||
}
|
}
|
||||||
repoPath := RepoPath(user.Name, repoName)
|
repoPath := RepoPath(user.Name, repo.Name)
|
||||||
|
|
||||||
sess := orm.NewSession()
|
sess := orm.NewSession()
|
||||||
defer sess.Close()
|
defer sess.Close()
|
||||||
|
@ -150,23 +230,27 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv
|
||||||
if err2 := os.RemoveAll(repoPath); err2 != nil {
|
if err2 := os.RemoveAll(repoPath); err2 != nil {
|
||||||
log.Error("repo.CreateRepository(repo): %v", err)
|
log.Error("repo.CreateRepository(repo): %v", err)
|
||||||
return nil, errors.New(fmt.Sprintf(
|
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()
|
sess.Rollback()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mode := AU_WRITABLE
|
||||||
|
if mirror {
|
||||||
|
mode = AU_READABLE
|
||||||
|
}
|
||||||
access := Access{
|
access := Access{
|
||||||
UserName: user.LowerName,
|
UserName: user.LowerName,
|
||||||
RepoName: strings.ToLower(path.Join(user.Name, repo.Name)),
|
RepoName: strings.ToLower(path.Join(user.Name, repo.Name)),
|
||||||
Mode: AU_WRITABLE,
|
Mode: mode,
|
||||||
}
|
}
|
||||||
if _, err = sess.Insert(&access); err != nil {
|
if _, err = sess.Insert(&access); err != nil {
|
||||||
sess.Rollback()
|
sess.Rollback()
|
||||||
if err2 := os.RemoveAll(repoPath); err2 != nil {
|
if err2 := os.RemoveAll(repoPath); err2 != nil {
|
||||||
log.Error("repo.CreateRepository(access): %v", err)
|
log.Error("repo.CreateRepository(access): %v", err)
|
||||||
return nil, errors.New(fmt.Sprintf(
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -177,7 +261,7 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv
|
||||||
if err2 := os.RemoveAll(repoPath); err2 != nil {
|
if err2 := os.RemoveAll(repoPath); err2 != nil {
|
||||||
log.Error("repo.CreateRepository(repo count): %v", err)
|
log.Error("repo.CreateRepository(repo count): %v", err)
|
||||||
return nil, errors.New(fmt.Sprintf(
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -187,7 +271,7 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv
|
||||||
if err2 := os.RemoveAll(repoPath); err2 != nil {
|
if err2 := os.RemoveAll(repoPath); err2 != nil {
|
||||||
log.Error("repo.CreateRepository(commit): %v", err)
|
log.Error("repo.CreateRepository(commit): %v", err)
|
||||||
return nil, errors.New(fmt.Sprintf(
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -202,7 +286,12 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv
|
||||||
log.Error("repo.CreateRepository(WatchRepo): %v", err)
|
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
|
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()))
|
tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond()))
|
||||||
os.MkdirAll(tmpDir, os.ModePerm)
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
if len(stderr) > 0 {
|
||||||
|
log.Trace("repo.initRepository(git clone): %s", stderr)
|
||||||
|
}
|
||||||
|
|
||||||
// README
|
// README
|
||||||
if initReadme {
|
if initReadme {
|
||||||
|
@ -379,6 +472,7 @@ func GetRepos(num, offset int) ([]UserRepo, error) {
|
||||||
return urepos, nil
|
return urepos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RepoPath returns repository path by given user and repository name.
|
||||||
func RepoPath(userName, repoName string) string {
|
func RepoPath(userName, repoName string) string {
|
||||||
return filepath.Join(UserPath(userName), strings.ToLower(repoName)+".git")
|
return filepath.Join(UserPath(userName), strings.ToLower(repoName)+".git")
|
||||||
}
|
}
|
||||||
|
@ -519,8 +613,7 @@ func DeleteRepository(userId, repoId int64, userName string) (err error) {
|
||||||
sess.Rollback()
|
sess.Rollback()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rawSql := "UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?"
|
if _, err := sess.Delete(&Action{RepoId: repo.Id}); err != nil {
|
||||||
if _, err = sess.Exec(rawSql, userId); err != nil {
|
|
||||||
sess.Rollback()
|
sess.Rollback()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -528,6 +621,12 @@ func DeleteRepository(userId, repoId int64, userName string) (err error) {
|
||||||
sess.Rollback()
|
sess.Rollback()
|
||||||
return err
|
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 {
|
if err = sess.Commit(); err != nil {
|
||||||
sess.Rollback()
|
sess.Rollback()
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -130,7 +130,9 @@ func validate(errors *binding.Errors, data base.TmplData, form Form) {
|
||||||
case binding.MaxSizeError:
|
case binding.MaxSizeError:
|
||||||
data["ErrorMsg"] = form.Name(field.Name) + " must contain at most " + getMinMaxSize(field) + " characters"
|
data["ErrorMsg"] = form.Name(field.Name) + " must contain at most " + getMinMaxSize(field) + " characters"
|
||||||
case binding.EmailError:
|
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:
|
default:
|
||||||
data["ErrorMsg"] = "Unknown error: " + err
|
data["ErrorMsg"] = "Unknown error: " + err
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,11 @@ import (
|
||||||
|
|
||||||
type CreateRepoForm struct {
|
type CreateRepoForm struct {
|
||||||
RepoName string `form:"repo" binding:"Required;AlphaDash"`
|
RepoName string `form:"repo" binding:"Required;AlphaDash"`
|
||||||
Private string `form:"private"`
|
Private bool `form:"private"`
|
||||||
Description string `form:"desc" binding:"MaxSize(100)"`
|
Description string `form:"desc" binding:"MaxSize(100)"`
|
||||||
Language string `form:"language"`
|
Language string `form:"language"`
|
||||||
License string `form:"license"`
|
License string `form:"license"`
|
||||||
InitReadme string `form:"initReadme"`
|
InitReadme bool `form:"initReadme"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *CreateRepoForm) Name(field string) string {
|
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)
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -190,27 +190,3 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
|
||||||
ctx.Data["IsRepositoryWatching"] = ctx.Repo.IsWatching
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -40,8 +40,8 @@ func CreatePost(ctx *middleware.Context, form auth.CreateRepoForm) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := models.CreateRepository(ctx.User, form.RepoName, form.Description,
|
repo, err := models.CreateRepository(ctx.User, form.RepoName, form.Description,
|
||||||
form.Language, form.License, form.Private == "on", form.InitReadme == "on")
|
form.Language, form.License, form.Private, false, form.InitReadme)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Trace("%s Repository created: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, form.RepoName)
|
log.Trace("%s Repository created: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, form.RepoName)
|
||||||
ctx.Redirect("/" + ctx.User.Name + "/" + 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)
|
ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), "repo/create", &form)
|
||||||
return
|
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)
|
ctx.Handle(500, "repo.Create", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Mirror(ctx *middleware.Context) {
|
func Migrate(ctx *middleware.Context) {
|
||||||
ctx.Data["Title"] = "Mirror repository"
|
ctx.Data["Title"] = "Migrate repository"
|
||||||
ctx.Data["PageIsNewRepo"] = true
|
ctx.Data["PageIsNewRepo"] = true
|
||||||
ctx.HTML(200, "repo/mirror")
|
ctx.HTML(200, "repo/migrate")
|
||||||
}
|
}
|
||||||
|
|
||||||
func MirrorPost(ctx *middleware.Context, form auth.CreateRepoForm) {
|
func MigratePost(ctx *middleware.Context, form auth.MigrateRepoForm) {
|
||||||
ctx.Data["Title"] = "Mirror repository"
|
ctx.Data["Title"] = "Migrate repository"
|
||||||
ctx.Data["PageIsNewRepo"] = true
|
ctx.Data["PageIsNewRepo"] = true
|
||||||
|
|
||||||
if ctx.HasError() {
|
if ctx.HasError() {
|
||||||
ctx.HTML(200, "repo/mirror")
|
ctx.HTML(200, "repo/migrate")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := models.CreateRepository(ctx.User, form.RepoName, form.Description,
|
url := strings.Replace(form.Url, "://", fmt.Sprintf("://%s:%s@", form.AuthUserName, form.AuthPasswd), 1)
|
||||||
"", form.License, form.Private == "on", false)
|
repo, err := models.MigrateRepository(ctx.User, form.RepoName, form.Description, form.Private,
|
||||||
|
form.Mirror, url)
|
||||||
if err == nil {
|
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)
|
ctx.Redirect("/" + ctx.User.Name + "/" + form.RepoName)
|
||||||
return
|
return
|
||||||
} else if err == models.ErrRepoAlreadyExist {
|
} 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
|
return
|
||||||
} else if err == models.ErrRepoNameIllegal {
|
} else if err == models.ErrRepoNameIllegal {
|
||||||
ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), "repo/mirror", &form)
|
ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), "repo/migrate", &form)
|
||||||
return
|
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) {
|
func Single(ctx *middleware.Context, params martini.Params) {
|
||||||
|
@ -425,7 +443,3 @@ func Action(ctx *middleware.Context, params martini.Params) {
|
||||||
"ok": true,
|
"ok": true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Import(ctx *middleware.Context, params martini.Params) {
|
|
||||||
ctx.ResponseWriter.Write([]byte("not done yet"))
|
|
||||||
}
|
|
||||||
|
|
|
@ -74,6 +74,20 @@ func Profile(ctx *middleware.Context, params martini.Params) {
|
||||||
ctx.HTML(200, "user/profile")
|
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) {
|
func SignIn(ctx *middleware.Context) {
|
||||||
ctx.Data["Title"] = "Log In"
|
ctx.Data["Title"] = "Log In"
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li><a href="/repo/create"><i class="fa fa-book"></i>Repository</a></li>
|
<li><a href="/repo/create"><i class="fa fa-book"></i>Repository</a></li>
|
||||||
<li><a href="/repo/mirror"><i class="fa fa-clipboard"></i>Mirror</a></li>
|
<li><a href="/repo/migrate"><i class="fa fa-clipboard"></i>Migration</a></li>
|
||||||
<!-- <li><a href="#"><i class="fa fa-users"></i>Organization</a></li> -->
|
<!-- <li><a href="#"><i class="fa fa-users"></i>Organization</a></li> -->
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
{{$r := List .Commits}}
|
{{$r := List .Commits}}
|
||||||
{{range $r}}
|
{{range $r}}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="author"><img class="avatar" src="{{AvatarLink .Author.Email}}" alt=""/><a href="/user/{{.Author.Name}}">{{.Author.Name}}</a></td>
|
<td class="author"><img class="avatar" src="{{AvatarLink .Author.Email}}" alt=""/><a href="/user/email2user?email={{.Author.Email}}">{{.Author.Name}}</a></td>
|
||||||
<td class="sha"><a class="label label-success" href="/{{$username}}/{{$reponame}}/commit/{{.Id}} ">{{SubStr .Id.String 0 10}} </a></td>
|
<td class="sha"><a class="label label-success" href="/{{$username}}/{{$reponame}}/commit/{{.Id}} ">{{SubStr .Id.String 0 10}} </a></td>
|
||||||
<td class="message">{{.Message}} </td>
|
<td class="message">{{.Message}} </td>
|
||||||
<td class="date">{{TimeSince .Author.When}}</td>
|
<td class="date">{{TimeSince .Author.When}}</td>
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
</span>
|
</span>
|
||||||
<p class="author">
|
<p class="author">
|
||||||
<img class="avatar" src="{{AvatarLink .Commit.Author.Email}}" alt=""/>
|
<img class="avatar" src="{{AvatarLink .Commit.Author.Email}}" alt=""/>
|
||||||
<a class="name" href="#"><strong>{{.Commit.Author.Name}}</strong></a>
|
<a class="name" href="/user/email2user?email={{.Commit.Author.Email}}"><strong>{{.Commit.Author.Name}}</strong></a>
|
||||||
<span class="time">{{TimeSince .Commit.Author.When}}</span>
|
<span class="time">{{TimeSince .Commit.Author.When}}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,24 +1,26 @@
|
||||||
{{template "base/head" .}}
|
{{template "base/head" .}}
|
||||||
{{template "base/navbar" .}}
|
{{template "base/navbar" .}}
|
||||||
<div class="container" id="body">
|
<div class="container" id="body">
|
||||||
<form action="/repo/create" method="post" class="form-horizontal card" id="repo-create">
|
<form action="/repo/migrate" method="post" class="form-horizontal card" id="repo-create">
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<h3>Create Repository Mirror</h3>
|
<h3>Repository Migration</h3>
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
<div class="form-group">
|
<!-- <div class="form-group">
|
||||||
<label class="col-md-2 control-label">From<strong class="text-danger">*</strong></label>
|
<label class="col-md-2 control-label">From<strong class="text-danger">*</strong></label>
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<select class="form-control" name="from">
|
<select class="form-control" name="from">
|
||||||
<option value="">GitHub</option>
|
<option value="github">GitHub</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-2 control-label">URL<strong class="text-danger">*</strong></label>
|
<label class="col-md-2 control-label">HTTPS URL<strong class="text-danger">*</strong></label>
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="url" type="text" class="form-control" placeholder="Type your mirror repository url link" required="required">
|
<input name="url" type="text" class="form-control" placeholder="Type your migration repository HTTPS URL" value="{{.url}}" required="required" >
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-md-offset-2 col-md-8">
|
<div class="col-md-offset-2 col-md-8">
|
||||||
<a class="btn btn-default" data-toggle="collapse" data-target="#repo-import-auth">Need Authorization</a>
|
<a class="btn btn-default" data-toggle="collapse" data-target="#repo-import-auth">Need Authorization</a>
|
||||||
|
@ -27,13 +29,13 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-2 control-label">Username</label>
|
<label class="col-md-2 control-label">Username</label>
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="auth-username" type="text" class="form-control">
|
<input name="auth_username" type="text" class="form-control" placeholder="Type your user name" value="{{.auth_username}}" >
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-2 control-label">Password</label>
|
<label class="col-md-2 control-label">Password</label>
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="auth-password" type="text" class="form-control">
|
<input name="auth_password" type="password" class="form-control" placeholder="Type your password" value="{{.auth_password}}" >
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -56,10 +58,26 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-2 control-label">Visibility<strong class="text-danger">*</strong></label>
|
<label class="col-md-2 control-label">Migration Type</label>
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<p class="form-control-static">Public</p>
|
<div class="checkbox">
|
||||||
<input type="hidden" value="public" name="visibility"/>
|
<label>
|
||||||
|
<input type="checkbox" name="mirror" {{if .mirror}}checked{{end}}>
|
||||||
|
<strong>This repository is a mirror</strong>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">Visibility</label>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="private" {{if .private}}checked{{end}}>
|
||||||
|
<strong>This repository is private</strong>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -72,7 +90,7 @@
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-md-offset-2 col-md-8">
|
<div class="col-md-offset-2 col-md-8">
|
||||||
<button type="submit" class="btn btn-lg btn-primary">Mirror repository</button>
|
<button type="submit" class="btn btn-lg btn-primary">Migrate repository</button>
|
||||||
<a href="/" class="text-danger">Cancel</a>
|
<a href="/" class="text-danger">Cancel</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-7">
|
<div class="col-md-7">
|
||||||
<h3 class="name"><i class="fa fa-book fa-lg"></i><a href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a> / <a href="/{{.Owner.Name}}/{{.Repository.Name}}">{{.Repository.Name}}</a>{{if .Repository.IsPrivate}} <span class="label label-default">Private</span> {{end}}</h3>
|
<h3 class="name"><i class="fa fa-book fa-lg"></i><a href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a> / <a href="/{{.Owner.Name}}/{{.Repository.Name}}">{{.Repository.Name}}</a> {{if .Repository.IsPrivate}}<span class="label label-default">Private</span>{{else if .Repository.IsMirror}}<span class="label label-default">Mirror</span>{{end}}</h3>
|
||||||
<p class="desc">{{.Repository.Description}}{{if .Repository.Website}} <a href="{{.Repository.Website}}">{{.Repository.Website}}</a>{{end}}</p>
|
<p class="desc">{{.Repository.Description}}{{if .Repository.Website}} <a href="{{.Repository.Website}}">{{.Repository.Website}}</a>{{end}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-5 actions text-right clone-group-btn">
|
<div class="col-md-5 actions text-right clone-group-btn">
|
||||||
|
|
|
@ -9,20 +9,6 @@
|
||||||
<h4>Quick Guide</h4>
|
<h4>Quick Guide</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body guide-content text-center">
|
<div class="panel-body guide-content text-center">
|
||||||
<form action="{{.RepoLink}}/import" method="post">
|
|
||||||
{{.CsrfTokenHtml}}
|
|
||||||
<h3>Clone from existing repository</h3>
|
|
||||||
<div class="input-group col-md-6 col-md-offset-3">
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button class="btn btn-default" type="button">URL</button>
|
|
||||||
</span>
|
|
||||||
<input name="import_url" class="form-control" placeholder="Type existing repository address" required="required">
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button type="submit" class="btn btn-default" type="button">Clone</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<h3>Clone this repository</h3>
|
<h3>Clone this repository</h3>
|
||||||
<div class="input-group col-md-8 col-md-offset-2 guide-buttons">
|
<div class="input-group col-md-8 col-md-offset-2 guide-buttons">
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
<div class="dropdown-menu dropdown-menu-right">
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li><a href="/repo/create"><i class="fa fa-book"></i>Repository</a></li>
|
<li><a href="/repo/create"><i class="fa fa-book"></i>Repository</a></li>
|
||||||
<li><a href="/repo/mirror"><i class="fa fa-clipboard"></i>Mirror</a></li>
|
<li><a href="/repo/migrate"><i class="fa fa-clipboard"></i>Migration</a></li>
|
||||||
<!-- <li><a href="#"><i class="fa fa-users"></i>Organization</a></li> -->
|
<!-- <li><a href="#"><i class="fa fa-users"></i>Organization</a></li> -->
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,7 +10,18 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="profile-info">
|
<div class="profile-info">
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
{{if .Owner.Location}}
|
||||||
|
<li class="list-group-item"><i class="fa fa-thumb-tack"></i>{{.Owner.Location}}</li>
|
||||||
|
{{end}}
|
||||||
|
{{if .Owner.Email}}
|
||||||
|
<li class="list-group-item"><i class="fa fa-envelope"></i><a href="mailto:{{.Owner.Email}}">{{.Owner.Email}}</a></li>
|
||||||
|
{{end}}
|
||||||
|
{{if .Owner.Website}}
|
||||||
|
<li class="list-group-item"><i class="fa fa-link"></i><a target="_blank" href="{{.Owner.Website}}">{{.Owner.Website}}</a></li>
|
||||||
|
{{end}}
|
||||||
|
<li class="list-group-item"><i class="fa fa-clock-o"></i>Joined on {{DateFormat .Owner.Created "M d, Y"}}</li>
|
||||||
|
<hr>
|
||||||
|
<li class="list-group-item" style="padding-top: 5px;">
|
||||||
<div class="profile-rel">
|
<div class="profile-rel">
|
||||||
<div class="col-md-6 followers">
|
<div class="col-md-6 followers">
|
||||||
<strong>123</strong>
|
<strong>123</strong>
|
||||||
|
@ -22,16 +33,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{{if .Owner.Location}}
|
<hr>
|
||||||
<li class="list-group-item"><i class="fa fa-thumb-tack"></i>{{.Owner.Location}}</li>
|
|
||||||
{{end}}
|
|
||||||
{{if .Owner.Email}}
|
|
||||||
<li class="list-group-item"><i class="fa fa-envelope"></i><a href="mailto:{{.Owner.Email}}">{{.Owner.Email}}</a></li>
|
|
||||||
{{end}}
|
|
||||||
{{if .Owner.Website}}
|
|
||||||
<li class="list-group-item"><i class="fa fa-link"></i><a target="_blank" href="{{.Owner.Website}}">{{.Owner.Website}}</a></li>
|
|
||||||
{{end}}
|
|
||||||
<li class="list-group-item"><i class="fa fa-clock-o"></i>Joined on {{DateFormat .Owner.Created "M d, Y"}}</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
14
web.go
14
web.go
|
@ -104,6 +104,7 @@ func runWeb(*cli.Context) {
|
||||||
m.Group("/user", func(r martini.Router) {
|
m.Group("/user", func(r martini.Router) {
|
||||||
r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds)
|
r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds)
|
||||||
r.Get("/activate", user.Activate)
|
r.Get("/activate", user.Activate)
|
||||||
|
r.Get("/email2user", user.Email2User)
|
||||||
r.Get("/forget_password", user.ForgotPasswd)
|
r.Get("/forget_password", user.ForgotPasswd)
|
||||||
r.Post("/forget_password", user.ForgotPasswdPost)
|
r.Post("/forget_password", user.ForgotPasswdPost)
|
||||||
})
|
})
|
||||||
|
@ -120,8 +121,8 @@ func runWeb(*cli.Context) {
|
||||||
m.Group("/repo", func(r martini.Router) {
|
m.Group("/repo", func(r martini.Router) {
|
||||||
m.Get("/create", repo.Create)
|
m.Get("/create", repo.Create)
|
||||||
m.Post("/create", bindIgnErr(auth.CreateRepoForm{}), repo.CreatePost)
|
m.Post("/create", bindIgnErr(auth.CreateRepoForm{}), repo.CreatePost)
|
||||||
m.Get("/mirror", repo.Mirror)
|
m.Get("/migrate", repo.Migrate)
|
||||||
m.Post("/mirror", bindIgnErr(auth.CreateRepoForm{}), repo.MirrorPost)
|
m.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), repo.MigratePost)
|
||||||
}, reqSignIn)
|
}, reqSignIn)
|
||||||
|
|
||||||
adminReq := middleware.Toggle(&middleware.ToggleOptions{SignInRequire: true, AdminRequire: true})
|
adminReq := middleware.Toggle(&middleware.ToggleOptions{SignInRequire: true, AdminRequire: true})
|
||||||
|
@ -144,24 +145,21 @@ func runWeb(*cli.Context) {
|
||||||
m.Get("/template/**", dev.TemplatePreview)
|
m.Get("/template/**", dev.TemplatePreview)
|
||||||
}
|
}
|
||||||
|
|
||||||
writeable := middleware.WriteAccess()
|
|
||||||
|
|
||||||
m.Group("/:username/:reponame", func(r martini.Router) {
|
m.Group("/:username/:reponame", func(r martini.Router) {
|
||||||
r.Get("/settings", writeable, repo.Setting)
|
r.Get("/settings", repo.Setting)
|
||||||
r.Post("/settings", writeable, repo.SettingPost)
|
r.Post("/settings", repo.SettingPost)
|
||||||
r.Get("/action/:action", repo.Action)
|
r.Get("/action/:action", repo.Action)
|
||||||
r.Get("/issues/new", repo.CreateIssue)
|
r.Get("/issues/new", repo.CreateIssue)
|
||||||
r.Post("/issues/new", bindIgnErr(auth.CreateIssueForm{}), repo.CreateIssuePost)
|
r.Post("/issues/new", bindIgnErr(auth.CreateIssueForm{}), repo.CreateIssuePost)
|
||||||
r.Post("/issues/:index", bindIgnErr(auth.CreateIssueForm{}), repo.UpdateIssue)
|
r.Post("/issues/:index", bindIgnErr(auth.CreateIssueForm{}), repo.UpdateIssue)
|
||||||
r.Post("/comment/:action", repo.Comment)
|
r.Post("/comment/:action", repo.Comment)
|
||||||
r.Post("/import", writeable, repo.Import)
|
|
||||||
}, reqSignIn, middleware.RepoAssignment(true))
|
}, reqSignIn, middleware.RepoAssignment(true))
|
||||||
|
|
||||||
m.Group("/:username/:reponame", func(r martini.Router) {
|
m.Group("/:username/:reponame", func(r martini.Router) {
|
||||||
r.Get("/issues", repo.Issues)
|
r.Get("/issues", repo.Issues)
|
||||||
r.Get("/issues/:index", repo.ViewIssue)
|
r.Get("/issues/:index", repo.ViewIssue)
|
||||||
r.Get("/releases", repo.Releases)
|
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("/pulls", repo.Pulls)
|
||||||
r.Get("/branches", repo.Branches)
|
r.Get("/branches", repo.Branches)
|
||||||
}, ignSignIn, middleware.RepoAssignment(true))
|
}, ignSignIn, middleware.RepoAssignment(true))
|
||||||
|
|
Reference in a new issue