From 93b04e67f633e96484c29158cad00e86abe64c1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Sun, 28 Feb 2016 11:51:51 +0100 Subject: [PATCH] Create template clone for late template execution Fixing some breaking blogs on Go 1.6 Fixes #1879 --- hugolib/site.go | 7 ++++++- tpl/template.go | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/hugolib/site.go b/hugolib/site.go index f3e14399b..bb88f756e 100644 --- a/hugolib/site.go +++ b/hugolib/site.go @@ -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 diff --git a/tpl/template.go b/tpl/template.go index c5a23628a..fa8347efd 100644 --- a/tpl/template.go +++ b/tpl/template.go @@ -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)