diff --git a/.gitignore b/.gitignore
index cd9109b8d..158421d04 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,3 @@
-<<<<<<< HEAD
-
-
-gogs
-*.exe
-*.exe~
.DS_Store
*.db
*.log
@@ -14,8 +8,6 @@ data/
*.iml
public/img/avatar/
-=======
->>>>>>> b4db9f67548a41922f1b337daf9c9d2b975b55c4
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
@@ -37,4 +29,7 @@ _cgo_export.*
_testmain.go
-*.exe
\ No newline at end of file
+*.exe
+*.exe~
+gogs
+__pycache__
diff --git a/.gobuild.yml b/.gobuild.yml
index 78a38f2d3..d5bc6606c 100644
--- a/.gobuild.yml
+++ b/.gobuild.yml
@@ -5,4 +5,6 @@ filesets:
- conf
- LICENSE
- README.md
- - README_ZH.md
\ No newline at end of file
+ - README_ZH.md
+ - start.bat
+ - start.sh
diff --git a/README.md b/README.md
index 7d688506d..1d3aaf3e8 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,9 @@ 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.1.9 Alpha
+##### Current version: 0.2.0 Alpha
+
+#### Due to testing purpose, data of [try.gogits.org](http://try.gogits.org) has been reset in March 29, 2014 and will reset multiple times after. Please do NOT put your important data on the site.
#### Other language version
diff --git a/README_ZH.md b/README_ZH.md
index 8e187c736..4590e36b1 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.1.9 Alpha
+##### 当前版本:0.2.0 Alpha
## 开发目的
diff --git a/conf/app.ini b/conf/app.ini
index a3c749be0..abc27c39c 100644
--- a/conf/app.ini
+++ b/conf/app.ini
@@ -7,7 +7,7 @@ RUN_USER = git
RUN_MODE = dev
[repository]
-ROOT = /Users/%(RUN_USER)s/git/gogs-repositories
+ROOT =
LANG_IGNS = Google Go|C|C++|Python|Ruby|C Sharp
LICENSES = Apache v2 License|GPL v2|MIT License|Affero GPL|Artistic License 2.0|BSD (3-Clause) License
@@ -20,7 +20,7 @@ HTTP_PORT = 3000
[database]
; Either "mysql", "postgres" or "sqlite3"(binary release only), it's your choice
DB_TYPE = mysql
-HOST =
+HOST = 127.0.0.1:3306
NAME = gogs
USER = root
PASSWD =
diff --git a/conf/mysql.sql b/conf/mysql.sql
new file mode 100644
index 000000000..6247d657b
--- /dev/null
+++ b/conf/mysql.sql
@@ -0,0 +1,2 @@
+DROP DATABASE gogs;
+CREATE DATABASE IF NOT EXISTS gogs CHARACTER SET utf8 COLLATE utf8_general_ci;
\ No newline at end of file
diff --git a/gogs.go b/gogs.go
index f4b7c72fe..bbd654212 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.1.9.0328 Alpha"
+const APP_VER = "0.2.0.0330 Alpha"
func init() {
base.AppVer = APP_VER
diff --git a/models/access.go b/models/access.go
index 84cad17a3..42fccae05 100644
--- a/models/access.go
+++ b/models/access.go
@@ -26,6 +26,8 @@ type Access struct {
// AddAccess adds new access record.
func AddAccess(access *Access) error {
+ access.UserName = strings.ToLower(access.UserName)
+ access.RepoName = strings.ToLower(access.RepoName)
_, err := orm.Insert(access)
return err
}
diff --git a/models/action.go b/models/action.go
index 9d99df854..1e55df85e 100644
--- a/models/action.go
+++ b/models/action.go
@@ -31,6 +31,7 @@ type Action struct {
OpType int // Operations: CREATE DELETE STAR ...
ActUserId int64 // Action user id.
ActUserName string // Action user name.
+ ActEmail string
RepoId int64
RepoName string
RefName string
@@ -46,6 +47,10 @@ func (a Action) GetActUserName() string {
return a.ActUserName
}
+func (a Action) GetActEmail() string {
+ return a.ActEmail
+}
+
func (a Action) GetRepoName() string {
return a.RepoName
}
@@ -59,7 +64,7 @@ func (a Action) GetContent() string {
}
// CommitRepoAction adds new action for committing repository.
-func CommitRepoAction(userId int64, userName string,
+func CommitRepoAction(userId int64, userName, actEmail string,
repoId int64, repoName string, refName string, commit *base.PushCommits) error {
log.Trace("action.CommitRepoAction(start): %d/%s", userId, repoName)
@@ -69,8 +74,8 @@ func CommitRepoAction(userId int64, userName string,
return err
}
- if err = NotifyWatchers(&Action{ActUserId: userId, ActUserName: userName, OpType: OP_COMMIT_REPO,
- Content: string(bs), RepoId: repoId, RepoName: repoName, RefName: refName}); err != nil {
+ if err = NotifyWatchers(&Action{ActUserId: userId, ActUserName: userName, ActEmail: actEmail,
+ OpType: OP_COMMIT_REPO, Content: string(bs), RepoId: repoId, RepoName: repoName, RefName: refName}); err != nil {
log.Error("action.CommitRepoAction(notify watchers): %d/%s", userId, repoName)
return err
}
@@ -93,8 +98,8 @@ func CommitRepoAction(userId int64, userName string,
// NewRepoAction adds new action for creating repository.
func NewRepoAction(user *User, repo *Repository) (err error) {
- if err = NotifyWatchers(&Action{ActUserId: user.Id, ActUserName: user.Name, OpType: OP_CREATE_REPO,
- RepoId: repo.Id, RepoName: repo.Name}); err != nil {
+ if err = NotifyWatchers(&Action{ActUserId: user.Id, ActUserName: user.Name, ActEmail: user.Email,
+ OpType: OP_CREATE_REPO, RepoId: repo.Id, RepoName: repo.Name}); err != nil {
log.Error("action.NewRepoAction(notify watchers): %d/%s", user.Id, repo.Name)
return err
}
diff --git a/models/git.go b/models/git.go
index 34f0267f6..d3bad6e0c 100644
--- a/models/git.go
+++ b/models/git.go
@@ -70,9 +70,12 @@ func GetTargetFile(userName, repoName, branchName, commitId, rpath string) (*Rep
return nil, err
}
- commit, err := repo.GetCommit(branchName, commitId)
+ commit, err := repo.GetCommitOfBranch(branchName)
if err != nil {
- return nil, err
+ commit, err = repo.GetCommit(commitId)
+ if err != nil {
+ return nil, err
+ }
}
parts := strings.Split(path.Clean(rpath), "/")
@@ -110,13 +113,22 @@ func GetTargetFile(userName, repoName, branchName, commitId, rpath string) (*Rep
}
// GetReposFiles returns a list of file object in given directory of repository.
-func GetReposFiles(userName, repoName, branchName, commitId, rpath string) ([]*RepoFile, error) {
+// func GetReposFilesOfBranch(userName, repoName, branchName, rpath string) ([]*RepoFile, error) {
+// return getReposFiles(userName, repoName, commitId, rpath)
+// }
+
+// GetReposFiles returns a list of file object in given directory of repository.
+func GetReposFiles(userName, repoName, commitId, rpath string) ([]*RepoFile, error) {
+ return getReposFiles(userName, repoName, commitId, rpath)
+}
+
+func getReposFiles(userName, repoName, commitId string, rpath string) ([]*RepoFile, error) {
repo, err := git.OpenRepository(RepoPath(userName, repoName))
if err != nil {
return nil, err
}
- commit, err := repo.GetCommit(branchName, commitId)
+ commit, err := repo.GetCommit(commitId)
if err != nil {
return nil, err
}
@@ -216,13 +228,13 @@ func GetReposFiles(userName, repoName, branchName, commitId, rpath string) ([]*R
return append(repodirs, repofiles...), nil
}
-func GetCommit(userName, repoName, branchname, commitid string) (*git.Commit, error) {
+func GetCommit(userName, repoName, commitId string) (*git.Commit, error) {
repo, err := git.OpenRepository(RepoPath(userName, repoName))
if err != nil {
return nil, err
}
- return repo.GetCommit(branchname, commitid)
+ return repo.GetCommit(commitId)
}
// GetCommitsByBranch returns all commits of given branch of repository.
@@ -397,7 +409,7 @@ func GetDiff(repoPath, commitid string) (*Diff, error) {
return nil, err
}
- commit, err := repo.GetCommit("", commitid)
+ commit, err := repo.GetCommit(commitid)
if err != nil {
return nil, err
}
diff --git a/models/issue.go b/models/issue.go
index 39558ae22..f14030df5 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -18,23 +18,24 @@ var (
// Issue represents an issue or pull request of repository.
type Issue struct {
- Id int64
- Index int64 // Index in one repository.
- Name string
- RepoId int64 `xorm:"index"`
- Repo *Repository `xorm:"-"`
- PosterId int64
- Poster *User `xorm:"-"`
- MilestoneId int64
- AssigneeId int64
- IsPull bool // Indicates whether is a pull request or not.
- IsClosed bool
- Labels string `xorm:"TEXT"`
- Mentions string `xorm:"TEXT"`
- Content string `xorm:"TEXT"`
- NumComments int
- Created time.Time `xorm:"created"`
- Updated time.Time `xorm:"updated"`
+ Id int64
+ Index int64 // Index in one repository.
+ Name string
+ RepoId int64 `xorm:"index"`
+ Repo *Repository `xorm:"-"`
+ PosterId int64
+ Poster *User `xorm:"-"`
+ MilestoneId int64
+ AssigneeId int64
+ IsPull bool // Indicates whether is a pull request or not.
+ IsClosed bool
+ Labels string `xorm:"TEXT"`
+ Mentions string `xorm:"TEXT"`
+ Content string `xorm:"TEXT"`
+ RenderedContent string `xorm:"-"`
+ NumComments int
+ Created time.Time `xorm:"created"`
+ Updated time.Time `xorm:"updated"`
}
// CreateIssue creates new issue for repository.
@@ -169,9 +170,17 @@ type Milestone struct {
Created time.Time `xorm:"created"`
}
+// Issue types.
+const (
+ IT_PLAIN = iota // Pure comment.
+ IT_REOPEN // Issue reopen status change prompt.
+ IT_CLOSE // Issue close status change prompt.
+)
+
// Comment represents a comment in commit and issue page.
type Comment struct {
Id int64
+ Type int
PosterId int64
Poster *User `xorm:"-"`
IssueId int64
@@ -182,21 +191,37 @@ type Comment struct {
}
// CreateComment creates comment of issue or commit.
-func CreateComment(userId, issueId, commitId, line int64, content string) error {
+func CreateComment(userId, repoId, issueId, commitId, line int64, cmtType int, content string) error {
sess := orm.NewSession()
defer sess.Close()
sess.Begin()
- if _, err := orm.Insert(&Comment{PosterId: userId, IssueId: issueId,
+ if _, err := orm.Insert(&Comment{PosterId: userId, Type: cmtType, IssueId: issueId,
CommitId: commitId, Line: line, Content: content}); err != nil {
sess.Rollback()
return err
}
- rawSql := "UPDATE `issue` SET num_comments = num_comments + 1 WHERE id = ?"
- if _, err := sess.Exec(rawSql, issueId); err != nil {
- sess.Rollback()
- return err
+ // Check comment type.
+ switch cmtType {
+ case IT_PLAIN:
+ rawSql := "UPDATE `issue` SET num_comments = num_comments + 1 WHERE id = ?"
+ if _, err := sess.Exec(rawSql, issueId); err != nil {
+ sess.Rollback()
+ return err
+ }
+ case IT_REOPEN:
+ rawSql := "UPDATE `repository` SET num_closed_issues = num_closed_issues - 1 WHERE id = ?"
+ if _, err := sess.Exec(rawSql, repoId); err != nil {
+ sess.Rollback()
+ return err
+ }
+ case IT_CLOSE:
+ rawSql := "UPDATE `repository` SET num_closed_issues = num_closed_issues + 1 WHERE id = ?"
+ if _, err := sess.Exec(rawSql, repoId); err != nil {
+ sess.Rollback()
+ return err
+ }
}
return sess.Commit()
}
diff --git a/models/models.go b/models/models.go
index 04a361c59..a626b98f6 100644
--- a/models/models.go
+++ b/models/models.go
@@ -12,20 +12,27 @@ 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"
)
var (
- orm *xorm.Engine
+ orm *xorm.Engine
+ HasEngine bool
DbCfg struct {
Type, Host, Name, User, Pwd, Path, SslMode string
}
+
+ UseSQLite3 bool
)
func LoadModelsConfig() {
DbCfg.Type = base.Cfg.MustValue("database", "DB_TYPE")
+ if DbCfg.Type == "sqlite3" {
+ UseSQLite3 = true
+ }
DbCfg.Host = base.Cfg.MustValue("database", "HOST")
DbCfg.Name = base.Cfg.MustValue("database", "NAME")
DbCfg.User = base.Cfg.MustValue("database", "USER")
@@ -34,11 +41,32 @@ func LoadModelsConfig() {
DbCfg.Path = base.Cfg.MustValue("database", "PATH", "data/gogs.db")
}
-func SetEngine() {
- var err error
+func NewTestEngine(x *xorm.Engine) (err error) {
switch DbCfg.Type {
case "mysql":
- orm, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@%s/%s?charset=utf8",
+ 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))
+ // 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\n", DbCfg.Type)
+ }
+ 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))
+}
+
+func SetEngine() (err error) {
+ switch DbCfg.Type {
+ case "mysql":
+ 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",
@@ -47,12 +75,10 @@ func SetEngine() {
os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm)
orm, err = xorm.NewEngine("sqlite3", DbCfg.Path)
default:
- fmt.Printf("Unknown database type: %s\n", DbCfg.Type)
- os.Exit(2)
+ return fmt.Errorf("Unknown database type: %s\n", DbCfg.Type)
}
if err != nil {
- fmt.Printf("models.init(fail to conntect database): %v\n", err)
- os.Exit(2)
+ return fmt.Errorf("models.init(fail to conntect database): %v\n", err)
}
// WARNNING: for serv command, MUST remove the output to os.stdout,
@@ -62,20 +88,21 @@ func SetEngine() {
//orm.ShowErr = true
f, err := os.Create("xorm.log")
if err != nil {
- fmt.Printf("models.init(fail to create xorm.log): %v\n", err)
- os.Exit(2)
+ return fmt.Errorf("models.init(fail to create xorm.log): %v\n", err)
}
orm.Logger = f
orm.ShowSQL = true
+ return nil
}
-func NewEngine() {
- SetEngine()
- if err := orm.Sync(new(User), new(PublicKey), new(Repository), new(Watch),
+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 {
- fmt.Printf("sync database struct error: %v\n", err)
- os.Exit(2)
+ return fmt.Errorf("sync database struct error: %v\n", err)
}
+ return nil
}
type Statistic struct {
diff --git a/models/repo.go b/models/repo.go
index 4be655d28..0c808f184 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -10,8 +10,8 @@ import (
"io/ioutil"
"os"
"os/exec"
+ "path"
"path/filepath"
- "regexp"
"strings"
"time"
"unicode/utf8"
@@ -59,15 +59,6 @@ func NewRepoContext() {
os.Exit(2)
}
}
-
- // Initialize illegal patterns.
- for i := range illegalPatterns[1:] {
- pattern := ""
- for j := range illegalPatterns[i+1] {
- pattern += "[" + string(illegalPatterns[i+1][j]-32) + string(illegalPatterns[i+1][j]) + "]"
- }
- illegalPatterns[i+1] = pattern
- }
}
// Repository represents a git repository.
@@ -105,15 +96,20 @@ func IsRepositoryExist(user *User, repoName string) (bool, error) {
}
var (
- // Define as all lower case!!
- illegalPatterns = []string{"[.][Gg][Ii][Tt]", "raw", "user", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin"}
+ illegalEquals = []string{"raw", "install", "api", "avatar", "user", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin"}
+ illegalSuffixs = []string{".git"}
)
// IsLegalName returns false if name contains illegal characters.
func IsLegalName(repoName string) bool {
- for _, pattern := range illegalPatterns {
- has, _ := regexp.MatchString(pattern, repoName)
- if has {
+ repoName = strings.ToLower(repoName)
+ for _, char := range illegalEquals {
+ if repoName == char {
+ return false
+ }
+ }
+ for _, char := range illegalSuffixs {
+ if strings.HasSuffix(repoName, char) {
return false
}
}
@@ -161,8 +157,8 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv
}
access := Access{
- UserName: user.Name,
- RepoName: repo.Name,
+ UserName: user.LowerName,
+ RepoName: strings.ToLower(path.Join(user.Name, repo.Name)),
Mode: AU_WRITABLE,
}
if _, err = session.Insert(&access); err != nil {
@@ -198,12 +194,19 @@ func CreateRepository(user *User, repoName, desc, repoLang, license string, priv
c := exec.Command("git", "update-server-info")
c.Dir = repoPath
- err = c.Run()
- if err != nil {
+ if err = c.Run(); err != nil {
log.Error("repo.CreateRepository(exec update-server-info): %v", err)
}
- return repo, NewRepoAction(user, repo)
+ if err = NewRepoAction(user, repo); err != nil {
+ log.Error("repo.CreateRepository(NewRepoAction): %v", err)
+ }
+
+ if err = WatchRepo(user.Id, repo.Id, true); err != nil {
+ log.Error("repo.CreateRepository(WatchRepo): %v", err)
+ }
+
+ return repo, nil
}
// extractGitBareZip extracts git-bare.zip to repository path.
@@ -362,7 +365,7 @@ func GetRepos(num, offset int) ([]UserRepo, error) {
}
func RepoPath(userName, repoName string) string {
- return filepath.Join(UserPath(userName), repoName+".git")
+ return filepath.Join(UserPath(userName), strings.ToLower(repoName)+".git")
}
func UpdateRepository(repo *Repository) error {
@@ -395,7 +398,7 @@ func DeleteRepository(userId, repoId int64, userName string) (err error) {
session.Rollback()
return err
}
- if _, err := session.Delete(&Access{UserName: userName, RepoName: repo.Name}); err != nil {
+ if _, err := session.Delete(&Access{RepoName: strings.ToLower(path.Join(userName, repo.Name))}); err != nil {
session.Rollback()
return err
}
@@ -510,7 +513,6 @@ func NotifyWatchers(act *Action) error {
continue
}
- act.Id = 0
act.UserId = watches[i].UserId
if _, err = orm.InsertOne(act); err != nil {
return errors.New("repo.NotifyWatchers(create action): " + err.Error())
diff --git a/models/user.go b/models/user.go
index 6ca16ec32..4908552f2 100644
--- a/models/user.go
+++ b/models/user.go
@@ -39,6 +39,7 @@ var (
ErrUserNotExist = errors.New("User does not exist")
ErrEmailAlreadyUsed = errors.New("E-mail already used")
ErrUserNameIllegal = errors.New("User name contains illegal characters")
+ ErrKeyNotExist = errors.New("Public key does not exist")
)
// User represents the object of individual and member of organization.
@@ -67,7 +68,7 @@ type User struct {
// HomeLink returns the user home page link.
func (user *User) HomeLink() string {
- return "/user/" + user.LowerName
+ return "/user/" + user.Name
}
// AvatarLink returns the user gravatar link.
diff --git a/modules/auth/admin.go b/modules/auth/admin.go
index eccab0071..fe889c238 100644
--- a/modules/auth/admin.go
+++ b/modules/auth/admin.go
@@ -8,7 +8,7 @@ import (
"net/http"
"reflect"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/binding"
diff --git a/modules/auth/auth.go b/modules/auth/auth.go
index 2e0555f6d..4561dd831 100644
--- a/modules/auth/auth.go
+++ b/modules/auth/auth.go
@@ -9,7 +9,7 @@ import (
"reflect"
"strings"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/binding"
@@ -161,3 +161,54 @@ func AssignForm(form interface{}, data base.TmplData) {
data[fieldName] = val.Field(i).Interface()
}
}
+
+type InstallForm struct {
+ Database string `form:"database" binding:"Required"`
+ Host string `form:"host"`
+ User string `form:"user"`
+ Passwd string `form:"passwd"`
+ DatabaseName string `form:"database_name"`
+ SslMode string `form:"ssl_mode"`
+ DatabasePath string `form:"database_path"`
+ RepoRootPath string `form:"repo_path"`
+ RunUser string `form:"run_user"`
+ Domain string `form:"domain"`
+ AppUrl string `form:"app_url"`
+ AdminName string `form:"admin_name" binding:"Required"`
+ AdminPasswd string `form:"admin_pwd" binding:"Required;MinSize(6);MaxSize(30)"`
+ AdminEmail string `form:"admin_email" binding:"Required;Email;MaxSize(50)"`
+ SmtpHost string `form:"smtp_host"`
+ SmtpEmail string `form:"mailer_user"`
+ SmtpPasswd string `form:"mailer_pwd"`
+ RegisterConfirm string `form:"register_confirm"`
+ MailNotify string `form:"mail_notify"`
+}
+
+func (f *InstallForm) Name(field string) string {
+ names := map[string]string{
+ "Database": "Database name",
+ "AdminName": "Admin user name",
+ "AdminPasswd": "Admin password",
+ "AdminEmail": "Admin e-maill address",
+ }
+ return names[field]
+}
+
+func (f *InstallForm) 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("InstallForm.Validate: %v", err)
+ }
+ return
+ }
+
+ validate(errors, data, f)
+}
diff --git a/modules/auth/issue.go b/modules/auth/issue.go
index 8bf49684c..36c876279 100644
--- a/modules/auth/issue.go
+++ b/modules/auth/issue.go
@@ -8,7 +8,7 @@ import (
"net/http"
"reflect"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/binding"
diff --git a/modules/auth/repo.go b/modules/auth/repo.go
index 2cc93744c..eddd64752 100644
--- a/modules/auth/repo.go
+++ b/modules/auth/repo.go
@@ -8,7 +8,7 @@ import (
"net/http"
"reflect"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/binding"
diff --git a/modules/auth/setting.go b/modules/auth/setting.go
index 0bc6afd4a..cada7eea6 100644
--- a/modules/auth/setting.go
+++ b/modules/auth/setting.go
@@ -9,7 +9,7 @@ import (
"reflect"
"strings"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/binding"
diff --git a/modules/auth/user.go b/modules/auth/user.go
index cb8db1b29..2d3c29fde 100644
--- a/modules/auth/user.go
+++ b/modules/auth/user.go
@@ -8,11 +8,10 @@ import (
"net/http"
"reflect"
- "github.com/codegangsta/martini"
-
- "github.com/gogits/session"
+ "github.com/go-martini/martini"
"github.com/gogits/binding"
+ "github.com/gogits/session"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/base"
@@ -21,6 +20,10 @@ import (
// SignedInId returns the id of signed in user.
func SignedInId(session session.SessionStore) int64 {
+ if !models.HasEngine {
+ return 0
+ }
+
userId := session.Get("userId")
if userId == nil {
return 0
diff --git a/modules/base/conf.go b/modules/base/conf.go
index b3a987e64..3ebc4ede1 100644
--- a/modules/base/conf.go
+++ b/modules/base/conf.go
@@ -212,9 +212,9 @@ func newMailService() {
if Cfg.MustBool("mailer", "ENABLED") {
MailService = &Mailer{
Name: Cfg.MustValue("mailer", "NAME", AppName),
- Host: Cfg.MustValue("mailer", "HOST", "127.0.0.1:25"),
- User: Cfg.MustValue("mailer", "USER", "example@example.com"),
- Passwd: Cfg.MustValue("mailer", "PASSWD", "******"),
+ Host: Cfg.MustValue("mailer", "HOST"),
+ User: Cfg.MustValue("mailer", "USER"),
+ Passwd: Cfg.MustValue("mailer", "PASSWD"),
}
log.Info("Mail Service Enabled")
}
@@ -253,7 +253,7 @@ func NewConfigContext() {
cfgPath := filepath.Join(workDir, "conf/app.ini")
Cfg, err = goconfig.LoadConfigFile(cfgPath)
if err != nil {
- fmt.Printf("Cannot load config file '%s'\n", cfgPath)
+ fmt.Printf("Cannot load config file(%s): %v\n", cfgPath, err)
os.Exit(2)
}
Cfg.BlockMode = false
@@ -261,7 +261,7 @@ func NewConfigContext() {
cfgPath = filepath.Join(workDir, "custom/conf/app.ini")
if com.IsFile(cfgPath) {
if err = Cfg.AppendFiles(cfgPath); err != nil {
- fmt.Printf("Cannot load config file '%s'\n", cfgPath)
+ fmt.Printf("Cannot load config file(%s): %v\n", cfgPath, err)
os.Exit(2)
}
}
@@ -272,18 +272,19 @@ func NewConfigContext() {
Domain = Cfg.MustValue("server", "DOMAIN")
SecretKey = Cfg.MustValue("security", "SECRET_KEY")
+ InstallLock = Cfg.MustBool("security", "INSTALL_LOCK", false)
+
RunUser = Cfg.MustValue("", "RUN_USER")
curUser := os.Getenv("USERNAME")
if len(curUser) == 0 {
curUser = os.Getenv("USER")
}
- if RunUser != curUser {
+ // Does not check run user when the install lock is off.
+ if InstallLock && RunUser != curUser {
fmt.Printf("Expect user(%s) but current user is: %s\n", RunUser, curUser)
os.Exit(2)
}
- InstallLock = Cfg.MustBool("security", "INSTALL_LOCK", false)
-
LogInRememberDays = Cfg.MustInt("security", "LOGIN_REMEMBER_DAYS")
CookieUserName = Cfg.MustValue("security", "COOKIE_USERNAME")
CookieRememberName = Cfg.MustValue("security", "COOKIE_REMEMBER_NAME")
@@ -291,9 +292,14 @@ func NewConfigContext() {
PictureService = Cfg.MustValue("picture", "SERVICE")
// Determine and create root git reposiroty path.
- RepoRootPath = Cfg.MustValue("repository", "ROOT")
+ homeDir, err := com.HomeDir()
+ if err != nil {
+ fmt.Printf("Fail to get home directory): %v\n", err)
+ os.Exit(2)
+ }
+ RepoRootPath = Cfg.MustValue("repository", "ROOT", filepath.Join(homeDir, "git/gogs-repositories"))
if err = os.MkdirAll(RepoRootPath, os.ModePerm); err != nil {
- fmt.Printf("models.init(fail to create RepoRootPath(%s)): %v\n", RepoRootPath, err)
+ fmt.Printf("Fail to create RepoRootPath(%s): %v\n", RepoRootPath, err)
os.Exit(2)
}
}
diff --git a/modules/base/template.go b/modules/base/template.go
index dca76fafd..dfcae9314 100644
--- a/modules/base/template.go
+++ b/modules/base/template.go
@@ -33,6 +33,13 @@ func List(l *list.List) chan interface{} {
return c
}
+func ShortSha(sha1 string) string {
+ if len(sha1) == 40 {
+ return sha1[:10]
+ }
+ return sha1
+}
+
var mailDomains = map[string]string{
"gmail.com": "gmail.com",
}
@@ -72,4 +79,5 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{
},
"DiffTypeToStr": DiffTypeToStr,
"DiffLineTypeToStr": DiffLineTypeToStr,
+ "ShortSha": ShortSha,
}
diff --git a/modules/base/tool.go b/modules/base/tool.go
index 9ddb90f72..6876da762 100644
--- a/modules/base/tool.go
+++ b/modules/base/tool.go
@@ -478,6 +478,7 @@ func (a argInt) Get(i int, args ...int) (r int) {
type Actioner interface {
GetOpType() int
GetActUserName() string
+ GetActEmail() string
GetRepoName() string
GetBranch() string
GetContent() string
@@ -506,15 +507,23 @@ const (
![user-avatar](%s?s=16)
%s
`
)
+type PushCommit struct {
+ Sha1 string
+ Message string
+ AuthorEmail string
+ AuthorName string
+}
+
type PushCommits struct {
Len int
- Commits [][]string
+ Commits []*PushCommit
}
// ActionDesc accepts int that represents action operation type
// and returns the description.
-func ActionDesc(act Actioner, avatarLink string) string {
+func ActionDesc(act Actioner) string {
actUserName := act.GetActUserName()
+ email := act.GetActEmail()
repoName := act.GetRepoName()
repoLink := actUserName + "/" + repoName
branch := act.GetBranch()
@@ -529,7 +538,7 @@ func ActionDesc(act Actioner, avatarLink string) string {
}
buf := bytes.NewBuffer([]byte("\n"))
for _, commit := range push.Commits {
- buf.WriteString(fmt.Sprintf(TPL_COMMIT_REPO_LI, avatarLink, repoLink, commit[0], commit[0][:7], commit[1]) + "\n")
+ buf.WriteString(fmt.Sprintf(TPL_COMMIT_REPO_LI, AvatarLink(commit.AuthorEmail), repoLink, commit.Sha1, commit.Sha1[:7], commit.Message) + "\n")
}
if push.Len > 3 {
buf.WriteString(fmt.Sprintf(``, actUserName, repoName, branch, push.Len))
@@ -539,7 +548,7 @@ func ActionDesc(act Actioner, avatarLink string) string {
case 6: // Create issue.
infos := strings.SplitN(content, "|", 2)
return fmt.Sprintf(TPL_CREATE_Issue, actUserName, actUserName, repoLink, infos[0], repoLink, infos[0],
- avatarLink, infos[1])
+ AvatarLink(email), infos[1])
default:
return "invalid type"
}
diff --git a/modules/log/log.go b/modules/log/log.go
index e1bab8ae4..f00675481 100644
--- a/modules/log/log.go
+++ b/modules/log/log.go
@@ -15,13 +15,14 @@ var (
)
func init() {
- logger = logs.NewLogger(10000)
- logger.SetLogger("console", `{"level": 0}`)
+ NewLogger(10000, "console", `{"level": 0}`)
}
func NewLogger(bufLen int64, mode, config string) {
Mode, Config = mode, config
logger = logs.NewLogger(bufLen)
+ logger.EnableFuncCallDepth(true)
+ logger.SetLogFuncCallDepth(4)
logger.SetLogger(mode, config)
}
diff --git a/modules/middleware/auth.go b/modules/middleware/auth.go
index 64f75d75c..bde3be726 100644
--- a/modules/middleware/auth.go
+++ b/modules/middleware/auth.go
@@ -7,7 +7,7 @@ package middleware
import (
"net/url"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/gogs/modules/base"
)
@@ -21,6 +21,11 @@ type ToggleOptions struct {
func Toggle(options *ToggleOptions) martini.Handler {
return func(ctx *Context) {
+ if !base.InstallLock {
+ ctx.Redirect("/install")
+ return
+ }
+
if options.SignOutRequire && ctx.IsSigned && ctx.Req.RequestURI != "/" {
ctx.Redirect("/")
return
diff --git a/modules/middleware/context.go b/modules/middleware/context.go
index d81ab999b..d2b268cd8 100644
--- a/modules/middleware/context.go
+++ b/modules/middleware/context.go
@@ -15,9 +15,10 @@ import (
"strings"
"time"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/cache"
+ "github.com/gogits/git"
"github.com/gogits/session"
"github.com/gogits/gogs/models"
@@ -41,11 +42,18 @@ type Context struct {
csrfToken string
Repo struct {
- IsValid bool
IsOwner bool
IsWatching bool
+ IsBranch bool
+ IsTag bool
+ IsCommit bool
Repository *models.Repository
Owner *models.User
+ Commit *git.Commit
+ GitRepo *git.Repository
+ BranchName string
+ CommitId string
+ RepoLink string
CloneLink struct {
SSH string
HTTPS string
@@ -98,6 +106,10 @@ func (ctx *Context) Handle(status int, title string, err error) {
ctx.HTML(status, fmt.Sprintf("status/%d", status))
}
+func (ctx *Context) Debug(msg string, args ...interface{}) {
+ log.Debug(msg, args...)
+}
+
func (ctx *Context) GetCookie(name string) string {
cookie, err := ctx.Req.Cookie(name)
if err != nil {
@@ -257,7 +269,7 @@ func InitContext() martini.Handler {
if user != nil {
ctx.Data["SignedUser"] = user
ctx.Data["SignedUserId"] = user.Id
- ctx.Data["SignedUserName"] = user.LowerName
+ ctx.Data["SignedUserName"] = user.Name
ctx.Data["IsAdmin"] = ctx.User.IsAdmin
}
diff --git a/modules/middleware/logger.go b/modules/middleware/logger.go
index dcf852460..fc8e1a811 100644
--- a/modules/middleware/logger.go
+++ b/modules/middleware/logger.go
@@ -11,7 +11,7 @@ import (
"runtime"
"time"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
)
var isWindows bool
diff --git a/modules/middleware/render.go b/modules/middleware/render.go
index 869ef9aba..98d485afe 100644
--- a/modules/middleware/render.go
+++ b/modules/middleware/render.go
@@ -17,7 +17,7 @@ import (
"path/filepath"
"time"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/gogs/modules/base"
)
diff --git a/modules/middleware/repo.go b/modules/middleware/repo.go
index 54b735af0..f446d6a85 100644
--- a/modules/middleware/repo.go
+++ b/modules/middleware/repo.go
@@ -9,24 +9,40 @@ import (
"fmt"
"strings"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
+
+ "github.com/gogits/git"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/base"
)
-func RepoAssignment(redirect bool) martini.Handler {
+func RepoAssignment(redirect bool, args ...bool) martini.Handler {
return func(ctx *Context, params martini.Params) {
- // assign false first
- ctx.Data["IsRepositoryValid"] = false
+ // valid brachname
+ var validBranch bool
+ // display bare quick start if it is a bare repo
+ var displayBare bool
+
+ if len(args) >= 1 {
+ validBranch = args[0]
+ }
+
+ if len(args) >= 2 {
+ displayBare = args[1]
+ }
var (
user *models.User
err error
)
+ userName := params["username"]
+ repoName := params["reponame"]
+ branchName := params["branchname"]
+
// get repository owner
- ctx.Repo.IsOwner = ctx.IsSigned && ctx.User.LowerName == strings.ToLower(params["username"])
+ ctx.Repo.IsOwner = ctx.IsSigned && ctx.User.LowerName == strings.ToLower(userName)
if !ctx.Repo.IsOwner {
user, err = models.GetUserByName(params["username"])
@@ -51,10 +67,8 @@ func RepoAssignment(redirect bool) martini.Handler {
return
}
- ctx.Repo.Owner = user
-
// get repository
- repo, err := models.GetRepositoryByName(user.Id, params["reponame"])
+ repo, err := models.GetRepositoryByName(user.Id, repoName)
if err != nil {
if err == models.ErrRepoNotExist {
ctx.Handle(404, "RepoAssignment", err)
@@ -62,30 +76,87 @@ func RepoAssignment(redirect bool) martini.Handler {
ctx.Redirect("/")
return
}
- ctx.Handle(200, "RepoAssignment", err)
+ ctx.Handle(404, "RepoAssignment", err)
+ return
+ }
+ ctx.Repo.Repository = repo
+
+ ctx.Data["IsBareRepo"] = ctx.Repo.Repository.IsBare
+
+ gitRepo, err := git.OpenRepository(models.RepoPath(userName, repoName))
+ if err != nil {
+ ctx.Handle(404, "RepoAssignment Invalid repo "+models.RepoPath(userName, repoName), err)
+ return
+ }
+ ctx.Repo.GitRepo = gitRepo
+
+ ctx.Repo.Owner = user
+ ctx.Repo.RepoLink = "/" + user.Name + "/" + repo.Name
+
+ ctx.Data["Title"] = user.Name + "/" + repo.Name
+ ctx.Data["Repository"] = repo
+ ctx.Data["Owner"] = user
+ ctx.Data["RepoLink"] = ctx.Repo.RepoLink
+ ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner
+ ctx.Data["BranchName"] = ""
+
+ ctx.Repo.CloneLink.SSH = fmt.Sprintf("%s@%s:%s/%s.git", base.RunUser, base.Domain, user.LowerName, repo.LowerName)
+ ctx.Repo.CloneLink.HTTPS = fmt.Sprintf("%s%s/%s.git", base.AppUrl, user.LowerName, repo.LowerName)
+ ctx.Data["CloneLink"] = ctx.Repo.CloneLink
+
+ // when repo is bare, not valid branch
+ if !ctx.Repo.Repository.IsBare && validBranch {
+ detect:
+ if len(branchName) > 0 {
+ // TODO check tag
+ if models.IsBranchExist(user.Name, repoName, branchName) {
+ ctx.Repo.IsBranch = true
+ ctx.Repo.BranchName = branchName
+
+ ctx.Repo.Commit, err = gitRepo.GetCommitOfBranch(branchName)
+ if err != nil {
+ ctx.Handle(404, "RepoAssignment invalid branch", nil)
+ return
+ }
+
+ ctx.Repo.CommitId = ctx.Repo.Commit.Oid.String()
+
+ } else if len(branchName) == 40 {
+ ctx.Repo.IsCommit = true
+ ctx.Repo.CommitId = branchName
+ ctx.Repo.BranchName = branchName
+
+ ctx.Repo.Commit, err = gitRepo.GetCommit(branchName)
+ if err != nil {
+ ctx.Handle(404, "RepoAssignment invalid commit", nil)
+ return
+ }
+ } else {
+ ctx.Handle(404, "RepoAssignment invalid repo", nil)
+ return
+ }
+
+ } else {
+ branchName = "master"
+ goto detect
+ }
+
+ ctx.Data["IsBranch"] = ctx.Repo.IsBranch
+ ctx.Data["IsCommit"] = ctx.Repo.IsCommit
+ }
+
+ // repo is bare and display enable
+ if displayBare && ctx.Repo.Repository.IsBare {
+ ctx.HTML(200, "repo/single_bare")
return
}
- ctx.Repo.IsValid = true
- if ctx.User != nil {
+ if ctx.IsSigned {
ctx.Repo.IsWatching = models.IsWatching(ctx.User.Id, repo.Id)
}
- ctx.Repo.Repository = repo
- ctx.Repo.CloneLink.SSH = fmt.Sprintf("%s@%s:%s/%s.git", base.RunUser, base.Domain, user.LowerName, repo.LowerName)
- ctx.Repo.CloneLink.HTTPS = fmt.Sprintf("%s%s/%s.git", base.AppUrl, user.LowerName, repo.LowerName)
- if len(params["branchname"]) == 0 {
- params["branchname"] = "master"
- }
- ctx.Data["Branchname"] = params["branchname"]
-
- ctx.Data["IsRepositoryValid"] = true
- ctx.Data["Repository"] = repo
- ctx.Data["Owner"] = user
- ctx.Data["Title"] = user.Name + "/" + repo.Name
- ctx.Data["CloneLink"] = ctx.Repo.CloneLink
- ctx.Data["RepositoryLink"] = ctx.Data["Title"]
- ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner
+ ctx.Data["BranchName"] = ctx.Repo.BranchName
+ ctx.Data["CommitId"] = ctx.Repo.CommitId
ctx.Data["IsRepositoryWatching"] = ctx.Repo.IsWatching
}
}
diff --git a/public/css/gogs.css b/public/css/gogs.css
index d6c117c84..965c90962 100755
--- a/public/css/gogs.css
+++ b/public/css/gogs.css
@@ -1197,13 +1197,13 @@ html, body {
line-height: 42px;
}
-#issue .issue-closed{
- border-bottom: 3px solid #CCC;
+#issue .issue-closed, #issue .issue-opened {
+ border-bottom: 2px solid #CCC;
margin-bottom: 24px;
padding-bottom: 24px;
}
-#issue .issue-closed .btn-danger,#issue .issue-opened .btn-success{
+#issue .issue-closed .label-danger,#issue .issue-opened .label-success{
margin: 0 .8em;
}
diff --git a/public/js/app.js b/public/js/app.js
index 9299a6b7a..5181933d2 100644
--- a/public/js/app.js
+++ b/public/js/app.js
@@ -56,6 +56,43 @@ var Gogits = {
},
toggleShow: function () {
$(this).removeClass("hidden");
+ },
+ toggleAjax: function (successCallback) {
+ var url = $(this).data("ajax");
+ var method = $(this).data('ajax-method') || 'get';
+ var ajaxName = $(this).data('ajax-name');
+ var data = {};
+ $('[data-ajax-rel=' + ajaxName + ']').each(function () {
+ var field = $(this).data("ajax-field");
+ var t = $(this).data("ajax-val");
+ if (t == "val") {
+ data[field] = $(this).val();
+ return true;
+ }
+ if (t == "txt") {
+ data[field] = $(this).text();
+ return true;
+ }
+ if (t == "html") {
+ data[field] = $(this).html();
+ return true;
+ }
+ if (t == "data") {
+ data[field] = $(this).data("ajax-data");
+ return true;
+ }
+ return true;
+ });
+ $.ajax({
+ url: url,
+ method: method.toUpperCase(),
+ data: data,
+ success: function (d) {
+ if (successCallback) {
+ successCallback(d);
+ }
+ }
+ })
}
})
}(jQuery));
@@ -362,21 +399,24 @@ function initRepository() {
function initInstall() {
// database type change
- $('#install-database').on("change", function () {
- var val = $(this).val();
- if (val != "sqlite") {
- $('.server-sql').show();
- $('.sqlite-setting').addClass("hide");
- if (val == "pgsql") {
- $('.pgsql-setting').removeClass("hide");
+ (function () {
+ $('#install-database').on("change", function () {
+ var val = $(this).val();
+ if (val != "sqlite") {
+ $('.server-sql').show();
+ $('.sqlite-setting').addClass("hide");
+ if (val == "pgsql") {
+ $('.pgsql-setting').removeClass("hide");
+ } else {
+ $('.pgsql-setting').addClass("hide");
+ }
} else {
- $('.pgsql-setting').addClass("hide");
+ $('.server-sql').hide();
+ $('.sqlite-setting').removeClass("hide");
}
- } else {
- $('.server-sql').hide();
- $('.sqlite-setting').removeClass("hide");
- }
- });
+ });
+ }());
+
}
function initIssue() {
@@ -386,11 +426,11 @@ function initIssue() {
var $openBtn = $('#issue-open-btn');
$('#issue-reply-content').on("keyup", function () {
if ($(this).val().length) {
- $closeBtn.text($closeBtn.data("text"));
- $openBtn.text($openBtn.data("text"));
+ $closeBtn.val($closeBtn.data("text"));
+ $openBtn.val($openBtn.data("text"));
} else {
- $closeBtn.text($closeBtn.data("origin"));
- $openBtn.text($openBtn.data("origin"));
+ $closeBtn.val($closeBtn.data("origin"));
+ $openBtn.val($openBtn.data("origin"));
}
});
}());
@@ -406,6 +446,35 @@ function initIssue() {
$('#issue-edit-title,#issue-edit-content,.issue-edit-cancel,.issue-edit-save').toggleHide();
})
}());
+
+ // issue ajax update
+ (function () {
+ $('.issue-edit-save').on("click", function () {
+ $(this).toggleAjax(function (json) {
+ if (json.ok) {
+ $('.issue-head h1.title').text(json.title);
+ $('.issue-main > .issue-content .content').html(json.content);
+ $('.issue-edit-cancel').trigger("click");
+ }
+ });
+ });
+ }());
+
+ // issue ajax preview
+ (function () {
+ $('[data-ajax-name=issue-preview]').on("click", function () {
+ var $this = $(this);
+ $this.toggleAjax(function (json) {
+ if (json.ok) {
+ $($this.data("preview")).html(json.content);
+ }
+ })
+ });
+ $('.issue-write a[data-toggle]').on("click", function () {
+ $('.issue-preview-content').html("loading...");
+ });
+ }())
+
}
(function ($) {
diff --git a/routers/admin/admin.go b/routers/admin/admin.go
index f303439fd..18a43ff81 100644
--- a/routers/admin/admin.go
+++ b/routers/admin/admin.go
@@ -10,7 +10,7 @@ import (
"strings"
"time"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/base"
diff --git a/routers/admin/user.go b/routers/admin/user.go
index 7f66c5528..9f043507d 100644
--- a/routers/admin/user.go
+++ b/routers/admin/user.go
@@ -7,7 +7,7 @@ package admin
import (
"strings"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/auth"
diff --git a/routers/api/v1/miscellaneous.go b/routers/api/v1/miscellaneous.go
new file mode 100644
index 000000000..0ff1eb04a
--- /dev/null
+++ b/routers/api/v1/miscellaneous.go
@@ -0,0 +1,18 @@
+// 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 v1
+
+import (
+ "github.com/gogits/gogs/modules/base"
+ "github.com/gogits/gogs/modules/middleware"
+)
+
+func Markdown(ctx *middleware.Context) {
+ content := ctx.Query("content")
+ ctx.Render.JSON(200, map[string]interface{}{
+ "ok": true,
+ "content": string(base.RenderMarkdown([]byte(content), "")),
+ })
+}
diff --git a/routers/dev/template.go b/routers/dev/template.go
index d2f77ac4d..63d5d9a5b 100644
--- a/routers/dev/template.go
+++ b/routers/dev/template.go
@@ -5,7 +5,7 @@
package dev
import (
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/base"
diff --git a/routers/install.go b/routers/install.go
index e0ac92f13..28c2d87f7 100644
--- a/routers/install.go
+++ b/routers/install.go
@@ -6,27 +6,188 @@ package routers
import (
"errors"
+ "os"
+ "strings"
+
+ "github.com/Unknwon/goconfig"
+ "github.com/go-martini/martini"
+ "github.com/lunny/xorm"
"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/mailer"
"github.com/gogits/gogs/modules/middleware"
)
-func Install(ctx *middleware.Context) {
+// Check run mode(Default of martini is Dev).
+func checkRunMode() {
+ switch base.Cfg.MustValue("", "RUN_MODE") {
+ case "prod":
+ martini.Env = martini.Prod
+ case "test":
+ martini.Env = martini.Test
+ }
+ log.Info("Run Mode: %s", strings.Title(martini.Env))
+}
+
+// GlobalInit is for global configuration reload-able.
+func GlobalInit() {
+ base.NewConfigContext()
+ mailer.NewMailerContext()
+ models.LoadModelsConfig()
+ models.LoadRepoConfig()
+ models.NewRepoContext()
+
+ if base.InstallLock {
+ if err := models.NewEngine(); err != nil {
+ log.Error("%v", err)
+ os.Exit(2)
+ }
+
+ models.HasEngine = true
+ }
+ base.NewServices()
+ checkRunMode()
+}
+
+func Install(ctx *middleware.Context, form auth.InstallForm) {
if base.InstallLock {
ctx.Handle(404, "install.Install", errors.New("Installation is prohibited"))
return
}
ctx.Data["Title"] = "Install"
- ctx.Data["DbCfg"] = models.DbCfg
- ctx.Data["RepoRootPath"] = base.RepoRootPath
- ctx.Data["RunUser"] = base.RunUser
- ctx.Data["AppUrl"] = base.AppUrl
ctx.Data["PageIsInstall"] = true
if ctx.Req.Method == "GET" {
+ // Get and assign value to install form.
+ if len(form.Host) == 0 {
+ form.Host = models.DbCfg.Host
+ }
+ if len(form.User) == 0 {
+ form.User = models.DbCfg.User
+ }
+ if len(form.Passwd) == 0 {
+ form.Passwd = models.DbCfg.Pwd
+ }
+ if len(form.DatabaseName) == 0 {
+ form.DatabaseName = models.DbCfg.Name
+ }
+ if len(form.DatabasePath) == 0 {
+ form.DatabasePath = models.DbCfg.Path
+ }
+
+ if len(form.RepoRootPath) == 0 {
+ form.RepoRootPath = base.RepoRootPath
+ }
+ if len(form.RunUser) == 0 {
+ form.RunUser = base.RunUser
+ }
+ if len(form.Domain) == 0 {
+ form.Domain = base.Domain
+ }
+ if len(form.AppUrl) == 0 {
+ form.AppUrl = base.AppUrl
+ }
+
+ auth.AssignForm(form, ctx.Data)
ctx.HTML(200, "install")
return
}
+
+ if ctx.HasError() {
+ ctx.HTML(200, "install")
+ return
+ }
+
+ // Pass basic check, now test configuration.
+ // Test database setting.
+ dbTypes := map[string]string{"mysql": "mysql", "pgsql": "postgres", "sqlite": "sqlite3"}
+ models.DbCfg.Type = dbTypes[form.Database]
+ models.DbCfg.Host = form.Host
+ models.DbCfg.User = form.User
+ models.DbCfg.Pwd = form.Passwd
+ models.DbCfg.Name = form.DatabaseName
+ models.DbCfg.SslMode = form.SslMode
+ models.DbCfg.Path = form.DatabasePath
+
+ // Set test engine.
+ var x *xorm.Engine
+ if err := models.NewTestEngine(x); err != nil {
+ if strings.Contains(err.Error(), `Unknown database type: sqlite3`) {
+ ctx.RenderWithErr("Your release version does not support SQLite3, please download the official binary version "+
+ "from https://github.com/gogits/gogs/wiki/Install-from-binary, NOT the gobuild version.", "install", &form)
+ } else {
+ ctx.RenderWithErr("Database setting is not correct: "+err.Error(), "install", &form)
+ }
+ return
+ }
+
+ // Test repository root path.
+ if err := os.MkdirAll(form.RepoRootPath, os.ModePerm); err != nil {
+ ctx.RenderWithErr("Repository root path is invalid: "+err.Error(), "install", &form)
+ return
+ }
+
+ // Check run user.
+ curUser := os.Getenv("USERNAME")
+ if len(curUser) == 0 {
+ curUser = os.Getenv("USER")
+ }
+ // Does not check run user when the install lock is off.
+ if form.RunUser != curUser {
+ ctx.RenderWithErr("Run user isn't the current user: "+form.RunUser+" -> "+curUser, "install", &form)
+ return
+ }
+
+ // Save settings.
+ base.Cfg.SetValue("database", "DB_TYPE", models.DbCfg.Type)
+ base.Cfg.SetValue("database", "HOST", models.DbCfg.Host)
+ base.Cfg.SetValue("database", "NAME", models.DbCfg.Name)
+ base.Cfg.SetValue("database", "USER", models.DbCfg.User)
+ base.Cfg.SetValue("database", "PASSWD", models.DbCfg.Pwd)
+ base.Cfg.SetValue("database", "SSL_MODE", models.DbCfg.SslMode)
+ base.Cfg.SetValue("database", "PATH", models.DbCfg.Path)
+
+ base.Cfg.SetValue("repository", "ROOT", form.RepoRootPath)
+ base.Cfg.SetValue("", "RUN_USER", form.RunUser)
+ base.Cfg.SetValue("server", "DOMAIN", form.Domain)
+ base.Cfg.SetValue("server", "ROOT_URL", form.AppUrl)
+
+ if len(strings.TrimSpace(form.SmtpHost)) > 0 {
+ base.Cfg.SetValue("mailer", "ENABLED", "true")
+ base.Cfg.SetValue("mailer", "HOST", form.SmtpHost)
+ base.Cfg.SetValue("mailer", "USER", form.SmtpEmail)
+ base.Cfg.SetValue("mailer", "PASSWD", form.SmtpPasswd)
+
+ base.Cfg.SetValue("service", "REGISTER_EMAIL_CONFIRM", base.ToStr(form.RegisterConfirm == "on"))
+ base.Cfg.SetValue("service", "ENABLE_NOTIFY_MAIL", base.ToStr(form.MailNotify == "on"))
+ }
+
+ base.Cfg.SetValue("", "RUN_MODE", "prod")
+
+ base.Cfg.SetValue("security", "INSTALL_LOCK", "true")
+
+ os.MkdirAll("custom/conf", os.ModePerm)
+ if err := goconfig.SaveConfigFile(base.Cfg, "custom/conf/app.ini"); err != nil {
+ ctx.RenderWithErr("Fail to save configuration: "+err.Error(), "install", &form)
+ return
+ }
+
+ GlobalInit()
+
+ // Create admin account.
+ if _, err := models.RegisterUser(&models.User{Name: form.AdminName, Email: form.AdminEmail, Passwd: form.AdminPasswd,
+ IsAdmin: true, IsActive: true}); err != nil {
+ if err != models.ErrUserAlreadyExist {
+ ctx.RenderWithErr("Admin account setting is invalid: "+err.Error(), "install", &form)
+ return
+ }
+ log.Info("Admin account already exist")
+ }
+
+ log.Info("First-time run install finished!")
+ ctx.Redirect("/user/login")
}
diff --git a/routers/repo/branch.go b/routers/repo/branch.go
index aed77cfaa..ffd118ae1 100644
--- a/routers/repo/branch.go
+++ b/routers/repo/branch.go
@@ -5,27 +5,22 @@
package repo
import (
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
+
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/middleware"
)
func Branches(ctx *middleware.Context, params martini.Params) {
- if !ctx.Repo.IsValid {
- return
- }
-
- brs, err := models.GetBranches(params["username"], params["reponame"])
+ brs, err := models.GetBranches(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
if err != nil {
- ctx.Handle(200, "repo.Branches", err)
+ ctx.Handle(404, "repo.Branches", err)
return
} else if len(brs) == 0 {
ctx.Handle(404, "repo.Branches", nil)
return
}
- ctx.Data["Username"] = params["username"]
- ctx.Data["Reponame"] = params["reponame"]
ctx.Data["Branches"] = brs
ctx.Data["IsRepoToolbarBranches"] = true
diff --git a/routers/repo/commit.go b/routers/repo/commit.go
index afc1ffda2..d29c40e67 100644
--- a/routers/repo/commit.go
+++ b/routers/repo/commit.go
@@ -8,7 +8,7 @@ import (
"container/list"
"path"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/base"
@@ -50,16 +50,12 @@ func Commits(ctx *middleware.Context, params martini.Params) {
}
func Diff(ctx *middleware.Context, params martini.Params) {
- userName := params["username"]
- repoName := params["reponame"]
- branchName := params["branchname"]
- commitId := params["commitid"]
+ userName := ctx.Repo.Owner.Name
+ repoName := ctx.Repo.Repository.Name
+ branchName := ctx.Repo.BranchName
+ commitId := ctx.Repo.CommitId
- commit, err := models.GetCommit(userName, repoName, branchName, commitId)
- if err != nil {
- ctx.Handle(404, "repo.Diff", err)
- return
- }
+ commit := ctx.Repo.Commit
diff, err := models.GetDiff(models.RepoPath(userName, repoName), commitId)
if err != nil {
@@ -85,11 +81,9 @@ func Diff(ctx *middleware.Context, params martini.Params) {
return isImage
}
- shortSha := params["commitid"][:10]
ctx.Data["IsImageFile"] = isImageFile
- ctx.Data["Title"] = commit.Message() + " · " + shortSha
+ ctx.Data["Title"] = commit.Message() + " · " + base.ShortSha(commitId)
ctx.Data["Commit"] = commit
- ctx.Data["ShortSha"] = shortSha
ctx.Data["Diff"] = diff
ctx.Data["IsRepoToolbarCommits"] = true
ctx.Data["SourcePath"] = "/" + path.Join(userName, repoName, "src", commitId)
diff --git a/routers/repo/issue.go b/routers/repo/issue.go
index c3d1a0d96..6cad2c25d 100644
--- a/routers/repo/issue.go
+++ b/routers/repo/issue.go
@@ -7,8 +7,9 @@ package repo
import (
"fmt"
"net/url"
+ "strings"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/auth"
@@ -19,10 +20,6 @@ import (
)
func Issues(ctx *middleware.Context) {
- if !ctx.Repo.IsValid {
- ctx.Handle(404, "issue.Issues(invalid repo):", nil)
- }
-
ctx.Data["Title"] = "Issues"
ctx.Data["IsRepoToolbarIssues"] = true
ctx.Data["IsRepoToolbarIssuesList"] = true
@@ -79,10 +76,6 @@ func Issues(ctx *middleware.Context) {
}
func CreateIssue(ctx *middleware.Context, params martini.Params, form auth.CreateIssueForm) {
- if !ctx.Repo.IsValid {
- ctx.Handle(404, "issue.CreateIssue(invalid repo):", nil)
- }
-
ctx.Data["Title"] = "Create issue"
ctx.Data["IsRepoToolbarIssues"] = true
ctx.Data["IsRepoToolbarIssuesList"] = false
@@ -105,7 +98,7 @@ func CreateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat
}
// Notify watchers.
- if err = models.NotifyWatchers(&models.Action{ActUserId: ctx.User.Id, ActUserName: ctx.User.Name,
+ if err = models.NotifyWatchers(&models.Action{ActUserId: ctx.User.Id, ActUserName: ctx.User.Name, ActEmail: ctx.User.Email,
OpType: models.OP_CREATE_ISSUE, Content: fmt.Sprintf("%d|%s", issue.Index, issue.Name),
RepoId: ctx.Repo.Repository.Id, RepoName: ctx.Repo.Repository.Name, RefName: ""}); err != nil {
ctx.Handle(200, "issue.CreateIssue", err)
@@ -125,10 +118,6 @@ func CreateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat
}
func ViewIssue(ctx *middleware.Context, params martini.Params) {
- if !ctx.Repo.IsValid {
- ctx.Handle(404, "issue.ViewIssue(invalid repo):", nil)
- }
-
index, err := base.StrTo(params["index"]).Int()
if err != nil {
ctx.Handle(404, "issue.ViewIssue", err)
@@ -152,7 +141,7 @@ func ViewIssue(ctx *middleware.Context, params martini.Params) {
return
}
issue.Poster = u
- issue.Content = string(base.RenderMarkdown([]byte(issue.Content), ""))
+ issue.RenderedContent = string(base.RenderMarkdown([]byte(issue.Content), ""))
// Get comments.
comments, err := models.GetIssueComments(issue.Id)
@@ -175,16 +164,13 @@ func ViewIssue(ctx *middleware.Context, params martini.Params) {
ctx.Data["Title"] = issue.Name
ctx.Data["Issue"] = issue
ctx.Data["Comments"] = comments
+ ctx.Data["IsIssueOwner"] = ctx.Repo.IsOwner || (ctx.IsSigned && issue.PosterId == ctx.User.Id)
ctx.Data["IsRepoToolbarIssues"] = true
ctx.Data["IsRepoToolbarIssuesList"] = false
ctx.HTML(200, "issue/view")
}
func UpdateIssue(ctx *middleware.Context, params martini.Params, form auth.CreateIssueForm) {
- if !ctx.Repo.IsValid {
- ctx.Handle(404, "issue.UpdateIssue(invalid repo):", nil)
- }
-
index, err := base.StrTo(params["index"]).Int()
if err != nil {
ctx.Handle(404, "issue.UpdateIssue", err)
@@ -216,22 +202,21 @@ func UpdateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat
return
}
- ctx.Data["Title"] = issue.Name
- ctx.Data["Issue"] = issue
+ ctx.JSON(200, map[string]interface{}{
+ "ok": true,
+ "title": issue.Name,
+ "content": string(base.RenderMarkdown([]byte(issue.Content), "")),
+ })
}
func Comment(ctx *middleware.Context, params martini.Params) {
- if !ctx.Repo.IsValid {
- ctx.Handle(404, "issue.Comment(invalid repo):", nil)
- }
-
- index, err := base.StrTo(ctx.Query("issueIndex")).Int()
+ index, err := base.StrTo(ctx.Query("issueIndex")).Int64()
if err != nil {
- ctx.Handle(404, "issue.Comment", err)
+ ctx.Handle(404, "issue.Comment(get index)", err)
return
}
- issue, err := models.GetIssueByIndex(ctx.Repo.Repository.Id, int64(index))
+ issue, err := models.GetIssueByIndex(ctx.Repo.Repository.Id, index)
if err != nil {
if err == models.ErrIssueNotExist {
ctx.Handle(404, "issue.Comment", err)
@@ -241,22 +226,46 @@ func Comment(ctx *middleware.Context, params martini.Params) {
return
}
- content := ctx.Query("content")
- if len(content) == 0 {
- ctx.Handle(404, "issue.Comment", err)
- return
+ // Check if issue owner changes the status of issue.
+ var newStatus string
+ if ctx.Repo.IsOwner || issue.PosterId == ctx.User.Id {
+ newStatus = ctx.Query("change_status")
+ }
+ if len(newStatus) > 0 {
+ if (strings.Contains(newStatus, "Reopen") && issue.IsClosed) ||
+ (strings.Contains(newStatus, "Close") && !issue.IsClosed) {
+ issue.IsClosed = !issue.IsClosed
+ if err = models.UpdateIssue(issue); err != nil {
+ ctx.Handle(200, "issue.Comment(update issue status)", err)
+ return
+ }
+
+ cmtType := models.IT_CLOSE
+ if !issue.IsClosed {
+ cmtType = models.IT_REOPEN
+ }
+
+ if err = models.CreateComment(ctx.User.Id, ctx.Repo.Repository.Id, issue.Id, 0, 0, cmtType, ""); err != nil {
+ ctx.Handle(200, "issue.Comment(create status change comment)", err)
+ return
+ }
+ log.Trace("%s Issue(%d) status changed: %v", ctx.Req.RequestURI, issue.Id, !issue.IsClosed)
+ }
}
- switch params["action"] {
- case "new":
- if err = models.CreateComment(ctx.User.Id, issue.Id, 0, 0, content); err != nil {
- ctx.Handle(500, "issue.Comment(create comment)", err)
+ content := ctx.Query("content")
+ if len(content) > 0 {
+ switch params["action"] {
+ case "new":
+ if err = models.CreateComment(ctx.User.Id, ctx.Repo.Repository.Id, issue.Id, 0, 0, models.IT_PLAIN, content); err != nil {
+ ctx.Handle(500, "issue.Comment(create comment)", err)
+ return
+ }
+ log.Trace("%s Comment created: %d", ctx.Req.RequestURI, issue.Id)
+ default:
+ ctx.Handle(404, "issue.Comment", err)
return
}
- log.Trace("%s Comment created: %d", ctx.Req.RequestURI, issue.Id)
- default:
- ctx.Handle(404, "issue.Comment", err)
- return
}
ctx.Redirect(fmt.Sprintf("/%s/%s/issues/%d", ctx.User.Name, ctx.Repo.Repository.Name, index))
diff --git a/routers/repo/pull.go b/routers/repo/pull.go
index 93b6a9f7c..430c6a815 100644
--- a/routers/repo/pull.go
+++ b/routers/repo/pull.go
@@ -5,7 +5,7 @@
package repo
import (
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/gogs/modules/middleware"
)
diff --git a/routers/repo/repo.go b/routers/repo/repo.go
index e7107ad1c..1cd3dd86b 100644
--- a/routers/repo/repo.go
+++ b/routers/repo/repo.go
@@ -9,7 +9,7 @@ import (
"path/filepath"
"strings"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/webdav"
@@ -53,20 +53,20 @@ func Create(ctx *middleware.Context, form auth.CreateRepoForm) {
}
func Single(ctx *middleware.Context, params martini.Params) {
- if !ctx.Repo.IsValid {
- return
- }
+ branchName := ctx.Repo.BranchName
+ commitId := ctx.Repo.CommitId
+ userName := ctx.Repo.Owner.Name
+ repoName := ctx.Repo.Repository.Name
- branchName := params["branchname"]
- userName := params["username"]
- repoName := params["reponame"]
+ repoLink := ctx.Repo.RepoLink
+ branchLink := ctx.Repo.RepoLink + "/src/" + branchName
+ rawLink := ctx.Repo.RepoLink + "/raw/" + branchName
// Get tree path
treename := params["_1"]
if len(treename) > 0 && treename[len(treename)-1] == '/' {
- ctx.Redirect("/" + ctx.Repo.Owner.LowerName + "/" +
- ctx.Repo.Repository.Name + "/src/" + branchName + "/" + treename[:len(treename)-1])
+ ctx.Redirect(repoLink + "/src/" + branchName + "/" + treename[:len(treename)-1])
return
}
@@ -77,30 +77,21 @@ func Single(ctx *middleware.Context, params martini.Params) {
if err != nil {
ctx.Handle(404, "repo.Single(GetBranches)", err)
return
- } else if ctx.Repo.Repository.IsBare {
- ctx.Data["IsBareRepo"] = true
- ctx.HTML(200, "repo/single")
- return
}
+
ctx.Data["Branches"] = brs
- var commitId string
- isViewBranch := models.IsBranchExist(userName, repoName, branchName)
- if !isViewBranch {
- commitId = branchName
- }
+ isViewBranch := ctx.Repo.IsBranch
ctx.Data["IsViewBranch"] = isViewBranch
repoFile, err := models.GetTargetFile(userName, repoName,
branchName, commitId, treename)
+
if err != nil && err != models.ErrRepoFileNotExist {
ctx.Handle(404, "repo.Single(GetTargetFile)", err)
return
}
- branchLink := "/" + ctx.Repo.Owner.LowerName + "/" + ctx.Repo.Repository.Name + "/src/" + branchName
- rawLink := "/" + ctx.Repo.Owner.LowerName + "/" + ctx.Repo.Repository.Name + "/raw/" + branchName
-
if len(treename) != 0 && repoFile == nil {
ctx.Handle(404, "repo.Single", nil)
return
@@ -142,8 +133,7 @@ func Single(ctx *middleware.Context, params martini.Params) {
} else {
// Directory and file list.
- files, err := models.GetReposFiles(userName, repoName,
- branchName, commitId, treename)
+ files, err := models.GetReposFiles(userName, repoName, ctx.Repo.CommitId, treename)
if err != nil {
ctx.Handle(404, "repo.Single(GetReposFiles)", err)
return
@@ -200,18 +190,7 @@ func Single(ctx *middleware.Context, params martini.Params) {
}
}
- // Get latest commit according username and repo name.
- commit, err := models.GetCommit(userName, repoName,
- branchName, commitId)
- if err != nil {
- log.Error("repo.Single(GetCommit): %v", err)
- ctx.Handle(404, "repo.Single(GetCommit)", err)
- return
- }
- ctx.Data["LastCommit"] = commit
-
- ctx.Data["CommitId"] = commitId
-
+ ctx.Data["LastCommit"] = ctx.Repo.Commit
ctx.Data["Paths"] = Paths
ctx.Data["Treenames"] = treenames
ctx.Data["BranchLink"] = branchLink
@@ -219,11 +198,6 @@ func Single(ctx *middleware.Context, params martini.Params) {
}
func SingleDownload(ctx *middleware.Context, params martini.Params) {
- if !ctx.Repo.IsValid {
- ctx.Handle(404, "repo.SingleDownload", nil)
- return
- }
-
// Get tree path
treename := params["_1"]
@@ -263,10 +237,6 @@ func SingleDownload(ctx *middleware.Context, params martini.Params) {
}
func Http(ctx *middleware.Context, params martini.Params) {
- /*if !ctx.Repo.IsValid {
- return
- }*/
-
// TODO: access check
username := params["username"]
@@ -276,11 +246,9 @@ func Http(ctx *middleware.Context, params martini.Params) {
}
prefix := path.Join("/", username, params["reponame"])
- server := &webdav.Server{
- Fs: webdav.Dir(models.RepoPath(username, reponame)),
- TrimPrefix: prefix,
- Listings: true,
- }
+ server := webdav.NewServer(
+ models.RepoPath(username, reponame),
+ prefix, true)
server.ServeHTTP(ctx.ResponseWriter, ctx.Req)
}
@@ -293,12 +261,6 @@ func Setting(ctx *middleware.Context, params martini.Params) {
ctx.Data["IsRepoToolbarSetting"] = true
- if ctx.Repo.Repository.IsBare {
- ctx.Data["IsBareRepo"] = true
- ctx.HTML(200, "repo/setting")
- return
- }
-
var title string
if t, ok := ctx.Data["Title"].(string); ok {
title = t
diff --git a/routers/user/user.go b/routers/user/user.go
index b0fc58397..08930e22d 100644
--- a/routers/user/user.go
+++ b/routers/user/user.go
@@ -9,7 +9,7 @@ import (
"net/url"
"strings"
- "github.com/codegangsta/martini"
+ "github.com/go-martini/martini"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/auth"
@@ -120,7 +120,7 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) {
return
}
- if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) {
+ if ctx.HasError() {
ctx.HTML(200, "user/signin")
return
}
@@ -279,7 +279,7 @@ func Feeds(ctx *middleware.Context, form auth.FeedsForm) {
feeds := make([]string, len(actions))
for i := range actions {
feeds[i] = fmt.Sprintf(TPL_FEED, base.ActionIcon(actions[i].OpType),
- base.TimeSince(actions[i].Created), base.ActionDesc(actions[i], ctx.User.AvatarLink()))
+ base.TimeSince(actions[i].Created), base.ActionDesc(actions[i]))
}
ctx.JSON(200, &feeds)
}
@@ -308,17 +308,19 @@ func Issues(ctx *middleware.Context) {
showRepos := make([]models.Repository, 0, len(repos))
- var closedIssueCount, createdByCount int
+ isShowClosed := ctx.Query("state") == "closed"
+ var closedIssueCount, createdByCount, allIssueCount int
// Get all issues.
allIssues := make([]models.Issue, 0, 5*len(repos))
for i, repo := range repos {
- issues, err := models.GetIssues(0, repo.Id, posterId, 0, page, false, false, "", "")
+ issues, err := models.GetIssues(0, repo.Id, posterId, 0, page, isShowClosed, false, "", "")
if err != nil {
ctx.Handle(200, "user.Issues(get issues)", err)
return
}
+ allIssueCount += repo.NumIssues
closedIssueCount += repo.NumClosedIssues
// Set repository information to issues.
@@ -330,12 +332,10 @@ func Issues(ctx *middleware.Context) {
repos[i].NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
if repos[i].NumOpenIssues > 0 {
showRepos = append(showRepos, repos[i])
-
}
}
showIssues := make([]models.Issue, 0, len(allIssues))
- isShowClosed := ctx.Query("state") == "closed"
ctx.Data["IsShowClosed"] = isShowClosed
// Get posters and filter issues.
@@ -361,9 +361,9 @@ func Issues(ctx *middleware.Context) {
ctx.Data["Repos"] = showRepos
ctx.Data["Issues"] = showIssues
- ctx.Data["AllIssueCount"] = len(allIssues)
+ ctx.Data["AllIssueCount"] = allIssueCount
ctx.Data["ClosedIssueCount"] = closedIssueCount
- ctx.Data["OpenIssueCount"] = len(allIssues) - closedIssueCount
+ ctx.Data["OpenIssueCount"] = allIssueCount - closedIssueCount
ctx.Data["CreatedByCount"] = createdByCount
ctx.HTML(200, "issue/user")
}
diff --git a/serve.go b/serve.go
index ad31260f0..96cd7e73d 100644
--- a/serve.go
+++ b/serve.go
@@ -74,29 +74,33 @@ func In(b string, sl map[string]int) bool {
func runServ(k *cli.Context) {
execDir, _ := base.ExecDir()
newLogger(execDir)
- log.Trace("new serv request " + log.Mode + ":" + log.Config)
base.NewConfigContext()
models.LoadModelsConfig()
+
+ if models.UseSQLite3 {
+ os.Chdir(execDir)
+ }
+
models.SetEngine()
keys := strings.Split(os.Args[2], "-")
if len(keys) != 2 {
- fmt.Println("auth file format error")
+ println("auth file format error")
log.Error("auth file format error")
return
}
keyId, err := strconv.ParseInt(keys[1], 10, 64)
if err != nil {
- fmt.Println("auth file format error")
- log.Error("auth file format error")
+ println("auth file format error")
+ log.Error("auth file format error", err)
return
}
user, err := models.GetUserByKeyId(keyId)
if err != nil {
- fmt.Println("You have no right to access")
- log.Error("You have no right to access")
+ println("You have no right to access")
+ log.Error("SSH visit error: %v", err)
return
}
@@ -107,13 +111,14 @@ func runServ(k *cli.Context) {
}
verb, args := parseCmd(cmd)
- rRepo := strings.Trim(args, "'")
- rr := strings.SplitN(rRepo, "/", 2)
+ repoPath := strings.Trim(args, "'")
+ rr := strings.SplitN(repoPath, "/", 2)
if len(rr) != 2 {
println("Unavilable repository", args)
log.Error("Unavilable repository %v", args)
return
}
+ repoUserName := rr[0]
repoName := rr[1]
if strings.HasSuffix(repoName, ".git") {
repoName = repoName[:len(repoName)-4]
@@ -122,46 +127,46 @@ func runServ(k *cli.Context) {
isWrite := In(verb, COMMANDS_WRITE)
isRead := In(verb, COMMANDS_READONLY)
- /*//repo, err := models.GetRepositoryByName(user.Id, repoName)
- //var isExist bool = true
+ repoUser, err := models.GetUserByName(repoUserName)
if err != nil {
- if err == models.ErrRepoNotExist {
- //isExist = false
- if isRead {
- println("Repository", user.Name+"/"+repoName, "is not exist")
- log.Error("Repository " + user.Name + "/" + repoName + " is not exist")
- return
- }
- } else {
- println("Get repository error:", err)
- log.Error("Get repository error: " + err.Error())
- return
- }
- }*/
+ fmt.Println("You have no right to access")
+ log.Error("Get user failed", err)
+ return
+ }
// access check
switch {
case isWrite:
- has, err := models.HasAccess(user.Name, repoName, models.AU_WRITABLE)
+ has, err := models.HasAccess(user.LowerName, path.Join(repoUserName, repoName), models.AU_WRITABLE)
if err != nil {
println("Inernel error:", err)
log.Error(err.Error())
return
- }
- if !has {
+ } else if !has {
println("You have no right to write this repository")
- log.Error("You have no right to access this repository")
+ log.Error("User %s has no right to write repository %s", user.Name, repoPath)
return
}
case isRead:
- has, err := models.HasAccess(user.Name, repoName, models.AU_READABLE)
+ repo, err := models.GetRepositoryByName(repoUser.Id, repoName)
+ if err != nil {
+ println("Get repository error:", err)
+ log.Error("Get repository error: " + err.Error())
+ return
+ }
+
+ if !repo.IsPrivate {
+ break
+ }
+
+ has, err := models.HasAccess(user.Name, repoPath, models.AU_READABLE)
if err != nil {
println("Inernel error")
log.Error(err.Error())
return
}
if !has {
- has, err = models.HasAccess(user.Name, repoName, models.AU_WRITABLE)
+ has, err = models.HasAccess(user.Name, repoPath, models.AU_WRITABLE)
if err != nil {
println("Inernel error")
log.Error(err.Error())
@@ -184,7 +189,7 @@ func runServ(k *cli.Context) {
os.Setenv("userId", strconv.Itoa(int(user.Id)))
os.Setenv("repoName", repoName)
- gitcmd := exec.Command(verb, rRepo)
+ gitcmd := exec.Command(verb, repoPath)
gitcmd.Dir = base.RepoRootPath
gitcmd.Stdout = os.Stdout
gitcmd.Stdin = os.Stdin
diff --git a/start.bat b/start.bat
new file mode 100644
index 000000000..02972b92d
--- /dev/null
+++ b/start.bat
@@ -0,0 +1,2 @@
+@echo off
+gogs.exe web
diff --git a/start.sh b/start.sh
new file mode 100755
index 000000000..331d340cd
--- /dev/null
+++ b/start.sh
@@ -0,0 +1,6 @@
+#!/bin/bash -
+#
+# start gogs web
+#
+cd "$(dirname $0)"
+./gogs web
diff --git a/templates/install.tmpl b/templates/install.tmpl
index be5a69186..1fbc74bc7 100644
--- a/templates/install.tmpl
+++ b/templates/install.tmpl
@@ -3,9 +3,8 @@