Finish close and reopen issue, install page, ready going to test stage of v0.2.0
This commit is contained in:
parent
1f671e5d29
commit
107a1eadac
15 changed files with 315 additions and 161 deletions
|
@ -5,7 +5,7 @@ Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language
|
||||||
|
|
||||||
![Demo](http://gowalker.org/public/gogs_demo.gif)
|
![Demo](http://gowalker.org/public/gogs_demo.gif)
|
||||||
|
|
||||||
##### Current version: 0.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.
|
#### 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.
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ Gogs(Go Git Service) 是一个由 Go 语言编写的自助 Git 托管服务。
|
||||||
|
|
||||||
![Demo](http://gowalker.org/public/gogs_demo.gif)
|
![Demo](http://gowalker.org/public/gogs_demo.gif)
|
||||||
|
|
||||||
##### 当前版本:0.1.9 Alpha
|
##### 当前版本:0.2.0 Alpha
|
||||||
|
|
||||||
## 开发目的
|
## 开发目的
|
||||||
|
|
||||||
|
|
2
gogs.go
2
gogs.go
|
@ -19,7 +19,7 @@ import (
|
||||||
// Test that go1.2 tag above is included in builds. main.go refers to this definition.
|
// Test that go1.2 tag above is included in builds. main.go refers to this definition.
|
||||||
const go12tag = true
|
const go12tag = true
|
||||||
|
|
||||||
const APP_VER = "0.1.9.0329 Alpha"
|
const APP_VER = "0.2.0.0329 Alpha"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
base.AppVer = APP_VER
|
base.AppVer = APP_VER
|
||||||
|
|
|
@ -170,9 +170,17 @@ type Milestone struct {
|
||||||
Created time.Time `xorm:"created"`
|
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.
|
// Comment represents a comment in commit and issue page.
|
||||||
type Comment struct {
|
type Comment struct {
|
||||||
Id int64
|
Id int64
|
||||||
|
Type int
|
||||||
PosterId int64
|
PosterId int64
|
||||||
Poster *User `xorm:"-"`
|
Poster *User `xorm:"-"`
|
||||||
IssueId int64
|
IssueId int64
|
||||||
|
@ -183,21 +191,37 @@ type Comment struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateComment creates comment of issue or commit.
|
// 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()
|
sess := orm.NewSession()
|
||||||
defer sess.Close()
|
defer sess.Close()
|
||||||
sess.Begin()
|
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 {
|
CommitId: commitId, Line: line, Content: content}); err != nil {
|
||||||
sess.Rollback()
|
sess.Rollback()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
rawSql := "UPDATE `issue` SET num_comments = num_comments + 1 WHERE id = ?"
|
// Check comment type.
|
||||||
if _, err := sess.Exec(rawSql, issueId); err != nil {
|
switch cmtType {
|
||||||
sess.Rollback()
|
case IT_PLAIN:
|
||||||
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
|
||||||
|
}
|
||||||
|
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()
|
return sess.Commit()
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,7 @@ func LoadModelsConfig() {
|
||||||
DbCfg.Path = base.Cfg.MustValue("database", "PATH", "data/gogs.db")
|
DbCfg.Path = base.Cfg.MustValue("database", "PATH", "data/gogs.db")
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetEngine() {
|
func SetEngine() (err error) {
|
||||||
var err error
|
|
||||||
switch DbCfg.Type {
|
switch DbCfg.Type {
|
||||||
case "mysql":
|
case "mysql":
|
||||||
orm, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8",
|
orm, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8",
|
||||||
|
@ -47,12 +46,10 @@ func SetEngine() {
|
||||||
os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm)
|
os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm)
|
||||||
orm, err = xorm.NewEngine("sqlite3", DbCfg.Path)
|
orm, err = xorm.NewEngine("sqlite3", DbCfg.Path)
|
||||||
default:
|
default:
|
||||||
fmt.Printf("Unknown database type: %s\n", DbCfg.Type)
|
return fmt.Errorf("Unknown database type: %s\n", DbCfg.Type)
|
||||||
os.Exit(2)
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("models.init(fail to conntect database): %v\n", err)
|
return fmt.Errorf("models.init(fail to conntect database): %v\n", err)
|
||||||
os.Exit(2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WARNNING: for serv command, MUST remove the output to os.stdout,
|
// WARNNING: for serv command, MUST remove the output to os.stdout,
|
||||||
|
@ -62,20 +59,21 @@ func SetEngine() {
|
||||||
//orm.ShowErr = true
|
//orm.ShowErr = true
|
||||||
f, err := os.Create("xorm.log")
|
f, err := os.Create("xorm.log")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("models.init(fail to create xorm.log): %v\n", err)
|
return fmt.Errorf("models.init(fail to create xorm.log): %v\n", err)
|
||||||
os.Exit(2)
|
|
||||||
}
|
}
|
||||||
orm.Logger = f
|
orm.Logger = f
|
||||||
orm.ShowSQL = true
|
orm.ShowSQL = true
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEngine() {
|
func NewEngine() (err error) {
|
||||||
SetEngine()
|
if err = SetEngine(); err != nil {
|
||||||
if err := orm.Sync(new(User), new(PublicKey), new(Repository), new(Watch),
|
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 {
|
new(Action), new(Access), new(Issue), new(Comment)); err != nil {
|
||||||
fmt.Printf("sync database struct error: %v\n", err)
|
return fmt.Errorf("sync database struct error: %v\n", err)
|
||||||
os.Exit(2)
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Statistic struct {
|
type Statistic struct {
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
@ -59,15 +58,6 @@ func NewRepoContext() {
|
||||||
os.Exit(2)
|
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.
|
// Repository represents a git repository.
|
||||||
|
@ -105,15 +95,20 @@ func IsRepositoryExist(user *User, repoName string) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Define as all lower case!!
|
illegalEquals = []string{"raw", "install", "api", "avatar", "user", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin"}
|
||||||
illegalPatterns = []string{"[.][Gg][Ii][Tt]", "raw", "user", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin"}
|
illegalSuffixs = []string{".git"}
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsLegalName returns false if name contains illegal characters.
|
// IsLegalName returns false if name contains illegal characters.
|
||||||
func IsLegalName(repoName string) bool {
|
func IsLegalName(repoName string) bool {
|
||||||
for _, pattern := range illegalPatterns {
|
repoName = strings.ToLower(repoName)
|
||||||
has, _ := regexp.MatchString(pattern, repoName)
|
for _, char := range illegalEquals {
|
||||||
if has {
|
if repoName == char {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, char := range illegalSuffixs {
|
||||||
|
if strings.HasSuffix(repoName, char) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,6 +172,7 @@ type InstallForm struct {
|
||||||
DatabasePath string `form:"database_path"`
|
DatabasePath string `form:"database_path"`
|
||||||
RepoRootPath string `form:"repo_path"`
|
RepoRootPath string `form:"repo_path"`
|
||||||
RunUser string `form:"run_user"`
|
RunUser string `form:"run_user"`
|
||||||
|
Domain string `form:"domain"`
|
||||||
AppUrl string `form:"app_url"`
|
AppUrl string `form:"app_url"`
|
||||||
AdminName string `form:"admin_name" binding:"Required"`
|
AdminName string `form:"admin_name" binding:"Required"`
|
||||||
AdminPasswd string `form:"admin_pwd" binding:"Required;MinSize(6);MaxSize(30)"`
|
AdminPasswd string `form:"admin_pwd" binding:"Required;MinSize(6);MaxSize(30)"`
|
||||||
|
|
|
@ -272,18 +272,19 @@ func NewConfigContext() {
|
||||||
Domain = Cfg.MustValue("server", "DOMAIN")
|
Domain = Cfg.MustValue("server", "DOMAIN")
|
||||||
SecretKey = Cfg.MustValue("security", "SECRET_KEY")
|
SecretKey = Cfg.MustValue("security", "SECRET_KEY")
|
||||||
|
|
||||||
|
InstallLock = Cfg.MustBool("security", "INSTALL_LOCK", false)
|
||||||
|
|
||||||
RunUser = Cfg.MustValue("", "RUN_USER")
|
RunUser = Cfg.MustValue("", "RUN_USER")
|
||||||
curUser := os.Getenv("USERNAME")
|
curUser := os.Getenv("USERNAME")
|
||||||
if len(curUser) == 0 {
|
if len(curUser) == 0 {
|
||||||
curUser = os.Getenv("USER")
|
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)
|
fmt.Printf("Expect user(%s) but current user is: %s\n", RunUser, curUser)
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
InstallLock = Cfg.MustBool("security", "INSTALL_LOCK", false)
|
|
||||||
|
|
||||||
LogInRememberDays = Cfg.MustInt("security", "LOGIN_REMEMBER_DAYS")
|
LogInRememberDays = Cfg.MustInt("security", "LOGIN_REMEMBER_DAYS")
|
||||||
CookieUserName = Cfg.MustValue("security", "COOKIE_USERNAME")
|
CookieUserName = Cfg.MustValue("security", "COOKIE_USERNAME")
|
||||||
CookieRememberName = Cfg.MustValue("security", "COOKIE_REMEMBER_NAME")
|
CookieRememberName = Cfg.MustValue("security", "COOKIE_REMEMBER_NAME")
|
||||||
|
|
|
@ -1197,13 +1197,13 @@ html, body {
|
||||||
line-height: 42px;
|
line-height: 42px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#issue .issue-closed{
|
#issue .issue-closed, #issue .issue-opened {
|
||||||
border-bottom: 3px solid #CCC;
|
border-bottom: 2px solid #CCC;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
padding-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;
|
margin: 0 .8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,46 @@ package routers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Unknwon/goconfig"
|
||||||
|
"github.com/codegangsta/martini"
|
||||||
|
|
||||||
"github.com/gogits/gogs/models"
|
"github.com/gogits/gogs/models"
|
||||||
"github.com/gogits/gogs/modules/auth"
|
"github.com/gogits/gogs/modules/auth"
|
||||||
"github.com/gogits/gogs/modules/base"
|
"github.com/gogits/gogs/modules/base"
|
||||||
|
"github.com/gogits/gogs/modules/log"
|
||||||
|
"github.com/gogits/gogs/modules/mailer"
|
||||||
"github.com/gogits/gogs/modules/middleware"
|
"github.com/gogits/gogs/modules/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 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 err := models.NewEngine(); err != nil && base.InstallLock {
|
||||||
|
log.Error("%v", err)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
base.NewServices()
|
||||||
|
checkRunMode()
|
||||||
|
}
|
||||||
|
|
||||||
func Install(ctx *middleware.Context, form auth.InstallForm) {
|
func Install(ctx *middleware.Context, form auth.InstallForm) {
|
||||||
if base.InstallLock {
|
if base.InstallLock {
|
||||||
ctx.Handle(404, "install.Install", errors.New("Installation is prohibited"))
|
ctx.Handle(404, "install.Install", errors.New("Installation is prohibited"))
|
||||||
|
@ -20,14 +53,114 @@ func Install(ctx *middleware.Context, form auth.InstallForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["Title"] = "Install"
|
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
|
ctx.Data["PageIsInstall"] = true
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
if ctx.Req.Method == "GET" {
|
if ctx.Req.Method == "GET" {
|
||||||
ctx.HTML(200, "install")
|
ctx.HTML(200, "install")
|
||||||
return
|
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
|
||||||
|
|
||||||
|
if err := models.NewEngine(); err != nil {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(form.Host) > 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("security", "INSTALL_LOCK", "true")
|
||||||
|
|
||||||
|
if err := goconfig.SaveConfigFile(base.Cfg, "custom/conf/app.ini"); err != nil {
|
||||||
|
ctx.RenderWithErr("Fail to save configuration: "+err.Error(), "install", &form)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalInit()
|
||||||
|
|
||||||
|
log.Info("First-time run install finished!")
|
||||||
|
ctx.Redirect("/user/login")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ package repo
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/codegangsta/martini"
|
"github.com/codegangsta/martini"
|
||||||
|
|
||||||
|
@ -175,7 +176,7 @@ func ViewIssue(ctx *middleware.Context, params martini.Params) {
|
||||||
ctx.Data["Title"] = issue.Name
|
ctx.Data["Title"] = issue.Name
|
||||||
ctx.Data["Issue"] = issue
|
ctx.Data["Issue"] = issue
|
||||||
ctx.Data["Comments"] = comments
|
ctx.Data["Comments"] = comments
|
||||||
ctx.Data["IsIssueOwner"] = issue.PosterId == ctx.User.Id
|
ctx.Data["IsIssueOwner"] = ctx.Repo.IsOwner || issue.PosterId == ctx.User.Id
|
||||||
ctx.Data["IsRepoToolbarIssues"] = true
|
ctx.Data["IsRepoToolbarIssues"] = true
|
||||||
ctx.Data["IsRepoToolbarIssuesList"] = false
|
ctx.Data["IsRepoToolbarIssuesList"] = false
|
||||||
ctx.HTML(200, "issue/view")
|
ctx.HTML(200, "issue/view")
|
||||||
|
@ -225,24 +226,17 @@ func UpdateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat
|
||||||
}
|
}
|
||||||
|
|
||||||
func Comment(ctx *middleware.Context, params martini.Params) {
|
func Comment(ctx *middleware.Context, params martini.Params) {
|
||||||
fmt.Println(ctx.Query("change_status"))
|
|
||||||
if !ctx.Repo.IsValid {
|
if !ctx.Repo.IsValid {
|
||||||
ctx.Handle(404, "issue.Comment(invalid repo):", nil)
|
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 {
|
if err != nil {
|
||||||
ctx.Handle(404, "issue.Comment", err)
|
ctx.Handle(404, "issue.Comment(get index)", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
content := ctx.Query("content")
|
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.Id, index)
|
||||||
if len(content) == 0 {
|
|
||||||
ctx.Redirect(fmt.Sprintf("/%s/%s/issues/%d", ctx.User.Name, ctx.Repo.Repository.Name, index))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.Id, int64(index))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == models.ErrIssueNotExist {
|
if err == models.ErrIssueNotExist {
|
||||||
ctx.Handle(404, "issue.Comment", err)
|
ctx.Handle(404, "issue.Comment", err)
|
||||||
|
@ -252,16 +246,46 @@ func Comment(ctx *middleware.Context, params martini.Params) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch params["action"] {
|
// Check if issue owner changes the status of issue.
|
||||||
case "new":
|
var newStatus string
|
||||||
if err = models.CreateComment(ctx.User.Id, issue.Id, 0, 0, content); err != nil {
|
if ctx.Repo.IsOwner || issue.PosterId == ctx.User.Id {
|
||||||
ctx.Handle(500, "issue.Comment(create comment)", err)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
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))
|
ctx.Redirect(fmt.Sprintf("/%s/%s/issues/%d", ctx.User.Name, ctx.Repo.Repository.Name, index))
|
||||||
|
|
|
@ -120,7 +120,7 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) {
|
if ctx.HasError() {
|
||||||
ctx.HTML(200, "user/signin")
|
ctx.HTML(200, "user/signin")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -308,17 +308,19 @@ func Issues(ctx *middleware.Context) {
|
||||||
|
|
||||||
showRepos := make([]models.Repository, 0, len(repos))
|
showRepos := make([]models.Repository, 0, len(repos))
|
||||||
|
|
||||||
var closedIssueCount, createdByCount int
|
isShowClosed := ctx.Query("state") == "closed"
|
||||||
|
var closedIssueCount, createdByCount, allIssueCount int
|
||||||
|
|
||||||
// Get all issues.
|
// Get all issues.
|
||||||
allIssues := make([]models.Issue, 0, 5*len(repos))
|
allIssues := make([]models.Issue, 0, 5*len(repos))
|
||||||
for i, repo := range 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 {
|
if err != nil {
|
||||||
ctx.Handle(200, "user.Issues(get issues)", err)
|
ctx.Handle(200, "user.Issues(get issues)", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allIssueCount += repo.NumIssues
|
||||||
closedIssueCount += repo.NumClosedIssues
|
closedIssueCount += repo.NumClosedIssues
|
||||||
|
|
||||||
// Set repository information to issues.
|
// Set repository information to issues.
|
||||||
|
@ -330,12 +332,10 @@ func Issues(ctx *middleware.Context) {
|
||||||
repos[i].NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
|
repos[i].NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
|
||||||
if repos[i].NumOpenIssues > 0 {
|
if repos[i].NumOpenIssues > 0 {
|
||||||
showRepos = append(showRepos, repos[i])
|
showRepos = append(showRepos, repos[i])
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showIssues := make([]models.Issue, 0, len(allIssues))
|
showIssues := make([]models.Issue, 0, len(allIssues))
|
||||||
isShowClosed := ctx.Query("state") == "closed"
|
|
||||||
ctx.Data["IsShowClosed"] = isShowClosed
|
ctx.Data["IsShowClosed"] = isShowClosed
|
||||||
|
|
||||||
// Get posters and filter issues.
|
// Get posters and filter issues.
|
||||||
|
@ -361,9 +361,9 @@ func Issues(ctx *middleware.Context) {
|
||||||
|
|
||||||
ctx.Data["Repos"] = showRepos
|
ctx.Data["Repos"] = showRepos
|
||||||
ctx.Data["Issues"] = showIssues
|
ctx.Data["Issues"] = showIssues
|
||||||
ctx.Data["AllIssueCount"] = len(allIssues)
|
ctx.Data["AllIssueCount"] = allIssueCount
|
||||||
ctx.Data["ClosedIssueCount"] = closedIssueCount
|
ctx.Data["ClosedIssueCount"] = closedIssueCount
|
||||||
ctx.Data["OpenIssueCount"] = len(allIssues) - closedIssueCount
|
ctx.Data["OpenIssueCount"] = allIssueCount - closedIssueCount
|
||||||
ctx.Data["CreatedByCount"] = createdByCount
|
ctx.Data["CreatedByCount"] = createdByCount
|
||||||
ctx.HTML(200, "issue/user")
|
ctx.HTML(200, "issue/user")
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
<form action="/install" method="post" class="form-horizontal card" id="install-card">
|
<form action="/install" method="post" class="form-horizontal card" id="install-card">
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<h3>Install Steps For First-time Run</h3>
|
<h3>Install Steps For First-time Run</h3>
|
||||||
|
|
||||||
<div class="alert alert-danger form-error{{if .HasError}}{{else}} hidden{{end}}">{{.ErrorMsg}}</div>
|
<div class="alert alert-danger form-error{{if .HasError}}{{else}} hidden{{end}}">{{.ErrorMsg}}</div>
|
||||||
<p class="help-block text-center">Gogs requires MySQL or PostgreSQL based on your choice</p>
|
<p class="help-block text-center">Gogs requires MySQL or PostgreSQL, SQLite3 only available for official binary version</p>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-3 control-label">Database Type: </label>
|
<label class="col-md-3 control-label">Database Type: </label>
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
|
@ -16,26 +15,28 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="server-sql">
|
<div class="server-sql">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-3 control-label">Host: </label>
|
<label class="col-md-3 control-label">Host: </label>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="host" class="form-control" placeholder="Type database server host, leave blank to keep default" value="{{.DbCfg.Host}}" required="required">
|
<input name="host" class="form-control" placeholder="Type database server host" value="{{.host}}" required="required">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-3 control-label">User: </label>
|
<label class="col-md-3 control-label">User: </label>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="user" class="form-control" placeholder="Type database username" required="required" value="{{.DbCfg.User}}">
|
<input name="user" class="form-control" placeholder="Type database username" required="required" value="{{.user}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-3 control-label">Password: </label>
|
<label class="col-md-3 control-label">Password: </label>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="passwd" type="password" class="form-control" placeholder="Type database password" required="required" value="{{.DbCfg.Pwd}}">
|
<input name="passwd" type="password" class="form-control" placeholder="Type database password" required="required" value="{{.passwd}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@
|
||||||
<label class="col-md-3 control-label">Database Name: </label>
|
<label class="col-md-3 control-label">Database Name: </label>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="database_name" type="text" class="form-control" placeholder="Type mysql database name" value="{{.DbCfg.Name}}" required="required">
|
<input name="database_name" type="text" class="form-control" placeholder="Type mysql database name" value="{{.database_name}}" required="required">
|
||||||
<p class="help-block">Recommend use INNODB engine with utf8_general_ci charset.</p>
|
<p class="help-block">Recommend use INNODB engine with utf8_general_ci charset.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -59,12 +60,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sqlite-setting hide">
|
<div class="sqlite-setting hide">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-3 control-label">Path: </label>
|
<label class="col-md-3 control-label">Path: </label>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="database_path" class="form-control" placeholder="Type sqlite3 file path" value="{{.DbCfg.Path}}">
|
<input name="database_path" class="form-control" placeholder="Type sqlite3 file path" value="{{.database_path}}">
|
||||||
<p class="help-block">The file path of SQLite3 database.</p>
|
<p class="help-block">The file path of SQLite3 database.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -73,12 +75,11 @@
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
<p class="help-block text-center">General Settings of Gogs</p>
|
<p class="help-block text-center">General Settings of Gogs</p>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-3 control-label">Repository Path: </label>
|
<label class="col-md-3 control-label">Repository Path: </label>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="repo_path" type="text" class="form-control" placeholder="Type your repository directory" value="{{.RepoRootPath}}" required="required">
|
<input name="repo_path" type="text" class="form-control" placeholder="Type your repository directory" value="{{.repo_path}}" required="required">
|
||||||
|
|
||||||
<p class="help-block">The git copy of each repository is saved in this directory.</p>
|
<p class="help-block">The git copy of each repository is saved in this directory.</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -88,16 +89,25 @@
|
||||||
<label class="col-md-3 control-label">Run User: </label>
|
<label class="col-md-3 control-label">Run User: </label>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="run_user" type="text" class="form-control" placeholder="Type system user name" value="{{.RunUser}}" required="required">
|
<input name="run_user" type="text" class="form-control" placeholder="Type system user name" value="{{.run_user}}" required="required">
|
||||||
<p class="help-block">The user has access to visit and run Gogs.</p>
|
<p class="help-block">The user has access to visit and run Gogs.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label">Domain: </label>
|
||||||
|
|
||||||
|
<div class="col-md-8">
|
||||||
|
<input name="domain" type="text" class="form-control" placeholder="Type your domain name" value="{{.domain}}" required="required">
|
||||||
|
<p class="help-block">This affects SSH clone URL.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-3 control-label">App URL: </label>
|
<label class="col-md-3 control-label">App URL: </label>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="app_url" type="text" class="form-control" placeholder="Type app root URL " value="{{.AppUrl}}" required="required">
|
<input name="app_url" type="text" class="form-control" placeholder="Type app root URL" value="{{.app_url}}" required="required">
|
||||||
<p class="help-block">This affects HTTP/HTTPS clone URL and somewhere in e-mail.</p>
|
<p class="help-block">This affects HTTP/HTTPS clone URL and somewhere in e-mail.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -105,35 +115,30 @@
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
<p class="help-block text-center">Admin Account Settings</p>
|
<p class="help-block text-center">Admin Account Settings</p>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-3 control-label">Username: </label>
|
<label class="col-md-3 control-label">Username: </label>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="admin_name" type="text" class="form-control" placeholder="Type admin user name" value="admin" required="required">
|
<input name="admin_name" type="text" class="form-control" placeholder="Type admin user name" value="{{.admin_name}}" required="required">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group {{if .Err_AdminPasswd}}has-error has-feedback{{end}}">
|
||||||
<label class="col-md-3 control-label">Password: </label>
|
<label class="col-md-3 control-label">Password: </label>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="admin_pwd" type="password" class="form-control" placeholder="Type admin user password" required="required">
|
<input name="admin_pwd" type="password" class="form-control" placeholder="Type admin user password" value="{{.admin_pwd}}" required="required">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group {{if .Err_AdminEmail}}has-error has-feedback{{end}}">
|
||||||
<label class="col-md-3 control-label">E-mail: </label>
|
<label class="col-md-3 control-label">E-mail: </label>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="admin_email" type="text" class="form-control" placeholder="Type admin user e-mail" required="required">
|
<input name="admin_email" type="text" class="form-control" placeholder="Type admin user e-mail" value="{{.admin_email}}" required="required">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
<div class="form-group text-center">
|
<div class="form-group text-center">
|
||||||
<!-- <button class="btn btn-primary btn-lg">Test Configuration</button> -->
|
|
||||||
<button class="btn btn-danger btn-lg">Install Gogs</button>
|
<button class="btn btn-danger btn-lg">Install Gogs</button>
|
||||||
<button class="btn btn-default btn-sm" type="button" data-toggle="modal" data-target="#advance-options-modal">
|
<button class="btn btn-default btn-sm" type="button" data-toggle="modal" data-target="#advance-options-modal">
|
||||||
Advanced Options
|
Advanced Options
|
||||||
|
@ -151,21 +156,21 @@
|
||||||
<label class="col-md-3 control-label">SMTP Host: </label>
|
<label class="col-md-3 control-label">SMTP Host: </label>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="smtp_host" type="text" class="form-control" placeholder="Type SMTP host address">
|
<input name="smtp_host" type="text" class="form-control" placeholder="Type SMTP host address" value="{{.smtp_host}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-3 control-label">Email: </label>
|
<label class="col-md-3 control-label">Email: </label>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="mailer_user" type="text" class="form-control" placeholder="Type SMTP user e-mail address">
|
<input name="mailer_user" type="text" class="form-control" placeholder="Type SMTP user e-mail address" value="{{.mailer_user}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-3 control-label">Password: </label>
|
<label class="col-md-3 control-label">Password: </label>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="mailer_pwd" type="password" class="form-control" placeholder="Type SMTP user password">
|
<input name="mailer_pwd" type="password" class="form-control" placeholder="Type SMTP user password" value="{{.mailer_pwd}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
|
@ -175,7 +180,7 @@
|
||||||
<div class="col-md-offset-3 col-md-7">
|
<div class="col-md-offset-3 col-md-7">
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input name="register_confirm" type="checkbox">
|
<input name="register_confirm" type="checkbox" {{if .register_confirm}}checked{{end}}>
|
||||||
<strong>Enable Register Confirmation</strong>
|
<strong>Enable Register Confirmation</strong>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
@ -186,7 +191,7 @@
|
||||||
<div class="col-md-offset-3 col-md-7">
|
<div class="col-md-offset-3 col-md-7">
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input name="mail_notify" type="checkbox">
|
<input name="mail_notify" type="checkbox" {{if .mail_notify}}checked{{end}}>
|
||||||
<strong>Enable Mail Notification</strong>
|
<strong>Enable Mail Notification</strong>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -30,37 +30,37 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{range .Comments}}
|
{{range .Comments}}
|
||||||
<div class="issue-child" id="issue-comment-{{.Id}}">
|
{{if eq .Type 0}}
|
||||||
<a class="user pull-left" href="/user/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt=""/></a>
|
<div class="issue-child" id="issue-comment-{{.Id}}">
|
||||||
<div class="issue-content panel panel-default">
|
<a class="user pull-left" href="/user/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt=""/></a>
|
||||||
<div class="panel-heading">
|
<div class="issue-content panel panel-default">
|
||||||
<a href="/user/{{.Poster.Name}}" class="user">{{.Poster.Name}}</a> commented <span class="time">{{TimeSince .Created}}</span>
|
<div class="panel-heading">
|
||||||
<!-- <a class="issue-comment-del pull-right issue-action" href="#" title="Edit Comment"><i class="fa fa-times-circle"></i></a>
|
<a href="/user/{{.Poster.Name}}" class="user">{{.Poster.Name}}</a> commented <span class="time">{{TimeSince .Created}}</span>
|
||||||
<a class="issue-comment-edit pull-right issue-action" href="#" title="Remove Comment" data-url="{remove-link}"><i class="fa fa-edit"></i></a> -->
|
<!-- <a class="issue-comment-del pull-right issue-action" href="#" title="Edit Comment"><i class="fa fa-times-circle"></i></a>
|
||||||
<span class="role label label-default pull-right">Owner</span>
|
<a class="issue-comment-edit pull-right issue-action" href="#" title="Remove Comment" data-url="{remove-link}"><i class="fa fa-edit"></i></a> -->
|
||||||
</div>
|
<span class="role label label-default pull-right">Owner</span>
|
||||||
<div class="panel-body markdown">
|
</div>
|
||||||
{{str2html .Content}}
|
<div class="panel-body markdown">
|
||||||
</div>
|
{{str2html .Content}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else if eq .Type 1}}
|
||||||
|
<div class="issue-child issue-opened">
|
||||||
|
<a class="user pull-left" href="/user/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt="" /></a>
|
||||||
|
<div class="issue-content">
|
||||||
|
<a class="user pull-left" href="/user/{{.Poster.Name}}">{{.Poster.Name}}</a> <span class="label label-success">Reopened</span> this issue <span class="time">{{TimeSince .Created}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else if eq .Type 2}}
|
||||||
|
<div class="issue-child issue-closed">
|
||||||
|
<a class="user pull-left" href="/user/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt=""/></a>
|
||||||
|
<div class="issue-content">
|
||||||
|
<a class="user pull-left" href="/user/{{.Poster.Name}}">{{.Poster.Name}}</a> <span class="label label-danger">Closed</span> this issue <span class="time">{{TimeSince .Created}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
<!-- <div class="issue-child issue-closed">
|
|
||||||
<a class="user pull-left" href="{user.link}"><img class="avatar" src="{user.avatar}" alt=""/></a>
|
|
||||||
<div class="issue-content">
|
|
||||||
<a class="user pull-left" href="{user.link}">{user.name}</a>
|
|
||||||
<span class="btn btn-danger">Closed</span> this
|
|
||||||
<span class="time">{close.time}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="issue-child issue-opened">
|
|
||||||
<a class="user pull-left" href="{user.link}"><img class="avatar" src="{user.avatar}" alt=""/></a>
|
|
||||||
<div class="issue-content">
|
|
||||||
<a class="user pull-left" href="{user.link}">{user.name}</a>
|
|
||||||
<span class="btn btn-success">Reopened</span> this
|
|
||||||
<span class="time">{close.time}</span>
|
|
||||||
</div>
|
|
||||||
</div> -->
|
|
||||||
<hr class="issue-line"/>
|
<hr class="issue-line"/>
|
||||||
{{if .SignedUser}}<div class="issue-child issue-reply">
|
{{if .SignedUser}}<div class="issue-child issue-reply">
|
||||||
<a class="user pull-left" href="/user/{{.SignedUser.Name}}"><img class="avatar" src="{{.SignedUser.AvatarLink}}" alt=""/></a>
|
<a class="user pull-left" href="/user/{{.SignedUser.Name}}"><img class="avatar" src="{{.SignedUser.AvatarLink}}" alt=""/></a>
|
||||||
|
@ -68,8 +68,7 @@
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="md-help pull-right"><!-- todo help link -->
|
<div class="md-help pull-right">Content with <a href="https://help.github.com/articles/markdown-basics">Markdown</a>
|
||||||
Content with <a href="https://help.github.com/articles/markdown-basics">Markdown</a>
|
|
||||||
</div>
|
</div>
|
||||||
<ul class="nav nav-tabs" data-init="tabs">
|
<ul class="nav nav-tabs" data-init="tabs">
|
||||||
<li class="active issue-write"><a href="#issue-textarea" data-toggle="tab">Write</a></li>
|
<li class="active issue-write"><a href="#issue-textarea" data-toggle="tab">Write</a></li>
|
||||||
|
@ -82,13 +81,13 @@
|
||||||
<textarea class="form-control" name="content" id="issue-reply-content" rows="10" placeholder="Write some content" data-ajax-rel="issue-preview" data-ajax-val="val" data-ajax-field="content">{{.content}}</textarea>
|
<textarea class="form-control" name="content" id="issue-reply-content" rows="10" placeholder="Write some content" data-ajax-rel="issue-preview" data-ajax-val="val" data-ajax-field="content">{{.content}}</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane issue-preview-content" id="issue-preview">loading...</div>
|
<div class="tab-pane issue-preview-content" id="issue-preview">Loading...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
{{if .Issue.IsClosed}}
|
{{if .Issue.IsClosed}}
|
||||||
<input type="submit" class="btn-default btn issue-open" id="issue-open-btn" data-origin="Re-Open" data-text="Re-Open & Comment" name="change_status" value="Reopen"/>{{else}}
|
<input type="submit" class="btn-default btn issue-open" id="issue-open-btn" data-origin="Reopen" data-text="Reopen & Comment" name="change_status" value="Reopen"/>{{else}}
|
||||||
<input type="submit" class="btn-default btn issue-close" id="issue-close-btn" data-origin="Close" data-text="Close & Comment" name="change_status" value="Close"/>{{end}}
|
<input type="submit" class="btn-default btn issue-close" id="issue-close-btn" data-origin="Close" data-text="Close & Comment" name="change_status" value="Close"/>{{end}}
|
||||||
<button class="btn-success btn" id="issue-reply-btn">Comment</button>
|
<button class="btn-success btn" id="issue-reply-btn">Comment</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
28
web.go
28
web.go
|
@ -8,19 +8,16 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
"github.com/codegangsta/martini"
|
"github.com/codegangsta/martini"
|
||||||
|
|
||||||
"github.com/gogits/binding"
|
"github.com/gogits/binding"
|
||||||
|
|
||||||
"github.com/gogits/gogs/models"
|
|
||||||
"github.com/gogits/gogs/modules/auth"
|
"github.com/gogits/gogs/modules/auth"
|
||||||
"github.com/gogits/gogs/modules/avatar"
|
"github.com/gogits/gogs/modules/avatar"
|
||||||
"github.com/gogits/gogs/modules/base"
|
"github.com/gogits/gogs/modules/base"
|
||||||
"github.com/gogits/gogs/modules/log"
|
"github.com/gogits/gogs/modules/log"
|
||||||
"github.com/gogits/gogs/modules/mailer"
|
|
||||||
"github.com/gogits/gogs/modules/middleware"
|
"github.com/gogits/gogs/modules/middleware"
|
||||||
"github.com/gogits/gogs/routers"
|
"github.com/gogits/gogs/routers"
|
||||||
"github.com/gogits/gogs/routers/admin"
|
"github.com/gogits/gogs/routers/admin"
|
||||||
|
@ -40,27 +37,6 @@ and it takes care of all the other things for you`,
|
||||||
Flags: []cli.Flag{},
|
Flags: []cli.Flag{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// globalInit is for global configuration reload-able.
|
|
||||||
func globalInit() {
|
|
||||||
base.NewConfigContext()
|
|
||||||
mailer.NewMailerContext()
|
|
||||||
models.LoadModelsConfig()
|
|
||||||
models.LoadRepoConfig()
|
|
||||||
models.NewRepoContext()
|
|
||||||
models.NewEngine()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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))
|
|
||||||
}
|
|
||||||
|
|
||||||
func newMartini() *martini.ClassicMartini {
|
func newMartini() *martini.ClassicMartini {
|
||||||
r := martini.NewRouter()
|
r := martini.NewRouter()
|
||||||
m := martini.New()
|
m := martini.New()
|
||||||
|
@ -74,9 +50,7 @@ func newMartini() *martini.ClassicMartini {
|
||||||
|
|
||||||
func runWeb(*cli.Context) {
|
func runWeb(*cli.Context) {
|
||||||
fmt.Println("Server is running...")
|
fmt.Println("Server is running...")
|
||||||
globalInit()
|
routers.GlobalInit()
|
||||||
base.NewServices()
|
|
||||||
checkRunMode()
|
|
||||||
log.Info("%s %s", base.AppName, base.AppVer)
|
log.Info("%s %s", base.AppName, base.AppVer)
|
||||||
|
|
||||||
m := newMartini()
|
m := newMartini()
|
||||||
|
|
Loading…
Reference in a new issue