summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--models/repo.go6
-rw-r--r--models/user.go2
-rw-r--r--modules/log/conn.go104
-rw-r--r--modules/log/console.go6
-rw-r--r--modules/log/database.go68
-rw-r--r--modules/log/log.go16
-rw-r--r--modules/log/smtp.go87
-rw-r--r--public/ng/css/gogs.css21
-rw-r--r--routers/install.go5
-rw-r--r--routers/user/home.go4
-rw-r--r--templates/org/home.tmpl2
-rw-r--r--templates/repo/home.tmpl6
-rw-r--r--templates/repo/view_file.tmpl8
-rw-r--r--templates/user/dashboard/dashboard.tmpl48
-rw-r--r--templates/user/dashboard/nav.tmpl2
-rw-r--r--templates/user/dashboard/repo_list.tmpl12
16 files changed, 359 insertions, 38 deletions
diff --git a/models/repo.go b/models/repo.go
index da0813e3b4..1e899c182b 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -11,6 +11,7 @@ import (
"html/template"
"io/ioutil"
"os"
+ "os/exec"
"path"
"path/filepath"
"regexp"
@@ -84,6 +85,11 @@ func LoadRepoConfig() {
func NewRepoContext() {
zip.Verbose = false
+ // Check Git installation.
+ if _, err := exec.LookPath("git"); err != nil {
+ log.Fatal(4, "Fail to test 'git' command: %v (forgotten install?)", err)
+ }
+
// Check Git version.
ver, err := git.GetVersion()
if err != nil {
diff --git a/models/user.go b/models/user.go
index 540f4b6af4..ca772556b7 100644
--- a/models/user.go
+++ b/models/user.go
@@ -81,7 +81,7 @@ type User struct {
// DashboardLink returns the user dashboard page link.
func (u *User) DashboardLink() string {
if u.IsOrganization() {
- return "/org/" + u.Name + "/dashboard"
+ return "/org/" + u.Name + "/dashboard/"
}
return "/"
}
diff --git a/modules/log/conn.go b/modules/log/conn.go
new file mode 100644
index 0000000000..c104a16c93
--- /dev/null
+++ b/modules/log/conn.go
@@ -0,0 +1,104 @@
+// 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 log
+
+import (
+ "encoding/json"
+ "io"
+ "log"
+ "net"
+)
+
+// ConnWriter implements LoggerInterface.
+// it writes messages in keep-live tcp connection.
+type ConnWriter struct {
+ lg *log.Logger
+ innerWriter io.WriteCloser
+ ReconnectOnMsg bool `json:"reconnectOnMsg"`
+ Reconnect bool `json:"reconnect"`
+ Net string `json:"net"`
+ Addr string `json:"addr"`
+ Level int `json:"level"`
+}
+
+// create new ConnWrite returning as LoggerInterface.
+func NewConn() LoggerInterface {
+ conn := new(ConnWriter)
+ conn.Level = TRACE
+ return conn
+}
+
+// init connection writer with json config.
+// json config only need key "level".
+func (cw *ConnWriter) Init(jsonconfig string) error {
+ return json.Unmarshal([]byte(jsonconfig), cw)
+}
+
+// write message in connection.
+// if connection is down, try to re-connect.
+func (cw *ConnWriter) WriteMsg(msg string, skip, level int) error {
+ if cw.Level > level {
+ return nil
+ }
+ if cw.neddedConnectOnMsg() {
+ if err := cw.connect(); err != nil {
+ return err
+ }
+ }
+
+ if cw.ReconnectOnMsg {
+ defer cw.innerWriter.Close()
+ }
+ cw.lg.Println(msg)
+ return nil
+}
+
+func (_ *ConnWriter) Flush() {
+}
+
+// destroy connection writer and close tcp listener.
+func (cw *ConnWriter) Destroy() {
+ if cw.innerWriter == nil {
+ return
+ }
+ cw.innerWriter.Close()
+}
+
+func (cw *ConnWriter) connect() error {
+ if cw.innerWriter != nil {
+ cw.innerWriter.Close()
+ cw.innerWriter = nil
+ }
+
+ conn, err := net.Dial(cw.Net, cw.Addr)
+ if err != nil {
+ return err
+ }
+
+ if tcpConn, ok := conn.(*net.TCPConn); ok {
+ tcpConn.SetKeepAlive(true)
+ }
+
+ cw.innerWriter = conn
+ cw.lg = log.New(conn, "", log.Ldate|log.Ltime)
+ return nil
+}
+
+func (cw *ConnWriter) neddedConnectOnMsg() bool {
+ if cw.Reconnect {
+ cw.Reconnect = false
+ return true
+ }
+
+ if cw.innerWriter == nil {
+ return true
+ }
+
+ return cw.ReconnectOnMsg
+}
+
+func init() {
+ Register("conn", NewConn)
+}
diff --git a/modules/log/console.go b/modules/log/console.go
index 92d6c2a406..f5a8b96fd7 100644
--- a/modules/log/console.go
+++ b/modules/log/console.go
@@ -61,13 +61,13 @@ func (cw *ConsoleWriter) WriteMsg(msg string, skip, level int) error {
return nil
}
-func (_ *ConsoleWriter) Destroy() {
-}
-
func (_ *ConsoleWriter) Flush() {
}
+func (_ *ConsoleWriter) Destroy() {
+}
+
func init() {
Register("console", NewConsole)
}
diff --git a/modules/log/database.go b/modules/log/database.go
new file mode 100644
index 0000000000..5857cb6d66
--- /dev/null
+++ b/modules/log/database.go
@@ -0,0 +1,68 @@
+// 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 log
+
+import (
+ "encoding/json"
+
+ "github.com/go-xorm/xorm"
+)
+
+type Log struct {
+ Id int64
+ Level int
+ Msg string `xorm:"TEXT"`
+}
+
+// DatabaseWriter implements LoggerInterface and is used to log into database.
+type DatabaseWriter struct {
+ Driver string `json:"driver"`
+ Conn string `json:"conn"`
+ Level int `json:"level"`
+ x *xorm.Engine
+}
+
+func NewDatabase() LoggerInterface {
+ return &DatabaseWriter{Level: TRACE}
+}
+
+// init database writer with json config.
+// config like:
+// {
+// "driver": "mysql"
+// "conn":"root:root@tcp(127.0.0.1:3306)/gogs?charset=utf8",
+// "level": 0
+// }
+// connection string is based on xorm.
+func (d *DatabaseWriter) Init(jsonconfig string) (err error) {
+ if err = json.Unmarshal([]byte(jsonconfig), d); err != nil {
+ return err
+ }
+ d.x, err = xorm.NewEngine(d.Driver, d.Conn)
+ if err != nil {
+ return err
+ }
+ return d.x.Sync(new(Log))
+}
+
+// write message in database writer.
+func (d *DatabaseWriter) WriteMsg(msg string, skip, level int) error {
+ if level < d.Level {
+ return nil
+ }
+
+ _, err := d.x.Insert(&Log{Level: level, Msg: msg})
+ return err
+}
+
+func (_ *DatabaseWriter) Flush() {
+}
+
+func (_ *DatabaseWriter) Destroy() {
+}
+
+func init() {
+ Register("database", NewDatabase)
+}
diff --git a/modules/log/log.go b/modules/log/log.go
index 6ca6b5b0b1..00f777e72a 100644
--- a/modules/log/log.go
+++ b/modules/log/log.go
@@ -87,12 +87,12 @@ func Fatal(skip int, format string, v ...interface{}) {
os.Exit(1)
}
-// .___ _______________________________________________________ _________ ___________
-// | |\ \__ ___/\_ _____/\______ \_ _____/ _ \ \_ ___ \\_ _____/
-// | |/ | \| | | __)_ | _/| __)/ /_\ \/ \ \/ | __)_
-// | / | \ | | \ | | \| \/ | \ \____| \
-// |___\____|__ /____| /_______ / |____|_ /\___ /\____|__ /\______ /_______ /
-// \/ \/ \/ \/ \/ \/ \/
+// .___ __ _____
+// | | _____/ |_ ____________/ ____\____ ____ ____
+// | |/ \ __\/ __ \_ __ \ __\\__ \ _/ ___\/ __ \
+// | | | \ | \ ___/| | \/| | / __ \\ \__\ ___/
+// |___|___| /__| \___ >__| |__| (____ /\___ >___ >
+// \/ \/ \/ \/ \/
type LogLevel int
@@ -168,7 +168,7 @@ func (l *Logger) SetLogger(adapter string, config string) error {
l.outputs[adapter] = lg
l.adapter = adapter
} else {
- panic("log: unknown adapter \"" + adapter + "\" (forgotten Register?)")
+ panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)")
}
return nil
}
@@ -181,7 +181,7 @@ func (l *Logger) DelLogger(adapter string) error {
lg.Destroy()
delete(l.outputs, adapter)
} else {
- panic("log: unknown adapter \"" + adapter + "\" (forgotten Register?)")
+ panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)")
}
return nil
}
diff --git a/modules/log/smtp.go b/modules/log/smtp.go
new file mode 100644
index 0000000000..0a10e56a63
--- /dev/null
+++ b/modules/log/smtp.go
@@ -0,0 +1,87 @@
+// 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 log
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/smtp"
+ "strings"
+ "time"
+)
+
+const (
+ subjectPhrase = "Diagnostic message from server"
+)
+
+// smtpWriter implements LoggerInterface and is used to send emails via given SMTP-server.
+type SmtpWriter struct {
+ Username string `json:"Username"`
+ Password string `json:"password"`
+ Host string `json:"Host"`
+ Subject string `json:"subject"`
+ RecipientAddresses []string `json:"sendTos"`
+ Level int `json:"level"`
+}
+
+// create smtp writer.
+func NewSmtpWriter() LoggerInterface {
+ return &SmtpWriter{Level: TRACE}
+}
+
+// init smtp writer with json config.
+// config like:
+// {
+// "Username":"example@gmail.com",
+// "password:"password",
+// "host":"smtp.gmail.com:465",
+// "subject":"email title",
+// "sendTos":["email1","email2"],
+// "level":LevelError
+// }
+func (sw *SmtpWriter) Init(jsonconfig string) error {
+ return json.Unmarshal([]byte(jsonconfig), sw)
+}
+
+// write message in smtp writer.
+// it will send an email with subject and only this message.
+func (s *SmtpWriter) WriteMsg(msg string, skip, level int) error {
+ if level < s.Level {
+ return nil
+ }
+
+ hp := strings.Split(s.Host, ":")
+
+ // Set up authentication information.
+ auth := smtp.PlainAuth(
+ "",
+ s.Username,
+ s.Password,
+ hp[0],
+ )
+ // Connect to the server, authenticate, set the sender and recipient,
+ // and send the email all in one step.
+ content_type := "Content-Type: text/plain" + "; charset=UTF-8"
+ mailmsg := []byte("To: " + strings.Join(s.RecipientAddresses, ";") + "\r\nFrom: " + s.Username + "<" + s.Username +
+ ">\r\nSubject: " + s.Subject + "\r\n" + content_type + "\r\n\r\n" + fmt.Sprintf(".%s", time.Now().Format("2006-01-02 15:04:05")) + msg)
+
+ return smtp.SendMail(
+ s.Host,
+ auth,
+ s.Username,
+ s.RecipientAddresses,
+ mailmsg,
+ )
+}
+
+func (_ *SmtpWriter) Flush() {
+}
+
+func (_ *SmtpWriter) Destroy() {
+}
+
+func init() {
+ Register("smtp", NewSmtpWriter)
+}
diff --git a/public/ng/css/gogs.css b/public/ng/css/gogs.css
index 96cf77a639..d352f0bf68 100644
--- a/public/ng/css/gogs.css
+++ b/public/ng/css/gogs.css
@@ -660,32 +660,41 @@ The dashboard page style
#dashboard-sidebar-menu > li.last > a {
border-top-right-radius: .3em;
}
+#dashboard-my-org li,
#dashboard-my-repo li {
border-bottom: 1px solid #EAEAEA;
}
+#dashboard-my-org li.private,
#dashboard-my-repo li.private {
background-color: #fcf8e9;
}
+#dashboard-my-org li:last-child,
#dashboard-my-repo li:last-child {
border-bottom: none;
}
+#dashboard-my-org li a,
#dashboard-my-repo li a {
padding: 6px 1.2em;
display: block;
}
+#dashboard-my-org li a .octicon,
#dashboard-my-repo li a .octicon {
margin-right: 6px;
color: #888;
}
+#dashboard-my-org li a:hover .repo-name,
#dashboard-my-repo li a:hover .repo-name {
text-decoration: underline;
}
+#dashboard-my-org .repo-name,
#dashboard-my-repo .repo-name {
font-size: 1.1em;
}
+#dashboard-my-org .repo-star,
#dashboard-my-repo .repo-star {
color: #888;
}
+#dashboard-my-org .repo-contrib-header,
#dashboard-my-repo .repo-contrib-header {
border-top: 1px solid #d6d6d6;
}
@@ -1139,6 +1148,17 @@ The register and sign-in page style
overflow: auto;
overflow-x: auto;
overflow-y: hidden;
+ background: white;
+}
+.code-view .view-raw {
+ min-height: 40px;
+ text-align: center;
+ padding-top: 20px;
+}
+.code-view .view-raw .btn {
+ font-size: 1.05em;
+ line-height: 16px;
+ padding: 6px 8px;
}
.code-view table {
width: 100%;
@@ -1163,7 +1183,6 @@ The register and sign-in page style
}
.code-view .lines-code > pre {
border: none;
- background: none;
border-left: 1px solid #ddd;
}
.code-view .lines-code > pre > ol.linenums > li {
diff --git a/routers/install.go b/routers/install.go
index 516d11e4aa..c63ac6909c 100644
--- a/routers/install.go
+++ b/routers/install.go
@@ -54,11 +54,12 @@ func GlobalInit() {
log.Trace("Log path: %s", setting.LogRootPath)
mailer.NewMailerContext()
models.LoadModelsConfig()
- models.LoadRepoConfig()
- models.NewRepoContext()
NewServices()
if setting.InstallLock {
+ models.LoadRepoConfig()
+ models.NewRepoContext()
+
if err := models.NewEngine(); err != nil {
log.Fatal(4, "Fail to initialize ORM engine: %v", err)
}
diff --git a/routers/user/home.go b/routers/user/home.go
index b5a789ae0e..186cbe41a7 100644
--- a/routers/user/home.go
+++ b/routers/user/home.go
@@ -32,7 +32,6 @@ func Dashboard(ctx *middleware.Context) {
ctx.Handle(500, "home.Dashboard(GetOrganizations)", err)
return
}
- ctx.Data["Orgs"] = ctx.User.Orgs
ctx.Data["ContextUser"] = ctx.User
repos, err := models.GetRepositories(ctx.User.Id, true)
@@ -40,9 +39,6 @@ func Dashboard(ctx *middleware.Context) {
ctx.Handle(500, "GetRepositories", err)
return
}
- for _, repo := range repos {
- repo.Owner = ctx.User
- }
ctx.Data["Repos"] = repos
ctx.Data["CollaborativeRepos"], err = models.GetCollaborativeRepos(ctx.User.Name)
diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl
index a3c2326230..b6675d3059 100644
--- a/templates/org/home.tmpl
+++ b/templates/org/home.tmpl
@@ -34,7 +34,7 @@
</div>
<h3 class="org-repo-name"><a href="/{{$.Org.Name}}/{{.Name}}">{{.Name}}</a></h3>
<p class="org-repo-description">{{.Description}}</p>
- <p class="org-repo-update">Updated {{TimeSince .Updated}}</p>
+ <p class="org-repo-update">Updated {{TimeSince .Updated $.Lang}}</p>
</div>
{{end}}
</div>
diff --git a/templates/repo/home.tmpl b/templates/repo/home.tmpl
index 1958c40998..5f16a7baf0 100644
--- a/templates/repo/home.tmpl
+++ b/templates/repo/home.tmpl
@@ -74,7 +74,7 @@
<a href="#">
<button class="btn btn-gray btn-small btn-radius">
<i class="octicon octicon-git-branch"></i> Branch :
- <strong id="repo-branch-current">{{.BranchName}}</strong>
+ <strong id="repo-branch-current">{{if .IsViewBranch}}{{.BranchName}}{{else}}{{ShortSha .BranchName}}{{end}}</strong>
</button>
</a>
<div class="drop-down panel">
@@ -87,7 +87,7 @@
</ul>
<ul class="menu menu-vertical switching-list" id="repo-branch-list">
{{range .Branches}}
- <li {{if eq . $.BranchName}}class="checked"{{end}}><a href="{{$.RepoLink}}/src/{{.}}"><i class="octicon octicon-check"></i>master</a></li>
+ <li {{if eq . $.BranchName}}class="checked"{{end}}><a href="{{$.RepoLink}}/src/{{.}}"><i class="octicon octicon-check"></i>{{.}}</a></li>
{{end}}
</ul>
<ul class="menu menu-vertical switching-list" id="repo-tag-list">
@@ -137,7 +137,7 @@
<a class="radius" href="{{.RepoLink}}/pulls"><i class="octicon octicon-git-pull-request"></i>Pull Requests<span class="num right label label-blue label-radius">{{.Repository.NumOpenPulls}}</span></a>
</li>
<li class="border-bottom"></li>
- <li class="head">{{.BranchName}}</li>
+ <li class="head">{{if .IsViewBranch}}{{.BranchName}}{{else}}{{ShortSha .BranchName}}{{end}}</li>
<li>
<a class="radius" href="{{.RepoLink}}/commits/{{.BranchName}}"><i class="octicon octicon-history"></i>Commits <span class="num right label label-gray label-radius">{{.CommitsCount}}</span></a>
</li>
diff --git a/templates/repo/view_file.tmpl b/templates/repo/view_file.tmpl
index be54419404..fb05945b9f 100644
--- a/templates/repo/view_file.tmpl
+++ b/templates/repo/view_file.tmpl
@@ -15,6 +15,14 @@
<div class="{{if .ReadmeExist}}panel-content markdown{{end}} code-view">
{{if .ReadmeExist}}
{{.FileContent | Str2html}}
+ {{else if not .IsFileText}}
+ <div class="view-raw">
+ {{if .IsImageFile}}
+ <img src="{{.FileLink}}">
+ {{else}}
+ <a href="{{.FileLink}}" rel="nofollow" class="btn btn-gray btn-radius">View Raw</a>
+ {{end}}
+ </div>
{{else if .FileSize}}
<table>
<tbody>
diff --git a/templates/user/dashboard/dashboard.tmpl b/templates/user/dashboard/dashboard.tmpl
index 209a495b58..b472953136 100644
--- a/templates/user/dashboard/dashboard.tmpl
+++ b/templates/user/dashboard/dashboard.tmpl
@@ -48,7 +48,9 @@
<div id="dashboard-sidebar" class="right grid-1-3">
<ul id="dashboard-sidebar-menu" class="menu menu-line">
<li class="js-tab-nav js-tab-nav-show first" data-tab-target="#dashboard-my-repo"><a href="#">{{.i18n.Tr "repository"}}</a></li>
+ {{if not .ContextUser.IsOrganization}}
<li class="js-tab-nav" data-tab-target="#dashboard-my-org"><a href="#">{{.i18n.Tr "organization"}}</a></li>
+ {{end}}
<li class="js-tab-nav last" data-tab-target="#dashboard-my-mirror"><a href="#">{{.i18n.Tr "mirror"}}</a></li>
<li class="drop right">
<button class="btn btn-green text-bold" id="dashboard-new-repo">
@@ -70,26 +72,68 @@
<div class="panel-body">
<ul class="list-no-style">
{{range .Repos}}
- {{template "user/dashboard/repo_list" .}}
+ <li {{if .IsPrivate}}class="private"{{end}}>
+ <a href="{{$.ContextUser.Name}}/{{.Name}}">
+ <i class="octicon octicon-{{if .IsPrivate}}lock{{else if .IsFork}}repo-forked{{else if .IsMirror}}repo-clone{{else}}repo{{end}}"></i>
+ <span class="repo-name">
+ <strong class="repo">{{.Name}}</strong>
+ </span>
+ <span class="right repo-star">
+ <i class="octicon octicon-star"></i>{{.NumStars}}
+ </span>
+ </a>
+ </li>
{{end}}
</ul>
</div>
+ {{if not .ContextUser.IsOrganization}}
<div class="panel-header repo-contrib-header">
<h4 class="text-bold">{{.i18n.Tr "home.collaborative_repos"}}</h4>
</div>
<div class="panel-body">
<ul class="list-no-style">
{{range .CollaborativeRepos}}
- {{template "user/dashboard/repo_list" .}}
+ <li {{if .IsPrivate}}class="private"{{end}}>
+ <a href="{{.Owner.Name}}/{{.Name}}">
+ <i class="octicon octicon-{{if .IsPrivate}}lock{{else if .IsFork}}repo-forked{{else if .IsMirror}}repo-clone{{else}}repo{{end}}"></i>
+ <span class="repo-name">
+ <span class="repo-name-prefix">{{.Owner.Name}} / </span>
+ <strong class="repo">{{.Name}}</strong>
+ </span>
+ <span class="right repo-star">
+ <i class="octicon octicon-star"></i>{{.NumStars}}
+ </span>
+ </a>
+ </li>
{{end}}
</ul>
</div>
+ {{end}}
</div>
+ {{if not .ContextUser.IsOrganization}}
<div class="panel" id="dashboard-my-org">
<div class="panel-header">
<h4 class="text-bold">{{.i18n.Tr "home.my_orgs"}}</h4>
</div>
+ <div class="panel-body">
+ <ul class="list-no-style">
+ {{range .ContextUser.Orgs}}
+ <li>
+ <a href="/{{.Name}}">
+ <i class="octicon octicon-organization"></i>
+ <span class="repo-name">
+ <strong class="repo">{{.Name}}</strong>
+ </span>
+ <span class="right repo-star">
+ <i class="octicon octicon-repo"></i>{{.NumRepos}}
+ </span>
+ </a>
+ </li>
+ {{end}}
+ </ul>
+ </div>
</div>
+ {{end}}
<div class="panel" id="dashboard-my-mirror">
<div class="panel-header">
<h4 class="text-bold">{{.i18n.Tr "home.my_mirrors"}}</h4>
diff --git a/templates/user/dashboard/nav.tmpl b/templates/user/dashboard/nav.tmpl
index 6064f35692..a2d990fa7d 100644
--- a/templates/user/dashboard/nav.tmpl
+++ b/templates/user/dashboard/nav.tmpl
@@ -15,7 +15,7 @@
{{.SignedUser.Name}}
</a>
</li>
- {{range .Orgs}}
+ {{range .ContextUser.Orgs}}
<li class="org {{if eq $.ContextUser.Id .Id}}checked{{end}}">
<a href="{{.DashboardLink}}">
<i class="octicon octicon-check"></i>
diff --git a/templates/user/dashboard/repo_list.tmpl b/templates/user/dashboard/repo_list.tmpl
deleted file mode 100644
index e3d35e8ecc..0000000000
--- a/templates/user/dashboard/repo_list.tmpl
+++ /dev/null
@@ -1,12 +0,0 @@
-<li {{if .IsPrivate}}class="private"{{end}}>
- <a href="{{.Owner.Name}}/{{.Name}}">
- <i class="octicon octicon-{{if .IsPrivate}}lock{{else if .IsFork}}repo-forked{{else if .IsMirror}}repo-clone{{else}}repo{{end}}"></i>
- <span class="repo-name">
- <!-- <span class="repo-name-prefix">gogits / </span> -->
- <strong class="repo">{{.Name}}</strong>
- </span>
- <span class="right repo-star">
- <i class="octicon octicon-star"></i>{{.NumStars}}
- </span>
- </a>
-</li> \ No newline at end of file