From 93b04e67f633e96484c29158cad00e86abe64c1e Mon Sep 17 00:00:00 2001
From: =?utf8?q?Bj=C3=B8rn=20Erik=20Pedersen?=
 <bjorn.erik.pedersen@gmail.com>
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 f3e14399..bb88f756 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 c5a23628..fa8347ef 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)
-- 
2.30.2