diff --git a/tpl/internal/go_templates/texttemplate/exec.go b/tpl/internal/go_templates/texttemplate/exec.go index 8b3871234..df249aecd 100644 --- a/tpl/internal/go_templates/texttemplate/exec.go +++ b/tpl/internal/go_templates/texttemplate/exec.go @@ -6,12 +6,13 @@ package template import ( "fmt" - "github.com/gohugoio/hugo/tpl/internal/go_templates/fmtsort" - "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/parse" "io" "reflect" "runtime" "strings" + + "github.com/gohugoio/hugo/tpl/internal/go_templates/fmtsort" + "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/parse" ) // maxExecDepth specifies the maximum stack depth of templates within @@ -179,10 +180,7 @@ func errRecover(errp *error) { // A template may be executed safely in parallel, although if parallel // executions share a Writer the output may be interleaved. func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error { - var tmpl *Template - if t.common != nil { - tmpl = t.tmpl[name] - } + tmpl := t.Lookup(name) if tmpl == nil { return fmt.Errorf("template: no template %q associated with template %q", name, t.name) } @@ -230,6 +228,9 @@ func (t *Template) DefinedTemplates() string { return "" } var b strings.Builder + // temporary Hugo-fix + t.muTmpl.RLock() + defer t.muTmpl.RUnlock() for name, tmpl := range t.tmpl { if tmpl.Tree == nil || tmpl.Root == nil { continue @@ -401,7 +402,7 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) { func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) { s.at(t) - tmpl := s.tmpl.tmpl[t.Name] + tmpl := s.tmpl.Lookup(t.Name) if tmpl == nil { s.errorf("template %q not defined", t.Name) } diff --git a/tpl/internal/go_templates/texttemplate/template.go b/tpl/internal/go_templates/texttemplate/template.go index 9c6ba6dfc..15f4a2f26 100644 --- a/tpl/internal/go_templates/texttemplate/template.go +++ b/tpl/internal/go_templates/texttemplate/template.go @@ -5,13 +5,15 @@ package template import ( - "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/parse" "reflect" "sync" + + "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/parse" ) // common holds the information shared by related templates. type common struct { + muTmpl sync.RWMutex // protects tmpl (temporary Hugo-fix) tmpl map[string]*Template // Map from name to defined templates. option option // We use two maps, one for parsing and one for execution. @@ -88,6 +90,9 @@ func (t *Template) Clone() (*Template, error) { if t.common == nil { return nt, nil } + // temporary Hugo-fix + t.muTmpl.RLock() + defer t.muTmpl.RUnlock() for k, v := range t.tmpl { if k == t.name { nt.tmpl[t.name] = nt @@ -124,6 +129,9 @@ func (t *Template) copy(c *common) *Template { // its definition. If it has been defined and already has that name, the existing // definition is replaced; otherwise a new template is created, defined, and returned. func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) { + // temporary Hugo-fix + t.muTmpl.Lock() + defer t.muTmpl.Unlock() t.init() nt := t if name != t.name { @@ -142,6 +150,9 @@ func (t *Template) Templates() []*Template { return nil } // Return a slice so we don't expose the map. + // temporary Hugo-fix + t.muTmpl.RLock() + defer t.muTmpl.RUnlock() m := make([]*Template, 0, len(t.tmpl)) for _, v := range t.tmpl { m = append(m, v) @@ -182,6 +193,9 @@ func (t *Template) Lookup(name string) *Template { if t.common == nil { return nil } + // temporary Hugo-fix + t.muTmpl.RLock() + defer t.muTmpl.RUnlock() return t.tmpl[name] }