mirror of
https://github.com/astaxie/beego.git
synced 2024-12-23 15:20:50 +00:00
Merge pull request #1727 from JessonChan/templates_bug_fix
lock the templates map when goroutie update the map
This commit is contained in:
commit
f0a41f978f
96
template.go
96
template.go
@ -23,6 +23,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/astaxie/beego/utils"
|
"github.com/astaxie/beego/utils"
|
||||||
)
|
)
|
||||||
@ -31,6 +32,7 @@ var (
|
|||||||
beegoTplFuncMap = make(template.FuncMap)
|
beegoTplFuncMap = make(template.FuncMap)
|
||||||
// BeeTemplates caching map and supported template file extensions.
|
// BeeTemplates caching map and supported template file extensions.
|
||||||
BeeTemplates = make(map[string]*template.Template)
|
BeeTemplates = make(map[string]*template.Template)
|
||||||
|
templatesLock sync.Mutex
|
||||||
// BeeTemplateExt stores the template extension which will build
|
// BeeTemplateExt stores the template extension which will build
|
||||||
BeeTemplateExt = []string{"tpl", "html"}
|
BeeTemplateExt = []string{"tpl", "html"}
|
||||||
)
|
)
|
||||||
@ -66,17 +68,21 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddFuncMap let user to register a func in the template.
|
// AddFuncMap let user to register a func in the template.
|
||||||
func AddFuncMap(key string, funname interface{}) error {
|
func AddFuncMap(key string, fn interface{}) error {
|
||||||
beegoTplFuncMap[key] = funname
|
beegoTplFuncMap[key] = fn
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type templatefile struct {
|
type templateFile struct {
|
||||||
root string
|
root string
|
||||||
files map[string][]string
|
files map[string][]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tf *templatefile) visit(paths string, f os.FileInfo, err error) error {
|
// visit will make the paths into two part,the first is subDir (without tf.root),the second is full path(without tf.root).
|
||||||
|
// if tf.root="views" and
|
||||||
|
// paths is "views/errors/404.html",the subDir will be "errors",the file will be "errors/404.html"
|
||||||
|
// paths is "views/admin/errors/404.html",the subDir will be "admin/errors",the file will be "admin/errors/404.html"
|
||||||
|
func (tf *templateFile) visit(paths string, f os.FileInfo, err error) error {
|
||||||
if f == nil {
|
if f == nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -88,18 +94,10 @@ func (tf *templatefile) visit(paths string, f os.FileInfo, err error) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
replace := strings.NewReplacer("\\", "/")
|
replace := strings.NewReplacer("\\", "/")
|
||||||
a := []byte(paths)
|
file := strings.TrimLeft(replace.Replace(paths[len(tf.root):]), "/")
|
||||||
a = a[len([]byte(tf.root)):]
|
subDir := filepath.Dir(file)
|
||||||
file := strings.TrimLeft(replace.Replace(string(a)), "/")
|
|
||||||
subdir := filepath.Dir(file)
|
|
||||||
if _, ok := tf.files[subdir]; ok {
|
|
||||||
tf.files[subdir] = append(tf.files[subdir], file)
|
|
||||||
} else {
|
|
||||||
m := make([]string, 1)
|
|
||||||
m[0] = file
|
|
||||||
tf.files[subdir] = m
|
|
||||||
}
|
|
||||||
|
|
||||||
|
tf.files[subDir] = append(tf.files[subDir], file)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +130,7 @@ func BuildTemplate(dir string, files ...string) error {
|
|||||||
}
|
}
|
||||||
return errors.New("dir open err")
|
return errors.New("dir open err")
|
||||||
}
|
}
|
||||||
self := &templatefile{
|
self := &templateFile{
|
||||||
root: dir,
|
root: dir,
|
||||||
files: make(map[string][]string),
|
files: make(map[string][]string),
|
||||||
}
|
}
|
||||||
@ -146,12 +144,14 @@ func BuildTemplate(dir string, files ...string) error {
|
|||||||
for _, v := range self.files {
|
for _, v := range self.files {
|
||||||
for _, file := range v {
|
for _, file := range v {
|
||||||
if len(files) == 0 || utils.InSlice(file, files) {
|
if len(files) == 0 || utils.InSlice(file, files) {
|
||||||
|
templatesLock.Lock()
|
||||||
t, err := getTemplate(self.root, file, v...)
|
t, err := getTemplate(self.root, file, v...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Trace("parse template err:", file, err)
|
Trace("parse template err:", file, err)
|
||||||
} else {
|
} else {
|
||||||
BeeTemplates[file] = t
|
BeeTemplates[file] = t
|
||||||
}
|
}
|
||||||
|
templatesLock.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,16 +159,16 @@ func BuildTemplate(dir string, files ...string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getTplDeep(root, file, parent string, t *template.Template) (*template.Template, [][]string, error) {
|
func getTplDeep(root, file, parent string, t *template.Template) (*template.Template, [][]string, error) {
|
||||||
var fileabspath string
|
var fileAbsPath string
|
||||||
if filepath.HasPrefix(file, "../") {
|
if filepath.HasPrefix(file, "../") {
|
||||||
fileabspath = filepath.Join(root, filepath.Dir(parent), file)
|
fileAbsPath = filepath.Join(root, filepath.Dir(parent), file)
|
||||||
} else {
|
} else {
|
||||||
fileabspath = filepath.Join(root, file)
|
fileAbsPath = filepath.Join(root, file)
|
||||||
}
|
}
|
||||||
if e := utils.FileExists(fileabspath); !e {
|
if e := utils.FileExists(fileAbsPath); !e {
|
||||||
panic("can't find template file:" + file)
|
panic("can't find template file:" + file)
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadFile(fileabspath)
|
data, err := ioutil.ReadFile(fileAbsPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, [][]string{}, err
|
return nil, [][]string{}, err
|
||||||
}
|
}
|
||||||
@ -177,11 +177,11 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp
|
|||||||
return nil, [][]string{}, err
|
return nil, [][]string{}, err
|
||||||
}
|
}
|
||||||
reg := regexp.MustCompile(BConfig.WebConfig.TemplateLeft + "[ ]*template[ ]+\"([^\"]+)\"")
|
reg := regexp.MustCompile(BConfig.WebConfig.TemplateLeft + "[ ]*template[ ]+\"([^\"]+)\"")
|
||||||
allsub := reg.FindAllStringSubmatch(string(data), -1)
|
allSub := reg.FindAllStringSubmatch(string(data), -1)
|
||||||
for _, m := range allsub {
|
for _, m := range allSub {
|
||||||
if len(m) == 2 {
|
if len(m) == 2 {
|
||||||
tlook := t.Lookup(m[1])
|
tl := t.Lookup(m[1])
|
||||||
if tlook != nil {
|
if tl != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !HasTemplateExt(m[1]) {
|
if !HasTemplateExt(m[1]) {
|
||||||
@ -193,17 +193,17 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t, allsub, nil
|
return t, allSub, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTemplate(root, file string, others ...string) (t *template.Template, err error) {
|
func getTemplate(root, file string, others ...string) (t *template.Template, err error) {
|
||||||
t = template.New(file).Delims(BConfig.WebConfig.TemplateLeft, BConfig.WebConfig.TemplateRight).Funcs(beegoTplFuncMap)
|
t = template.New(file).Delims(BConfig.WebConfig.TemplateLeft, BConfig.WebConfig.TemplateRight).Funcs(beegoTplFuncMap)
|
||||||
var submods [][]string
|
var subMods [][]string
|
||||||
t, submods, err = getTplDeep(root, file, "", t)
|
t, subMods, err = getTplDeep(root, file, "", t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
t, err = _getTemplate(t, root, submods, others...)
|
t, err = _getTemplate(t, root, subMods, others...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -211,44 +211,44 @@ func getTemplate(root, file string, others ...string) (t *template.Template, err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func _getTemplate(t0 *template.Template, root string, submods [][]string, others ...string) (t *template.Template, err error) {
|
func _getTemplate(t0 *template.Template, root string, subMods [][]string, others ...string) (t *template.Template, err error) {
|
||||||
t = t0
|
t = t0
|
||||||
for _, m := range submods {
|
for _, m := range subMods {
|
||||||
if len(m) == 2 {
|
if len(m) == 2 {
|
||||||
templ := t.Lookup(m[1])
|
tpl := t.Lookup(m[1])
|
||||||
if templ != nil {
|
if tpl != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
//first check filename
|
//first check filename
|
||||||
for _, otherfile := range others {
|
for _, otherFile := range others {
|
||||||
if otherfile == m[1] {
|
if otherFile == m[1] {
|
||||||
var submods1 [][]string
|
var subMods1 [][]string
|
||||||
t, submods1, err = getTplDeep(root, otherfile, "", t)
|
t, subMods1, err = getTplDeep(root, otherFile, "", t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Trace("template parse file err:", err)
|
Trace("template parse file err:", err)
|
||||||
} else if submods1 != nil && len(submods1) > 0 {
|
} else if subMods1 != nil && len(subMods1) > 0 {
|
||||||
t, err = _getTemplate(t, root, submods1, others...)
|
t, err = _getTemplate(t, root, subMods1, others...)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//second check define
|
//second check define
|
||||||
for _, otherfile := range others {
|
for _, otherFile := range others {
|
||||||
fileabspath := filepath.Join(root, otherfile)
|
fileAbsPath := filepath.Join(root, otherFile)
|
||||||
data, err := ioutil.ReadFile(fileabspath)
|
data, err := ioutil.ReadFile(fileAbsPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
reg := regexp.MustCompile(BConfig.WebConfig.TemplateLeft + "[ ]*define[ ]+\"([^\"]+)\"")
|
reg := regexp.MustCompile(BConfig.WebConfig.TemplateLeft + "[ ]*define[ ]+\"([^\"]+)\"")
|
||||||
allsub := reg.FindAllStringSubmatch(string(data), -1)
|
allSub := reg.FindAllStringSubmatch(string(data), -1)
|
||||||
for _, sub := range allsub {
|
for _, sub := range allSub {
|
||||||
if len(sub) == 2 && sub[1] == m[1] {
|
if len(sub) == 2 && sub[1] == m[1] {
|
||||||
var submods1 [][]string
|
var subMods1 [][]string
|
||||||
t, submods1, err = getTplDeep(root, otherfile, "", t)
|
t, subMods1, err = getTplDeep(root, otherFile, "", t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Trace("template parse file err:", err)
|
Trace("template parse file err:", err)
|
||||||
} else if submods1 != nil && len(submods1) > 0 {
|
} else if subMods1 != nil && len(subMods1) > 0 {
|
||||||
t, err = _getTemplate(t, root, submods1, others...)
|
t, err = _getTemplate(t, root, subMods1, others...)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user