Create template clone for late template execution
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 28 Feb 2016 10:51:51 +0000 (11:51 +0100)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 28 Feb 2016 10:51:51 +0000 (11:51 +0100)
Fixing some breaking blogs on Go 1.6

Fixes #1879

hugolib/site.go
tpl/template.go

index f3e14399b618dac6a83aaa42a9ae3672c5d830c6..bb88f756ec4532e648945a007990438a109c1f71 100644 (file)
@@ -595,6 +595,7 @@ func (s *Site) prepTemplates() {
        if s.hasTheme() {
                s.Tmpl.LoadTemplatesWithPrefix(s.absThemeDir()+"/layouts", "theme")
        }
+       s.Tmpl.MarkReady()
 }
 
 func (s *Site) addTemplate(name, data string) error {
@@ -1366,11 +1367,15 @@ func (s *Site) RenderPages() error {
        // this cannot be fanned out to multiple Go routines
        // See issue #1601
        // TODO(bep): Check the IsRenderable logic.
+
+       // Issue #1879
+       templ := s.Tmpl.Clone()
+
        for _, p := range s.Pages {
                var layouts []string
                if !p.IsRenderable() {
                        self := "__" + p.TargetPath()
-                       _, err := s.Tmpl.New(self).Parse(string(p.Content))
+                       _, err := templ.New(self).Parse(string(p.Content))
                        if err != nil {
                                results <- err
                                continue
index c5a23628a14d7f9a28530c8bf3666df4604ee5ee..fa8347efddff42086314439911540527dd852f25 100644 (file)
@@ -37,12 +37,14 @@ type Template interface {
        Lookup(name string) *template.Template
        Templates() []*template.Template
        New(name string) *template.Template
+       Clone() *template.Template
        LoadTemplates(absPath string)
        LoadTemplatesWithPrefix(absPath, prefix string)
        AddTemplate(name, tpl string) error
        AddAceTemplate(name, basePath, innerPath string, baseContent, innerContent []byte) error
        AddInternalTemplate(prefix, name, tpl string) error
        AddInternalShortcode(name, tpl string) error
+       MarkReady()
        PrintErrors()
 }
 
@@ -53,6 +55,8 @@ type templateErr struct {
 
 type GoHTMLTemplate struct {
        template.Template
+       clone  *template.Template
+       ready  bool
        errors []*templateErr
 }
 
@@ -140,6 +144,22 @@ func (t *GoHTMLTemplate) LoadEmbedded() {
        t.EmbedTemplates()
 }
 
+// MarkReady marks the template as "ready for execution". No changes allowed
+// after this is set.
+func (t *GoHTMLTemplate) MarkReady() {
+       t.clone = template.Must(t.Template.Clone())
+       t.ready = true
+}
+
+// Since Go 1.6, the template cannot change once executed. So we have to create
+// a clone and work with that in some rare cases.
+func (t *GoHTMLTemplate) Clone() *template.Template {
+       if !t.ready {
+               panic("template clone called too early")
+       }
+       return template.Must(t.clone.Clone())
+}
+
 func (t *GoHTMLTemplate) AddInternalTemplate(prefix, name, tpl string) error {
        if prefix != "" {
                return t.AddTemplate("_internal/"+prefix+"/"+name, tpl)