Repository: gohugoio/hugo (language: go)

Issue:
v.145 httpcache crashes
### What version of Hugo are you using (`hugo version`)?

<pre>
0.145

</pre>

### Does this issue reproduce with the latest release?
YES

Repo to reproduce
https://github.com/gj52/HugoSample

HugoSample\config\_default\hugo.toml
````
[caches]
  [caches.assets]
    dir = ':resourceDir/_gen'
    maxAge = -1
  [caches.getcsv]
    dir = ':cacheDir/:project'
    maxAge = -1
  [caches.getjson]
    dir = ':cacheDir/:project'
    maxAge = -1
  [caches.getresource]
    dir = ':cacheDir/:project'
    maxAge = -1
  [caches.images]
    dir = ':resourceDir/_gen'
    maxAge = -1
  [caches.misc]
    dir = ':cacheDir/:project'
    maxAge = -1
  [caches.modules]
    dir = ':cacheDir/modules'
    maxAge = -1

# https://gohugo.io/getting-started/configuration/#configure-http-cache
#[httpcache]
#  [httpcache.cache]
#    [httpcache.cache.for]
#      includes = ['https://img.youtube.com/**']
#    [[httpcache.polls]]
#      disable = true

````
**remove the comment for httcache and hugo will crash**

````
hugo server --watch -b http://localhost --renderToMemory --noHTTPCache --navigateToChanged --panicOnWarning --disableFastRender
panic: no includes or excludes

goroutine 1 [running]:
github.com/gohugoio/hugo/cache/httpcache.(*GlobMatcher).CompilePredicate(0xc0004971d0?)
        /root/project/hugo/cache/httpcache/httpcache.go:163 +0x3be
github.com/gohugoio/hugo/cache/httpcache.(*Config).Compile(0xc0004971d0)
        /root/project/hugo/cache/httpcache/httpcache.go:71 +0x170
github.com/gohugoio/hugo/config/allconfig.(*Config).CompileConfig(0xc000496d88, {0x2384a38, 0xc0003b2320})
        /root/project/hugo/config/allconfig/allconfig.go:392 +0xe36
github.com/gohugoio/hugo/config/allconfig.fromLoadConfigResult({0x237a000, 0x35927e0}, {0x2384a38, 0xc0003b2320}, {{0x237ca90, 0xc0003a61e0}, {0xc00025e780, 0x2, 0x2}, {{0xc00034e2c0, ...}, ...}})
        /root/project/hugo/config/allconfig/allconfig.go:935 +0x297
github.com/gohugoio/hugo/config/allconfig.LoadConfig({{0x237a000, 0x35927e0}, {0x2384a38, 0xc0003b2320}, {0x237ca90, 0xc0003a6140}, {0x0, 0x0}, {0x1df4a31, 0x6}, ...})
        /root/project/hugo/config/allconfig/load.go:62 +0x465
github.com/gohugoio/hugo/commands.(*rootCommand).ConfigFromProvider.func1({0x5b7900?, 0xc0?})
        /root/project/hugo/commands/commandeer.go:244 +0x2dc
github.com/bep/lazycache.(*Cache[...]).GetOrCreate.func1(0xc0005b798a?, 0x0, {0x330b10?, 0xc0?}, 0x0?, 0x0?)
        /root/project/gomodcache/github.com/bep/lazycache@v0.7.0/lazycache.go:140 +0xa5
github.com/bep/lazycache.(*Cache[...]).GetOrCreate(0x23913e0, {0xad500, 0xc0?}, 0xc0005b79e0?)
        /root/project/gomodcache/github.com/bep/lazycache@v0.7.0/lazycache.go:144 +0x15e
github.com/gohugoio/hugo/commands.(*rootCommand).ConfigFromProvider(0xc00014ecc0?, {0x237ca90?, 0x0?}, {0x237ca90, 0xc0003a6140})
        /root/project/hugo/commands/commandeer.go:223 +0x51
github.com/gohugoio/hugo/commands.(*hugoBuilder).loadConfig(0xc0003f6300, 0xc00014ecc0, 0x1)
        /root/project/hugo/commands/hugobuilder.go:1055 +0x413
github.com/gohugoio/hugo/commands.(*serverCommand).PreRun(0xc000445d60, 0xc00014ecc0, 0xc00014ecc0?)
        /root/project/hugo/commands/server.go:617 +0x25e
github.com/bep/simplecobra.(*Commandeer).init(0xc00014ecc0)
        /root/project/gomodcache/github.com/bep/simplecobra@v0.5.0/simplecobra.go:92 +0xc2
github.com/bep/simplecobra.(*Commandeer).compile.func2(0xc0000ad500?, {0x1dec94a?, 0x4?, 0x1dec72e?})
        /root/project/gomodcache/github.com/bep/simplecobra@v0.5.0/simplecobra.go:119 +0x17
github.com/spf13/cobra.(*Command).execute(0xc000240008, {0xc0003f6200, 0x8, 0x8})
        /root/project/gomodcache/github.com/spf13/cobra@v1.9.1/command.go:1000 +0xa13
github.com/spf13/cobra.(*Command).ExecuteC(0xc0002df208)
        /root/project/gomodcache/github.com/spf13/cobra@v1.9.1/command.go:1148 +0x40c
github.com/spf13/cobra.(*Command).ExecuteContextC(...)
        /root/project/gomodcache/github.com/spf13/cobra@v1.9.1/command.go:1080
github.com/bep/simplecobra.(*Exec).Execute(0xc00041c7f0, {0x236adb0?, 0x35927e0?}, {0xc0000ac010?, 0x381d200?, 0x15?})
        /root/project/gomodcache/github.com/bep/simplecobra@v0.5.0/simplecobra.go:155 +0xd4
github.com/gohugoio/hugo/commands.Execute({0xc0000ac010, 0x9, 0xf})
        /root/project/hugo/commands/commandeer.go:68 +0x2f3
main.main()
        /root/project/hugo/main.go:25 +0x56

````




Discussion / hints:
You can probably get rid of the panic if you either remove the `polls` config or add e.g. `excludes = ['**']`.

removing **polls** helps
THANKS

Fix patch:
diff --git a/cache/httpcache/httpcache.go b/cache/httpcache/httpcache.go
index 2e8d9b8b49e..bd6d4bf7db4 100644
--- a/cache/httpcache/httpcache.go
+++ b/cache/httpcache/httpcache.go
@@ -188,7 +188,7 @@ func (gm *GlobMatcher) CompilePredicate() (func(string) bool, error) {
 	return p, nil
 }
 
-func DecodeConfig(bcfg config.BaseConfig, m map[string]any) (Config, error) {
+func DecodeConfig(_ config.BaseConfig, m map[string]any) (Config, error) {
 	if len(m) == 0 {
 		return DefaultConfig, nil
 	}
@@ -214,5 +214,16 @@ func DecodeConfig(bcfg config.BaseConfig, m map[string]any) (Config, error) {
 		c.Cache.For = DefaultConfig.Cache.For
 	}
 
+	for pci := range c.Polls {
+		if c.Polls[pci].For.IsZero() {
+			c.Polls[pci].For = DefaultConfig.Cache.For
+			c.Polls[pci].Disable = true
+		}
+	}
+
+	if len(c.Polls) == 0 {
+		c.Polls = DefaultConfig.Polls
+	}
+
 	return c, nil
 }


Test patch:
diff --git a/cache/httpcache/httpcache_test.go b/cache/httpcache/httpcache_test.go
index e3659f97bcb..60c07d05613 100644
--- a/cache/httpcache/httpcache_test.go
+++ b/cache/httpcache/httpcache_test.go
@@ -17,6 +17,7 @@ import (
 	"testing"
 
 	qt "github.com/frankban/quicktest"
+	"github.com/gohugoio/hugo/config"
 )
 
 func TestGlobMatcher(t *testing.T) {
@@ -40,3 +41,33 @@ func TestGlobMatcher(t *testing.T) {
 	c.Assert(p("foo/bar/foo.css"), qt.IsFalse)
 	c.Assert(p("foo/bar/foo.xml"), qt.IsTrue)
 }
+
+func TestDefaultConfig(t *testing.T) {
+	c := qt.New(t)
+
+	_, err := DefaultConfig.Compile()
+	c.Assert(err, qt.IsNil)
+}
+
+func TestDecodeConfigInjectsDefaultAndCompiles(t *testing.T) {
+	c := qt.New(t)
+
+	cfg, err := DecodeConfig(config.BaseConfig{}, map[string]interface{}{})
+	c.Assert(err, qt.IsNil)
+	c.Assert(cfg, qt.DeepEquals, DefaultConfig)
+
+	_, err = cfg.Compile()
+	c.Assert(err, qt.IsNil)
+
+	cfg, err = DecodeConfig(config.BaseConfig{}, map[string]any{
+		"cache": map[string]any{
+			"polls": []map[string]any{
+				{"disable": true},
+			},
+		},
+	})
+	c.Assert(err, qt.IsNil)
+
+	_, err = cfg.Compile()
+	c.Assert(err, qt.IsNil)
+}