URI: 
       Detect now invalid path patterns in cascade - hugo - [fork] hugo port for 9front
  HTML git clone git@git.drkhsh.at/hugo.git
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
   DIR commit 058f230a1be1abaf589b5a194ef6ec12d14c4021
   DIR parent a66480f70c1ac734ba5af035e626d29ffcde157d
  HTML Author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
       Date:   Sat,  3 Feb 2024 13:09:53 +0100
       
       Detect now invalid path patterns in cascade
       
       Closes #11977
       
       Diffstat:
         M config/allconfig/allconfig.go       |       2 +-
         M config/allconfig/alldecoders.go     |      12 +++++++-----
         M hugolib/cascade_test.go             |      29 +++++++++++++++++++++++++++++
         M hugolib/page__meta.go               |       6 +++---
         M hugolib/page__new.go                |       2 +-
         M resources/page/page_matcher.go      |      17 ++++++++++++++---
         M resources/page/page_matcher_test.go |      19 +++++++++++++++++--
       
       7 files changed, 72 insertions(+), 15 deletions(-)
       ---
   DIR diff --git 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)
                        }
   DIR diff --git 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
                        },
                },
   DIR diff --git 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/`)
       +}
   DIR diff --git 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.:
   DIR diff --git 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
   DIR diff --git 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
                }
   DIR diff --git 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)
       +}