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
This commit is contained in:
Bjørn Erik Pedersen 2016-11-16 20:32:38 +01:00
parent 62e9e7e6ba
commit 99d11386a7
6 changed files with 32 additions and 30 deletions

View file

@ -304,6 +304,7 @@ func (h *HugoSites) createMissingPages() error {
// Move the new* methods after cleanup in site.go // Move the new* methods after cleanup in site.go
func (s *Site) newNodePage(typ string) *Page { func (s *Site) newNodePage(typ string) *Page {
return &Page{ return &Page{
pageInit: &pageInit{},
Kind: typ, Kind: typ,
Data: make(map[string]interface{}), Data: make(map[string]interface{}),
Site: &s.Info, Site: &s.Info,

View file

@ -70,6 +70,7 @@ const (
) )
type Page struct { type Page struct {
*pageInit
// Kind is the discriminator that identifies the different page types // Kind is the discriminator that identifies the different page types
// in the different page collections. This can, as an example, be used // in the different page collections. This can, as an example, be used
@ -145,18 +146,14 @@ type Page struct {
shortcodes map[string]shortcode shortcodes map[string]shortcode
// the content stripped for HTML // the content stripped for HTML
plain string // TODO should be []byte plain string // TODO should be []byte
plainWords []string plainWords []string
plainInit sync.Once
plainWordsInit sync.Once
// rendering configuration // rendering configuration
renderingConfig *helpers.Blackfriday renderingConfig *helpers.Blackfriday
renderingConfigInit sync.Once
// menus // menus
pageMenus PageMenus pageMenus PageMenus
pageMenusInit sync.Once
Source Source
@ -196,14 +193,24 @@ type Page struct {
URLPath URLPath
paginator *Pager paginator *Pager
paginatorInit sync.Once
scratch *Scratch scratch *Scratch
language *helpers.Language language *helpers.Language
languageInit sync.Once lang string
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, // IsNode returns whether this is an item of one of the list types in Hugo,
@ -231,7 +238,6 @@ type PageMeta struct {
wordCount int wordCount int
fuzzyWordCount int fuzzyWordCount int
readingTime int readingTime int
pageMetaInit sync.Once
Weight int Weight int
} }
@ -532,6 +538,7 @@ func (p *Page) getRenderingConfig() *helpers.Blackfriday {
func newPage(filename string) *Page { func newPage(filename string) *Page {
page := Page{ page := Page{
pageInit: &pageInit{},
Kind: kindFromFilename(filename), Kind: kindFromFilename(filename),
contentType: "", contentType: "",
Source: Source{File: *source.NewFile(filename)}, 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 creates a copy of this page with the lazy sync.Once vars reset
// copy the Page by value. So for the situations where we need a copy, // so they will be evaluated again, for word count calculations etc.
// the paginators etc., we do it manually here.
// TODO(bep) np do better
func (p *Page) copy() *Page { func (p *Page) copy() *Page {
c := &Page{Kind: p.Kind, Site: p.Site} c := *p
c.Title = p.Title c.pageInit = &pageInit{}
c.Data = p.Data return &c
c.Date = p.Date
c.Lastmod = p.Lastmod
c.language = p.language
c.lang = p.lang
c.URLPath = p.URLPath
return c
} }
// TODO(bep) np these are pulled over from Node. Needs regrouping / embed // TODO(bep) np these are pulled over from Node. Needs regrouping / embed

View file

@ -147,7 +147,7 @@ func createSortTestPages(num int) Pages {
for i := 0; i < num; i++ { for i := 0; i < num; i++ {
pages[i] = &Page{ pages[i] = &Page{
pageInit: &pageInit{},
URLPath: URLPath{ URLPath: URLPath{
Section: "z", Section: "z",
URL: fmt.Sprintf("http://base/x/y/p%d.html", i), URL: fmt.Sprintf("http://base/x/y/p%d.html", i),

View file

@ -66,7 +66,8 @@ func TestPermalink(t *testing.T) {
info := newSiteInfo(siteBuilderCfg{baseURL: string(test.base), language: helpers.NewDefaultLanguage()}) info := newSiteInfo(siteBuilderCfg{baseURL: string(test.base), language: helpers.NewDefaultLanguage()})
p := &Page{ p := &Page{
Kind: KindPage, pageInit: &pageInit{},
Kind: KindPage,
URLPath: URLPath{ URLPath: URLPath{
Section: "z", Section: "z",
URL: test.url, URL: test.url,

View file

@ -1269,7 +1269,7 @@ func TestIndexPageSimpleMethods(t *testing.T) {
{func(n *Page) bool { return n.Now().Unix() == time.Now().Unix() }}, {func(n *Page) bool { return n.Now().Unix() == time.Now().Unix() }},
} { } {
n := &Page{Kind: KindHome} n := &Page{pageInit: &pageInit{}, Kind: KindHome}
n.RSSLink = "rssLink" n.RSSLink = "rssLink"
if !this.assertFunc(n) { if !this.assertFunc(n) {

View file

@ -457,6 +457,7 @@ func createTestPages(num int) Pages {
info := newSiteInfo(siteBuilderCfg{baseURL: "http://base/", language: helpers.NewDefaultLanguage()}) info := newSiteInfo(siteBuilderCfg{baseURL: "http://base/", language: helpers.NewDefaultLanguage()})
for i := 0; i < num; i++ { for i := 0; i < num; i++ {
pages[i] = &Page{ pages[i] = &Page{
pageInit: &pageInit{},
URLPath: URLPath{ URLPath: URLPath{
Section: "z", Section: "z",
URL: fmt.Sprintf("http://base/x/y/p%d.html", i), URL: fmt.Sprintf("http://base/x/y/p%d.html", i),