diff --git a/config/allconfig/allconfig.go b/config/allconfig/allconfig.go index 469a164cf..9cafc876e 100644 --- a/config/allconfig/allconfig.go +++ b/config/allconfig/allconfig.go @@ -671,6 +671,13 @@ type Configs struct { configLangs []config.AllProvider } +func (c *Configs) Validate(logger loggers.Logger) error { + for p := range c.Base.Cascade.Config { + page.CheckCascadePattern(logger, p) + } + return nil +} + // transientErr returns the last transient error found during config compilation. func (c *Configs) transientErr() error { for _, l := range c.LanguageConfigSlice { @@ -969,7 +976,7 @@ func decodeConfigFromParams(fs afero.Fs, logger loggers.Logger, bcfg config.Base }) for _, v := range decoderSetups { - p := decodeConfig{p: p, c: target, fs: fs, logger: logger, bcfg: bcfg} + p := decodeConfig{p: p, c: target, fs: fs, 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 9c1d08144..5d31d5d35 100644 --- a/config/allconfig/alldecoders.go +++ b/config/allconfig/alldecoders.go @@ -18,7 +18,6 @@ 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" @@ -43,11 +42,10 @@ import ( ) type decodeConfig struct { - p config.Provider - c *Config - fs afero.Fs - logger loggers.Logger - bcfg config.BaseConfig + p config.Provider + c *Config + fs afero.Fs + bcfg config.BaseConfig } type decodeWeight struct { @@ -293,7 +291,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.logger, p.p.Get(d.key)) + p.c.Cascade, err = page.DecodeCascadeConfig(nil, p.p.Get(d.key)) return err }, }, diff --git a/hugolib/cascade_test.go b/hugolib/cascade_test.go index bb328f761..b9b80a3a1 100644 --- a/hugolib/cascade_test.go +++ b/hugolib/cascade_test.go @@ -674,6 +674,8 @@ S1|p1:|p2:p2| // Issue 11977. func TestCascadeExtensionInPath(t *testing.T) { + t.Parallel() + files := ` -- hugo.toml -- baseURL = "https://example.org" @@ -700,3 +702,67 @@ title: "Post 1" 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/`) } + +func TestCascadeExtensionInPathIgnore(t *testing.T) { + t.Parallel() + + files := ` +-- hugo.toml -- +baseURL = "https://example.org" +ignoreLogs = ['cascade-pattern-with-extension'] +[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 := Test(t, files) + b.AssertLogNotContains(`looks like a path with an extension`) +} + +func TestCascadConfigExtensionInPath(t *testing.T) { + t.Parallel() + + files := ` +-- hugo.toml -- +baseURL = "https://example.org" +[[cascade]] +[cascade.params] +foo = 'bar' +[cascade._target] +path = '/p1.md' +` + b, err := TestE(t, files) + b.Assert(err, qt.IsNotNil) + b.AssertLogContains(`looks like a path with an extension`) +} + +func TestCascadConfigExtensionInPathIgnore(t *testing.T) { + t.Parallel() + + files := ` +-- hugo.toml -- +baseURL = "https://example.org" +ignoreLogs = ['cascade-pattern-with-extension'] +[[cascade]] +[cascade.params] +foo = 'bar' +[cascade._target] +path = '/p1.md' +` + b := Test(t, files) + b.AssertLogNotContains(`looks like a path with an extension`) +} diff --git a/hugolib/integrationtest_builder.go b/hugolib/integrationtest_builder.go index 8c7017a87..acbc093ba 100644 --- a/hugolib/integrationtest_builder.go +++ b/hugolib/integrationtest_builder.go @@ -169,10 +169,11 @@ type IntegrationTestBuilder struct { renamedFiles []string renamedDirs []string - buildCount int - GCCount int - counters *buildCounters - logBuff lockingBuffer + buildCount int + GCCount int + counters *buildCounters + logBuff lockingBuffer + lastBuildLog string builderInit sync.Once } @@ -192,21 +193,21 @@ func (b *lockingBuffer) Write(p []byte) (n int, err error) { func (s *IntegrationTestBuilder) AssertLogContains(els ...string) { s.Helper() for _, el := range els { - s.Assert(s.logBuff.String(), qt.Contains, el) + s.Assert(s.lastBuildLog, qt.Contains, el) } } func (s *IntegrationTestBuilder) AssertLogNotContains(els ...string) { s.Helper() for _, el := range els { - s.Assert(s.logBuff.String(), qt.Not(qt.Contains), el) + s.Assert(s.lastBuildLog, qt.Not(qt.Contains), el) } } func (s *IntegrationTestBuilder) AssertLogMatches(expression string) { s.Helper() re := regexp.MustCompile(expression) - s.Assert(re.MatchString(s.logBuff.String()), qt.IsTrue, qt.Commentf(s.logBuff.String())) + s.Assert(re.MatchString(s.lastBuildLog), qt.IsTrue, qt.Commentf(s.lastBuildLog)) } func (s *IntegrationTestBuilder) AssertBuildCountData(count int) { @@ -341,7 +342,7 @@ func (s *IntegrationTestBuilder) Build() *IntegrationTestBuilder { s.Helper() _, err := s.BuildE() if s.Cfg.Verbose || err != nil { - fmt.Println(s.logBuff.String()) + fmt.Println(s.lastBuildLog) if s.H != nil && err == nil { for _, s := range s.H.Sites { m := s.pageMap @@ -352,7 +353,7 @@ func (s *IntegrationTestBuilder) Build() *IntegrationTestBuilder { } } } else if s.Cfg.LogLevel <= logg.LevelDebug { - fmt.Println(s.logBuff.String()) + fmt.Println(s.lastBuildLog) } s.Assert(err, qt.IsNil) if s.Cfg.RunGC { @@ -364,7 +365,7 @@ func (s *IntegrationTestBuilder) Build() *IntegrationTestBuilder { } func (s *IntegrationTestBuilder) LogString() string { - return s.logBuff.String() + return s.lastBuildLog } func (s *IntegrationTestBuilder) BuildE() (*IntegrationTestBuilder, error) { @@ -381,6 +382,7 @@ func (s *IntegrationTestBuilder) Init() *IntegrationTestBuilder { if err := s.initBuilder(); err != nil { s.Fatalf("Failed to init builder: %s", err) } + s.lastBuildLog = s.logBuff.String() return s } @@ -626,10 +628,11 @@ func (s *IntegrationTestBuilder) build(cfg BuildCfg) error { s.Helper() defer func() { s.reset() + s.lastBuildLog = s.logBuff.String() + s.logBuff.Reset() }() changeEvents := s.changeEvents() - s.logBuff.Reset() s.counters = &buildCounters{} cfg.testCounters = s.counters @@ -643,10 +646,6 @@ func (s *IntegrationTestBuilder) build(cfg BuildCfg) error { if err != nil { return err } - logErrorCount := s.H.NumLogErrors() - if logErrorCount > 0 { - return fmt.Errorf("logged %d error(s): %s", logErrorCount, s.logBuff.String()) - } return nil } diff --git a/hugolib/site_new.go b/hugolib/site_new.go index 2e8933497..3bcc307ad 100644 --- a/hugolib/site_new.go +++ b/hugolib/site_new.go @@ -127,6 +127,7 @@ func NewHugoSites(cfg deps.DepsCfg) (*HugoSites, error) { SuppressStatements: conf.IgnoredLogs(), } logger = loggers.New(logOpts) + } memCache := dynacache.New(dynacache.Options{Running: conf.Running(), Log: logger}) @@ -145,6 +146,9 @@ func NewHugoSites(cfg deps.DepsCfg) (*HugoSites, error) { } confm := cfg.Configs + if err := confm.Validate(logger); err != nil { + return nil, err + } var sites []*Site ns := &contentNodeShifter{ diff --git a/resources/page/page_matcher.go b/resources/page/page_matcher.go index 466b6fe53..f2075273a 100644 --- a/resources/page/page_matcher.go +++ b/resources/page/page_matcher.go @@ -98,6 +98,12 @@ func isGlobWithExtension(s string) bool { return strings.Count(last, ".") > 0 } +func CheckCascadePattern(logger loggers.Logger, m PageMatcher) { + if logger != nil && 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) + } +} + 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) @@ -127,9 +133,7 @@ func DecodeCascadeConfig(logger loggers.Logger, in any) (*config.ConfigNamespace 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) - } + CheckCascadePattern(logger, m) c, found := cascade[m] if found { // Merge