Skip to content

Commit

Permalink
hugolib: Fix bundle resource publishing when multiple output formats
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bep committed Apr 15, 2019
1 parent b799b12 commit 49d0a82
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 39 deletions.
58 changes: 31 additions & 27 deletions hugolib/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,40 +360,44 @@ func (p *pageState) setPages(pages page.Pages) {
p.pages = pages
}

func (p *pageState) renderResources() error {
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
}
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
}

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) {
Expand Down
5 changes: 3 additions & 2 deletions hugolib/page__common.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ type pageCommon struct {
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
Expand Down
34 changes: 34 additions & 0 deletions hugolib/pagebundler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -896,3 +896,37 @@ TheContent.

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")

}
14 changes: 9 additions & 5 deletions hugolib/shortcode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,7 @@ func TestShortcodeParentResourcesOnRebuild(t *testing.T) {
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" }}
Expand Down Expand Up @@ -933,20 +934,23 @@ SHORTCODE: {{< c >}}

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.")

}

Expand Down
9 changes: 4 additions & 5 deletions hugolib/site_render.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type siteRenderContext struct {
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
Expand Down Expand Up @@ -130,11 +131,9 @@ func pageRenderer(
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()
Expand Down

0 comments on commit 49d0a82

Please sign in to comment.