Browse Source

Integrate templates into bindata optionally (#314)

Integrated optional bindata for the templates
Thomas Boerger 3 years ago
parent
commit
83ed234472

+ 1 - 0
.gitignore

@@ -29,6 +29,7 @@ _testmain.go
29 29
 coverage.out
30 30
 
31 31
 /modules/public/bindata.go
32
+/modules/templates/bindata.go
32 33
 
33 34
 *.db
34 35
 *.log

+ 3 - 55
cmd/web.go

@@ -7,7 +7,6 @@ package cmd
7 7
 import (
8 8
 	"crypto/tls"
9 9
 	"fmt"
10
-	"io/ioutil"
11 10
 	"net"
12 11
 	"net/http"
13 12
 	"net/http/fcgi"
@@ -15,7 +14,6 @@ import (
15 14
 	"path"
16 15
 	"strings"
17 16
 
18
-	"code.gitea.io/git"
19 17
 	"code.gitea.io/gitea/models"
20 18
 	"code.gitea.io/gitea/modules/auth"
21 19
 	"code.gitea.io/gitea/modules/bindata"
@@ -23,7 +21,7 @@ import (
23 21
 	"code.gitea.io/gitea/modules/log"
24 22
 	"code.gitea.io/gitea/modules/public"
25 23
 	"code.gitea.io/gitea/modules/setting"
26
-	"code.gitea.io/gitea/modules/template"
24
+	"code.gitea.io/gitea/modules/templates"
27 25
 	"code.gitea.io/gitea/routers"
28 26
 	"code.gitea.io/gitea/routers/admin"
29 27
 	apiv1 "code.gitea.io/gitea/routers/api/v1"
@@ -39,10 +37,7 @@ import (
39 37
 	"github.com/go-macaron/i18n"
40 38
 	"github.com/go-macaron/session"
41 39
 	"github.com/go-macaron/toolbox"
42
-	"github.com/go-xorm/xorm"
43
-	version "github.com/mcuadros/go-version"
44 40
 	"github.com/urfave/cli"
45
-	ini "gopkg.in/ini.v1"
46 41
 	macaron "gopkg.in/macaron.v1"
47 42
 )
48 43
 
@@ -74,45 +69,6 @@ type VerChecker struct {
74 69
 	Expected   string
75 70
 }
76 71
 
77
-// checkVersion checks if binary matches the version of templates files.
78
-func checkVersion() {
79
-	// Templates.
80
-	data, err := ioutil.ReadFile(setting.StaticRootPath + "/templates/.VERSION")
81
-	if err != nil {
82
-		log.Fatal(4, "Fail to read 'templates/.VERSION': %v", err)
83
-	}
84
-	tplVer := string(data)
85
-	if tplVer != setting.AppVer {
86
-		if version.Compare(tplVer, setting.AppVer, ">") {
87
-			log.Fatal(4, "Binary version is lower than template file version, did you forget to recompile Gogs?")
88
-		} else {
89
-			log.Fatal(4, "Binary version is higher than template file version, did you forget to update template files?")
90
-		}
91
-	}
92
-
93
-	// Check dependency version.
94
-	checkers := []VerChecker{
95
-		{"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.5.5"},
96
-		{"github.com/go-macaron/binding", binding.Version, "0.3.2"},
97
-		{"github.com/go-macaron/cache", cache.Version, "0.1.2"},
98
-		{"github.com/go-macaron/csrf", csrf.Version, "0.1.0"},
99
-		{"github.com/go-macaron/i18n", i18n.Version, "0.3.0"},
100
-		{"github.com/go-macaron/session", session.Version, "0.1.6"},
101
-		{"github.com/go-macaron/toolbox", toolbox.Version, "0.1.0"},
102
-		{"gopkg.in/ini.v1", ini.Version, "1.8.4"},
103
-		{"gopkg.in/macaron.v1", macaron.Version, "1.1.7"},
104
-		{"code.gitea.io/git", git.Version, "0.4.1"},
105
-	}
106
-	for _, c := range checkers {
107
-		if !version.Compare(c.Version(), c.Expected, ">=") {
108
-			log.Fatal(4, `Dependency outdated!
109
-Package '%s' current version (%s) is below requirement (%s),
110
-please use following command to update this package and recompile Gogs:
111
-go get -u %[1]s`, c.ImportPath, c.Version(), c.Expected)
112
-		}
113
-	}
114
-}
115
-
116 72
 // newMacaron initializes Macaron instance.
117 73
 func newMacaron() *macaron.Macaron {
118 74
 	m := macaron.New()
@@ -140,15 +96,8 @@ func newMacaron() *macaron.Macaron {
140 96
 		},
141 97
 	))
142 98
 
143
-	funcMap := template.NewFuncMap()
144
-	m.Use(macaron.Renderer(macaron.RenderOptions{
145
-		Directory:         path.Join(setting.StaticRootPath, "templates"),
146
-		AppendDirectories: []string{path.Join(setting.CustomPath, "templates")},
147
-		Funcs:             funcMap,
148
-		IndentJSON:        macaron.Env != macaron.PROD,
149
-	}))
150
-	models.InitMailRender(path.Join(setting.StaticRootPath, "templates/mail"),
151
-		path.Join(setting.CustomPath, "templates/mail"), funcMap)
99
+	m.Use(templates.Renderer())
100
+	models.InitMailRender(templates.Mailer())
152 101
 
153 102
 	localeNames, err := bindata.AssetDir("conf/locale")
154 103
 	if err != nil {
@@ -200,7 +149,6 @@ func runWeb(ctx *cli.Context) error {
200 149
 		setting.CustomConf = ctx.String("config")
201 150
 	}
202 151
 	routers.GlobalInit()
203
-	checkVersion()
204 152
 
205 153
 	m := newMacaron()
206 154
 

+ 1 - 1
models/git_diff.go

@@ -18,10 +18,10 @@ import (
18 18
 
19 19
 	"code.gitea.io/git"
20 20
 	"code.gitea.io/gitea/modules/base"
21
+	"code.gitea.io/gitea/modules/highlight"
21 22
 	"code.gitea.io/gitea/modules/log"
22 23
 	"code.gitea.io/gitea/modules/process"
23 24
 	"code.gitea.io/gitea/modules/setting"
24
-	"code.gitea.io/gitea/modules/template/highlight"
25 25
 	"github.com/Unknwon/com"
26 26
 	"github.com/sergi/go-diff/diffmatchpatch"
27 27
 	"golang.org/x/net/html/charset"

+ 37 - 42
models/mail.go

@@ -5,18 +5,18 @@
5 5
 package models
6 6
 
7 7
 import (
8
+	"bytes"
8 9
 	"fmt"
9 10
 	"html/template"
10 11
 	"path"
11 12
 
12
-	"gopkg.in/gomail.v2"
13
-	"gopkg.in/macaron.v1"
14
-
15 13
 	"code.gitea.io/gitea/modules/base"
16 14
 	"code.gitea.io/gitea/modules/log"
17 15
 	"code.gitea.io/gitea/modules/mailer"
18 16
 	"code.gitea.io/gitea/modules/markdown"
19 17
 	"code.gitea.io/gitea/modules/setting"
18
+	"gopkg.in/gomail.v2"
19
+	"gopkg.in/macaron.v1"
20 20
 )
21 21
 
22 22
 const (
@@ -31,27 +31,11 @@ const (
31 31
 	mailNotifyCollaborator base.TplName = "notify/collaborator"
32 32
 )
33 33
 
34
-type mailRenderInterface interface {
35
-	HTMLString(string, interface{}, ...macaron.HTMLOptions) (string, error)
36
-}
37
-
38
-var mailRender mailRenderInterface
34
+var templates *template.Template
39 35
 
40 36
 // InitMailRender initializes the macaron mail renderer
41
-func InitMailRender(dir, appendDir string, funcMap []template.FuncMap) {
42
-	opt := &macaron.RenderOptions{
43
-		Directory:         dir,
44
-		AppendDirectories: []string{appendDir},
45
-		Funcs:             funcMap,
46
-		Extensions:        []string{".tmpl", ".html"},
47
-	}
48
-	ts := macaron.NewTemplateSet()
49
-	ts.Set(macaron.DEFAULT_TPL_SET_NAME, opt)
50
-
51
-	mailRender = &macaron.TplRender{
52
-		TemplateSet: ts,
53
-		Opt:         opt,
54
-	}
37
+func InitMailRender(tmpls *template.Template) {
38
+	templates = tmpls
55 39
 }
56 40
 
57 41
 // SendTestMail sends a test mail
@@ -67,13 +51,15 @@ func SendUserMail(c *macaron.Context, u *User, tpl base.TplName, code, subject,
67 51
 		"ResetPwdCodeLives": setting.Service.ResetPwdCodeLives / 60,
68 52
 		"Code":              code,
69 53
 	}
70
-	body, err := mailRender.HTMLString(string(tpl), data)
71
-	if err != nil {
72
-		log.Error(3, "HTMLString: %v", err)
54
+
55
+	var content bytes.Buffer
56
+
57
+	if err := templates.ExecuteTemplate(&content, string(tpl), data); err != nil {
58
+		log.Error(3, "Template: %v", err)
73 59
 		return
74 60
 	}
75 61
 
76
-	msg := mailer.NewMessage([]string{u.Email}, subject, body)
62
+	msg := mailer.NewMessage([]string{u.Email}, subject, content.String())
77 63
 	msg.Info = fmt.Sprintf("UID: %d, %s", u.ID, info)
78 64
 
79 65
 	mailer.SendAsync(msg)
@@ -97,13 +83,15 @@ func SendActivateEmailMail(c *macaron.Context, u *User, email *EmailAddress) {
97 83
 		"Code":            u.GenerateEmailActivateCode(email.Email),
98 84
 		"Email":           email.Email,
99 85
 	}
100
-	body, err := mailRender.HTMLString(string(mailAuthActivateEmail), data)
101
-	if err != nil {
102
-		log.Error(3, "HTMLString: %v", err)
86
+
87
+	var content bytes.Buffer
88
+
89
+	if err := templates.ExecuteTemplate(&content, string(mailAuthActivateEmail), data); err != nil {
90
+		log.Error(3, "Template: %v", err)
103 91
 		return
104 92
 	}
105 93
 
106
-	msg := mailer.NewMessage([]string{email.Email}, c.Tr("mail.activate_email"), body)
94
+	msg := mailer.NewMessage([]string{email.Email}, c.Tr("mail.activate_email"), content.String())
107 95
 	msg.Info = fmt.Sprintf("UID: %d, activate email", u.ID)
108 96
 
109 97
 	mailer.SendAsync(msg)
@@ -114,13 +102,15 @@ func SendRegisterNotifyMail(c *macaron.Context, u *User) {
114 102
 	data := map[string]interface{}{
115 103
 		"Username": u.DisplayName(),
116 104
 	}
117
-	body, err := mailRender.HTMLString(string(mailAuthRegisterNotify), data)
118
-	if err != nil {
119
-		log.Error(3, "HTMLString: %v", err)
105
+
106
+	var content bytes.Buffer
107
+
108
+	if err := templates.ExecuteTemplate(&content, string(mailAuthRegisterNotify), data); err != nil {
109
+		log.Error(3, "Template: %v", err)
120 110
 		return
121 111
 	}
122 112
 
123
-	msg := mailer.NewMessage([]string{u.Email}, c.Tr("mail.register_notify"), body)
113
+	msg := mailer.NewMessage([]string{u.Email}, c.Tr("mail.register_notify"), content.String())
124 114
 	msg.Info = fmt.Sprintf("UID: %d, registration notify", u.ID)
125 115
 
126 116
 	mailer.SendAsync(msg)
@@ -136,13 +126,15 @@ func SendCollaboratorMail(u, doer *User, repo *Repository) {
136 126
 		"RepoName": repoName,
137 127
 		"Link":     repo.HTMLURL(),
138 128
 	}
139
-	body, err := mailRender.HTMLString(string(mailNotifyCollaborator), data)
140
-	if err != nil {
141
-		log.Error(3, "HTMLString: %v", err)
129
+
130
+	var content bytes.Buffer
131
+
132
+	if err := templates.ExecuteTemplate(&content, string(mailNotifyCollaborator), data); err != nil {
133
+		log.Error(3, "Template: %v", err)
142 134
 		return
143 135
 	}
144 136
 
145
-	msg := mailer.NewMessage([]string{u.Email}, subject, body)
137
+	msg := mailer.NewMessage([]string{u.Email}, subject, content.String())
146 138
 	msg.Info = fmt.Sprintf("UID: %d, add collaborator", u.ID)
147 139
 
148 140
 	mailer.SendAsync(msg)
@@ -161,11 +153,14 @@ func composeIssueMessage(issue *Issue, doer *User, tplName base.TplName, tos []s
161 153
 	body := string(markdown.RenderSpecialLink([]byte(issue.Content), issue.Repo.HTMLURL(), issue.Repo.ComposeMetas()))
162 154
 	data := composeTplData(subject, body, issue.HTMLURL())
163 155
 	data["Doer"] = doer
164
-	content, err := mailRender.HTMLString(string(tplName), data)
165
-	if err != nil {
166
-		log.Error(3, "HTMLString (%s): %v", tplName, err)
156
+
157
+	var content bytes.Buffer
158
+
159
+	if err := templates.ExecuteTemplate(&content, string(tplName), data); err != nil {
160
+		log.Error(3, "Template: %v", err)
167 161
 	}
168
-	msg := mailer.NewMessageFrom(tos, fmt.Sprintf(`"%s" <%s>`, doer.DisplayName(), setting.MailService.FromEmail), subject, content)
162
+
163
+	msg := mailer.NewMessageFrom(tos, fmt.Sprintf(`"%s" <%s>`, doer.DisplayName(), setting.MailService.FromEmail), subject, content.String())
169 164
 	msg.Info = fmt.Sprintf("Subject: %s, %s", subject, info)
170 165
 	return msg
171 166
 }

modules/template/highlight/highlight.go → modules/highlight/highlight.go


+ 2 - 0
modules/public/public.go

@@ -6,6 +6,8 @@ package public
6 6
 
7 7
 //go:generate go-bindata -tags "bindata" -ignore "\\.go|\\.less" -pkg "public" -o "bindata.go" ../../public/...
8 8
 //go:generate go fmt bindata.go
9
+//go:generate sed -i.bak s/..\/..\/public\/// bindata.go
10
+//go:generate rm -f bindata.go.bak
9 11
 
10 12
 // Options represents the available options to configure the macaron handler.
11 13
 type Options struct {

+ 1 - 1
modules/public/static.go

@@ -22,7 +22,7 @@ func Static(opts *Options) macaron.Handler {
22 22
 				AssetDir:   AssetDir,
23 23
 				AssetInfo:  AssetInfo,
24 24
 				AssetNames: AssetNames,
25
-				Prefix:     "../../public",
25
+				Prefix:     "",
26 26
 			}),
27 27
 		},
28 28
 	)

+ 103 - 0
modules/templates/dynamic.go

@@ -0,0 +1,103 @@
1
+// +build !bindata
2
+
3
+// Copyright 2016 The Gitea Authors. All rights reserved.
4
+// Use of this source code is governed by a MIT-style
5
+// license that can be found in the LICENSE file.
6
+
7
+package templates
8
+
9
+import (
10
+	"html/template"
11
+	"io/ioutil"
12
+	"path"
13
+	"strings"
14
+
15
+	"code.gitea.io/gitea/modules/log"
16
+	"code.gitea.io/gitea/modules/setting"
17
+	"github.com/Unknwon/com"
18
+	"gopkg.in/macaron.v1"
19
+)
20
+
21
+var (
22
+	templates = template.New("")
23
+)
24
+
25
+// Renderer implements the macaron handler for serving the templates.
26
+func Renderer() macaron.Handler {
27
+	return macaron.Renderer(macaron.RenderOptions{
28
+		Funcs:     NewFuncMap(),
29
+		Directory: path.Join(setting.StaticRootPath, "templates"),
30
+		AppendDirectories: []string{
31
+			path.Join(setting.CustomPath, "templates"),
32
+		},
33
+	})
34
+}
35
+
36
+// Mailer provides the templates required for sending notification mails.
37
+func Mailer() *template.Template {
38
+	for _, funcs := range NewFuncMap() {
39
+		templates.Funcs(funcs)
40
+	}
41
+
42
+	staticDir := path.Join(setting.StaticRootPath, "templates", "mail")
43
+
44
+	if com.IsDir(staticDir) {
45
+		files, err := com.StatDir(staticDir)
46
+
47
+		if err != nil {
48
+			log.Warn("Failed to read %s templates dir. %v", staticDir, err)
49
+		} else {
50
+			for _, filePath := range files {
51
+				if !strings.HasSuffix(filePath, ".tmpl") {
52
+					continue
53
+				}
54
+
55
+				content, err := ioutil.ReadFile(path.Join(staticDir, filePath))
56
+
57
+				if err != nil {
58
+					log.Warn("Failed to read static %s template. %v", filePath, err)
59
+					continue
60
+				}
61
+
62
+				templates.New(
63
+					strings.TrimSuffix(
64
+						filePath,
65
+						".tmpl",
66
+					),
67
+				).Parse(string(content))
68
+			}
69
+		}
70
+	}
71
+
72
+	customDir := path.Join(setting.CustomPath, "templates", "mail")
73
+
74
+	if com.IsDir(customDir) {
75
+		files, err := com.StatDir(customDir)
76
+
77
+		if err != nil {
78
+			log.Warn("Failed to read %s templates dir. %v", customDir, err)
79
+		} else {
80
+			for _, filePath := range files {
81
+				if !strings.HasSuffix(filePath, ".tmpl") {
82
+					continue
83
+				}
84
+
85
+				content, err := ioutil.ReadFile(path.Join(customDir, filePath))
86
+
87
+				if err != nil {
88
+					log.Warn("Failed to read custom %s template. %v", filePath, err)
89
+					continue
90
+				}
91
+
92
+				templates.New(
93
+					strings.TrimSuffix(
94
+						filePath,
95
+						".tmpl",
96
+					),
97
+				).Parse(string(content))
98
+			}
99
+		}
100
+	}
101
+
102
+	return templates
103
+}

+ 1 - 1
modules/template/template.go

@@ -2,7 +2,7 @@
2 2
 // Use of this source code is governed by a MIT-style
3 3
 // license that can be found in the LICENSE file.
4 4
 
5
-package template
5
+package templates
6 6
 
7 7
 import (
8 8
 	"container/list"

+ 109 - 0
modules/templates/static.go

@@ -0,0 +1,109 @@
1
+// +build bindata
2
+
3
+// Copyright 2016 The Gitea Authors. All rights reserved.
4
+// Use of this source code is governed by a MIT-style
5
+// license that can be found in the LICENSE file.
6
+
7
+package templates
8
+
9
+import (
10
+	"html/template"
11
+	"io/ioutil"
12
+	"path"
13
+	"strings"
14
+
15
+	"code.gitea.io/gitea/modules/log"
16
+	"code.gitea.io/gitea/modules/setting"
17
+	"github.com/Unknwon/com"
18
+	"github.com/go-macaron/bindata"
19
+	"gopkg.in/macaron.v1"
20
+)
21
+
22
+var (
23
+	templates = template.New("")
24
+)
25
+
26
+// Renderer implements the macaron handler for serving the templates.
27
+func Renderer() macaron.Handler {
28
+	return macaron.Renderer(macaron.RenderOptions{
29
+		Funcs: NewFuncMap(),
30
+		AppendDirectories: []string{
31
+			path.Join(setting.CustomPath, "templates"),
32
+		},
33
+		TemplateFileSystem: bindata.Templates(
34
+			bindata.Options{
35
+				Asset:      Asset,
36
+				AssetDir:   AssetDir,
37
+				AssetInfo:  AssetInfo,
38
+				AssetNames: AssetNames,
39
+				Prefix:     "",
40
+			},
41
+		),
42
+	})
43
+}
44
+
45
+// Mailer provides the templates required for sending notification mails.
46
+func Mailer() *template.Template {
47
+	for _, funcs := range NewFuncMap() {
48
+		templates.Funcs(funcs)
49
+	}
50
+
51
+	for _, assetPath := range AssetNames() {
52
+		if !strings.HasPrefix(assetPath, "mail/") {
53
+			continue
54
+		}
55
+
56
+		if !strings.HasSuffix(assetPath, ".tmpl") {
57
+			continue
58
+		}
59
+
60
+		content, err := Asset(assetPath)
61
+
62
+		if err != nil {
63
+			log.Warn("Failed to read embedded %s template. %v", assetPath, err)
64
+			continue
65
+		}
66
+
67
+		templates.New(
68
+			strings.TrimPrefix(
69
+				strings.TrimSuffix(
70
+					assetPath,
71
+					".tmpl",
72
+				),
73
+				"mail/",
74
+			),
75
+		).Parse(string(content))
76
+	}
77
+
78
+	customDir := path.Join(setting.CustomPath, "templates", "mail")
79
+
80
+	if com.IsDir(customDir) {
81
+		files, err := com.StatDir(customDir)
82
+
83
+		if err != nil {
84
+			log.Warn("Failed to read %s templates dir. %v", customDir, err)
85
+		} else {
86
+			for _, filePath := range files {
87
+				if !strings.HasSuffix(filePath, ".tmpl") {
88
+					continue
89
+				}
90
+
91
+				content, err := ioutil.ReadFile(path.Join(customDir, filePath))
92
+
93
+				if err != nil {
94
+					log.Warn("Failed to read custom %s template. %v", filePath, err)
95
+					continue
96
+				}
97
+
98
+				templates.New(
99
+					strings.TrimSuffix(
100
+						filePath,
101
+						".tmpl",
102
+					),
103
+				).Parse(string(content))
104
+			}
105
+		}
106
+	}
107
+
108
+	return templates
109
+}

+ 10 - 0
modules/templates/templates.go

@@ -0,0 +1,10 @@
1
+// Copyright 2016 The Gitea Authors. All rights reserved.
2
+// Use of this source code is governed by a MIT-style
3
+// license that can be found in the LICENSE file.
4
+
5
+package templates
6
+
7
+//go:generate go-bindata -tags "bindata" -ignore "\\.go" -pkg "templates" -o "bindata.go" ../../templates/...
8
+//go:generate go fmt bindata.go
9
+//go:generate sed -i.bak s/..\/..\/templates\/// bindata.go
10
+//go:generate rm -f bindata.go.bak

+ 1 - 1
routers/init.go

@@ -11,12 +11,12 @@ import (
11 11
 	"code.gitea.io/git"
12 12
 	"code.gitea.io/gitea/models"
13 13
 	"code.gitea.io/gitea/modules/cron"
14
+	"code.gitea.io/gitea/modules/highlight"
14 15
 	"code.gitea.io/gitea/modules/log"
15 16
 	"code.gitea.io/gitea/modules/mailer"
16 17
 	"code.gitea.io/gitea/modules/markdown"
17 18
 	"code.gitea.io/gitea/modules/setting"
18 19
 	"code.gitea.io/gitea/modules/ssh"
19
-	"code.gitea.io/gitea/modules/template/highlight"
20 20
 	macaron "gopkg.in/macaron.v1"
21 21
 )
22 22
 

+ 2 - 2
routers/repo/editor.go

@@ -18,7 +18,7 @@ import (
18 18
 	"code.gitea.io/gitea/modules/context"
19 19
 	"code.gitea.io/gitea/modules/log"
20 20
 	"code.gitea.io/gitea/modules/setting"
21
-	"code.gitea.io/gitea/modules/template"
21
+	"code.gitea.io/gitea/modules/templates"
22 22
 )
23 23
 
24 24
 const (
@@ -74,7 +74,7 @@ func editFile(ctx *context.Context, isNewFile bool) {
74 74
 
75 75
 		d, _ := ioutil.ReadAll(dataRc)
76 76
 		buf = append(buf, d...)
77
-		if content, err := template.ToUTF8WithErr(buf); err != nil {
77
+		if content, err := templates.ToUTF8WithErr(buf); err != nil {
78 78
 			if err != nil {
79 79
 				log.Error(4, "ToUTF8WithErr: %v", err)
80 80
 			}

+ 3 - 3
routers/repo/view.go

@@ -16,11 +16,11 @@ import (
16 16
 	"code.gitea.io/gitea/models"
17 17
 	"code.gitea.io/gitea/modules/base"
18 18
 	"code.gitea.io/gitea/modules/context"
19
+	"code.gitea.io/gitea/modules/highlight"
19 20
 	"code.gitea.io/gitea/modules/log"
20 21
 	"code.gitea.io/gitea/modules/markdown"
21 22
 	"code.gitea.io/gitea/modules/setting"
22
-	"code.gitea.io/gitea/modules/template"
23
-	"code.gitea.io/gitea/modules/template/highlight"
23
+	"code.gitea.io/gitea/modules/templates"
24 24
 	"github.com/Unknwon/paginater"
25 25
 )
26 26
 
@@ -164,7 +164,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
164 164
 		} else {
165 165
 			// Building code view blocks with line number on server side.
166 166
 			var fileContent string
167
-			if content, err := template.ToUTF8WithErr(buf); err != nil {
167
+			if content, err := templates.ToUTF8WithErr(buf); err != nil {
168 168
 				if err != nil {
169 169
 					log.Error(4, "ToUTF8WithErr: %s", err)
170 170
 				}

+ 0 - 1
templates/.VERSION

@@ -1 +0,0 @@
1
-0.9.99.0915