Show custom avatars in commits

tokarchuk/v1.17
Unknwon 9 years ago
parent 1559bd58e7
commit 1d57f0d64f
  1. 2
      README.md
  2. 6
      cmd/web.go
  3. 2
      gogs.go
  4. 46
      models/action.go
  5. 9
      models/update.go
  6. 2
      models/user.go
  7. 18
      modules/base/tool.go
  8. 64
      modules/template/template.go
  9. 3
      routers/repo/view.go
  10. 2
      templates/.VERSION
  11. 8
      templates/user/dashboard/dashboard.tmpl
  12. 2
      templates/user/dashboard/feeds.tmpl

@ -5,7 +5,7 @@ Gogs - Go Git Service [![Build Status](https://travis-ci.org/gogits/gogs.svg?bra
![](public/img/gogs-large-resize.png) ![](public/img/gogs-large-resize.png)
##### Current version: 0.7.7 Beta ##### Current version: 0.7.8 Beta
<table> <table>
<tr> <tr>

@ -7,7 +7,7 @@ package cmd
import ( import (
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"html/template" gotmpl "html/template"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/http/fcgi" "net/http/fcgi"
@ -35,11 +35,11 @@ import (
"github.com/gogits/gogs/modules/auth" "github.com/gogits/gogs/modules/auth"
"github.com/gogits/gogs/modules/auth/apiv1" "github.com/gogits/gogs/modules/auth/apiv1"
"github.com/gogits/gogs/modules/avatar" "github.com/gogits/gogs/modules/avatar"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/bindata" "github.com/gogits/gogs/modules/bindata"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/middleware" "github.com/gogits/gogs/modules/middleware"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/template"
"github.com/gogits/gogs/routers" "github.com/gogits/gogs/routers"
"github.com/gogits/gogs/routers/admin" "github.com/gogits/gogs/routers/admin"
"github.com/gogits/gogs/routers/api/v1" "github.com/gogits/gogs/routers/api/v1"
@ -124,7 +124,7 @@ func newMacaron() *macaron.Macaron {
)) ))
m.Use(macaron.Renderer(macaron.RenderOptions{ m.Use(macaron.Renderer(macaron.RenderOptions{
Directory: path.Join(setting.StaticRootPath, "templates"), Directory: path.Join(setting.StaticRootPath, "templates"),
Funcs: []template.FuncMap{base.TemplateFuncs}, Funcs: []gotmpl.FuncMap{template.Funcs},
IndentJSON: macaron.Env != macaron.PROD, IndentJSON: macaron.Env != macaron.PROD,
})) }))

@ -17,7 +17,7 @@ import (
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
) )
const APP_VER = "0.7.7.1113 Beta" const APP_VER = "0.7.8.1113 Beta"
func init() { func init() {
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())

@ -208,8 +208,48 @@ func issueIndexTrimRight(c rune) bool {
return !unicode.IsDigit(c) return !unicode.IsDigit(c)
} }
type PushCommit struct {
Sha1 string
Message string
AuthorEmail string
AuthorName string
}
type PushCommits struct {
Len int
Commits []*PushCommit
CompareUrl string
avatars map[string]string
}
func NewPushCommits() *PushCommits {
return &PushCommits{
avatars: make(map[string]string),
}
}
// AvatarLink tries to match user in database with e-mail
// in order to show custom avatar, and falls back to general avatar link.
func (push *PushCommits) AvatarLink(email string) string {
_, ok := push.avatars[email]
if !ok {
u, err := GetUserByEmail(email)
if err != nil {
push.avatars[email] = base.AvatarLink(email)
if !IsErrUserNotExist(err) {
log.Error(4, "GetUserByEmail: %v", err)
}
} else {
push.avatars[email] = u.AvatarLink()
}
}
return push.avatars[email]
}
// updateIssuesCommit checks if issues are manipulated by commit message. // updateIssuesCommit checks if issues are manipulated by commit message.
func updateIssuesCommit(u *User, repo *Repository, repoUserName, repoName string, commits []*base.PushCommit) error { func updateIssuesCommit(u *User, repo *Repository, repoUserName, repoName string, commits []*PushCommit) error {
// Commits are appended in the reverse order. // Commits are appended in the reverse order.
for i := len(commits) - 1; i >= 0; i-- { for i := len(commits) - 1; i >= 0; i-- {
c := commits[i] c := commits[i]
@ -343,7 +383,7 @@ func CommitRepoAction(
repoID int64, repoID int64,
repoUserName, repoName string, repoUserName, repoName string,
refFullName string, refFullName string,
commit *base.PushCommits, commit *PushCommits,
oldCommitID string, newCommitID string) error { oldCommitID string, newCommitID string) error {
u, err := GetUserByID(userID) u, err := GetUserByID(userID)
@ -369,7 +409,7 @@ func CommitRepoAction(
// Check it's tag push or branch. // Check it's tag push or branch.
if strings.HasPrefix(refFullName, "refs/tags/") { if strings.HasPrefix(refFullName, "refs/tags/") {
opType = PUSH_TAG opType = PUSH_TAG
commit = &base.PushCommits{} commit = &PushCommits{}
} else { } else {
// if not the first commit, set the compareUrl // if not the first commit, set the compareUrl
if !strings.HasPrefix(oldCommitID, "0000000") { if !strings.HasPrefix(oldCommitID, "0000000") {

@ -10,7 +10,6 @@ import (
"os/exec" "os/exec"
"strings" "strings"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/git" "github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
) )
@ -100,7 +99,7 @@ func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName
actEmail = cmt.Committer.Email actEmail = cmt.Committer.Email
} }
commit := &base.PushCommits{} commit := &PushCommits{}
if err = CommitRepoAction(userID, user.Id, userName, actEmail, if err = CommitRepoAction(userID, user.Id, userName, actEmail,
repo.ID, repoUserName, repoName, refName, commit, oldCommitID, newCommitID); err != nil { repo.ID, repoUserName, repoName, refName, commit, oldCommitID, newCommitID); err != nil {
@ -133,7 +132,7 @@ func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName
} }
// Push commits. // Push commits.
commits := make([]*base.PushCommit, 0) commits := make([]*PushCommit, 0)
var actEmail string var actEmail string
for e := l.Front(); e != nil; e = e.Next() { for e := l.Front(); e != nil; e = e.Next() {
commit := e.Value.(*git.Commit) commit := e.Value.(*git.Commit)
@ -141,7 +140,7 @@ func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName
actEmail = commit.Committer.Email actEmail = commit.Committer.Email
} }
commits = append(commits, commits = append(commits,
&base.PushCommit{commit.ID.String(), &PushCommit{commit.ID.String(),
commit.Message(), commit.Message(),
commit.Author.Email, commit.Author.Email,
commit.Author.Name, commit.Author.Name,
@ -149,7 +148,7 @@ func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName
} }
if err = CommitRepoAction(userID, user.Id, userName, actEmail, if err = CommitRepoAction(userID, user.Id, userName, actEmail,
repo.ID, repoUserName, repoName, refName, &base.PushCommits{l.Len(), commits, ""}, oldCommitID, newCommitID); err != nil { repo.ID, repoUserName, repoName, refName, &PushCommits{l.Len(), commits, "", nil}, oldCommitID, newCommitID); err != nil {
return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err) return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
} }
return nil return nil

@ -991,7 +991,7 @@ func GetUserByEmail(email string) (*User, error) {
return GetUserByID(emailAddress.UID) return GetUserByID(emailAddress.UID)
} }
return nil, ErrUserNotExist{0, "email"} return nil, ErrUserNotExist{0, email}
} }
// SearchUserByName returns given number of users whose name contains keyword. // SearchUserByName returns given number of users whose name contains keyword.

@ -23,6 +23,8 @@ import (
"github.com/Unknwon/i18n" "github.com/Unknwon/i18n"
"github.com/microcosm-cc/bluemonday" "github.com/microcosm-cc/bluemonday"
"github.com/gogits/chardet"
"github.com/gogits/gogs/modules/avatar" "github.com/gogits/gogs/modules/avatar"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
) )
@ -43,6 +45,22 @@ func EncodeSha1(str string) string {
return hex.EncodeToString(h.Sum(nil)) return hex.EncodeToString(h.Sum(nil))
} }
func ShortSha(sha1 string) string {
if len(sha1) == 40 {
return sha1[:10]
}
return sha1
}
func DetectEncoding(content []byte) (string, error) {
detector := chardet.NewTextDetector()
result, err := detector.DetectBest(content)
if result.Charset != "UTF-8" && len(setting.Repository.AnsiCharset) > 0 {
return setting.Repository.AnsiCharset, err
}
return result.Charset, err
}
func BasicAuthDecode(encoded string) (string, string, error) { func BasicAuthDecode(encoded string) (string, string, error) {
s, err := base64.StdEncoding.DecodeString(encoded) s, err := base64.StdEncoding.DecodeString(encoded)
if err != nil { if err != nil {

@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style // Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package base package template
import ( import (
"container/list" "container/list"
@ -16,7 +16,8 @@ import (
"golang.org/x/net/html/charset" "golang.org/x/net/html/charset"
"golang.org/x/text/transform" "golang.org/x/text/transform"
"github.com/gogits/chardet" "github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
) )
@ -25,7 +26,7 @@ func Safe(raw string) template.HTML {
} }
func Str2html(raw string) template.HTML { func Str2html(raw string) template.HTML {
return template.HTML(Sanitizer.Sanitize(raw)) return template.HTML(base.Sanitizer.Sanitize(raw))
} }
func Range(l int) []int { func Range(l int) []int {
@ -46,27 +47,11 @@ func List(l *list.List) chan interface{} {
} }
func Sha1(str string) string { func Sha1(str string) string {
return EncodeSha1(str) return base.EncodeSha1(str)
}
func ShortSha(sha1 string) string {
if len(sha1) == 40 {
return sha1[:10]
}
return sha1
}
func DetectEncoding(content []byte) (string, error) {
detector := chardet.NewTextDetector()
result, err := detector.DetectBest(content)
if result.Charset != "UTF-8" && len(setting.Repository.AnsiCharset) > 0 {
return setting.Repository.AnsiCharset, err
}
return result.Charset, err
} }
func ToUtf8WithErr(content []byte) (error, string) { func ToUtf8WithErr(content []byte) (error, string) {
charsetLabel, err := DetectEncoding(content) charsetLabel, err := base.DetectEncoding(content)
if err != nil { if err != nil {
return err, "" return err, ""
} }
@ -124,7 +109,7 @@ func ReplaceLeft(s, old, new string) string {
// RenderCommitMessage renders commit message with XSS-safe and special links. // RenderCommitMessage renders commit message with XSS-safe and special links.
func RenderCommitMessage(msg, urlPrefix string) template.HTML { func RenderCommitMessage(msg, urlPrefix string) template.HTML {
cleanMsg := template.HTMLEscapeString(msg) cleanMsg := template.HTMLEscapeString(msg)
fullMessage := string(RenderIssueIndexPattern([]byte(cleanMsg), urlPrefix)) fullMessage := string(base.RenderIssueIndexPattern([]byte(cleanMsg), urlPrefix))
msgLines := strings.Split(strings.TrimSpace(fullMessage), "\n") msgLines := strings.Split(strings.TrimSpace(fullMessage), "\n")
for i := range msgLines { for i := range msgLines {
msgLines[i] = ReplaceLeft(msgLines[i], " ", "&nbsp;") msgLines[i] = ReplaceLeft(msgLines[i], " ", "&nbsp;")
@ -134,7 +119,7 @@ func RenderCommitMessage(msg, urlPrefix string) template.HTML {
return template.HTML(fullMessage) return template.HTML(fullMessage)
} }
var TemplateFuncs template.FuncMap = map[string]interface{}{ var Funcs template.FuncMap = map[string]interface{}{
"GoVer": func() string { "GoVer": func() string {
return strings.Title(runtime.Version()) return strings.Title(runtime.Version())
}, },
@ -156,13 +141,13 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{
"LoadTimes": func(startTime time.Time) string { "LoadTimes": func(startTime time.Time) string {
return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms" return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms"
}, },
"AvatarLink": AvatarLink, "AvatarLink": base.AvatarLink,
"Safe": Safe, "Safe": Safe,
"Str2html": Str2html, "Str2html": Str2html,
"TimeSince": TimeSince, "TimeSince": base.TimeSince,
"RawTimeSince": RawTimeSince, "RawTimeSince": base.RawTimeSince,
"FileSize": FileSize, "FileSize": base.FileSize,
"Subtract": Subtract, "Subtract": base.Subtract,
"Add": func(a, b int) int { "Add": func(a, b int) int {
return a + b return a + b
}, },
@ -197,8 +182,8 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{
"DiffTypeToStr": DiffTypeToStr, "DiffTypeToStr": DiffTypeToStr,
"DiffLineTypeToStr": DiffLineTypeToStr, "DiffLineTypeToStr": DiffLineTypeToStr,
"Sha1": Sha1, "Sha1": Sha1,
"ShortSha": ShortSha, "ShortSha": base.ShortSha,
"Md5": EncodeMd5, "Md5": base.EncodeMd5,
"ActionContent2Commits": ActionContent2Commits, "ActionContent2Commits": ActionContent2Commits,
"Oauth2Icon": Oauth2Icon, "Oauth2Icon": Oauth2Icon,
"Oauth2Name": Oauth2Name, "Oauth2Name": Oauth2Name,
@ -240,22 +225,9 @@ func ActionIcon(opType int) string {
} }
} }
type PushCommit struct { func ActionContent2Commits(act Actioner) *models.PushCommits {
Sha1 string push := models.NewPushCommits()
Message string if err := json.Unmarshal([]byte(act.GetContent()), push); err != nil {
AuthorEmail string
AuthorName string
}
type PushCommits struct {
Len int
Commits []*PushCommit
CompareUrl string
}
func ActionContent2Commits(act Actioner) *PushCommits {
var push *PushCommits
if err := json.Unmarshal([]byte(act.GetContent()), &push); err != nil {
return nil return nil
} }
return push return push

@ -16,6 +16,7 @@ import (
"github.com/gogits/gogs/modules/git" "github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/middleware" "github.com/gogits/gogs/modules/middleware"
"github.com/gogits/gogs/modules/template"
) )
const ( const (
@ -105,7 +106,7 @@ func Home(ctx *middleware.Context) {
if readmeExist { if readmeExist {
ctx.Data["FileContent"] = string(base.RenderMarkdown(buf, path.Dir(treeLink))) ctx.Data["FileContent"] = string(base.RenderMarkdown(buf, path.Dir(treeLink)))
} else { } else {
if err, content := base.ToUtf8WithErr(buf); err != nil { if err, content := template.ToUtf8WithErr(buf); err != nil {
if err != nil { if err != nil {
log.Error(4, "Convert content encoding: %s", err) log.Error(4, "Convert content encoding: %s", err)
} }

@ -1 +1 @@
0.7.7.1113 Beta 0.7.8.1113 Beta

@ -26,7 +26,7 @@
{{range .Repos}} {{range .Repos}}
<li {{if .IsPrivate}}class="private"{{end}}> <li {{if .IsPrivate}}class="private"{{end}}>
<a href="{{AppSubUrl}}/{{$.ContextUser.Name}}/{{.Name}}"> <a href="{{AppSubUrl}}/{{$.ContextUser.Name}}/{{.Name}}">
<i class="octicon octicon-{{if .IsPrivate}}lock{{else if .IsFork}}repo-forked{{else if .IsMirror}}repo-clone{{else}}repo{{end}}"></i> <i class="icon octicon octicon-{{if .IsPrivate}}lock{{else if .IsFork}}repo-forked{{else if .IsMirror}}repo-clone{{else}}repo{{end}}"></i>
<strong>{{.Name}}</strong> <strong>{{.Name}}</strong>
<span class="ui right text light grey"> <span class="ui right text light grey">
<i class="octicon octicon-star"></i>{{.NumStars}} <i class="octicon octicon-star"></i>{{.NumStars}}
@ -46,7 +46,7 @@
{{range .CollaborativeRepos}} {{range .CollaborativeRepos}}
<li {{if .IsPrivate}}class="private"{{end}}> <li {{if .IsPrivate}}class="private"{{end}}>
<a href="{{AppSubUrl}}/{{.Owner.Name}}/{{.Name}}"> <a href="{{AppSubUrl}}/{{.Owner.Name}}/{{.Name}}">
<i class="octicon octicon-{{if .IsPrivate}}lock{{else if .IsFork}}repo-forked{{else if .IsMirror}}repo-clone{{else}}repo{{end}}"></i> <i class="icon octicon octicon-{{if .IsPrivate}}lock{{else if .IsFork}}repo-forked{{else if .IsMirror}}repo-clone{{else}}repo{{end}}"></i>
{{.Owner.Name}} / <strong>{{.Name}}</strong> {{.Owner.Name}} / <strong>{{.Name}}</strong>
<span class="ui right text light grey"> <span class="ui right text light grey">
<i class="octicon octicon-star"></i>{{.NumStars}} <i class="octicon octicon-star"></i>{{.NumStars}}
@ -72,7 +72,7 @@
{{range .ContextUser.Orgs}} {{range .ContextUser.Orgs}}
<li> <li>
<a href="{{AppSubUrl}}/{{.Name}}"> <a href="{{AppSubUrl}}/{{.Name}}">
<i class="octicon octicon-organization"></i> <i class="icon octicon octicon-organization"></i>
<strong>{{.Name}}</strong> <strong>{{.Name}}</strong>
<span class="ui right text light grey"> <span class="ui right text light grey">
<i class="octicon octicon-repo"></i>{{.NumRepos}} <i class="octicon octicon-repo"></i>{{.NumRepos}}
@ -94,7 +94,7 @@
{{range .Mirrors}} {{range .Mirrors}}
<li {{if .IsPrivate}}class="private"{{end}}> <li {{if .IsPrivate}}class="private"{{end}}>
<a href="{{AppSubUrl}}/{{$.ContextUser.Name}}/{{.Name}}"> <a href="{{AppSubUrl}}/{{$.ContextUser.Name}}/{{.Name}}">
<i class="octicon octicon-repo-clone"></i> <i class="icon octicon octicon-repo-clone"></i>
<strong>{{.Name}}</strong> <strong>{{.Name}}</strong>
<span class="ui right text light grey"> <span class="ui right text light grey">
<i class="octicon octicon-sync"></i>{{.Interval}}H <i class="octicon octicon-sync"></i>{{.Interval}}H

@ -39,7 +39,7 @@
{{ $repoLink := .GetRepoLink}} {{ $repoLink := .GetRepoLink}}
{{if $push.Commits}} {{if $push.Commits}}
{{range $push.Commits}} {{range $push.Commits}}
<li><img class="img-8" src="{{AvatarLink .AuthorEmail}}"> <a href="{{$repoLink}}/commit/{{.Sha1}}">{{ShortSha .Sha1}}</a> <span class="text truncate light grey">{{.Message}}</span></li> <li><img class="img-8" src="{{$push.AvatarLink .AuthorEmail}}"> <a href="{{$repoLink}}/commit/{{.Sha1}}">{{ShortSha .Sha1}}</a> <span class="text truncate light grey">{{.Message}}</span></li>
{{end}} {{end}}
{{end}} {{end}}
{{if $push.CompareUrl}}<li><a href="{{AppSubUrl}}/{{$push.CompareUrl}}">{{$.i18n.Tr "action.compare_2_commits"}} »</a></li>{{end}} {{if $push.CompareUrl}}<li><a href="{{AppSubUrl}}/{{$push.CompareUrl}}">{{$.i18n.Tr "action.compare_2_commits"}} »</a></li>{{end}}

Loading…
Cancel
Save