summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2024-02-03 13:09:53 +0100
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2024-02-03 15:07:59 +0100
commit058f230a1be1abaf589b5a194ef6ec12d14c4021 (patch)
tree92d84e4e453c3e66075553445e09d78b3ae92d5d
parenta66480f70c1ac734ba5af035e626d29ffcde157d (diff)
Detect now invalid path patterns in cascade
Closes #11977
-rw-r--r--config/allconfig/allconfig.go2
-rw-r--r--config/allconfig/alldecoders.go12
-rw-r--r--hugolib/cascade_test.go29
-rw-r--r--hugolib/page__meta.go6
-rw-r--r--hugolib/page__new.go2
-rw-r--r--resources/page/page_matcher.go17
-rw-r--r--resources/page/page_matcher_test.go19
7 files changed, 72 insertions, 15 deletions
diff --git a/config/allconfig/allconfig.go b/config/allconfig/allconfig.go
index 413baebd1..7052f0abd 100644
--- a/config/allconfig/allconfig.go
+++ b/config/allconfig/allconfig.go
@@ -965,7 +965,7 @@ func decodeConfigFromParams(fs afero.Fs, logger loggers.Logger, bcfg config.Base
})
for _, v := range decoderSetups {
- p := decodeConfig{p: p, c: target, fs: fs, bcfg: bcfg}
+ p := decodeConfig{p: p, c: target, fs: fs, logger: logger, bcfg: bcfg}
if err := v.decode(v, p); err != nil {
return fmt.Errorf("failed to decode %q: %w", v.key, err)
}
diff --git a/config/allconfig/alldecoders.go b/config/allconfig/alldecoders.go
index f96c19cfc..5ab76dec5 100644
--- a/config/allconfig/alldecoders.go
+++ b/config/allconfig/alldecoders.go
@@ -18,6 +18,7 @@ import (
"strings"
"github.com/gohugoio/hugo/cache/filecache"
+ "github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/config"
@@ -42,10 +43,11 @@ import (
)
type decodeConfig struct {
- p config.Provider
- c *Config
- fs afero.Fs
- bcfg config.BaseConfig
+ p config.Provider
+ c *Config
+ fs afero.Fs
+ logger loggers.Logger
+ bcfg config.BaseConfig
}
type decodeWeight struct {
@@ -291,7 +293,7 @@ var allDecoderSetups = map[string]decodeWeight{
key: "cascade",
decode: func(d decodeWeight, p decodeConfig) error {
var err error
- p.c.Cascade, err = page.DecodeCascadeConfig(p.p.Get(d.key))
+ p.c.Cascade, err = page.DecodeCascadeConfig(p.logger, p.p.Get(d.key))
return err
},
},
diff --git a/hugolib/cascade_test.go b/hugolib/cascade_test.go
index 194faeb0a..bb328f761 100644
--- a/hugolib/cascade_test.go
+++ b/hugolib/cascade_test.go
@@ -671,3 +671,32 @@ S1|p1:|p2:p2|
`)
})
}
+
+// Issue 11977.
+func TestCascadeExtensionInPath(t *testing.T) {
+ files := `
+-- hugo.toml --
+baseURL = "https://example.org"
+[languages]
+[languages.en]
+weight = 1
+[languages.de]
+-- content/_index.de.md --
++++
+[[cascade]]
+[cascade.params]
+foo = 'bar'
+[cascade._target]
+path = '/posts/post-1.de.md'
++++
+-- content/posts/post-1.de.md --
+---
+title: "Post 1"
+---
+-- layouts/_default/single.html --
+{{ .Title }}|{{ .Params.foo }}$
+`
+ b, err := TestE(t, files)
+ b.Assert(err, qt.IsNotNil)
+ b.AssertLogContains(`cascade target path "/posts/post-1.de.md" looks like a path with an extension; since Hugo v0.123.0 this will not match anything, see https://gohugo.io/methods/page/path/`)
+}
diff --git a/hugolib/page__meta.go b/hugolib/page__meta.go
index 35b7766b6..7b785abb6 100644
--- a/hugolib/page__meta.go
+++ b/hugolib/page__meta.go
@@ -33,6 +33,7 @@ import (
"github.com/gohugoio/hugo/common/constants"
"github.com/gohugoio/hugo/common/hugo"
+ "github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/paths"
"github.com/gohugoio/hugo/config"
@@ -272,7 +273,7 @@ func (p *pageMeta) Weight() int {
return p.pageConfig.Weight
}
-func (p *pageMeta) setMetaPre(pi *contentParseInfo, conf config.AllProvider) error {
+func (p *pageMeta) setMetaPre(pi *contentParseInfo, logger loggers.Logger, conf config.AllProvider) error {
frontmatter := pi.frontMatter
if frontmatter != nil {
pcfg := p.pageConfig
@@ -285,7 +286,7 @@ func (p *pageMeta) setMetaPre(pi *contentParseInfo, conf config.AllProvider) err
// Check for any cascade define on itself.
if cv, found := frontmatter["cascade"]; found {
var err error
- cascade, err := page.DecodeCascade(cv)
+ cascade, err := page.DecodeCascade(logger, cv)
if err != nil {
return err
}
@@ -437,7 +438,6 @@ func (p *pageState) setMetaPostParams() error {
}
pm.pageConfig.Build, err = pagemeta.DecodeBuildConfig(buildConfig)
if err != nil {
- //lint:ignore ST1005 end user message.
var msgDetail string
if isNewBuildKeyword {
msgDetail = `. We renamed the _build keyword to build in Hugo 0.123.0. We recommend putting user defined params in the params section, e.g.:
diff --git a/hugolib/page__new.go b/hugolib/page__new.go
index d846fe03c..818cbb5db 100644
--- a/hugolib/page__new.go
+++ b/hugolib/page__new.go
@@ -56,7 +56,7 @@ func (h *HugoSites) newPage(m *pageMeta) (*pageState, *paths.Path, error) {
return nil, nil, err
}
- if err := m.setMetaPre(pi, h.Conf); err != nil {
+ if err := m.setMetaPre(pi, h.Log, h.Conf); err != nil {
return nil, nil, m.wrapError(err, h.BaseFs.SourceFs)
}
pcfg := m.pageConfig
diff --git a/resources/page/page_matcher.go b/resources/page/page_matcher.go
index fbdb25d72..466b6fe53 100644
--- a/resources/page/page_matcher.go
+++ b/resources/page/page_matcher.go
@@ -18,6 +18,7 @@ import (
"path/filepath"
"strings"
+ "github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/hugofs/glob"
@@ -90,7 +91,14 @@ var disallowedCascadeKeys = map[string]bool{
"lang": true,
}
-func DecodeCascadeConfig(in any) (*config.ConfigNamespace[[]PageMatcherParamsConfig, map[PageMatcher]maps.Params], error) {
+// See issue 11977.
+func isGlobWithExtension(s string) bool {
+ pathParts := strings.Split(s, "/")
+ last := pathParts[len(pathParts)-1]
+ return strings.Count(last, ".") > 0
+}
+
+func DecodeCascadeConfig(logger loggers.Logger, in any) (*config.ConfigNamespace[[]PageMatcherParamsConfig, map[PageMatcher]maps.Params], error) {
buildConfig := func(in any) (map[PageMatcher]maps.Params, any, error) {
cascade := make(map[PageMatcher]maps.Params)
if in == nil {
@@ -119,6 +127,9 @@ func DecodeCascadeConfig(in any) (*config.ConfigNamespace[[]PageMatcherParamsCon
for _, cfg := range cfgs {
m := cfg.Target
+ if isGlobWithExtension(m.Path) {
+ logger.Erroridf("cascade-pattern-with-extension", "cascade target path %q looks like a path with an extension; since Hugo v0.123.0 this will not match anything, see https://gohugo.io/methods/page/path/", m.Path)
+ }
c, found := cascade[m]
if found {
// Merge
@@ -139,8 +150,8 @@ func DecodeCascadeConfig(in any) (*config.ConfigNamespace[[]PageMatcherParamsCon
}
// DecodeCascade decodes in which could be either a map or a slice of maps.
-func DecodeCascade(in any) (map[PageMatcher]maps.Params, error) {
- conf, err := DecodeCascadeConfig(in)
+func DecodeCascade(logger loggers.Logger, in any) (map[PageMatcher]maps.Params, error) {
+ conf, err := DecodeCascadeConfig(logger, in)
if err != nil {
return nil, err
}
diff --git a/resources/page/page_matcher_test.go b/resources/page/page_matcher_test.go
index c27a2e9b2..e659eb3b5 100644
--- a/resources/page/page_matcher_test.go
+++ b/resources/page/page_matcher_test.go
@@ -18,6 +18,7 @@ import (
"testing"
"github.com/gohugoio/hugo/common/hugo"
+ "github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/maps"
qt "github.com/frankban/quicktest"
@@ -128,7 +129,7 @@ func TestDecodeCascadeConfig(t *testing.T) {
},
}
- got, err := DecodeCascadeConfig(in)
+ got, err := DecodeCascadeConfig(loggers.NewDefault(), in)
c.Assert(err, qt.IsNil)
c.Assert(got, qt.IsNotNil)
@@ -150,7 +151,7 @@ func TestDecodeCascadeConfig(t *testing.T) {
{Params: maps.Params{"b": string("bv")}, Target: PageMatcher{Kind: "page"}},
})
- got, err = DecodeCascadeConfig(nil)
+ got, err = DecodeCascadeConfig(loggers.NewDefault(), nil)
c.Assert(err, qt.IsNil)
c.Assert(got, qt.IsNotNil)
}
@@ -172,3 +173,17 @@ func (c testConfig) Running() bool {
func (c testConfig) WorkingDir() string {
return c.workingDir
}
+
+func TestIsGlobWithExtension(t *testing.T) {
+ c := qt.New(t)
+
+ c.Assert(isGlobWithExtension("index.md"), qt.Equals, true)
+ c.Assert(isGlobWithExtension("foo/index.html"), qt.Equals, true)
+ c.Assert(isGlobWithExtension("posts/page"), qt.Equals, false)
+ c.Assert(isGlobWithExtension("pa.th/foo"), qt.Equals, false)
+ c.Assert(isGlobWithExtension(""), qt.Equals, false)
+ c.Assert(isGlobWithExtension("*.md?"), qt.Equals, true)
+ c.Assert(isGlobWithExtension("*.md*"), qt.Equals, true)
+ c.Assert(isGlobWithExtension("posts/*"), qt.Equals, false)
+ c.Assert(isGlobWithExtension("*.md"), qt.Equals, true)
+}