Skip to content

Commit

Permalink
Fix stale pages on rebuilds in GetPage with short refs
Browse files Browse the repository at this point in the history
Fixes #13004
  • Loading branch information
bep committed Nov 3, 2024
1 parent 1f23b49 commit 30d9aea
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 11 deletions.
12 changes: 8 additions & 4 deletions hugolib/content_map_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/gohugoio/hugo/hugolib/doctree"
"github.com/gohugoio/hugo/hugolib/pagesfromdata"
"github.com/gohugoio/hugo/identity"
"github.com/gohugoio/hugo/lazy"
"github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/output"
"github.com/gohugoio/hugo/resources"
Expand Down Expand Up @@ -109,6 +110,11 @@ type pageMap struct {
cfg contentMapConfig
}

// Invoked on rebuilds.
func (m *pageMap) Reset() {
m.pageReverseIndex.Reset()
}

// pageTrees holds pages and resources in a tree structure for all sites/languages.
// Each site gets its own tree set via the Shape method.
type pageTrees struct {
Expand Down Expand Up @@ -958,9 +964,7 @@ type contentTreeReverseIndex struct {
}

func (c *contentTreeReverseIndex) Reset() {
c.contentTreeReverseIndexMap = &contentTreeReverseIndexMap{
m: make(map[any]contentNodeI),
}
c.init.ResetWithLock().Unlock()
}

func (c *contentTreeReverseIndex) Get(key any) contentNodeI {
Expand All @@ -972,7 +976,7 @@ func (c *contentTreeReverseIndex) Get(key any) contentNodeI {
}

type contentTreeReverseIndexMap struct {
init sync.Once
init lazy.OnceMore
m map[any]contentNodeI
}

Expand Down
35 changes: 35 additions & 0 deletions hugolib/rendershortcodes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,3 +445,38 @@ code_p3
b.AssertNoRenderShortcodesArtifacts()
b.AssertFileContentEquals("public/p1/index.html", "<p>Content p1 id-100.</p>\n<code>codep2</code><p>Foo.\n</p>\n<code>code_p3_edited</code><p></p>\n<code>code_p1</code><code>code_p1_2</code><code>code_p1_3</code>")
}

// Issue 13004.
func TestRenderShortcodesIncludeShortRefEdit(t *testing.T) {
t.Parallel()

files := `
-- hugo.toml --
disableLiveReload = true
disableKinds = ["home", "taxonomy", "term", "section", "rss", "sitemap", "robotsTXT", "404"]
-- content/first/p1.md --
---
title: "p1"
---
## p1-h1
{{% include "p2" %}}
-- content/second/p2.md --
---
title: "p2"
---
### p2-h1
This is some **markup**.
-- layouts/shortcodes/include.html --
{{ $p := site.GetPage (.Get 0) -}}
{{ $p.RenderShortcodes -}}
-- layouts/_default/single.html --
{{ .Content }}
`
b := TestRunning(t, files)
b.AssertNoRenderShortcodesArtifacts()
b.AssertFileContentEquals("public/first/p1/index.html", "<h2 id=\"p1-h1\">p1-h1</h2>\n<p></p>\n<h3 id=\"p2-h1\">p2-h1</h3>\n<p>This is some <strong>markup</strong>.\n</p>\n")
b.EditFileReplaceAll("content/second/p2.md", "p2-h1", "p2-h1-edited").Build()
b.AssertNoRenderShortcodesArtifacts()
b.AssertFileContentEquals("public/first/p1/index.html", "<h2 id=\"p1-h1\">p1-h1</h2>\n<p></p>\n<h3 id=\"p2-h1-edited\">p2-h1-edited</h3>\n<p>This is some <strong>markup</strong>.\n</p>\n")
}
1 change: 1 addition & 0 deletions hugolib/site.go
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,7 @@ func (s *Site) getLanguagePermalinkLang(alwaysInSubDir bool) string {
func (s *Site) resetBuildState(sourceChanged bool) {
s.relatedDocsHandler = s.relatedDocsHandler.Clone()
s.init.Reset()
s.pageMap.Reset()
}

func (s *Site) errorCollator(results <-chan error, errs chan<- error) {
Expand Down
2 changes: 1 addition & 1 deletion lazy/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type Init struct {
prev *Init
children []*Init

init onceMore
init OnceMore
out any
err error
f func(context.Context) (any, error)
Expand Down
12 changes: 6 additions & 6 deletions lazy/once.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ import (
"sync/atomic"
)

// onceMore is similar to sync.Once.
// OnceMore is similar to sync.Once.
//
// Additional features are:
// * it can be reset, so the action can be repeated if needed
// * it has methods to check if it's done or in progress

type onceMore struct {
type OnceMore struct {
mu sync.Mutex
lock uint32
done uint32
}

func (t *onceMore) Do(f func()) {
func (t *OnceMore) Do(f func()) {
if atomic.LoadUint32(&t.done) == 1 {
return
}
Expand All @@ -53,15 +53,15 @@ func (t *onceMore) Do(f func()) {
f()
}

func (t *onceMore) InProgress() bool {
func (t *OnceMore) InProgress() bool {
return atomic.LoadUint32(&t.lock) == 1
}

func (t *onceMore) Done() bool {
func (t *OnceMore) Done() bool {
return atomic.LoadUint32(&t.done) == 1
}

func (t *onceMore) ResetWithLock() *sync.Mutex {
func (t *OnceMore) ResetWithLock() *sync.Mutex {
t.mu.Lock()
defer atomic.StoreUint32(&t.done, 0)
return &t.mu
Expand Down

0 comments on commit 30d9aea

Please sign in to comment.