shithub: hugo

Download patch

ref: 99d11386a7de544f044f30782310175cf2df4004
parent: 62e9e7e6ba3eee386c95d0420386132ad8acaa7e
author: Bjørn Erik Pedersen <[email protected]>
date: Wed Nov 16 15:32:38 EST 2016

node to page: Fix the Page copy()

By embeding the init sync.Once var in a pointer so we can reset it when we copy the page.

Updates #2297

--- a/hugolib/hugo_sites.go
+++ b/hugolib/hugo_sites.go
@@ -304,6 +304,7 @@
 // Move the new* methods after cleanup in site.go
 func (s *Site) newNodePage(typ string) *Page {
 	return &Page{
+		pageInit: &pageInit{},
 		Kind:     typ,
 		Data:     make(map[string]interface{}),
 		Site:     &s.Info,
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -70,6 +70,7 @@
 )
 
 type Page struct {
+	*pageInit
 
 	// Kind is the discriminator that identifies the different page types
 	// in the different page collections. This can, as an example, be used
@@ -145,18 +146,14 @@
 	shortcodes        map[string]shortcode
 
 	// the content stripped for HTML
-	plain          string // TODO should be []byte
-	plainWords     []string
-	plainInit      sync.Once
-	plainWordsInit sync.Once
+	plain      string // TODO should be []byte
+	plainWords []string
 
 	// rendering configuration
-	renderingConfig     *helpers.Blackfriday
-	renderingConfigInit sync.Once
+	renderingConfig *helpers.Blackfriday
 
 	// menus
-	pageMenus     PageMenus
-	pageMenusInit sync.Once
+	pageMenus PageMenus
 
 	Source
 
@@ -196,16 +193,26 @@
 
 	URLPath
 
-	paginator     *Pager
-	paginatorInit sync.Once
+	paginator *Pager
 
 	scratch *Scratch
 
-	language     *helpers.Language
-	languageInit sync.Once
-	lang         string
+	language *helpers.Language
+	lang     string
 }
 
+// pageInit lazy initializes different parts of the page. It is extracted
+// into its own type so we can easily create a copy of a given page.
+type pageInit struct {
+	languageInit        sync.Once
+	pageMenusInit       sync.Once
+	pageMetaInit        sync.Once
+	paginatorInit       sync.Once
+	plainInit           sync.Once
+	plainWordsInit      sync.Once
+	renderingConfigInit sync.Once
+}
+
 // IsNode returns whether this is an item of one of the list types in Hugo,
 // i.e. not a regular content page.
 func (p *Page) IsNode() bool {
@@ -231,7 +238,6 @@
 	wordCount      int
 	fuzzyWordCount int
 	readingTime    int
-	pageMetaInit   sync.Once
 	Weight         int
 }
 
@@ -532,6 +538,7 @@
 
 func newPage(filename string) *Page {
 	page := Page{
+		pageInit:    &pageInit{},
 		Kind:        kindFromFilename(filename),
 		contentType: "",
 		Source:      Source{File: *source.NewFile(filename)},
@@ -1538,20 +1545,12 @@
 	}
 }
 
-// Page constains some sync.Once which have a mutex, so we cannot just
-// copy the Page by value. So for the situations where we need a copy,
-// the paginators etc., we do it manually here.
-// TODO(bep) np do better
+// copy creates a copy of this page with the lazy sync.Once vars reset
+// so they will be evaluated again, for word count calculations etc.
 func (p *Page) copy() *Page {
-	c := &Page{Kind: p.Kind, Site: p.Site}
-	c.Title = p.Title
-	c.Data = p.Data
-	c.Date = p.Date
-	c.Lastmod = p.Lastmod
-	c.language = p.language
-	c.lang = p.lang
-	c.URLPath = p.URLPath
-	return c
+	c := *p
+	c.pageInit = &pageInit{}
+	return &c
 }
 
 // TODO(bep) np these are pulled over from Node. Needs regrouping / embed
--- a/hugolib/pageSort_test.go
+++ b/hugolib/pageSort_test.go
@@ -147,7 +147,7 @@
 
 	for i := 0; i < num; i++ {
 		pages[i] = &Page{
-
+			pageInit: &pageInit{},
 			URLPath: URLPath{
 				Section: "z",
 				URL:     fmt.Sprintf("http://base/x/y/p%d.html", i),
--- a/hugolib/page_permalink_test.go
+++ b/hugolib/page_permalink_test.go
@@ -66,7 +66,8 @@
 		info := newSiteInfo(siteBuilderCfg{baseURL: string(test.base), language: helpers.NewDefaultLanguage()})
 
 		p := &Page{
-			Kind: KindPage,
+			pageInit: &pageInit{},
+			Kind:     KindPage,
 			URLPath: URLPath{
 				Section: "z",
 				URL:     test.url,
--- a/hugolib/page_test.go
+++ b/hugolib/page_test.go
@@ -1269,7 +1269,7 @@
 		{func(n *Page) bool { return n.Now().Unix() == time.Now().Unix() }},
 	} {
 
-		n := &Page{Kind: KindHome}
+		n := &Page{pageInit: &pageInit{}, Kind: KindHome}
 		n.RSSLink = "rssLink"
 
 		if !this.assertFunc(n) {
--- a/hugolib/pagination_test.go
+++ b/hugolib/pagination_test.go
@@ -457,6 +457,7 @@
 	info := newSiteInfo(siteBuilderCfg{baseURL: "http://base/", language: helpers.NewDefaultLanguage()})
 	for i := 0; i < num; i++ {
 		pages[i] = &Page{
+			pageInit: &pageInit{},
 			URLPath: URLPath{
 				Section: "z",
 				URL:     fmt.Sprintf("http://base/x/y/p%d.html", i),