From 3d640728c3a98de488f50ed82e17abef35b4c441 Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Tue, 29 Nov 2016 15:29:15 +0100 Subject: [PATCH 01/14] Ignore templates bindata --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9825b96ee3d9d..0bca5df1dfded 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ _testmain.go coverage.out /modules/public/bindata.go +/modules/templates/bindata.go *.db *.log From 3c76da96adee39eed9cf8857b4d7a2fb7eb9597b Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Tue, 29 Nov 2016 15:52:11 +0100 Subject: [PATCH 02/14] Integrated dynamic and static bindata for templates --- modules/templates/dynamic.go | 21 +++++++++++++++++++++ modules/templates/static.go | 30 ++++++++++++++++++++++++++++++ modules/templates/templates.go | 14 ++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 modules/templates/dynamic.go create mode 100644 modules/templates/static.go create mode 100644 modules/templates/templates.go diff --git a/modules/templates/dynamic.go b/modules/templates/dynamic.go new file mode 100644 index 0000000000000..bfdbd3730ecf4 --- /dev/null +++ b/modules/templates/dynamic.go @@ -0,0 +1,21 @@ +// +build !bindata + +// Copyright 2016 The Gitea 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 templates + +import ( + "github.com/go-gitea/gitea/modules/template" + "gopkg.in/macaron.v1" +) + +// Renderer implements the macaron handler for serving the templates. +func Renderer(opts *Options) macaron.Handler { + return macaron.Renderer(macaron.RenderOptions{ + Directory: opts.Directory, + AppendDirectories: opts.Custom, + Funcs: template.NewFuncMap(), + }) +} diff --git a/modules/templates/static.go b/modules/templates/static.go new file mode 100644 index 0000000000000..ddee546bf4cfc --- /dev/null +++ b/modules/templates/static.go @@ -0,0 +1,30 @@ +// +build bindata + +// Copyright 2016 The Gitea 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 templates + +import ( + "github.com/go-gitea/gitea/modules/template" + "github.com/go-macaron/bindata" + "gopkg.in/macaron.v1" +) + +// Renderer implements the macaron handler for serving the templates. +func Renderer(opts *Options) macaron.Handler { + return macaron.Renderer(macaron.RenderOptions{ + AppendDirectories: opts.Custom, + Funcs: template.NewFuncMap(), + TemplateFileSystem: bindata.Templates( + bindata.Options{ + Asset: Asset, + AssetDir: AssetDir, + AssetInfo: AssetInfo, + AssetNames: AssetNames, + Prefix: "../../templates", + }, + ), + }) +} diff --git a/modules/templates/templates.go b/modules/templates/templates.go new file mode 100644 index 0000000000000..2b066d7979dae --- /dev/null +++ b/modules/templates/templates.go @@ -0,0 +1,14 @@ +// Copyright 2016 The Gitea 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 templates + +//go:generate go-bindata -tags "bindata" -ignore "\\.go" -pkg "templates" -o "bindata.go" ../../templates/... +//go:generate go fmt bindata.go + +// Options represents the available options to configure the macaron handler. +type Options struct { + Directory string + Custom []string +} From 884f49dc689683025bce4001727aaaa0b6650bf4 Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Wed, 30 Nov 2016 11:14:16 +0100 Subject: [PATCH 03/14] Dropped the template version check --- cmd/web.go | 15 --------------- templates/.VERSION | 1 - 2 files changed, 16 deletions(-) delete mode 100644 templates/.VERSION diff --git a/cmd/web.go b/cmd/web.go index 5442850561379..cdbd96c00eebe 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -76,21 +76,6 @@ type VerChecker struct { // checkVersion checks if binary matches the version of templates files. func checkVersion() { - // Templates. - data, err := ioutil.ReadFile(setting.StaticRootPath + "/templates/.VERSION") - if err != nil { - log.Fatal(4, "Fail to read 'templates/.VERSION': %v", err) - } - tplVer := string(data) - if tplVer != setting.AppVer { - if version.Compare(tplVer, setting.AppVer, ">") { - log.Fatal(4, "Binary version is lower than template file version, did you forget to recompile Gogs?") - } else { - log.Fatal(4, "Binary version is higher than template file version, did you forget to update template files?") - } - } - - // Check dependency version. checkers := []VerChecker{ {"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.5.5"}, {"github.com/go-macaron/binding", binding.Version, "0.3.2"}, diff --git a/templates/.VERSION b/templates/.VERSION deleted file mode 100644 index 927f673c535dc..0000000000000 --- a/templates/.VERSION +++ /dev/null @@ -1 +0,0 @@ -0.9.99.0915 \ No newline at end of file From b5af25b73d1b66df6995a6889c75abe3ca6885bf Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Wed, 30 Nov 2016 11:16:21 +0100 Subject: [PATCH 04/14] Dropped the dependency version checks Since we have bundled all required dependencies via the vendoring we don't need to provide these checks anymore. We make sure to have the correct versions with that. --- cmd/web.go | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/cmd/web.go b/cmd/web.go index cdbd96c00eebe..d4dd21c631bb9 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -7,7 +7,6 @@ package cmd import ( "crypto/tls" "fmt" - "io/ioutil" "net" "net/http" "net/http/fcgi" @@ -15,7 +14,6 @@ import ( "path" "strings" - "code.gitea.io/git" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/bindata" @@ -39,10 +37,7 @@ import ( "github.com/go-macaron/i18n" "github.com/go-macaron/session" "github.com/go-macaron/toolbox" - "github.com/go-xorm/xorm" - version "github.com/mcuadros/go-version" "github.com/urfave/cli" - ini "gopkg.in/ini.v1" macaron "gopkg.in/macaron.v1" ) @@ -74,30 +69,6 @@ type VerChecker struct { Expected string } -// checkVersion checks if binary matches the version of templates files. -func checkVersion() { - checkers := []VerChecker{ - {"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.5.5"}, - {"github.com/go-macaron/binding", binding.Version, "0.3.2"}, - {"github.com/go-macaron/cache", cache.Version, "0.1.2"}, - {"github.com/go-macaron/csrf", csrf.Version, "0.1.0"}, - {"github.com/go-macaron/i18n", i18n.Version, "0.3.0"}, - {"github.com/go-macaron/session", session.Version, "0.1.6"}, - {"github.com/go-macaron/toolbox", toolbox.Version, "0.1.0"}, - {"gopkg.in/ini.v1", ini.Version, "1.8.4"}, - {"gopkg.in/macaron.v1", macaron.Version, "1.1.7"}, - {"code.gitea.io/git", git.Version, "0.4.1"}, - } - for _, c := range checkers { - if !version.Compare(c.Version(), c.Expected, ">=") { - log.Fatal(4, `Dependency outdated! -Package '%s' current version (%s) is below requirement (%s), -please use following command to update this package and recompile Gogs: -go get -u %[1]s`, c.ImportPath, c.Version(), c.Expected) - } - } -} - // newMacaron initializes Macaron instance. func newMacaron() *macaron.Macaron { m := macaron.New() @@ -185,7 +156,6 @@ func runWeb(ctx *cli.Context) error { setting.CustomConf = ctx.String("config") } routers.GlobalInit() - checkVersion() m := newMacaron() From ee0ed2230fe061218b7fea2d79749154487a2807 Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Wed, 30 Nov 2016 11:42:45 +0100 Subject: [PATCH 05/14] Fixed templates import paths Since the -prefix option of go-bindata seems to be broken I'm forced to rewrite the paths of the templates with sed. --- modules/templates/static.go | 2 +- modules/templates/templates.go | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/templates/static.go b/modules/templates/static.go index ddee546bf4cfc..670e45a554435 100644 --- a/modules/templates/static.go +++ b/modules/templates/static.go @@ -23,7 +23,7 @@ func Renderer(opts *Options) macaron.Handler { AssetDir: AssetDir, AssetInfo: AssetInfo, AssetNames: AssetNames, - Prefix: "../../templates", + Prefix: "", }, ), }) diff --git a/modules/templates/templates.go b/modules/templates/templates.go index 2b066d7979dae..23d099c61d105 100644 --- a/modules/templates/templates.go +++ b/modules/templates/templates.go @@ -6,6 +6,8 @@ package templates //go:generate go-bindata -tags "bindata" -ignore "\\.go" -pkg "templates" -o "bindata.go" ../../templates/... //go:generate go fmt bindata.go +//go:generate sed -i.bak s/..\/..\/templates\/// bindata.go +//go:generate rm -f bindata.go.bak // Options represents the available options to configure the macaron handler. type Options struct { From d9e456fcc959f02f721d7fcd447223495125228c Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Wed, 30 Nov 2016 13:39:33 +0100 Subject: [PATCH 06/14] Use the optional embedded templates --- cmd/web.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/web.go b/cmd/web.go index d4dd21c631bb9..cece708619792 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -22,6 +22,7 @@ import ( "code.gitea.io/gitea/modules/public" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/template" + "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/routers" "code.gitea.io/gitea/routers/admin" apiv1 "code.gitea.io/gitea/routers/api/v1" @@ -95,16 +96,15 @@ func newMacaron() *macaron.Macaron { SkipLogging: setting.DisableRouterLog, }, )) + m.Use(templates.Renderer( + &templates.Options{ + Directory: path.Join(setting.StaticRootPath, "templates"), + Custom: []string{path.Join(setting.CustomPath, "templates")}, + }, + )) - funcMap := template.NewFuncMap() - m.Use(macaron.Renderer(macaron.RenderOptions{ - Directory: path.Join(setting.StaticRootPath, "templates"), - AppendDirectories: []string{path.Join(setting.CustomPath, "templates")}, - Funcs: funcMap, - IndentJSON: macaron.Env != macaron.PROD, - })) models.InitMailRender(path.Join(setting.StaticRootPath, "templates/mail"), - path.Join(setting.CustomPath, "templates/mail"), funcMap) + path.Join(setting.CustomPath, "templates/mail"), template.NewFuncMap()) localeNames, err := bindata.AssetDir("conf/locale") if err != nil { From af1d48f1ca9b8770d406ec71ce6f687274c58502 Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Wed, 30 Nov 2016 13:40:09 +0100 Subject: [PATCH 07/14] Drop the prefix from public bindata --- modules/public/public.go | 2 ++ modules/public/static.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/public/public.go b/modules/public/public.go index 261ed88874c08..9c9e9d533dadc 100644 --- a/modules/public/public.go +++ b/modules/public/public.go @@ -6,6 +6,8 @@ package public //go:generate go-bindata -tags "bindata" -ignore "\\.go|\\.less" -pkg "public" -o "bindata.go" ../../public/... //go:generate go fmt bindata.go +//go:generate sed -i.bak s/..\/..\/public\/// bindata.go +//go:generate rm -f bindata.go.bak // Options represents the available options to configure the macaron handler. type Options struct { diff --git a/modules/public/static.go b/modules/public/static.go index 8184bc214978b..f68400d329c1e 100644 --- a/modules/public/static.go +++ b/modules/public/static.go @@ -22,7 +22,7 @@ func Static(opts *Options) macaron.Handler { AssetDir: AssetDir, AssetInfo: AssetInfo, AssetNames: AssetNames, - Prefix: "../../public", + Prefix: "", }), }, ) From 1626da033737526f6f3284e136dd2136e34dca0d Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Wed, 30 Nov 2016 21:26:22 +0100 Subject: [PATCH 08/14] Started to integrate mail templates --- cmd/web.go | 7 ++-- models/mail.go | 79 +++++++++++++++++------------------- modules/templates/dynamic.go | 36 +++++++++++++++- modules/templates/static.go | 44 +++++++++++++++++++- 4 files changed, 117 insertions(+), 49 deletions(-) diff --git a/cmd/web.go b/cmd/web.go index cece708619792..e551387e4990c 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -21,7 +21,6 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/public" "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/template" "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/routers" "code.gitea.io/gitea/routers/admin" @@ -103,8 +102,10 @@ func newMacaron() *macaron.Macaron { }, )) - models.InitMailRender(path.Join(setting.StaticRootPath, "templates/mail"), - path.Join(setting.CustomPath, "templates/mail"), template.NewFuncMap()) + models.InitMailRender(templates.Mailer(&templates.Options{ + Directory: path.Join(setting.StaticRootPath, "templates", "mail"), + Custom: []string{path.Join(setting.CustomPath, "templates", "mail")}, + })) localeNames, err := bindata.AssetDir("conf/locale") if err != nil { diff --git a/models/mail.go b/models/mail.go index f89e38e625294..a5e9bd551feb6 100644 --- a/models/mail.go +++ b/models/mail.go @@ -5,18 +5,18 @@ package models import ( + "bytes" "fmt" "html/template" "path" - "gopkg.in/gomail.v2" - "gopkg.in/macaron.v1" - "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/mailer" "code.gitea.io/gitea/modules/markdown" "code.gitea.io/gitea/modules/setting" + "gopkg.in/gomail.v2" + "gopkg.in/macaron.v1" ) const ( @@ -31,27 +31,11 @@ const ( mailNotifyCollaborator base.TplName = "notify/collaborator" ) -type mailRenderInterface interface { - HTMLString(string, interface{}, ...macaron.HTMLOptions) (string, error) -} - -var mailRender mailRenderInterface +var templates *template.Template // InitMailRender initializes the macaron mail renderer -func InitMailRender(dir, appendDir string, funcMap []template.FuncMap) { - opt := &macaron.RenderOptions{ - Directory: dir, - AppendDirectories: []string{appendDir}, - Funcs: funcMap, - Extensions: []string{".tmpl", ".html"}, - } - ts := macaron.NewTemplateSet() - ts.Set(macaron.DEFAULT_TPL_SET_NAME, opt) - - mailRender = &macaron.TplRender{ - TemplateSet: ts, - Opt: opt, - } +func InitMailRender(tmpls *template.Template) { + templates = tmpls } // SendTestMail sends a test mail @@ -67,13 +51,15 @@ func SendUserMail(c *macaron.Context, u *User, tpl base.TplName, code, subject, "ResetPwdCodeLives": setting.Service.ResetPwdCodeLives / 60, "Code": code, } - body, err := mailRender.HTMLString(string(tpl), data) - if err != nil { - log.Error(3, "HTMLString: %v", err) + + var content bytes.Buffer + + if err := templates.ExecuteTemplate(&content, string(tpl), data); err != nil { + log.Error(3, "Template: %v", err) return } - msg := mailer.NewMessage([]string{u.Email}, subject, body) + msg := mailer.NewMessage([]string{u.Email}, subject, content.String()) msg.Info = fmt.Sprintf("UID: %d, %s", u.ID, info) mailer.SendAsync(msg) @@ -97,13 +83,15 @@ func SendActivateEmailMail(c *macaron.Context, u *User, email *EmailAddress) { "Code": u.GenerateEmailActivateCode(email.Email), "Email": email.Email, } - body, err := mailRender.HTMLString(string(mailAuthActivateEmail), data) - if err != nil { - log.Error(3, "HTMLString: %v", err) + + var content bytes.Buffer + + if err := templates.ExecuteTemplate(&content, string(mailAuthActivateEmail), data); err != nil { + log.Error(3, "Template: %v", err) return } - msg := mailer.NewMessage([]string{email.Email}, c.Tr("mail.activate_email"), body) + msg := mailer.NewMessage([]string{email.Email}, c.Tr("mail.activate_email"), content.String()) msg.Info = fmt.Sprintf("UID: %d, activate email", u.ID) mailer.SendAsync(msg) @@ -114,13 +102,15 @@ func SendRegisterNotifyMail(c *macaron.Context, u *User) { data := map[string]interface{}{ "Username": u.DisplayName(), } - body, err := mailRender.HTMLString(string(mailAuthRegisterNotify), data) - if err != nil { - log.Error(3, "HTMLString: %v", err) + + var content bytes.Buffer + + if err := templates.ExecuteTemplate(&content, string(mailAuthRegisterNotify), data); err != nil { + log.Error(3, "Template: %v", err) return } - msg := mailer.NewMessage([]string{u.Email}, c.Tr("mail.register_notify"), body) + msg := mailer.NewMessage([]string{u.Email}, c.Tr("mail.register_notify"), content.String()) msg.Info = fmt.Sprintf("UID: %d, registration notify", u.ID) mailer.SendAsync(msg) @@ -136,13 +126,15 @@ func SendCollaboratorMail(u, doer *User, repo *Repository) { "RepoName": repoName, "Link": repo.HTMLURL(), } - body, err := mailRender.HTMLString(string(mailNotifyCollaborator), data) - if err != nil { - log.Error(3, "HTMLString: %v", err) + + var content bytes.Buffer + + if err := templates.ExecuteTemplate(&content, string(mailNotifyCollaborator), data); err != nil { + log.Error(3, "Template: %v", err) return } - msg := mailer.NewMessage([]string{u.Email}, subject, body) + msg := mailer.NewMessage([]string{u.Email}, subject, content.String()) msg.Info = fmt.Sprintf("UID: %d, add collaborator", u.ID) mailer.SendAsync(msg) @@ -161,11 +153,14 @@ func composeIssueMessage(issue *Issue, doer *User, tplName base.TplName, tos []s body := string(markdown.RenderSpecialLink([]byte(issue.Content), issue.Repo.HTMLURL(), issue.Repo.ComposeMetas())) data := composeTplData(subject, body, issue.HTMLURL()) data["Doer"] = doer - content, err := mailRender.HTMLString(string(tplName), data) - if err != nil { - log.Error(3, "HTMLString (%s): %v", tplName, err) + + var content bytes.Buffer + + if err := templates.ExecuteTemplate(&content, string(tplName), data); err != nil { + log.Error(3, "Template: %v", err) } - msg := mailer.NewMessageFrom(tos, fmt.Sprintf(`"%s" <%s>`, doer.DisplayName(), setting.MailService.FromEmail), subject, content) + + msg := mailer.NewMessageFrom(tos, fmt.Sprintf(`"%s" <%s>`, doer.DisplayName(), setting.MailService.FromEmail), subject, content.String()) msg.Info = fmt.Sprintf("Subject: %s, %s", subject, info) return msg } diff --git a/modules/templates/dynamic.go b/modules/templates/dynamic.go index bfdbd3730ecf4..6c7a2bb0a2b6f 100644 --- a/modules/templates/dynamic.go +++ b/modules/templates/dynamic.go @@ -7,7 +7,12 @@ package templates import ( - "github.com/go-gitea/gitea/modules/template" + "html/template" + "os" + "path" + + "code.gitea.io/gitea/modules/log" + template_func "code.gitea.io/gitea/modules/template" "gopkg.in/macaron.v1" ) @@ -16,6 +21,33 @@ func Renderer(opts *Options) macaron.Handler { return macaron.Renderer(macaron.RenderOptions{ Directory: opts.Directory, AppendDirectories: opts.Custom, - Funcs: template.NewFuncMap(), + Funcs: template_func.NewFuncMap(), }) } + +// Mailer provides the templates required for sending notification mails. +func Mailer(opts *Options) *template.Template { + templates := template.New("") + + for _, funcs := range template_func.NewFuncMap() { + templates.Funcs(funcs) + } + + if _, err := os.Stat(opts.Directory); err == nil { + if _, err := templates.ParseGlob(path.Join(opts.Directory, "*", "*.tmpl")); err != nil { + log.Error(3, "Unable to parse template directory %s. %s", opts.Directory, err) + } + } + + for _, asset := range opts.Custom { + if _, err := os.Stat(asset); err == nil { + if _, err := templates.ParseGlob(path.Join(asset, "*", "*.tmpl")); err != nil { + log.Error(3, "Unable to parse template directory %s. %s", asset, err) + } + } + } + + log.Error(3, templates.DefinedTemplates()) + + return templates +} diff --git a/modules/templates/static.go b/modules/templates/static.go index 670e45a554435..4629e04b61349 100644 --- a/modules/templates/static.go +++ b/modules/templates/static.go @@ -7,7 +7,12 @@ package templates import ( - "github.com/go-gitea/gitea/modules/template" + "html/template" + "os" + "path" + + "code.gitea.io/gitea/modules/log" + template_func "code.gitea.io/gitea/modules/template" "github.com/go-macaron/bindata" "gopkg.in/macaron.v1" ) @@ -16,7 +21,7 @@ import ( func Renderer(opts *Options) macaron.Handler { return macaron.Renderer(macaron.RenderOptions{ AppendDirectories: opts.Custom, - Funcs: template.NewFuncMap(), + Funcs: template_func.NewFuncMap(), TemplateFileSystem: bindata.Templates( bindata.Options{ Asset: Asset, @@ -28,3 +33,38 @@ func Renderer(opts *Options) macaron.Handler { ), }) } + +// Mailer provides the templates required for sending notification mails. +func Mailer(opts *Options) *template.Template { + templates := template.New("") + + for _, funcs := range template_func.NewFuncMap() { + templates.Funcs(funcs) + } + + assets, err := AssetDir("mail") + + if err != nil { + log.Error(3, "Unable to read mail asset dir. %s", err) + } + + for _, asset := range assets { + bytes, err := Asset(asset) + + if err != nil { + log.Error(3, "Unable to parse template %s. %s", asset, err) + } + + templates.New(asset).Parse(string(bytes)) + } + + for _, asset := range opts.Custom { + if _, err := os.Stat(opts.Directory); err == nil { + if _, err := templates.ParseGlob(path.Join(asset, "*", "*.tmpl")); err != nil { + log.Error(3, "Unable to parse template directory %s. %s", opts.Directory, err) + } + } + } + + return templates +} From 2ddb59699cf7bde528130fc6d8fa7034ed4ffe0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20=22BKC=22=20Carlb=C3=A4cker?= Date: Sat, 3 Dec 2016 08:18:59 +0100 Subject: [PATCH 09/14] This is how you do it --- modules/templates/dynamic.go | 45 ++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/modules/templates/dynamic.go b/modules/templates/dynamic.go index 6c7a2bb0a2b6f..4d885a50fca1a 100644 --- a/modules/templates/dynamic.go +++ b/modules/templates/dynamic.go @@ -7,9 +7,12 @@ package templates import ( + "fmt" "html/template" + "io/ioutil" "os" - "path" + "path/filepath" + "strings" "code.gitea.io/gitea/modules/log" template_func "code.gitea.io/gitea/modules/template" @@ -34,15 +37,39 @@ func Mailer(opts *Options) *template.Template { } if _, err := os.Stat(opts.Directory); err == nil { - if _, err := templates.ParseGlob(path.Join(opts.Directory, "*", "*.tmpl")); err != nil { - log.Error(3, "Unable to parse template directory %s. %s", opts.Directory, err) + if err := filepath.Walk(opts.Directory, func(path string, info os.FileInfo, _ error) error { + if info.IsDir() || !strings.HasSuffix(path, ".tmpl") { + return nil + } + name := strings.TrimSuffix(strings.TrimPrefix(path, opts.Directory+"/"), ".tmpl") + log.Info("Found new template: %s", name) + ts, err := loadTemplate(name, path) + if err != nil { + return nil + } + _, err = templates.Parse(ts) + return err + }); err != nil { + log.Error(3, "Unable to parse template directory %s. %v", opts.Directory, err) } } for _, asset := range opts.Custom { if _, err := os.Stat(asset); err == nil { - if _, err := templates.ParseGlob(path.Join(asset, "*", "*.tmpl")); err != nil { - log.Error(3, "Unable to parse template directory %s. %s", asset, err) + if err := filepath.Walk(asset, func(path string, info os.FileInfo, _ error) error { + if info.IsDir() || !strings.HasSuffix(path, ".tmpl") { + return nil + } + name := strings.TrimSuffix(strings.TrimPrefix(path, asset+"/"), ".tmpl") + log.Info("Found new template: %s", name) + ts, err := loadTemplate(name, path) + if err != nil { + return nil + } + _, err = templates.Parse(ts) + return err + }); err != nil { + log.Error(3, "Unable to parse template directory %s. %v", asset, err) } } } @@ -51,3 +78,11 @@ func Mailer(opts *Options) *template.Template { return templates } + +func loadTemplate(name, path string) (string, error) { + t, err := ioutil.ReadFile(path) + if err != nil { + return "", err + } + return fmt.Sprintf(`{{define "%s"}}%s{{end}}`, name, t), nil +} From 971de3ae0db7c9cc9bdabb2efa7ba31c7e32ecc4 Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Tue, 6 Dec 2016 14:05:26 +0100 Subject: [PATCH 10/14] Moved highlight helper into separate module --- models/git_diff.go | 2 +- modules/{template => }/highlight/highlight.go | 0 routers/init.go | 2 +- routers/repo/editor.go | 2 +- routers/repo/view.go | 4 ++-- 5 files changed, 5 insertions(+), 5 deletions(-) rename modules/{template => }/highlight/highlight.go (100%) diff --git a/models/git_diff.go b/models/git_diff.go index b8f9cacec9f66..1d4cf8c6420f5 100644 --- a/models/git_diff.go +++ b/models/git_diff.go @@ -21,7 +21,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/template/highlight" + "code.gitea.io/gitea/modules/highlight" "github.com/Unknwon/com" "github.com/sergi/go-diff/diffmatchpatch" "golang.org/x/net/html/charset" diff --git a/modules/template/highlight/highlight.go b/modules/highlight/highlight.go similarity index 100% rename from modules/template/highlight/highlight.go rename to modules/highlight/highlight.go diff --git a/routers/init.go b/routers/init.go index b6b9911c80996..ba529ccd54fcc 100644 --- a/routers/init.go +++ b/routers/init.go @@ -16,7 +16,7 @@ import ( "code.gitea.io/gitea/modules/markdown" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/ssh" - "code.gitea.io/gitea/modules/template/highlight" + "code.gitea.io/gitea/modules/highlight" macaron "gopkg.in/macaron.v1" ) diff --git a/routers/repo/editor.go b/routers/repo/editor.go index f037b39b21d36..99a653eac2352 100644 --- a/routers/repo/editor.go +++ b/routers/repo/editor.go @@ -18,7 +18,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/template" + "code.gitea.io/gitea/modules/templates" ) const ( diff --git a/routers/repo/view.go b/routers/repo/view.go index 3ef3716f27df9..b2ca87e1b5ea8 100644 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -19,8 +19,8 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markdown" "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/template" - "code.gitea.io/gitea/modules/template/highlight" + "code.gitea.io/gitea/modules/templates" + "code.gitea.io/gitea/modules/highlight" "github.com/Unknwon/paginater" ) From 8619ec51f692792b8d38cab81f39301de2ab500b Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Tue, 6 Dec 2016 14:08:14 +0100 Subject: [PATCH 11/14] Moved template helper into templates module --- modules/{template/template.go => templates/helper.go} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename modules/{template/template.go => templates/helper.go} (99%) diff --git a/modules/template/template.go b/modules/templates/helper.go similarity index 99% rename from modules/template/template.go rename to modules/templates/helper.go index 65d78c2f6e0f1..c2564553992b0 100644 --- a/modules/template/template.go +++ b/modules/templates/helper.go @@ -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 template +package templates import ( "container/list" From 0230d7913800384b1d712eb0dd3733ba45abd993 Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Tue, 6 Dec 2016 15:03:57 +0100 Subject: [PATCH 12/14] Fixed highlight and helper move --- models/git_diff.go | 2 +- routers/init.go | 2 +- routers/repo/editor.go | 2 +- routers/repo/view.go | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/models/git_diff.go b/models/git_diff.go index 1d4cf8c6420f5..fe99f61bfea18 100644 --- a/models/git_diff.go +++ b/models/git_diff.go @@ -18,10 +18,10 @@ import ( "code.gitea.io/git" "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/highlight" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/highlight" "github.com/Unknwon/com" "github.com/sergi/go-diff/diffmatchpatch" "golang.org/x/net/html/charset" diff --git a/routers/init.go b/routers/init.go index ba529ccd54fcc..3d5235d79d200 100644 --- a/routers/init.go +++ b/routers/init.go @@ -11,12 +11,12 @@ import ( "code.gitea.io/git" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/cron" + "code.gitea.io/gitea/modules/highlight" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/mailer" "code.gitea.io/gitea/modules/markdown" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/ssh" - "code.gitea.io/gitea/modules/highlight" macaron "gopkg.in/macaron.v1" ) diff --git a/routers/repo/editor.go b/routers/repo/editor.go index 99a653eac2352..8d45521a2ee9e 100644 --- a/routers/repo/editor.go +++ b/routers/repo/editor.go @@ -74,7 +74,7 @@ func editFile(ctx *context.Context, isNewFile bool) { d, _ := ioutil.ReadAll(dataRc) buf = append(buf, d...) - if content, err := template.ToUTF8WithErr(buf); err != nil { + if content, err := templates.ToUTF8WithErr(buf); err != nil { if err != nil { log.Error(4, "ToUTF8WithErr: %v", err) } diff --git a/routers/repo/view.go b/routers/repo/view.go index b2ca87e1b5ea8..4417383bdc7ea 100644 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -16,11 +16,11 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/highlight" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markdown" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/templates" - "code.gitea.io/gitea/modules/highlight" "github.com/Unknwon/paginater" ) @@ -164,7 +164,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st } else { // Building code view blocks with line number on server side. var fileContent string - if content, err := template.ToUTF8WithErr(buf); err != nil { + if content, err := templates.ToUTF8WithErr(buf); err != nil { if err != nil { log.Error(4, "ToUTF8WithErr: %s", err) } From 0e17dd0ab25a235bca0e36c117ede3826a75405a Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Tue, 6 Dec 2016 15:04:42 +0100 Subject: [PATCH 13/14] Simplyfied the templates module --- modules/templates/dynamic.go | 113 +++++++++++++++++++-------------- modules/templates/static.go | 81 +++++++++++++++++------ modules/templates/templates.go | 6 -- 3 files changed, 124 insertions(+), 76 deletions(-) diff --git a/modules/templates/dynamic.go b/modules/templates/dynamic.go index 4d885a50fca1a..c127b69470805 100644 --- a/modules/templates/dynamic.go +++ b/modules/templates/dynamic.go @@ -7,82 +7,97 @@ package templates import ( - "fmt" "html/template" "io/ioutil" - "os" - "path/filepath" + "path" "strings" "code.gitea.io/gitea/modules/log" - template_func "code.gitea.io/gitea/modules/template" + "code.gitea.io/gitea/modules/setting" + "github.com/Unknwon/com" "gopkg.in/macaron.v1" ) +var ( + templates = template.New("") +) + // Renderer implements the macaron handler for serving the templates. -func Renderer(opts *Options) macaron.Handler { +func Renderer() macaron.Handler { return macaron.Renderer(macaron.RenderOptions{ - Directory: opts.Directory, - AppendDirectories: opts.Custom, - Funcs: template_func.NewFuncMap(), + Funcs: NewFuncMap(), + Directory: path.Join(setting.StaticRootPath, "templates"), + AppendDirectories: []string{ + path.Join(setting.CustomPath, "templates"), + }, }) } // Mailer provides the templates required for sending notification mails. -func Mailer(opts *Options) *template.Template { - templates := template.New("") - - for _, funcs := range template_func.NewFuncMap() { +func Mailer() *template.Template { + for _, funcs := range NewFuncMap() { templates.Funcs(funcs) } - if _, err := os.Stat(opts.Directory); err == nil { - if err := filepath.Walk(opts.Directory, func(path string, info os.FileInfo, _ error) error { - if info.IsDir() || !strings.HasSuffix(path, ".tmpl") { - return nil - } - name := strings.TrimSuffix(strings.TrimPrefix(path, opts.Directory+"/"), ".tmpl") - log.Info("Found new template: %s", name) - ts, err := loadTemplate(name, path) - if err != nil { - return nil + staticDir := path.Join(setting.StaticRootPath, "templates", "mail") + + if com.IsDir(staticDir) { + files, err := com.StatDir(staticDir) + + if err != nil { + log.Warn("Failed to read %s templates dir. %v", staticDir, err) + } else { + for _, filePath := range files { + if !strings.HasSuffix(filePath, ".tmpl") { + continue + } + + content, err := ioutil.ReadFile(path.Join(staticDir, filePath)) + + if err != nil { + log.Warn("Failed to read static %s template. %v", filePath, err) + continue + } + + templates.New( + strings.TrimSuffix( + filePath, + ".tmpl", + ), + ).Parse(string(content)) } - _, err = templates.Parse(ts) - return err - }); err != nil { - log.Error(3, "Unable to parse template directory %s. %v", opts.Directory, err) } } - for _, asset := range opts.Custom { - if _, err := os.Stat(asset); err == nil { - if err := filepath.Walk(asset, func(path string, info os.FileInfo, _ error) error { - if info.IsDir() || !strings.HasSuffix(path, ".tmpl") { - return nil + customDir := path.Join(setting.CustomPath, "templates", "mail") + + if com.IsDir(customDir) { + files, err := com.StatDir(customDir) + + if err != nil { + log.Warn("Failed to read %s templates dir. %v", customDir, err) + } else { + for _, filePath := range files { + if !strings.HasSuffix(filePath, ".tmpl") { + continue } - name := strings.TrimSuffix(strings.TrimPrefix(path, asset+"/"), ".tmpl") - log.Info("Found new template: %s", name) - ts, err := loadTemplate(name, path) + + content, err := ioutil.ReadFile(path.Join(customDir, filePath)) + if err != nil { - return nil + log.Warn("Failed to read custom %s template. %v", filePath, err) + continue } - _, err = templates.Parse(ts) - return err - }); err != nil { - log.Error(3, "Unable to parse template directory %s. %v", asset, err) + + templates.New( + strings.TrimSuffix( + filePath, + ".tmpl", + ), + ).Parse(string(content)) } } } - log.Error(3, templates.DefinedTemplates()) - return templates } - -func loadTemplate(name, path string) (string, error) { - t, err := ioutil.ReadFile(path) - if err != nil { - return "", err - } - return fmt.Sprintf(`{{define "%s"}}%s{{end}}`, name, t), nil -} diff --git a/modules/templates/static.go b/modules/templates/static.go index 4629e04b61349..5c9903cde6579 100644 --- a/modules/templates/static.go +++ b/modules/templates/static.go @@ -8,20 +8,28 @@ package templates import ( "html/template" - "os" + "io/ioutil" "path" + "strings" "code.gitea.io/gitea/modules/log" - template_func "code.gitea.io/gitea/modules/template" + "code.gitea.io/gitea/modules/setting" + "github.com/Unknwon/com" "github.com/go-macaron/bindata" "gopkg.in/macaron.v1" ) +var ( + templates = template.New("") +) + // Renderer implements the macaron handler for serving the templates. -func Renderer(opts *Options) macaron.Handler { +func Renderer() macaron.Handler { return macaron.Renderer(macaron.RenderOptions{ - AppendDirectories: opts.Custom, - Funcs: template_func.NewFuncMap(), + Funcs: NewFuncMap(), + AppendDirectories: []string{ + path.Join(setting.CustomPath, "templates"), + }, TemplateFileSystem: bindata.Templates( bindata.Options{ Asset: Asset, @@ -35,33 +43,64 @@ func Renderer(opts *Options) macaron.Handler { } // Mailer provides the templates required for sending notification mails. -func Mailer(opts *Options) *template.Template { - templates := template.New("") - - for _, funcs := range template_func.NewFuncMap() { +func Mailer() *template.Template { + for _, funcs := range NewFuncMap() { templates.Funcs(funcs) } - assets, err := AssetDir("mail") + for _, assetPath := range AssetNames() { + if !strings.HasPrefix(assetPath, "mail/") { + continue + } - if err != nil { - log.Error(3, "Unable to read mail asset dir. %s", err) - } + if !strings.HasSuffix(assetPath, ".tmpl") { + continue + } - for _, asset := range assets { - bytes, err := Asset(asset) + content, err := Asset(assetPath) if err != nil { - log.Error(3, "Unable to parse template %s. %s", asset, err) + log.Warn("Failed to read embedded %s template. %v", assetPath, err) + continue } - templates.New(asset).Parse(string(bytes)) + templates.New( + strings.TrimPrefix( + strings.TrimSuffix( + assetPath, + ".tmpl", + ), + "mail/", + ), + ).Parse(string(content)) } - for _, asset := range opts.Custom { - if _, err := os.Stat(opts.Directory); err == nil { - if _, err := templates.ParseGlob(path.Join(asset, "*", "*.tmpl")); err != nil { - log.Error(3, "Unable to parse template directory %s. %s", opts.Directory, err) + customDir := path.Join(setting.CustomPath, "templates", "mail") + + if com.IsDir(customDir) { + files, err := com.StatDir(customDir) + + if err != nil { + log.Warn("Failed to read %s templates dir. %v", customDir, err) + } else { + for _, filePath := range files { + if !strings.HasSuffix(filePath, ".tmpl") { + continue + } + + content, err := ioutil.ReadFile(path.Join(customDir, filePath)) + + if err != nil { + log.Warn("Failed to read custom %s template. %v", filePath, err) + continue + } + + templates.New( + strings.TrimSuffix( + filePath, + ".tmpl", + ), + ).Parse(string(content)) } } } diff --git a/modules/templates/templates.go b/modules/templates/templates.go index 23d099c61d105..91c8db522894e 100644 --- a/modules/templates/templates.go +++ b/modules/templates/templates.go @@ -8,9 +8,3 @@ package templates //go:generate go fmt bindata.go //go:generate sed -i.bak s/..\/..\/templates\/// bindata.go //go:generate rm -f bindata.go.bak - -// Options represents the available options to configure the macaron handler. -type Options struct { - Directory string - Custom []string -} From 1f414a95db07481b9809f9015e85a6de08807618 Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Tue, 6 Dec 2016 15:05:02 +0100 Subject: [PATCH 14/14] Correctly call the new templates handler --- cmd/web.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/cmd/web.go b/cmd/web.go index e551387e4990c..dfb3ac2385461 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -95,17 +95,9 @@ func newMacaron() *macaron.Macaron { SkipLogging: setting.DisableRouterLog, }, )) - m.Use(templates.Renderer( - &templates.Options{ - Directory: path.Join(setting.StaticRootPath, "templates"), - Custom: []string{path.Join(setting.CustomPath, "templates")}, - }, - )) - models.InitMailRender(templates.Mailer(&templates.Options{ - Directory: path.Join(setting.StaticRootPath, "templates", "mail"), - Custom: []string{path.Join(setting.CustomPath, "templates", "mail")}, - })) + m.Use(templates.Renderer()) + models.InitMailRender(templates.Mailer()) localeNames, err := bindata.AssetDir("conf/locale") if err != nil {