| @@ -5,7 +5,7 @@ Gogs - Go Git Service [ | |||
| ##### Current version: 0.7.7 Beta | |||
| ##### Current version: 0.7.8 Beta | |||
| <table> | |||
| <tr> | |||
| @@ -7,7 +7,7 @@ package cmd | |||
| import ( | |||
| "crypto/tls" | |||
| "fmt" | |||
| "html/template" | |||
| gotmpl "html/template" | |||
| "io/ioutil" | |||
| "net/http" | |||
| "net/http/fcgi" | |||
| @@ -35,11 +35,11 @@ import ( | |||
| "github.com/gogits/gogs/modules/auth" | |||
| "github.com/gogits/gogs/modules/auth/apiv1" | |||
| "github.com/gogits/gogs/modules/avatar" | |||
| "github.com/gogits/gogs/modules/base" | |||
| "github.com/gogits/gogs/modules/bindata" | |||
| "github.com/gogits/gogs/modules/log" | |||
| "github.com/gogits/gogs/modules/middleware" | |||
| "github.com/gogits/gogs/modules/setting" | |||
| "github.com/gogits/gogs/modules/template" | |||
| "github.com/gogits/gogs/routers" | |||
| "github.com/gogits/gogs/routers/admin" | |||
| "github.com/gogits/gogs/routers/api/v1" | |||
| @@ -124,7 +124,7 @@ func newMacaron() *macaron.Macaron { | |||
| )) | |||
| m.Use(macaron.Renderer(macaron.RenderOptions{ | |||
| Directory: path.Join(setting.StaticRootPath, "templates"), | |||
| Funcs: []template.FuncMap{base.TemplateFuncs}, | |||
| Funcs: []gotmpl.FuncMap{template.Funcs}, | |||
| IndentJSON: macaron.Env != macaron.PROD, | |||
| })) | |||
| @@ -17,7 +17,7 @@ import ( | |||
| "github.com/gogits/gogs/modules/setting" | |||
| ) | |||
| const APP_VER = "0.7.7.1113 Beta" | |||
| const APP_VER = "0.7.8.1113 Beta" | |||
| func init() { | |||
| runtime.GOMAXPROCS(runtime.NumCPU()) | |||
| @@ -208,8 +208,48 @@ func issueIndexTrimRight(c rune) bool { | |||
| 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. | |||
| 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. | |||
| for i := len(commits) - 1; i >= 0; i-- { | |||
| c := commits[i] | |||
| @@ -343,7 +383,7 @@ func CommitRepoAction( | |||
| repoID int64, | |||
| repoUserName, repoName string, | |||
| refFullName string, | |||
| commit *base.PushCommits, | |||
| commit *PushCommits, | |||
| oldCommitID string, newCommitID string) error { | |||
| u, err := GetUserByID(userID) | |||
| @@ -369,7 +409,7 @@ func CommitRepoAction( | |||
| // Check it's tag push or branch. | |||
| if strings.HasPrefix(refFullName, "refs/tags/") { | |||
| opType = PUSH_TAG | |||
| commit = &base.PushCommits{} | |||
| commit = &PushCommits{} | |||
| } else { | |||
| // if not the first commit, set the compareUrl | |||
| if !strings.HasPrefix(oldCommitID, "0000000") { | |||
| @@ -10,7 +10,6 @@ import ( | |||
| "os/exec" | |||
| "strings" | |||
| "github.com/gogits/gogs/modules/base" | |||
| "github.com/gogits/gogs/modules/git" | |||
| "github.com/gogits/gogs/modules/log" | |||
| ) | |||
| @@ -100,7 +99,7 @@ func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName | |||
| actEmail = cmt.Committer.Email | |||
| } | |||
| commit := &base.PushCommits{} | |||
| commit := &PushCommits{} | |||
| if err = CommitRepoAction(userID, user.Id, userName, actEmail, | |||
| repo.ID, repoUserName, repoName, refName, commit, oldCommitID, newCommitID); err != nil { | |||
| @@ -133,7 +132,7 @@ func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName | |||
| } | |||
| // Push commits. | |||
| commits := make([]*base.PushCommit, 0) | |||
| commits := make([]*PushCommit, 0) | |||
| var actEmail string | |||
| for e := l.Front(); e != nil; e = e.Next() { | |||
| commit := e.Value.(*git.Commit) | |||
| @@ -141,7 +140,7 @@ func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName | |||
| actEmail = commit.Committer.Email | |||
| } | |||
| commits = append(commits, | |||
| &base.PushCommit{commit.ID.String(), | |||
| &PushCommit{commit.ID.String(), | |||
| commit.Message(), | |||
| commit.Author.Email, | |||
| commit.Author.Name, | |||
| @@ -149,7 +148,7 @@ func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName | |||
| } | |||
| 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 nil | |||
| @@ -991,7 +991,7 @@ func GetUserByEmail(email string) (*User, error) { | |||
| return GetUserByID(emailAddress.UID) | |||
| } | |||
| return nil, ErrUserNotExist{0, "email"} | |||
| return nil, ErrUserNotExist{0, email} | |||
| } | |||
| // SearchUserByName returns given number of users whose name contains keyword. | |||
| @@ -23,6 +23,8 @@ import ( | |||
| "github.com/Unknwon/i18n" | |||
| "github.com/microcosm-cc/bluemonday" | |||
| "github.com/gogits/chardet" | |||
| "github.com/gogits/gogs/modules/avatar" | |||
| "github.com/gogits/gogs/modules/setting" | |||
| ) | |||
| @@ -43,6 +45,22 @@ func EncodeSha1(str string) string { | |||
| 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) { | |||
| s, err := base64.StdEncoding.DecodeString(encoded) | |||
| if err != nil { | |||
| @@ -2,7 +2,7 @@ | |||
| // Use of this source code is governed by a MIT-style | |||
| // license that can be found in the LICENSE file. | |||
| package base | |||
| package template | |||
| import ( | |||
| "container/list" | |||
| @@ -16,7 +16,8 @@ import ( | |||
| "golang.org/x/net/html/charset" | |||
| "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" | |||
| ) | |||
| @@ -25,7 +26,7 @@ func Safe(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 { | |||
| @@ -46,27 +47,11 @@ func List(l *list.List) chan interface{} { | |||
| } | |||
| func Sha1(str string) string { | |||
| return 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 | |||
| return base.EncodeSha1(str) | |||
| } | |||
| func ToUtf8WithErr(content []byte) (error, string) { | |||
| charsetLabel, err := DetectEncoding(content) | |||
| charsetLabel, err := base.DetectEncoding(content) | |||
| if err != nil { | |||
| return err, "" | |||
| } | |||
| @@ -124,7 +109,7 @@ func ReplaceLeft(s, old, new string) string { | |||
| // RenderCommitMessage renders commit message with XSS-safe and special links. | |||
| func RenderCommitMessage(msg, urlPrefix string) template.HTML { | |||
| cleanMsg := template.HTMLEscapeString(msg) | |||
| fullMessage := string(RenderIssueIndexPattern([]byte(cleanMsg), urlPrefix)) | |||
| fullMessage := string(base.RenderIssueIndexPattern([]byte(cleanMsg), urlPrefix)) | |||
| msgLines := strings.Split(strings.TrimSpace(fullMessage), "\n") | |||
| for i := range msgLines { | |||
| msgLines[i] = ReplaceLeft(msgLines[i], " ", " ") | |||
| @@ -134,7 +119,7 @@ func RenderCommitMessage(msg, urlPrefix string) template.HTML { | |||
| return template.HTML(fullMessage) | |||
| } | |||
| var TemplateFuncs template.FuncMap = map[string]interface{}{ | |||
| var Funcs template.FuncMap = map[string]interface{}{ | |||
| "GoVer": func() string { | |||
| return strings.Title(runtime.Version()) | |||
| }, | |||
| @@ -156,13 +141,13 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{ | |||
| "LoadTimes": func(startTime time.Time) string { | |||
| return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms" | |||
| }, | |||
| "AvatarLink": AvatarLink, | |||
| "AvatarLink": base.AvatarLink, | |||
| "Safe": Safe, | |||
| "Str2html": Str2html, | |||
| "TimeSince": TimeSince, | |||
| "RawTimeSince": RawTimeSince, | |||
| "FileSize": FileSize, | |||
| "Subtract": Subtract, | |||
| "TimeSince": base.TimeSince, | |||
| "RawTimeSince": base.RawTimeSince, | |||
| "FileSize": base.FileSize, | |||
| "Subtract": base.Subtract, | |||
| "Add": func(a, b int) int { | |||
| return a + b | |||
| }, | |||
| @@ -197,8 +182,8 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{ | |||
| "DiffTypeToStr": DiffTypeToStr, | |||
| "DiffLineTypeToStr": DiffLineTypeToStr, | |||
| "Sha1": Sha1, | |||
| "ShortSha": ShortSha, | |||
| "Md5": EncodeMd5, | |||
| "ShortSha": base.ShortSha, | |||
| "Md5": base.EncodeMd5, | |||
| "ActionContent2Commits": ActionContent2Commits, | |||
| "Oauth2Icon": Oauth2Icon, | |||
| "Oauth2Name": Oauth2Name, | |||
| @@ -240,22 +225,9 @@ func ActionIcon(opType int) string { | |||
| } | |||
| } | |||
| type PushCommit struct { | |||
| Sha1 string | |||
| Message string | |||
| 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 { | |||
| func ActionContent2Commits(act Actioner) *models.PushCommits { | |||
| push := models.NewPushCommits() | |||
| if err := json.Unmarshal([]byte(act.GetContent()), push); err != nil { | |||
| return nil | |||
| } | |||
| return push | |||
| @@ -16,6 +16,7 @@ import ( | |||
| "github.com/gogits/gogs/modules/git" | |||
| "github.com/gogits/gogs/modules/log" | |||
| "github.com/gogits/gogs/modules/middleware" | |||
| "github.com/gogits/gogs/modules/template" | |||
| ) | |||
| const ( | |||
| @@ -105,7 +106,7 @@ func Home(ctx *middleware.Context) { | |||
| if readmeExist { | |||
| ctx.Data["FileContent"] = string(base.RenderMarkdown(buf, path.Dir(treeLink))) | |||
| } else { | |||
| if err, content := base.ToUtf8WithErr(buf); err != nil { | |||
| if err, content := template.ToUtf8WithErr(buf); err != nil { | |||
| if err != nil { | |||
| 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}} | |||
| <li {{if .IsPrivate}}class="private"{{end}}> | |||
| <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> | |||
| <span class="ui right text light grey"> | |||
| <i class="octicon octicon-star"></i>{{.NumStars}} | |||
| @@ -46,7 +46,7 @@ | |||
| {{range .CollaborativeRepos}} | |||
| <li {{if .IsPrivate}}class="private"{{end}}> | |||
| <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> | |||
| <span class="ui right text light grey"> | |||
| <i class="octicon octicon-star"></i>{{.NumStars}} | |||
| @@ -72,7 +72,7 @@ | |||
| {{range .ContextUser.Orgs}} | |||
| <li> | |||
| <a href="{{AppSubUrl}}/{{.Name}}"> | |||
| <i class="octicon octicon-organization"></i> | |||
| <i class="icon octicon octicon-organization"></i> | |||
| <strong>{{.Name}}</strong> | |||
| <span class="ui right text light grey"> | |||
| <i class="octicon octicon-repo"></i>{{.NumRepos}} | |||
| @@ -94,7 +94,7 @@ | |||
| {{range .Mirrors}} | |||
| <li {{if .IsPrivate}}class="private"{{end}}> | |||
| <a href="{{AppSubUrl}}/{{$.ContextUser.Name}}/{{.Name}}"> | |||
| <i class="octicon octicon-repo-clone"></i> | |||
| <i class="icon octicon octicon-repo-clone"></i> | |||
| <strong>{{.Name}}</strong> | |||
| <span class="ui right text light grey"> | |||
| <i class="octicon octicon-sync"></i>{{.Interval}}H | |||
| @@ -39,7 +39,7 @@ | |||
| {{ $repoLink := .GetRepoLink}} | |||
| {{if $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}} | |||
| {{if $push.CompareUrl}}<li><a href="{{AppSubUrl}}/{{$push.CompareUrl}}">{{$.i18n.Tr "action.compare_2_commits"}} »</a></li>{{end}} | |||