From 99d11386a7de544f044f30782310175cf2df4004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Wed, 16 Nov 2016 20:32:38 +0100 Subject: [PATCH] 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 --- hugolib/hugo_sites.go | 1 + hugolib/page.go | 53 +++++++++++++++++----------------- hugolib/pageSort_test.go | 2 +- hugolib/page_permalink_test.go | 3 +- hugolib/page_test.go | 2 +- hugolib/pagination_test.go | 1 + 6 files changed, 32 insertions(+), 30 deletions(-) diff --git a/hugolib/hugo_sites.go b/hugolib/hugo_sites.go index 42e6cb503..e4ee4ff9f 100644 --- a/hugolib/hugo_sites.go +++ b/hugolib/hugo_sites.go @@ -304,6 +304,7 @@ func (h *HugoSites) createMissingPages() error { // 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, diff --git a/hugolib/page.go b/hugolib/page.go index aa08c66f7..96a78ee73 100644 --- a/hugolib/page.go +++ b/hugolib/page.go @@ -70,6 +70,7 @@ const ( ) 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 @@ type Page struct { 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,14 +193,24 @@ type Page struct { 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, @@ -231,7 +238,6 @@ type PageMeta struct { wordCount int fuzzyWordCount int readingTime int - pageMetaInit sync.Once Weight int } @@ -532,6 +538,7 @@ func (p *Page) getRenderingConfig() *helpers.Blackfriday { func newPage(filename string) *Page { page := Page{ + pageInit: &pageInit{}, Kind: kindFromFilename(filename), contentType: "", Source: Source{File: *source.NewFile(filename)}, @@ -1538,20 +1545,12 @@ func (p *Page) updatePageDates() { } } -// 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 diff --git a/hugolib/pageSort_test.go b/hugolib/pageSort_test.go index 7ecbee98a..126c1b4ad 100644 --- a/hugolib/pageSort_test.go +++ b/hugolib/pageSort_test.go @@ -147,7 +147,7 @@ func createSortTestPages(num int) Pages { 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), diff --git a/hugolib/page_permalink_test.go b/hugolib/page_permalink_test.go index 341639529..007f9eefc 100644 --- a/hugolib/page_permalink_test.go +++ b/hugolib/page_permalink_test.go @@ -66,7 +66,8 @@ func TestPermalink(t *testing.T) { 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, diff --git a/hugolib/page_test.go b/hugolib/page_test.go index 45ca241fd..a2e75c7ec 100644 --- a/hugolib/page_test.go +++ b/hugolib/page_test.go @@ -1269,7 +1269,7 @@ func TestIndexPageSimpleMethods(t *testing.T) { {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) { diff --git a/hugolib/pagination_test.go b/hugolib/pagination_test.go index 591d09047..2b3b18a5b 100644 --- a/hugolib/pagination_test.go +++ b/hugolib/pagination_test.go @@ -457,6 +457,7 @@ func createTestPages(num int) Pages { 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),