hugo

Unnamed repository; edit this file 'description' to name the repository.

git clone git://git.shimmy1996.com/hugo.git
commit 9650e568418a316e71ad94d7e27caf544a4a2d0d
parent e77b2e3aa0b24c5ca960905772335b27845705eb
Author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Date:   Fri, 29 Jan 2021 17:45:38 +0100

tpl: Add temporary patch to fix template data race

Keep this as a separate commit so we can reapply it if needed.

Fixes #7293

Diffstat:
Mtpl/internal/go_templates/texttemplate/exec.go | 15++++++++-------
Mtpl/internal/go_templates/texttemplate/template.go | 16+++++++++++++++-
2 files changed, 23 insertions(+), 8 deletions(-)
diff --git 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
@@ -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]
 }