summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-07-16 10:42:13 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-07-16 11:32:28 +0200
commit1277fd738f18d85371c79daf1e3e1975cc9ac96e (patch)
tree1041f90b035a4918dec3d458eb551dcb93990694
parent286821e360e13b3a174854914c9cedd437bdd25e (diff)
Fix setting config from env with complex (e.g. YAML) stringsfix/configjsontake2-11249
So you can do ``` HUGO_OUTPUTS="home: [rss]" hugo ``` And similar. Fixes #11249
-rw-r--r--config/allconfig/alldecoders.go2
-rw-r--r--config/allconfig/load.go16
-rw-r--r--hugolib/config_test.go115
-rw-r--r--parser/metadecoders/decoder.go3
4 files changed, 130 insertions, 6 deletions
diff --git a/config/allconfig/alldecoders.go b/config/allconfig/alldecoders.go
index a40a02372..6b8a4568c 100644
--- a/config/allconfig/alldecoders.go
+++ b/config/allconfig/alldecoders.go
@@ -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)
diff --git a/config/allconfig/load.go b/config/allconfig/load.go
index b9bb38aaf..8551039a0 100644
--- a/config/allconfig/load.go
+++ b/config/allconfig/load.go
@@ -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)
+ }
+ }
}
}
diff --git a/hugolib/config_test.go b/hugolib/config_test.go
index 100144ca1..9720522ad 100644
--- a/hugolib/config_test.go
+++ b/hugolib/config_test.go
@@ -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"})
+
+ })
+
+}
diff --git a/parser/metadecoders/decoder.go b/parser/metadecoders/decoder.go
index 93eb32e47..40b3a336c 100644
--- a/parser/metadecoders/decoder.go
+++ b/parser/metadecoders/decoder.go
@@ -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: