From ce350a737a63aeb4e2ca5924adf28862a6a6cfb1 Mon Sep 17 00:00:00 2001 From: skyblue Date: Sat, 5 Apr 2014 22:46:32 +0800 Subject: update models, add licence in start.sh --- models/models.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'models/models.go') diff --git a/models/models.go b/models/models.go index 384f1fc4..0dc4d51e 100644 --- a/models/models.go +++ b/models/models.go @@ -18,7 +18,9 @@ import ( ) var ( - orm *xorm.Engine + orm *xorm.Engine + tables []interface{} + HasEngine bool DbCfg struct { @@ -28,6 +30,11 @@ var ( UseSQLite3 bool ) +func init() { + tables = append(tables, new(User), new(PublicKey), new(Repository), new(Watch), + new(Action), new(Access), new(Issue), new(Comment)) +} + func LoadModelsConfig() { DbCfg.Type = base.Cfg.MustValue("database", "DB_TYPE") if DbCfg.Type == "sqlite3" { @@ -58,9 +65,7 @@ func NewTestEngine(x *xorm.Engine) (err error) { if err != nil { return fmt.Errorf("models.init(fail to conntect database): %v\n", err) } - - return x.Sync(new(User), new(PublicKey), new(Repository), new(Watch), - new(Action), new(Access), new(Issue), new(Comment)) + return x.Sync(tables...) } func SetEngine() (err error) { @@ -102,8 +107,8 @@ func SetEngine() (err error) { func NewEngine() (err error) { if err = SetEngine(); err != nil { return err - } else if err = orm.Sync(new(User), new(PublicKey), new(Repository), new(Watch), - new(Action), new(Access), new(Issue), new(Comment)); err != nil { + } + if err = orm.Sync(tables...); err != nil { return fmt.Errorf("sync database struct error: %v\n", err) } return nil -- cgit v1.2.3 From 7d07b58114199f682a9caa059f239e24c820dc41 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 11 Apr 2014 13:24:19 -0400 Subject: UPDATE README --- CONTRIBUTING.md | 2 +- README.md | 2 +- README_ZH.md | 2 +- models/models.go | 2 +- models/user.go | 2 ++ templates/base/navbar.tmpl | 12 ++++++------ templates/user/dashboard.tmpl | 2 +- 7 files changed, 13 insertions(+), 11 deletions(-) (limited to 'models/models.go') diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 17a3ebe6..cfc6c14f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ > Thanks [drone](https://github.com/drone/drone) because this guidelines sheet is forked from its [CONTRIBUTING.md](https://github.com/drone/drone/blob/master/CONTRIBUTING.md). -**This document is pre^3 release, we're not ready for receiving contribution until v0.5.0 release.** +**This document is pre^2 release, we're not ready for receiving contribution until v0.5.0 release.** Want to hack on Gogs? Awesome! Here are instructions to get you started. They are probably not perfect, please let us know if anything feels wrong or incomplete. diff --git a/README.md b/README.md index d30e8135..37a2b9e2 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ More importantly, Gogs only needs one binary to setup your own project hosting o Make sure you install [Prerequirements](https://github.com/gogits/gogs/wiki/Prerequirements) first. -There are two ways to install Gogs: +There are 3 ways to install Gogs: - [Install from binary](https://github.com/gogits/gogs/wiki/Install-from-binary): **STRONGLY RECOMMENDED** - [Install from source](https://github.com/gogits/gogs/wiki/Install-from-source) diff --git a/README_ZH.md b/README_ZH.md index 43303cdf..b16e7a58 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -37,7 +37,7 @@ Gogs 完全使用 Go 语言来实现对 Git 数据的操作,实现 **零** 依 在安装 Gogs 之前,您需要先安装 [基本环境](https://github.com/gogits/gogs/wiki/Prerequirements)。 -然后,您可以通过以下两种方式来安装 Gogs: +然后,您可以通过以下 3 种方式来安装 Gogs: - [二进制安装](https://github.com/gogits/gogs/wiki/Install-from-binary): **强烈推荐** - [源码安装](https://github.com/gogits/gogs/wiki/Install-from-source) diff --git a/models/models.go b/models/models.go index ee96207d..b380d0e0 100644 --- a/models/models.go +++ b/models/models.go @@ -32,7 +32,7 @@ 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(Action), new(Access), new(Issue), new(Comment), new(Oauth2), new(Follow)) } func LoadModelsConfig() { diff --git a/models/user.go b/models/user.go index b2fddd0a..5274970f 100644 --- a/models/user.go +++ b/models/user.go @@ -294,6 +294,8 @@ func DeleteUser(user *User) error { return err } + // Delete oauth2. + // Delete all feeds. if _, err = orm.Delete(&Action{UserId: user.Id}); err != nil { return err diff --git a/templates/base/navbar.tmpl b/templates/base/navbar.tmpl index 8d6ca47e..e74fd316 100644 --- a/templates/base/navbar.tmpl +++ b/templates/base/navbar.tmpl @@ -4,19 +4,19 @@ Dashboard Help{{if .IsSigned}} - {{if .Repository}}{{end}} + user-avatar @@ -29,7 +29,7 @@ diff --git a/templates/user/dashboard.tmpl b/templates/user/dashboard.tmpl index e2d7a509..efa78d88 100644 --- a/templates/user/dashboard.tmpl +++ b/templates/user/dashboard.tmpl @@ -35,7 +35,7 @@ -- cgit v1.2.3 From 25fd495b2e790001e9c138205606ec4fa16bf129 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Sat, 12 Apr 2014 11:48:12 -0700 Subject: Add sqlite build tag This adds a sqlite build tag so that you don't have to have the sqlite import commented out in code and users can run: go build -tags sqlite if they want to have sqlite support enabled. It is disabled by default so nothing changes with the default go get or build commands. --- models/models.go | 7 +++---- models/models_sqlite.go | 11 +++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 models/models_sqlite.go (limited to 'models/models.go') diff --git a/models/models.go b/models/models.go index ee96207d..3e3dbbf8 100644 --- a/models/models.go +++ b/models/models.go @@ -12,7 +12,6 @@ import ( _ "github.com/go-sql-driver/mysql" _ "github.com/lib/pq" "github.com/lunny/xorm" - // _ "github.com/mattn/go-sqlite3" "github.com/gogits/gogs/modules/base" ) @@ -56,9 +55,9 @@ func NewTestEngine(x *xorm.Engine) (err error) { case "postgres": x, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s dbname=%s sslmode=%s", DbCfg.User, DbCfg.Pwd, DbCfg.Name, DbCfg.SslMode)) - // case "sqlite3": - // os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm) - // x, err = xorm.NewEngine("sqlite3", DbCfg.Path) + case "sqlite3": + os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm) + x, err = xorm.NewEngine("sqlite3", DbCfg.Path) default: return fmt.Errorf("Unknown database type: %s", DbCfg.Type) } diff --git a/models/models_sqlite.go b/models/models_sqlite.go new file mode 100644 index 00000000..02c3f582 --- /dev/null +++ b/models/models_sqlite.go @@ -0,0 +1,11 @@ +// +build sqlite + +// Copyright 2014 The Gogs 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 models + +import ( + _ "github.com/mattn/go-sqlite3" +) -- cgit v1.2.3 From 23bba7633bbd8ae8f9f41404352c327f9e8c9fdc Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 12 Apr 2014 16:24:09 -0400 Subject: Mirror fix on sqlite3 tag --- models/models.go | 6 +++++- models/models_sqlite.go | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'models/models.go') diff --git a/models/models.go b/models/models.go index 010228ae..b8374a3d 100644 --- a/models/models.go +++ b/models/models.go @@ -26,7 +26,8 @@ var ( Type, Host, Name, User, Pwd, Path, SslMode string } - UseSQLite3 bool + EnableSQLite3 bool + UseSQLite3 bool ) func init() { @@ -56,6 +57,9 @@ func NewTestEngine(x *xorm.Engine) (err error) { x, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s dbname=%s sslmode=%s", DbCfg.User, DbCfg.Pwd, DbCfg.Name, DbCfg.SslMode)) case "sqlite3": + if !EnableSQLite3 { + return fmt.Errorf("Unknown database type: %s", DbCfg.Type) + } os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm) x, err = xorm.NewEngine("sqlite3", DbCfg.Path) default: diff --git a/models/models_sqlite.go b/models/models_sqlite.go index 02c3f582..1d80823f 100644 --- a/models/models_sqlite.go +++ b/models/models_sqlite.go @@ -1,11 +1,15 @@ -// +build sqlite - // Copyright 2014 The Gogs Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. +// +build sqlite + package models import ( _ "github.com/mattn/go-sqlite3" ) + +func init() { + EnableSQLite3 = true +} -- cgit v1.2.3 From 90f6aa8cd19e489723ddffc40d6507782c29756c Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 12 Apr 2014 20:35:35 -0400 Subject: Add repo mirror and import --- README.md | 9 ++- README_ZH.md | 9 ++- gogs.go | 2 +- models/access.go | 2 +- models/models.go | 3 +- models/repo.go | 131 +++++++++++++++++++++++++++++++++++----- modules/auth/auth.go | 4 +- modules/auth/repo.go | 42 ++++++++++++- modules/middleware/repo.go | 24 -------- routers/repo/repo.go | 50 +++++++++------ routers/user/user.go | 14 +++++ templates/base/navbar.tmpl | 2 +- templates/repo/commits.tmpl | 2 +- templates/repo/diff.tmpl | 2 +- templates/repo/migrate.tmpl | 99 ++++++++++++++++++++++++++++++ templates/repo/mirror.tmpl | 81 ------------------------- templates/repo/nav.tmpl | 2 +- templates/repo/single_bare.tmpl | 14 ----- templates/user/dashboard.tmpl | 2 +- templates/user/profile.tmpl | 24 ++++---- web.go | 14 ++--- 21 files changed, 339 insertions(+), 193 deletions(-) create mode 100644 templates/repo/migrate.tmpl delete mode 100644 templates/repo/mirror.tmpl (limited to 'models/models.go') diff --git a/README.md b/README.md index d48c05c2..fa48027d 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 62996d4d..beb5a105 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 f726e809..a42d7225 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 5bf93f1b..f20f8fa7 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 b8374a3d..f1d43531 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 d01a716b..a2c63a50 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 4561dd83..7329cbdc 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 1c740bed..aa94058f 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 75d9f999..2a6d300e 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 3ffbde1a..f19ae02e 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 + } + + 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.Mirror", err) + 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 8585267a..e5328173 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 708a3976..cd3f2b83 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 68b14035..8125feda 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 796a8e94..f3d935ae 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/migrate.tmpl b/templates/repo/migrate.tmpl new file mode 100644 index 00000000..34a4077e --- /dev/null +++ b/templates/repo/migrate.tmpl @@ -0,0 +1,99 @@ +{{template "base/head" .}} +{{template "base/navbar" .}} +
+
+ {{.CsrfTokenHtml}} +

Repository Migration

+ {{template "base/alert" .}} + + +
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+
+ +
+

{{.SignedUserName}}

+ +
+
+ +
+ +
+ + Great repository names are short and memorable. +
+
+ +
+ +
+
+ +
+
+
+ +
+ +
+
+ +
+
+
+ +
+ +
+ +
+
+ +
+
+ + Cancel +
+
+
+
+{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/repo/mirror.tmpl b/templates/repo/mirror.tmpl deleted file mode 100644 index 0f10d1f5..00000000 --- a/templates/repo/mirror.tmpl +++ /dev/null @@ -1,81 +0,0 @@ -{{template "base/head" .}} -{{template "base/navbar" .}} -
-
- {{.CsrfTokenHtml}} -

Create Repository Mirror

- {{template "base/alert" .}} -
- -
- -
-
-
- -
- -
-
-
- -
-
- -
- -
-
-
- -
- -
-
-
-
-
-
- -
-

{{.SignedUserName}}

- -
-
- -
- -
- - Great repository names are short and memorable. -
-
- -
- -
-

Public

- -
-
- -
- -
- -
-
- -
-
- - Cancel -
-
-
-
-{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/repo/nav.tmpl b/templates/repo/nav.tmpl index f365ab64..f9f74dd1 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 7d7016e5..fc0a3bd9 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 efa78d88..167ae9ab 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 0cbd3489..255eb71c 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 de8e7250..a17be2a3 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)) -- cgit v1.2.3 From f644cefa865c04b440902695ba90114b224c640d Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 14 Apr 2014 01:57:25 -0400 Subject: Finish release --- models/models.go | 2 +- models/release.go | 83 +++++++++++++++++++++++++++ modules/auth/release.go | 50 +++++++++++++++++ modules/base/markdown.go | 4 ++ routers/repo/release.go | 133 +++++++++++++++++++++++++++++++++++++++++++- templates/release/list.tmpl | 56 +++++++++---------- templates/release/new.tmpl | 23 ++++---- web.go | 10 +++- 8 files changed, 313 insertions(+), 48 deletions(-) create mode 100644 models/release.go create mode 100644 modules/auth/release.go (limited to 'models/models.go') diff --git a/models/models.go b/models/models.go index f1d43531..0e20a1ab 100644 --- a/models/models.go +++ b/models/models.go @@ -33,7 +33,7 @@ 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(Mirror)) + new(Mirror), new(Release)) } func LoadModelsConfig() { diff --git a/models/release.go b/models/release.go new file mode 100644 index 00000000..08d74d3f --- /dev/null +++ b/models/release.go @@ -0,0 +1,83 @@ +// Copyright 2014 The Gogs 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 models + +import ( + "errors" + "strings" + "time" + + "github.com/Unknwon/com" + "github.com/gogits/git" +) + +var ( + ErrReleaseAlreadyExist = errors.New("Release already exist") +) + +// Release represents a release of repository. +type Release struct { + Id int64 + RepoId int64 + PublisherId int64 + Publisher *User `xorm:"-"` + Title string + TagName string + LowerTagName string + SHA1 string + NumCommits int + NumCommitsBehind int `xorm:"-"` + Note string `xorm:"TEXT"` + IsPrerelease bool + Created time.Time `xorm:"created"` +} + +// GetReleasesByRepoId returns a list of releases of repository. +func GetReleasesByRepoId(repoId int64) (rels []*Release, err error) { + err = orm.Desc("created").Find(&rels, Release{RepoId: repoId}) + return rels, err +} + +// IsReleaseExist returns true if release with given tag name already exists. +func IsReleaseExist(repoId int64, tagName string) (bool, error) { + if len(tagName) == 0 { + return false, nil + } + + return orm.Get(&Release{RepoId: repoId, LowerTagName: strings.ToLower(tagName)}) +} + +// CreateRelease creates a new release of repository. +func CreateRelease(repoPath string, rel *Release, gitRepo *git.Repository) error { + isExist, err := IsReleaseExist(rel.RepoId, rel.TagName) + if err != nil { + return err + } else if isExist { + return ErrReleaseAlreadyExist + } + + if !git.IsTagExist(repoPath, rel.TagName) { + _, stderr, err := com.ExecCmdDir(repoPath, "git", "tag", rel.TagName, "-m", "\""+rel.Title+"\"") + if err != nil { + return err + } else if strings.Contains(stderr, "fatal:") { + return errors.New(stderr) + } + } else { + commit, err := gitRepo.GetCommitOfTag(rel.TagName) + if err != nil { + return err + } + + rel.NumCommits, err = commit.CommitsCount() + if err != nil { + return err + } + } + + rel.LowerTagName = strings.ToLower(rel.TagName) + _, err = orm.InsertOne(rel) + return err +} diff --git a/modules/auth/release.go b/modules/auth/release.go new file mode 100644 index 00000000..a29028e0 --- /dev/null +++ b/modules/auth/release.go @@ -0,0 +1,50 @@ +// Copyright 2014 The Gogs 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 auth + +import ( + "net/http" + "reflect" + + "github.com/go-martini/martini" + + "github.com/gogits/gogs/modules/base" + "github.com/gogits/gogs/modules/log" +) + +type NewReleaseForm struct { + TagName string `form:"tag_name" binding:"Required"` + Title string `form:"title" binding:"Required"` + Content string `form:"content" binding:"Required"` + Prerelease bool `form:"prerelease"` +} + +func (f *NewReleaseForm) Name(field string) string { + names := map[string]string{ + "TagName": "Tag name", + "Title": "Release title", + "Content": "Release content", + } + return names[field] +} + +func (f *NewReleaseForm) Validate(errors *base.BindingErrors, 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("NewReleaseForm.Validate: %v", err) + } + return + } + + validate(errors, data, f) +} diff --git a/modules/base/markdown.go b/modules/base/markdown.go index cc180775..95b4b212 100644 --- a/modules/base/markdown.go +++ b/modules/base/markdown.go @@ -166,3 +166,7 @@ func RenderMarkdown(rawBytes []byte, urlPrefix string) []byte { // fmt.Println(string(body)) return body } + +func RenderMarkdownString(raw, urlPrefix string) string { + return string(RenderMarkdown([]byte(raw), urlPrefix)) +} diff --git a/routers/repo/release.go b/routers/repo/release.go index 3d549bf7..a4baa479 100644 --- a/routers/repo/release.go +++ b/routers/repo/release.go @@ -5,25 +5,152 @@ package repo import ( + "sort" + + "github.com/gogits/gogs/models" + "github.com/gogits/gogs/modules/auth" + "github.com/gogits/gogs/modules/base" + "github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/middleware" ) +type ReleaseSorter struct { + rels []*models.Release +} + +func (rs *ReleaseSorter) Len() int { + return len(rs.rels) +} + +func (rs *ReleaseSorter) Less(i, j int) bool { + return rs.rels[i].NumCommits > rs.rels[j].NumCommits +} + +func (rs *ReleaseSorter) Swap(i, j int) { + rs.rels[i], rs.rels[j] = rs.rels[j], rs.rels[i] +} + func Releases(ctx *middleware.Context) { ctx.Data["Title"] = "Releases" ctx.Data["IsRepoToolbarReleases"] = true ctx.Data["IsRepoReleaseNew"] = false - tags, err := ctx.Repo.GitRepo.GetTags() + rawTags, err := ctx.Repo.GitRepo.GetTags() + if err != nil { + ctx.Handle(500, "release.Releases(GetTags)", err) + return + } + + rels, err := models.GetReleasesByRepoId(ctx.Repo.Repository.Id) + if err != nil { + ctx.Handle(500, "release.Releases(GetReleasesByRepoId)", err) + return + } + + commitsCount, err := ctx.Repo.Commit.CommitsCount() if err != nil { - ctx.Handle(404, "repo.Releases(GetTags)", err) + ctx.Handle(500, "release.Releases(CommitsCount)", err) return } - ctx.Data["Releases"] = tags + + var tags ReleaseSorter + tags.rels = make([]*models.Release, len(rawTags)) + for i, rawTag := range rawTags { + for _, rel := range rels { + if rel.TagName == rawTag { + rel.Publisher, err = models.GetUserById(rel.PublisherId) + if err != nil { + ctx.Handle(500, "release.Releases(GetUserById)", err) + return + } + rel.NumCommitsBehind = commitsCount - rel.NumCommits + rel.Note = base.RenderMarkdownString(rel.Note, ctx.Repo.RepoLink) + tags.rels[i] = rel + break + } + } + + if tags.rels[i] == nil { + commit, err := ctx.Repo.GitRepo.GetCommitOfTag(rawTag) + if err != nil { + ctx.Handle(500, "release.Releases(GetCommitOfTag)", err) + return + } + + tags.rels[i] = &models.Release{ + Title: rawTag, + TagName: rawTag, + SHA1: commit.Id.String(), + } + tags.rels[i].NumCommits, err = ctx.Repo.GitRepo.CommitsCount(commit.Id.String()) + if err != nil { + ctx.Handle(500, "release.Releases(CommitsCount)", err) + return + } + tags.rels[i].NumCommitsBehind = commitsCount - tags.rels[i].NumCommits + tags.rels[i].Created = commit.Author.When + } + } + + sort.Sort(&tags) + + ctx.Data["Releases"] = tags.rels ctx.HTML(200, "release/list") } func ReleasesNew(ctx *middleware.Context) { + if !ctx.Repo.IsOwner { + ctx.Handle(404, "release.ReleasesNew", nil) + return + } + ctx.Data["Title"] = "New Release" ctx.Data["IsRepoToolbarReleases"] = true ctx.Data["IsRepoReleaseNew"] = true ctx.HTML(200, "release/new") } + +func ReleasesNewPost(ctx *middleware.Context, form auth.NewReleaseForm) { + if !ctx.Repo.IsOwner { + ctx.Handle(404, "release.ReleasesNew", nil) + return + } + + ctx.Data["Title"] = "New Release" + ctx.Data["IsRepoToolbarReleases"] = true + ctx.Data["IsRepoReleaseNew"] = true + + if ctx.HasError() { + ctx.HTML(200, "release/new") + return + } + + commitsCount, err := ctx.Repo.Commit.CommitsCount() + if err != nil { + ctx.Handle(500, "release.ReleasesNewPost(CommitsCount)", err) + return + } + + rel := &models.Release{ + RepoId: ctx.Repo.Repository.Id, + PublisherId: ctx.User.Id, + Title: form.Title, + TagName: form.TagName, + SHA1: ctx.Repo.Commit.Id.String(), + NumCommits: commitsCount, + Note: form.Content, + IsPrerelease: form.Prerelease, + } + + if err = models.CreateRelease(models.RepoPath(ctx.User.Name, ctx.Repo.Repository.Name), + rel, ctx.Repo.GitRepo); err != nil { + if err == models.ErrReleaseAlreadyExist { + ctx.RenderWithErr("Release with this tag name has already existed", "release/new", &form) + } else { + ctx.Handle(500, "release.ReleasesNewPost(IsReleaseExist)", err) + } + return + } + log.Trace("%s Release created: %s/%s:%s", ctx.Req.RequestURI, ctx.User.LowerName, ctx.Repo.Repository.Name, form.TagName) + + ctx.Redirect(ctx.Repo.RepoLink + "/releases") +} diff --git a/templates/release/list.tmpl b/templates/release/list.tmpl index 9541265c..dd37e9c1 100644 --- a/templates/release/list.tmpl +++ b/templates/release/list.tmpl @@ -10,50 +10,47 @@
- {{range .Releases}} - {{.}} - {{end}}
{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/release/new.tmpl b/templates/release/new.tmpl index fe5aa179..439496ea 100644 --- a/templates/release/new.tmpl +++ b/templates/release/new.tmpl @@ -5,30 +5,34 @@

New Release

-
+ {{template "base/alert" .}} + + {{.CsrfTokenHtml}}
- + @
-

Choose an existing tag without release notes

+

Choose an existing tag, or create a new tag on publish

- +
@@ -41,7 +45,7 @@
- +
loading...
@@ -50,15 +54,14 @@

We’ll point out that this release is identified as non-production ready.

- - +
diff --git a/web.go b/web.go index 268d9e71..04c41b9d 100644 --- a/web.go +++ b/web.go @@ -63,7 +63,7 @@ func runWeb(*cli.Context) { SignInRequire: base.Service.RequireSignInView, DisableCsrf: true, }) - + reqSignOut := middleware.Toggle(&middleware.ToggleOptions{SignOutRequire: true}) bindIgnErr := middleware.BindIgnErr @@ -153,13 +153,16 @@ func runWeb(*cli.Context) { 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.Get("/releases/new", repo.ReleasesNew) }, reqSignIn, middleware.RepoAssignment(true)) + m.Group("/:username/:reponame", func(r martini.Router) { + r.Post("/releases/new", bindIgnErr(auth.NewReleaseForm{}), repo.ReleasesNewPost) + }, reqSignIn, middleware.RepoAssignment(true, 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", repo.ReleasesNew) // TODO: r.Get("/pulls", repo.Pulls) r.Get("/branches", repo.Branches) }, ignSignIn, middleware.RepoAssignment(true)) @@ -172,6 +175,7 @@ func runWeb(*cli.Context) { r.Get("/commits/:branchname/search", repo.SearchCommits) r.Get("/commit/:branchname", repo.Diff) r.Get("/commit/:branchname/**", repo.Diff) + r.Get("/releases", repo.Releases) }, ignSignIn, middleware.RepoAssignment(true, true)) m.Group("/:username", func(r martini.Router) { -- cgit v1.2.3 From 6cee65db5a6e6ef7372f19d45c22a416e130afed Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 14 Apr 2014 14:49:50 +0800 Subject: bug fixed #76 --- models/models.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'models/models.go') diff --git a/models/models.go b/models/models.go index f1d43531..ab13548e 100644 --- a/models/models.go +++ b/models/models.go @@ -8,6 +8,7 @@ import ( "fmt" "os" "path" + "strings" _ "github.com/go-sql-driver/mysql" _ "github.com/lib/pq" @@ -55,8 +56,18 @@ func NewTestEngine(x *xorm.Engine) (err error) { x, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8", DbCfg.User, DbCfg.Pwd, DbCfg.Host, DbCfg.Name)) case "postgres": - x, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s dbname=%s sslmode=%s", - DbCfg.User, DbCfg.Pwd, DbCfg.Name, DbCfg.SslMode)) + var host, port = "127.0.0.1", "5432" + fields := strings.Split(DbCfg.Host, ":") + if len(fields) > 0 { + host = fields[0] + } + if len(fields) > 1 { + port = fields[1] + } + cnnstr := fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=%s", + DbCfg.User, DbCfg.Pwd, host, port, DbCfg.Name, DbCfg.SslMode) + //fmt.Println(cnnstr) + x, err = xorm.NewEngine("postgres", cnnstr) case "sqlite3": if !EnableSQLite3 { return fmt.Errorf("Unknown database type: %s", DbCfg.Type) -- cgit v1.2.3 From c36e7d322e74a55749ce2c2934c6fcfa82cff274 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 14 Apr 2014 04:11:33 -0400 Subject: Mirror updates --- models/models.go | 10 +++++++++- models/repo.go | 28 ++++++++++++++++------------ modules/base/conf.go | 6 +++--- routers/dashboard.go | 6 ++++++ templates/admin/dashboard.tmpl | 2 +- templates/base/head.tmpl | 1 + templates/home.tmpl | 19 +++++++++++++++++++ templates/user/profile.tmpl | 3 +-- 8 files changed, 56 insertions(+), 19 deletions(-) (limited to 'models/models.go') diff --git a/models/models.go b/models/models.go index 0e20a1ab..d4854895 100644 --- a/models/models.go +++ b/models/models.go @@ -120,7 +120,10 @@ func NewEngine() (err error) { type Statistic struct { Counter struct { - User, PublicKey, Repo, Watch, Action, Access int64 + User, PublicKey, Repo, + Watch, Action, Access, + Issue, Comment, + Mirror, Oauth, Release int64 } } @@ -131,5 +134,10 @@ func GetStatistic() (stats Statistic) { stats.Counter.Watch, _ = orm.Count(new(Watch)) stats.Counter.Action, _ = orm.Count(new(Action)) stats.Counter.Access, _ = orm.Count(new(Access)) + stats.Counter.Issue, _ = orm.Count(new(Issue)) + stats.Counter.Comment, _ = orm.Count(new(Comment)) + stats.Counter.Mirror, _ = orm.Count(new(Mirror)) + stats.Counter.Oauth, _ = orm.Count(new(Oauth2)) + stats.Counter.Release, _ = orm.Count(new(Release)) return } diff --git a/models/repo.go b/models/repo.go index bb0c164e..6943d05e 100644 --- a/models/repo.go +++ b/models/repo.go @@ -66,6 +66,7 @@ func NewRepoContext() { type Repository struct { Id int64 OwnerId int64 `xorm:"unique(s)"` + Owner *User `xorm:"-"` ForkId int64 LowerName string `xorm:"unique(s) index not null"` Name string `xorm:"index not null"` @@ -364,24 +365,21 @@ func initRepoCommit(tmpPath string, sig *git.Signature) (err error) { var stderr string if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "add", "--all"); err != nil { return err - } - if len(stderr) > 0 { - log.Trace("stderr(1): %s", stderr) + } else if strings.Contains(stderr, "fatal:") { + return errors.New("git add: " + stderr) } if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email), "-m", "Init commit"); err != nil { return err - } - if len(stderr) > 0 { - log.Trace("stderr(2): %s", stderr) + } else if strings.Contains(stderr, "fatal:") { + return errors.New("git commit: " + stderr) } if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "push", "origin", "master"); err != nil { return err - } - if len(stderr) > 0 { - log.Trace("stderr(3): %s", stderr) + } else if strings.Contains(stderr, "fatal:") { + return errors.New("git push: " + stderr) } return nil } @@ -439,9 +437,8 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep _, 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) + } else if strings.Contains(stderr, "fatal:") { + return errors.New("git clone: " + stderr) } // README @@ -725,6 +722,13 @@ func GetRepositories(user *User, private bool) ([]Repository, error) { return repos, err } +// GetRecentUpdatedRepositories returns the list of repositories that are recently updated. +func GetRecentUpdatedRepositories() (repos []*Repository, err error) { + err = orm.Where("is_private=?", false).Limit(5).Desc("updated").Find(&repos) + return repos, err +} + +// GetRepositoryCount returns the total number of repositories of user. func GetRepositoryCount(user *User) (int64, error) { return orm.Count(&Repository{OwnerId: user.Id}) } diff --git a/modules/base/conf.go b/modules/base/conf.go index 957ec57b..c5d73bbc 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -37,9 +37,9 @@ type OauthInfo struct { // Oauther represents oauth service. type Oauther struct { - GitHub, Google, Tencent bool - Twitter, Weibo bool - OauthInfos map[string]*OauthInfo + GitHub, Google, Tencent, + Twitter, Weibo bool + OauthInfos map[string]*OauthInfo } var ( diff --git a/routers/dashboard.go b/routers/dashboard.go index 2c81cf23..71bdcc9f 100644 --- a/routers/dashboard.go +++ b/routers/dashboard.go @@ -5,6 +5,7 @@ package routers import ( + "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/middleware" "github.com/gogits/gogs/routers/user" @@ -23,6 +24,11 @@ func Home(ctx *middleware.Context) { return } + repos, _ := models.GetRecentUpdatedRepositories() + for _, repo := range repos { + repo.Owner, _ = models.GetUserById(repo.OwnerId) + } + ctx.Data["Repos"] = repos ctx.Data["PageIsHome"] = true ctx.HTML(200, "home") } diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl index 2334c676..76539842 100644 --- a/templates/admin/dashboard.tmpl +++ b/templates/admin/dashboard.tmpl @@ -9,7 +9,7 @@
- Gogs database has {{.Stats.Counter.User}} users, {{.Stats.Counter.PublicKey}} SSH keys, {{.Stats.Counter.Repo}} repositories, {{.Stats.Counter.Watch}} watches, {{.Stats.Counter.Action}} actions, and {{.Stats.Counter.Access}} accesses. + Gogs database has {{.Stats.Counter.User}} users, {{.Stats.Counter.PublicKey}} SSH keys, {{.Stats.Counter.Repo}} repositories, {{.Stats.Counter.Watch}} watches, {{.Stats.Counter.Action}} actions, {{.Stats.Counter.Access}} accesses, {{.Stats.Counter.Issue}} issues, {{.Stats.Counter.Comment}} comments, {{.Stats.Counter.Mirror}} mirrors, {{.Stats.Counter.Oauth}} oauthes, {{.Stats.Counter.Release}} releases.
diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl index 68231391..109ddd35 100644 --- a/templates/base/head.tmpl +++ b/templates/base/head.tmpl @@ -10,6 +10,7 @@ {{if .Repository.IsGoget}}{{end}} + {{if IsProdMode}} diff --git a/templates/home.tmpl b/templates/home.tmpl index d3a8c0c3..5827f618 100644 --- a/templates/home.tmpl +++ b/templates/home.tmpl @@ -1,8 +1,27 @@ {{template "base/head" .}} {{template "base/navbar" .}}
+ {{if not .Repos}}

Hey there, welcome to the land of Gogs!

If you just get your Gogs server running, go install guide page will help you setup things for your first-time run.

+ {{else}} +

Hey there, welcome to the land of Gogs!

+
Here are some recent updated repositories:
+
+
    + {{range .Repos}} +
  • +
    {{.NumForks}}
    +

    + {{.Name}} +

    +

    {{.Description}}

    +
    Last updated {{.Updated|TimeSince}}
    +
  • + {{end}} +
+
+ {{end}}
{{template "base/footer" .}} diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl index a336bfb2..e80b2394 100644 --- a/templates/user/profile.tmpl +++ b/templates/user/profile.tmpl @@ -58,14 +58,13 @@
{{else}} - {{$owner := .Owner}}
    {{range .Repos}}
  • {{.NumForks}}

    - {{.Name}}{{if .IsPrivate}} Private{{end}} + {{.Name}}{{if .IsPrivate}} Private{{end}}

    {{.Description}}

    Last updated {{.Updated|TimeSince}}
    -- cgit v1.2.3 From caeddb79a339d8eaff78ac0212ac2959700d77de Mon Sep 17 00:00:00 2001 From: Christopher Brickley Date: Mon, 14 Apr 2014 21:07:21 -0400 Subject: update SetEngine for postgresql #76 --- models/models.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'models/models.go') diff --git a/models/models.go b/models/models.go index cd9dc38a..fe17229c 100644 --- a/models/models.go +++ b/models/models.go @@ -89,8 +89,16 @@ func SetEngine() (err error) { orm, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8", DbCfg.User, DbCfg.Pwd, DbCfg.Host, DbCfg.Name)) case "postgres": - orm, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s dbname=%s sslmode=%s", - DbCfg.User, DbCfg.Pwd, DbCfg.Name, DbCfg.SslMode)) + var host, port = "127.0.0.1", "5432" + fields := strings.Split(DbCfg.Host, ":") + if len(fields) > 0 { + host = fields[0] + } + if len(fields) > 1 { + port = fields[1] + } + orm, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=%s", + DbCfg.User, DbCfg.Pwd, host, port, DbCfg.Name, DbCfg.SslMode)) case "sqlite3": os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm) orm, err = xorm.NewEngine("sqlite3", DbCfg.Path) -- cgit v1.2.3 From f8571f4db1b0b8794fe1a7b614e35a5dd8b70f3e Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 17 Apr 2014 03:31:21 -0400 Subject: Bug fix on build tag --- models/models.go | 1 + 1 file changed, 1 insertion(+) (limited to 'models/models.go') diff --git a/models/models.go b/models/models.go index fe17229c..6c323684 100644 --- a/models/models.go +++ b/models/models.go @@ -11,6 +11,7 @@ import ( "strings" _ "github.com/go-sql-driver/mysql" + _ "github.com/gogits/cache" _ "github.com/lib/pq" "github.com/lunny/xorm" -- cgit v1.2.3 From 49c01c0b5748a5ab5529b39cd1e69b21eaf3091a Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 18 Apr 2014 09:35:09 -0400 Subject: Fix import path --- models/access.go | 2 +- models/models.go | 2 +- routers/install.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'models/models.go') diff --git a/models/access.go b/models/access.go index f20f8fa7..970f4a94 100644 --- a/models/access.go +++ b/models/access.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "github.com/lunny/xorm" + "github.com/go-xorm/xorm" ) // Access types. diff --git a/models/models.go b/models/models.go index 6c323684..1eb418ba 100644 --- a/models/models.go +++ b/models/models.go @@ -11,9 +11,9 @@ import ( "strings" _ "github.com/go-sql-driver/mysql" + "github.com/go-xorm/xorm" _ "github.com/gogits/cache" _ "github.com/lib/pq" - "github.com/lunny/xorm" "github.com/gogits/gogs/modules/base" ) diff --git a/routers/install.go b/routers/install.go index f0940137..81b16403 100644 --- a/routers/install.go +++ b/routers/install.go @@ -12,7 +12,7 @@ import ( "github.com/Unknwon/goconfig" "github.com/go-martini/martini" - "github.com/lunny/xorm" + "github.com/go-xorm/xorm" qlog "github.com/qiniu/log" "github.com/gogits/gogs/models" -- cgit v1.2.3 From ea29a9b84631b03ee2f60ffa85fd9e402ceaf8a4 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 21 Apr 2014 02:24:35 -0400 Subject: API fix --- conf/app.ini | 2 +- conf/gitignore/Android | 23 +++++++++++++++++++++++ gogs.go | 2 +- models/models.go | 2 +- 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 conf/gitignore/Android (limited to 'models/models.go') diff --git a/conf/app.ini b/conf/app.ini index 2aab7178..7dbbf600 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -9,7 +9,7 @@ RUN_MODE = dev [repository] ROOT = SCRIPT_TYPE = bash -LANG_IGNS = Google Go|C|C++|Python|Ruby|C Sharp|Java|Objective-C +LANG_IGNS = Google Go|C|C++|Python|Ruby|C Sharp|Java|Objective-C|Android LICENSES = Apache v2 License|GPL v2|MIT License|Affero GPL|Artistic License 2.0|BSD (3-Clause) License [server] diff --git a/conf/gitignore/Android b/conf/gitignore/Android new file mode 100644 index 00000000..37e8cf6c --- /dev/null +++ b/conf/gitignore/Android @@ -0,0 +1,23 @@ +# Built application files +*.apk +*.ap_ + +# Files for the Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ \ No newline at end of file diff --git a/gogs.go b/gogs.go index c9d78acb..73555ada 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.3.0.0420 Alpha" +const APP_VER = "0.3.0.0421 Alpha" func init() { base.AppVer = APP_VER diff --git a/models/models.go b/models/models.go index 1eb418ba..216084f1 100644 --- a/models/models.go +++ b/models/models.go @@ -120,7 +120,7 @@ func SetEngine() (err error) { if err != nil { return fmt.Errorf("models.init(fail to create xorm.log): %v", err) } - orm.Logger = f + orm.Logger = xorm.NewSimpleLogger(f) orm.ShowSQL = true orm.ShowDebug = true -- cgit v1.2.3 From de01f814892666298d24f79f769a7c0766119c87 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 21 Apr 2014 06:54:07 -0400 Subject: Prepare for v0.3.0 release --- models/models.go | 1 - modules/base/base_memcache.go | 11 +++++++++++ modules/base/base_redis.go | 11 +++++++++++ modules/base/conf.go | 7 +++++-- 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 modules/base/base_memcache.go create mode 100644 modules/base/base_redis.go (limited to 'models/models.go') diff --git a/models/models.go b/models/models.go index 216084f1..8e8835ab 100644 --- a/models/models.go +++ b/models/models.go @@ -12,7 +12,6 @@ import ( _ "github.com/go-sql-driver/mysql" "github.com/go-xorm/xorm" - _ "github.com/gogits/cache" _ "github.com/lib/pq" "github.com/gogits/gogs/modules/base" diff --git a/modules/base/base_memcache.go b/modules/base/base_memcache.go new file mode 100644 index 00000000..93ca93a4 --- /dev/null +++ b/modules/base/base_memcache.go @@ -0,0 +1,11 @@ +// +build memcache + +package base + +import ( + _ "github.com/gogits/cache/memcache" +) + +func init() { + EnableMemcache = true +} diff --git a/modules/base/base_redis.go b/modules/base/base_redis.go new file mode 100644 index 00000000..327af841 --- /dev/null +++ b/modules/base/base_redis.go @@ -0,0 +1,11 @@ +// +build redis + +package base + +import ( + _ "github.com/gogits/cache/redis" +) + +func init() { + EnableRedis = true +} diff --git a/modules/base/conf.go b/modules/base/conf.go index 720b8610..48ba4658 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -77,6 +77,9 @@ var ( SessionManager *session.Manager PictureService string + + EnableRedis bool + EnableMemcache bool ) var Service struct { @@ -174,10 +177,10 @@ func newLogService() { func newCacheService() { CacheAdapter = Cfg.MustValue("cache", "ADAPTER", "memory") - if cache.EnableRedis { + if EnableRedis { log.Info("Redis Enabled") } - if cache.EnableMemcache { + if EnableMemcache { log.Info("Memcache Enabled") } -- cgit v1.2.3