summaryrefslogtreecommitdiffstats
path: root/hugolib
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2018-03-24 09:19:49 +0100
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2018-03-24 10:06:58 +0100
commit93e24a03ce98d3212a2d49ad04739141229d0809 (patch)
treef906ca508aed65af8e4bbf6141dff8f57499b4d6 /hugolib
parente9c7b6205f94a7edac0e0df2cd18d1456cb26a06 (diff)
hugolib: Fix freeze in invalid front matter error case
Fixes #4526
Diffstat (limited to 'hugolib')
-rw-r--r--hugolib/hugo_sites_build_failures_test.go42
-rw-r--r--hugolib/page_bundler.go36
-rw-r--r--hugolib/site.go19
-rw-r--r--hugolib/testhelpers_test.go12
4 files changed, 95 insertions, 14 deletions
diff --git a/hugolib/hugo_sites_build_failures_test.go b/hugolib/hugo_sites_build_failures_test.go
new file mode 100644
index 000000000..b347490cd
--- /dev/null
+++ b/hugolib/hugo_sites_build_failures_test.go
@@ -0,0 +1,42 @@
+package hugolib
+
+import (
+ "fmt"
+ "testing"
+)
+
+// https://github.com/gohugoio/hugo/issues/4526
+func TestSiteBuildFailureInvalidPageMetadata(t *testing.T) {
+ t.Parallel()
+
+ validContentFile := `
+---
+title = "This is good"
+---
+
+Some content.
+`
+
+ invalidContentFile := `
+---
+title = "PDF EPUB: Anne Bradstreet: Poems "The Prologue Summary And Analysis EBook Full Text "
+---
+
+Some content.
+`
+
+ var contentFiles []string
+ for i := 0; i <= 30; i++ {
+ name := fmt.Sprintf("valid%d.md", i)
+ contentFiles = append(contentFiles, name, validContentFile)
+ if i%5 == 0 {
+ name = fmt.Sprintf("invalid%d.md", i)
+ contentFiles = append(contentFiles, name, invalidContentFile)
+ }
+ }
+
+ b := newTestSitesBuilder(t)
+ b.WithSimpleConfigFile().WithContent(contentFiles...)
+ b.CreateSites().BuildFail(BuildCfg{})
+
+}
diff --git a/hugolib/page_bundler.go b/hugolib/page_bundler.go
index 2f6b4d094..bedfd58f0 100644
--- a/hugolib/page_bundler.go
+++ b/hugolib/page_bundler.go
@@ -32,6 +32,8 @@ type siteContentProcessor struct {
handleContent contentHandler
+ ctx context.Context
+
// The input file bundles.
fileBundlesChan chan *bundleDir
@@ -51,7 +53,28 @@ type siteContentProcessor struct {
partialBuild bool
}
-func newSiteContentProcessor(baseDir string, partialBuild bool, s *Site) *siteContentProcessor {
+func (s *siteContentProcessor) processBundle(b *bundleDir) {
+ select {
+ case s.fileBundlesChan <- b:
+ case <-s.ctx.Done():
+ }
+}
+
+func (s *siteContentProcessor) processSingle(fi *fileInfo) {
+ select {
+ case s.fileSinglesChan <- fi:
+ case <-s.ctx.Done():
+ }
+}
+
+func (s *siteContentProcessor) processAssets(assets []string) {
+ select {
+ case s.fileAssetsChan <- assets:
+ case <-s.ctx.Done():
+ }
+}
+
+func newSiteContentProcessor(ctx context.Context, baseDir string, partialBuild bool, s *Site) *siteContentProcessor {
numWorkers := 12
if n := runtime.NumCPU() * 3; n > numWorkers {
numWorkers = n
@@ -60,6 +83,7 @@ func newSiteContentProcessor(baseDir string, partialBuild bool, s *Site) *siteCo
numWorkers = int(math.Ceil(float64(numWorkers) / float64(len(s.owner.Sites))))
return &siteContentProcessor{
+ ctx: ctx,
partialBuild: partialBuild,
baseDir: baseDir,
site: s,
@@ -80,7 +104,7 @@ func (s *siteContentProcessor) closeInput() {
func (s *siteContentProcessor) process(ctx context.Context) error {
g1, ctx := errgroup.WithContext(ctx)
- g2, _ := errgroup.WithContext(ctx)
+ g2, ctx := errgroup.WithContext(ctx)
// There can be only one of these per site.
g1.Go(func() error {
@@ -161,12 +185,14 @@ func (s *siteContentProcessor) process(ctx context.Context) error {
})
}
- if err := g2.Wait(); err != nil {
- return err
- }
+ err := g2.Wait()
close(s.pagesChan)
+ if err != nil {
+ return err
+ }
+
if err := g1.Wait(); err != nil {
return err
}
diff --git a/hugolib/site.go b/hugolib/site.go
index 0ffe153e9..c3e2d9cb0 100644
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -1281,19 +1281,19 @@ func (c *contentCaptureResultHandler) getContentProcessor(lang string) *siteCont
func (c *contentCaptureResultHandler) handleSingles(fis ...*fileInfo) {
for _, fi := range fis {
proc := c.getContentProcessor(fi.Lang())
- proc.fileSinglesChan <- fi
+ proc.processSingle(fi)
}
}
func (c *contentCaptureResultHandler) handleBundles(d *bundleDirs) {
for _, b := range d.bundles {
proc := c.getContentProcessor(b.fi.Lang())
- proc.fileBundlesChan <- b
+ proc.processBundle(b)
}
}
func (c *contentCaptureResultHandler) handleCopyFiles(filenames ...string) {
for _, proc := range c.contentProcessors {
- proc.fileAssetsChan <- filenames
+ proc.processAssets(filenames)
}
}
@@ -1309,7 +1309,7 @@ func (s *Site) readAndProcessContent(filenames ...string) error {
var defaultContentProcessor *siteContentProcessor
sites := s.owner.langSite()
for k, v := range sites {
- proc := newSiteContentProcessor(baseDir, len(filenames) > 0, v)
+ proc := newSiteContentProcessor(ctx, baseDir, len(filenames) > 0, v)
contentProcessors[k] = proc
if k == defaultContentLanguage {
defaultContentProcessor = proc
@@ -1337,15 +1337,18 @@ func (s *Site) readAndProcessContent(filenames ...string) error {
c := newCapturer(s.Log, sourceSpec, handler, bundleMap, baseDir, filenames...)
- if err := c.capture(); err != nil {
- return err
- }
+ err1 := c.capture()
for _, proc := range contentProcessors {
proc.closeInput()
}
- return g.Wait()
+ err2 := g.Wait()
+
+ if err1 != nil {
+ return err1
+ }
+ return err2
}
func (s *Site) buildSiteMeta() (err error) {
diff --git a/hugolib/testhelpers_test.go b/hugolib/testhelpers_test.go
index 1f22e428d..6f513b3bf 100644
--- a/hugolib/testhelpers_test.go
+++ b/hugolib/testhelpers_test.go
@@ -272,12 +272,22 @@ func (s *sitesBuilder) CreateSites() *sitesBuilder {
}
func (s *sitesBuilder) Build(cfg BuildCfg) *sitesBuilder {
+ return s.build(cfg, false)
+}
+
+func (s *sitesBuilder) BuildFail(cfg BuildCfg) *sitesBuilder {
+ return s.build(cfg, true)
+}
+
+func (s *sitesBuilder) build(cfg BuildCfg, shouldFail bool) *sitesBuilder {
if s.H == nil {
s.CreateSites()
}
err := s.H.Build(cfg)
- if err != nil {
+ if err != nil && !shouldFail {
s.Fatalf("Build failed: %s", err)
+ } else if err == nil && shouldFail {
+ s.Fatalf("Expected error")
}
return s