hugolib: Fix panic for unused taxonomy content files

In Hugo 0.55 we connected the taxonomy nodes with their owning Page.

This failed if you had, say, a content file for a author that did not author anything in the site:

```
content/authors/silent-persin/_index.md
```

Fixes #5847
This commit is contained in:
Bjørn Erik Pedersen 2019-04-15 09:38:14 +02:00
parent 701486728e
commit b799b12f4a
5 changed files with 52 additions and 17 deletions

View file

@ -14,7 +14,9 @@
package hugolib package hugolib
import ( import (
"fmt"
"io" "io"
"path"
"path/filepath" "path/filepath"
"sort" "sort"
"strings" "strings"
@ -650,7 +652,19 @@ func (h *HugoSites) createMissingPages() error {
// Make them navigable from WeightedPage etc. // Make them navigable from WeightedPage etc.
for _, p := range taxonomyPages { for _, p := range taxonomyPages {
p.getTaxonomyNodeInfo().TransferValues(p) ni := p.getTaxonomyNodeInfo()
if ni == nil {
// This can be nil for taxonomies, e.g. an author,
// with a content file, but no actual usage.
// Create one.
sections := p.SectionsEntries()
if len(sections) < 2 {
// Invalid state
panic(fmt.Sprintf("invalid taxonomy state for %q with sections %v", p.pathOrTitle(), sections))
}
ni = p.s.taxonomyNodes.GetOrAdd(sections[0], path.Join(sections[1:]...))
}
ni.TransferValues(p)
} }
for _, p := range taxonomyTermsPages { for _, p := range taxonomyTermsPages {
p.getTaxonomyNodeInfo().TransferValues(p) p.getTaxonomyNodeInfo().TransferValues(p)

View file

@ -746,8 +746,10 @@ func (p *pageState) getTaxonomyNodeInfo() *taxonomyNodeInfo {
info := p.s.taxonomyNodes.Get(p.SectionsEntries()...) info := p.s.taxonomyNodes.Get(p.SectionsEntries()...)
if info == nil { if info == nil {
// This should never happpen // There can be unused content pages for taxonomies (e.g. author that
panic(fmt.Sprintf("invalid taxonomy state for %q with sections %v", p.pathOrTitle(), p.SectionsEntries())) // has not written anything, yet), and these will not have a taxonomy
// node created in the assemble taxonomies step.
return nil
} }
return info return info

View file

@ -94,7 +94,7 @@ type Site struct {
Taxonomies TaxonomyList Taxonomies TaxonomyList
taxonomyNodes taxonomyNodeInfos taxonomyNodes *taxonomyNodeInfos
Sections Taxonomy Sections Taxonomy
Info SiteInfo Info SiteInfo
@ -1566,24 +1566,23 @@ func (s *Site) assembleTaxonomies() error {
s.Taxonomies[plural] = make(Taxonomy) s.Taxonomies[plural] = make(Taxonomy)
} }
s.taxonomyNodes = make(taxonomyNodeInfos) s.taxonomyNodes = &taxonomyNodeInfos{
m: make(map[string]*taxonomyNodeInfo),
getKey: s.getTaxonomyKey,
}
s.Log.INFO.Printf("found taxonomies: %#v\n", taxonomies) s.Log.INFO.Printf("found taxonomies: %#v\n", taxonomies)
for singular, plural := range taxonomies { for singular, plural := range taxonomies {
parent := s.taxonomyNodes.GetOrCreate(plural, "", "") parent := s.taxonomyNodes.GetOrCreate(plural, "")
parent.singular = singular parent.singular = singular
addTaxonomy := func(plural, term string, weight int, p page.Page) { addTaxonomy := func(plural, term string, weight int, p page.Page) {
key := s.getTaxonomyKey(term) key := s.getTaxonomyKey(term)
n := s.taxonomyNodes.GetOrCreate(plural, key, term) n := s.taxonomyNodes.GetOrCreate(plural, term)
n.parent = parent n.parent = parent
// There may be different spellings before normalization, so the
// last one will win, e.g. "hugo" vs "Hugo".
n.term = term
w := page.NewWeightedPage(weight, p, n.owner) w := page.NewWeightedPage(weight, p, n.owner)
s.Taxonomies[plural].add(key, w) s.Taxonomies[plural].add(key, w)

View file

@ -193,16 +193,33 @@ func (t *taxonomyNodeInfo) TransferValues(p *pageState) {
// Maps either plural or plural/term to a taxonomy node. // Maps either plural or plural/term to a taxonomy node.
// TODO(bep) consolidate somehow with s.Taxonomies // TODO(bep) consolidate somehow with s.Taxonomies
type taxonomyNodeInfos map[string]*taxonomyNodeInfo type taxonomyNodeInfos struct {
m map[string]*taxonomyNodeInfo
getKey func(string) string
}
// map[string]*taxonomyNodeInfo
func (t taxonomyNodeInfos) key(parts ...string) string { func (t taxonomyNodeInfos) key(parts ...string) string {
return path.Join(parts...) return path.Join(parts...)
} }
func (t taxonomyNodeInfos) GetOrCreate(plural, termKey, term string) *taxonomyNodeInfo { // GetOrAdd will get or create and add a new taxonomy node to the parent identified with plural.
// It will panic if the parent does not exist.
func (t taxonomyNodeInfos) GetOrAdd(plural, term string) *taxonomyNodeInfo {
parent := t.GetOrCreate(plural, "")
if parent == nil {
panic(fmt.Sprintf("no parent found with plural %q", plural))
}
child := t.GetOrCreate(plural, term)
child.parent = parent
return child
}
func (t taxonomyNodeInfos) GetOrCreate(plural, term string) *taxonomyNodeInfo {
termKey := t.getKey(term)
key := t.key(plural, termKey) key := t.key(plural, termKey)
n, found := t[key] n, found := t.m[key]
if found { if found {
return n return n
} }
@ -214,7 +231,7 @@ func (t taxonomyNodeInfos) GetOrCreate(plural, termKey, term string) *taxonomyNo
owner: &page.PageWrapper{}, // Page will be assigned later. owner: &page.PageWrapper{}, // Page will be assigned later.
} }
t[key] = n t.m[key] = n
return n return n
} }
@ -222,7 +239,7 @@ func (t taxonomyNodeInfos) GetOrCreate(plural, termKey, term string) *taxonomyNo
func (t taxonomyNodeInfos) Get(sections ...string) *taxonomyNodeInfo { func (t taxonomyNodeInfos) Get(sections ...string) *taxonomyNodeInfo {
key := t.key(sections...) key := t.key(sections...)
n, found := t[key] n, found := t.m[key]
if found { if found {
return n return n
} }

View file

@ -117,6 +117,9 @@ permalinkeds:
writeNewContentFile(t, fs.Source, "Category Terms", "2017-01-01", "content/categories/_index.md", 10) writeNewContentFile(t, fs.Source, "Category Terms", "2017-01-01", "content/categories/_index.md", 10)
writeNewContentFile(t, fs.Source, "Tag1 List", "2017-01-01", "content/tags/Tag1/_index.md", 10) writeNewContentFile(t, fs.Source, "Tag1 List", "2017-01-01", "content/tags/Tag1/_index.md", 10)
// https://github.com/gohugoio/hugo/issues/5847
writeNewContentFile(t, fs.Source, "Unused Tag List", "2018-01-01", "content/tags/not-used/_index.md", 10)
err := h.Build(BuildCfg{}) err := h.Build(BuildCfg{})
require.NoError(t, err) require.NoError(t, err)
@ -159,7 +162,7 @@ permalinkeds:
// Make sure that each page.KindTaxonomyTerm page has an appropriate number // Make sure that each page.KindTaxonomyTerm page has an appropriate number
// of page.KindTaxonomy pages in its Pages slice. // of page.KindTaxonomy pages in its Pages slice.
taxonomyTermPageCounts := map[string]int{ taxonomyTermPageCounts := map[string]int{
"tags": 2, "tags": 3,
"categories": 2, "categories": 2,
"others": 2, "others": 2,
"empties": 0, "empties": 0,