]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Fix stale pages on rebuilds in GetPage with short refs
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 3 Nov 2024 09:41:34 +0000 (10:41 +0100)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 3 Nov 2024 12:33:31 +0000 (13:33 +0100)
Fixes #13004

hugolib/content_map_page.go
hugolib/rendershortcodes_test.go
hugolib/site.go
lazy/init.go
lazy/once.go

index c3f06a592ba3760ca82bd3534f15140891bf5e15..5e8646b21c464fd442b61c1a49ee18e65a8f3658 100644 (file)
@@ -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"
@@ -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 {
@@ -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 {
@@ -972,7 +976,7 @@ func (c *contentTreeReverseIndex) Get(key any) contentNodeI {
 }
 
 type contentTreeReverseIndexMap struct {
-       init sync.Once
+       init lazy.OnceMore
        m    map[any]contentNodeI
 }
 
index 9a31b6536dc742762317523e1fd28652d6c0b674..0eebf46eb3ee268571aae5e57d7dd819547f5625 100644 (file)
@@ -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")
+}
index 24ee5dcc506c48ddae635331b13b9ae1788f4a34..c5a4956e228d221cfaccc726f95134fd49144ef7 100644 (file)
@@ -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) {
index 7b88a53518be3b72c715ac7dc609e292ef8cf50e..bef3867a9a0c7535a0645a50e97ea2a5974442dc 100644 (file)
@@ -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)
index c6abcd884930bd60c18ad7a09b328b4b5e84e6e2..dac689df393644252acadcc68cc5a335ea8d510a 100644 (file)
@@ -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
        }
@@ -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