]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Fix setting config from env with complex (e.g. YAML) strings
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 16 Jul 2023 08:42:13 +0000 (10:42 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 16 Jul 2023 16:08:23 +0000 (18:08 +0200)
So you can do

```
HUGO_OUTPUTS="home: [rss]"  hugo
```

And similar.

Fixes #11249

config/allconfig/alldecoders.go
config/allconfig/load.go
hugolib/config_test.go
parser/metadecoders/decoder.go

index a40a02372b18751834720afc2079b5ae46a2c2c1..6b8a4568cfdd4b148686f1eb2a1a3972e3b791e0 100644 (file)
@@ -150,7 +150,7 @@ var allDecoderSetups = map[string]decodeWeight{
                key: "outputs",
                decode: func(d decodeWeight, p decodeConfig) error {
                        defaults := createDefaultOutputFormats(p.c.OutputFormats.Config)
-                       m := p.p.GetStringMap("outputs")
+                       m := maps.CleanConfigStringMap(p.p.GetStringMap("outputs"))
                        p.c.Outputs = make(map[string][]string)
                        for k, v := range m {
                                s := types.ToStringSlicePreserveString(v)
index b9bb38aaf40da917978256ca3550c3394bbf26b5..8551039a0ee00aaa9123f3569c747223be6991e2 100644 (file)
@@ -293,11 +293,19 @@ func (l configLoader) applyOsEnvOverrides(environ []string) error {
                        } else {
                                l.cfg.Set(env.Key, val)
                        }
-               } else if nestedKey != "" {
-                       owner[nestedKey] = env.Value
                } else {
-                       // The container does not exist yet.
-                       l.cfg.Set(strings.ReplaceAll(env.Key, delim, "."), env.Value)
+                       if nestedKey != "" {
+                               owner[nestedKey] = env.Value
+                       } else {
+                               var val any = env.Value
+                               if _, ok := allDecoderSetups[env.Key]; ok {
+                                       // A map.
+                                       val, err = metadecoders.Default.UnmarshalStringTo(env.Value, map[string]interface{}{})
+                               }
+                               if err == nil {
+                                       l.cfg.Set(strings.ReplaceAll(env.Key, delim, "."), val)
+                               }
+                       }
                }
        }
 
index 100144ca14662a8b897fcb27c64f852c24833fba..9720522ad0e658dedb8d91d000b9da4a30261b13 100644 (file)
@@ -1419,3 +1419,118 @@ Home.
        b.Assert(len(b.H.Sites), qt.Equals, 1)
 
 }
+
+func TestLoadConfigYamlEnvVar(t *testing.T) {
+
+       defaultEnv := []string{`HUGO_OUTPUTS=home: ['json']`}
+
+       runVariant := func(t testing.TB, files string, env []string) *IntegrationTestBuilder {
+               if env == nil {
+                       env = defaultEnv
+               }
+
+               b := NewIntegrationTestBuilder(
+                       IntegrationTestConfig{
+                               T:           t,
+                               TxtarString: files,
+                               Environ:     env,
+                               BuildCfg:    BuildCfg{SkipRender: true},
+                       },
+               ).Build()
+
+               outputs := b.H.Configs.Base.Outputs
+               if env == nil {
+                       home := outputs["home"]
+                       b.Assert(home, qt.Not(qt.IsNil))
+                       b.Assert(home, qt.DeepEquals, []string{"json"})
+               }
+
+               return b
+
+       }
+
+       t.Run("with empty slice", func(t *testing.T) {
+               t.Parallel()
+
+               files := `
+-- hugo.toml --
+baseURL = "https://example.com"
+disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT", "page", "section"]
+[outputs]
+home = ["html"]
+
+               `
+               b := runVariant(t, files, []string{`HUGO_OUTPUTS=section: []`})
+               outputs := b.H.Configs.Base.Outputs
+               b.Assert(outputs, qt.DeepEquals, map[string][]string{
+                       "home":     {"html"},
+                       "page":     {"html"},
+                       "rss":      {"rss"},
+                       "section":  nil,
+                       "taxonomy": {"html", "rss"},
+                       "term":     {"html", "rss"},
+               })
+
+       })
+
+       t.Run("with existing outputs", func(t *testing.T) {
+               t.Parallel()
+
+               files := `
+-- hugo.toml --
+baseURL = "https://example.com"
+disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT", "page", "section"]
+[outputs]
+home = ["html"]
+
+               `
+
+               runVariant(t, files, nil)
+
+       })
+
+       {
+               t.Run("with existing outputs direct", func(t *testing.T) {
+                       t.Parallel()
+
+                       files := `
+-- hugo.toml --
+baseURL = "https://example.com"
+disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT", "page", "section"]
+[outputs]
+home = ["html"]
+
+               `
+                       runVariant(t, files, []string{"HUGO_OUTPUTS_HOME=json"})
+
+               })
+       }
+
+       t.Run("without existing outputs", func(t *testing.T) {
+               t.Parallel()
+
+               files := `
+-- hugo.toml --
+baseURL = "https://example.com"
+disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT", "page", "section"]
+               
+               `
+
+               runVariant(t, files, nil)
+
+       })
+
+       t.Run("without existing outputs direct", func(t *testing.T) {
+               t.Parallel()
+
+               files := `
+-- hugo.toml --
+baseURL = "https://example.com"
+disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT", "page", "section"]
+               `
+
+               runVariant(t, files, []string{"HUGO_OUTPUTS_HOME=json"})
+
+       })
+
+}
index 93eb32e475ad4cd81dbce72c34a2f2e07c6997ad..40b3a336cede1d5889ef46a23c5a3a05782327f0 100644 (file)
@@ -23,6 +23,7 @@ import (
        "strings"
 
        "github.com/gohugoio/hugo/common/herrors"
+       "github.com/gohugoio/hugo/common/maps"
        "github.com/niklasfasching/go-org/org"
 
        xml "github.com/clbanning/mxj/v2"
@@ -90,7 +91,7 @@ func (d Decoder) UnmarshalStringTo(data string, typ any) (any, error) {
        switch typ.(type) {
        case string:
                return data, nil
-       case map[string]any:
+       case map[string]any, maps.Params:
                format := d.FormatFromContentString(data)
                return d.UnmarshalToMap([]byte(data), format)
        case []any: