ref: 49d0a82641581aa7dd66b9d5e8c7d75e23260083
parent: b799b12f4a693dfeae8a5a362f131081a727bb8f
author: Bjørn Erik Pedersen <[email protected]>
date: Mon Apr 15 08:06:12 EDT 2019
hugolib: Fix bundle resource publishing when multiple output formats The faulty logic published the bundled resources for the "first output" format. This worked most of the time, but since the output formats list is sorted, any output format only used for some of the pages (e.g. CSS) would not work properly. Fixes #5858
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -360,40 +360,44 @@
p.pages = pages
}
-func (p *pageState) renderResources() error {
- var toBeDeleted []int
+func (p *pageState) renderResources() (err error) {
+ p.resourcesPublishInit.Do(func() {
+ var toBeDeleted []int
- for i, r := range p.Resources() {
- if _, ok := r.(page.Page); ok {
- // Pages gets rendered with the owning page but we count them here.
- p.s.PathSpec.ProcessingStats.Incr(&p.s.PathSpec.ProcessingStats.Pages)
- continue
- }
+ for i, r := range p.Resources() {
+ if _, ok := r.(page.Page); ok {
+ // Pages gets rendered with the owning page but we count them here.
+ p.s.PathSpec.ProcessingStats.Incr(&p.s.PathSpec.ProcessingStats.Pages)
+ continue
+ }
- src, ok := r.(resource.Source)
- if !ok {
- return errors.Errorf("Resource %T does not support resource.Source", src)
- }
+ src, ok := r.(resource.Source)
+ if !ok {
+ err = errors.Errorf("Resource %T does not support resource.Source", src)
+ return
+ }
- if err := src.Publish(); err != nil {
- if os.IsNotExist(err) {
- // The resource has been deleted from the file system.
- // This should be extremely rare, but can happen on live reload in server
- // mode when the same resource is member of different page bundles.
- toBeDeleted = append(toBeDeleted, i)
+ if err := src.Publish(); err != nil {
+ if os.IsNotExist(err) {
+ // The resource has been deleted from the file system.
+ // This should be extremely rare, but can happen on live reload in server
+ // mode when the same resource is member of different page bundles.
+ toBeDeleted = append(toBeDeleted, i)
+ } else {
+ p.s.Log.ERROR.Printf("Failed to publish Resource for page %q: %s", p.pathOrTitle(), err)
+ }
} else {
- p.s.Log.ERROR.Printf("Failed to publish Resource for page %q: %s", p.pathOrTitle(), err)
+ p.s.PathSpec.ProcessingStats.Incr(&p.s.PathSpec.ProcessingStats.Files)
}
- } else {
- p.s.PathSpec.ProcessingStats.Incr(&p.s.PathSpec.ProcessingStats.Files)
}
- }
- for _, i := range toBeDeleted {
- p.deleteResource(i)
- }
+ for _, i := range toBeDeleted {
+ p.deleteResource(i)
+ }
- return nil
+ })
+
+ return
}
func (p *pageState) deleteResource(i int) {
--- a/hugolib/page__common.go
+++ b/hugolib/page__common.go
@@ -91,8 +91,9 @@
pagesInit sync.Once
// Any bundled resources
- resources resource.Resources
- resourcesInit sync.Once
+ resources resource.Resources
+ resourcesInit sync.Once
+ resourcesPublishInit sync.Once
translations page.Pages
allTranslations page.Pages
--- a/hugolib/pagebundler_test.go
+++ b/hugolib/pagebundler_test.go
@@ -896,3 +896,37 @@
return ps, clean, workDir
}
+
+// https://github.com/gohugoio/hugo/issues/5858
+func TestBundledResourcesWhenMultipleOutputFormats(t *testing.T) {
+ t.Parallel()
+
+ b := newTestSitesBuilder(t).Running().WithConfigFile("toml", `
+baseURL = "https://example.org"
+[outputs]
+ # This looks odd, but it triggers the behaviour in #5858
+ # The total output formats list gets sorted, so CSS before HTML.
+ home = [ "CSS" ]
+
+`)
+ b.WithContent("mybundle/index.md", `
+---
+title: Page
+date: 2017-01-15
+---
+`,
+ "mybundle/data.json", "MyData",
+ )
+
+ b.CreateSites().Build(BuildCfg{})
+
+ b.AssertFileContent("public/mybundle/data.json", "MyData")
+
+ // Change the bundled JSON file and make sure it gets republished.
+ b.EditFiles("content/mybundle/data.json", "My changed data")
+
+ b.Build(BuildCfg{})
+
+ b.AssertFileContent("public/mybundle/data.json", "My changed data")
+
+}
--- a/hugolib/shortcode_test.go
+++ b/hugolib/shortcode_test.go
@@ -903,6 +903,7 @@
b.WithTemplatesAdded(
"index.html", `
{{ $b := .Site.GetPage "b1" }}
+b1 Content: {{ $b.Content }}
{{$p := $b.Resources.GetMatch "p1*" }}
Content: {{ $p.Content }}
{{ $article := .Site.GetPage "blog/article" }}
@@ -933,20 +934,23 @@
b.Build(BuildCfg{})
- assert := func() {
- b.AssertFileContent("public/index.html",
- "Parent resource: logo.png: /b1/logo.png",
+ assert := func(matchers ...string) {
+ allMatchers := append(matchers, "Parent resource: logo.png: /b1/logo.png",
"Article Content: <p>SHORTCODE: \n\n* Parent resource: logo-article.png: /blog/logo-article.png",
)
+
+ b.AssertFileContent("public/index.html",
+ allMatchers...,
+ )
}
assert()
- b.EditFiles("b1/index.md", pageContent+" Edit.")
+ b.EditFiles("content/b1/index.md", pageContent+" Edit.")
b.Build(BuildCfg{})
- assert()
+ assert("Edit.")
}
--- a/hugolib/site_render.go
+++ b/hugolib/site_render.go
@@ -35,6 +35,7 @@
sitesOutIdx int
// Zero based index of the output formats configured within a Site.
+ // Note that these outputs are sorted, so CSS will come before HTML.
outIdx int
multihost bool
@@ -130,11 +131,9 @@
continue
}
- if ctx.outIdx == 0 {
- if err := p.renderResources(); err != nil {
- s.SendError(p.errorf(err, "failed to render page resources"))
- continue
- }
+ if err := p.renderResources(); err != nil {
+ s.SendError(p.errorf(err, "failed to render page resources"))
+ continue
}
layouts, err := p.getLayouts()