diff --git a/hugolib/cascade_test.go b/hugolib/cascade_test.go index 8075f190f..7a4b6e6be 100644 --- a/hugolib/cascade_test.go +++ b/hugolib/cascade_test.go @@ -329,7 +329,7 @@ cascade: counters := &buildCounters{} b.Build(BuildCfg{testCounters: counters}) - b.Assert(int(counters.contentRenderCounter.Load()), qt.Equals, 2) + b.Assert(int(counters.contentRenderCounter.Load()), qt.Equals, 1) b.AssertFileContent("public/post/index.html", `Banner: post.jpg|Layout: postlayout|Type: posttype|Content:
content edit
`) b.AssertFileContent("public/post/dir/p1/index.html", `Banner: post.jpg|Layout: postlayout|`) @@ -672,6 +672,55 @@ S1|p1:|p2:p2| }) } +func TestCascadeEditIssue12449(t *testing.T) { + t.Parallel() + + files := ` +-- hugo.toml -- +baseURL = "https://example.com" +disableKinds = ['sitemap','rss', 'home', 'taxonomy','term'] +disableLiveReload = true +-- layouts/_default/list.html -- +Title: {{ .Title }}|{{ .Content }}|cascadeparam: {{ .Params.cascadeparam }}| +-- layouts/_default/single.html -- +Title: {{ .Title }}|{{ .Content }}|cascadeparam: {{ .Params.cascadeparam }}| +-- content/mysect/_index.md -- +--- +title: mysect +cascade: + description: descriptionvalue + params: + cascadeparam: cascadeparamvalue +--- +mysect-content| +-- content/mysect/p1/index.md -- +--- +slug: p1 +--- +p1-content| +-- content/mysect/subsect/_index.md -- +--- +slug: subsect +--- +subsect-content| +` + + b := TestRunning(t, files) + + // Make the cascade set the title. + b.EditFileReplaceAll("content/mysect/_index.md", "description: descriptionvalue", "title: cascadetitle").Build() + b.AssertFileContent("public/mysect/subsect/index.html", "Title: cascadetitle|") + + // Edit cascade title. + b.EditFileReplaceAll("content/mysect/_index.md", "title: cascadetitle", "title: cascadetitle-edit").Build() + b.AssertFileContent("public/mysect/subsect/index.html", "Title: cascadetitle-edit|") + + // Revert title change. + // The step below failed in #12449. + b.EditFileReplaceAll("content/mysect/_index.md", "title: cascadetitle-edit", "description: descriptionvalue").Build() + b.AssertFileContent("public/mysect/subsect/index.html", "Title: |") +} + // Issue 11977. func TestCascadeExtensionInPath(t *testing.T) { t.Parallel() diff --git a/hugolib/hugo_sites_build.go b/hugolib/hugo_sites_build.go index a4546ff44..c96629cd6 100644 --- a/hugolib/hugo_sites_build.go +++ b/hugolib/hugo_sites_build.go @@ -277,7 +277,7 @@ func (h *HugoSites) assemble(ctx context.Context, l logg.LevelLogger, bcfg *Buil changes := assembleChanges.Changes() - // Changes from the assemble step (e.g. lastMod, cascase) needs a re-calculation + // Changes from the assemble step (e.g. lastMod, cascade) needs a re-calculation // of what needs to be re-built. if len(changes) > 0 { if err := h.resolveAndClearStateForIdentities(ctx, l, nil, changes); err != nil { @@ -598,6 +598,10 @@ type pathChange struct { isDir bool } +func (p pathChange) isStructuralChange() bool { + return p.delete || p.isDir +} + // processPartial prepares the Sites' sources for a partial rebuild. func (h *HugoSites) processPartial(ctx context.Context, l logg.LevelLogger, config *BuildCfg, init func(config *BuildCfg) error, events []fsnotify.Event) error { h.Log.Trace(logg.StringFunc(func() string { diff --git a/hugolib/page__meta.go b/hugolib/page__meta.go index d8203fe75..a88fe528d 100644 --- a/hugolib/page__meta.go +++ b/hugolib/page__meta.go @@ -74,7 +74,9 @@ type pageMeta struct { // Prepare for a rebuild of the data passed in from front matter. func (m *pageMeta) setMetaPostPrepareRebuild() { params := xmaps.Clone[map[string]any](m.paramsOriginal) - m.pageMetaParams.pageConfig.Params = params + m.pageMetaParams.pageConfig = &pagemeta.PageConfig{ + Params: params, + } m.pageMetaFrontMatter = pageMetaFrontMatter{} } @@ -275,6 +277,7 @@ func (p *pageMeta) Weight() int { func (p *pageMeta) setMetaPre(pi *contentParseInfo, logger loggers.Logger, conf config.AllProvider) error { frontmatter := pi.frontMatter + if frontmatter != nil { pcfg := p.pageConfig if pcfg == nil { @@ -362,6 +365,7 @@ func (ps *pageState) setMetaPost(cascade map[page.PageMatcher]maps.Params) error if ps.m.setMetaPostCount > 1 { ps.m.setMetaPostCascadeChanged = cascadeHashPre != identity.HashUint64(ps.m.pageConfig.Cascade) if !ps.m.setMetaPostCascadeChanged { + // No changes, restore any value that may be changed by aggregation. ps.m.pageConfig.Dates = ps.m.datesOriginal return nil diff --git a/hugolib/pages_capture.go b/hugolib/pages_capture.go index 231c2efad..1633feb3e 100644 --- a/hugolib/pages_capture.go +++ b/hugolib/pages_capture.go @@ -147,7 +147,7 @@ func (c *pagesCollector) Collect() (collectErr error) { false, func(fim hugofs.FileMetaInfo) bool { if fim.IsDir() { - return true + return id.isStructuralChange() } fimp := fim.Meta().PathInfo if fimp == nil { @@ -160,7 +160,7 @@ func (c *pagesCollector) Collect() (collectErr error) { } else { // We always start from a directory. collectErr = c.collectDir(id.p, id.isDir, func(fim hugofs.FileMetaInfo) bool { - if id.delete || id.isDir { + if id.isStructuralChange() { if id.isDir && fim.Meta().PathInfo.IsLeafBundle() { return strings.HasPrefix(fim.Meta().PathInfo.Path(), paths.AddTrailingSlash(id.p.Path())) } diff --git a/hugolib/rebuild_test.go b/hugolib/rebuild_test.go index a847af3af..542810b64 100644 --- a/hugolib/rebuild_test.go +++ b/hugolib/rebuild_test.go @@ -1614,9 +1614,11 @@ p1-content| b.AssertFileContent("public/index.html", "home-content|") b.AssertFileContent("public/p1/index.html", "p1-content|") + b.AssertRenderCountPage(3) b.EditFileReplaceAll("content/_index.md", "home-content", "home-content-foo").Build() b.AssertFileContent("public/index.html", "home-content-foo") + b.AssertRenderCountPage(2) // Home page rss + html b.EditFileReplaceAll("content/p1/index.md", "p1-content", "p1-content-foo").Build() b.AssertFileContent("public/p1/index.html", "p1-content-foo")