]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Detect now invalid path patterns in cascade
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sat, 3 Feb 2024 12:09:53 +0000 (13:09 +0100)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sat, 3 Feb 2024 14:07:59 +0000 (15:07 +0100)
Closes #11977

config/allconfig/allconfig.go
config/allconfig/alldecoders.go
hugolib/cascade_test.go
hugolib/page__meta.go
hugolib/page__new.go
resources/page/page_matcher.go
resources/page/page_matcher_test.go

index 413baebd12fe6ac9d28346dd719e6f3f28575977..7052f0abde028fa853a2e401e4e53c713b8cf67c 100644 (file)
@@ -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)
                }
index f96c19cfc756f43d8f62963623799d7cf40d0564..5ab76dec59f679e1f0627fc483d48dd56c49b4b8 100644 (file)
@@ -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
                },
        },
index 194faeb0a39955927d0af5482f9e8742f455c572..bb328f76178f3e30384ffa3022830e8a79080049 100644 (file)
@@ -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/`)
+}
index 35b7766b6f1ad4561642c7121bc351f5b2c0c2b9..7b785abb6133eaa40eb70830e4edf8c400adb3e7 100644 (file)
@@ -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.:
index d846fe03c25e2089b3aa04ae79be4b68f496eb7d..818cbb5db2b34a9612829289322e1089dcb764d0 100644 (file)
@@ -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
index fbdb25d72475c85ef5c04ba36af6448b33d8ef04..466b6fe53c8b5b2bafe94d221a2d3eb244093638 100644 (file)
@@ -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
        }
index c27a2e9b22a71ba67b45e4b3e6fd024b01535048..e659eb3b5d0e8bfc986ead6b840619518ad66518 100644 (file)
@@ -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)
+}