mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
Fix setting config from env with complex (e.g. YAML) strings
So you can do ``` HUGO_OUTPUTS="home: [rss]" hugo ``` And similar. Fixes #11249
This commit is contained in:
parent
286821e360
commit
c406fd3a0e
4 changed files with 130 additions and 6 deletions
|
@ -150,7 +150,7 @@ var allDecoderSetups = map[string]decodeWeight{
|
||||||
key: "outputs",
|
key: "outputs",
|
||||||
decode: func(d decodeWeight, p decodeConfig) error {
|
decode: func(d decodeWeight, p decodeConfig) error {
|
||||||
defaults := createDefaultOutputFormats(p.c.OutputFormats.Config)
|
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)
|
p.c.Outputs = make(map[string][]string)
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
s := types.ToStringSlicePreserveString(v)
|
s := types.ToStringSlicePreserveString(v)
|
||||||
|
|
|
@ -293,11 +293,19 @@ func (l configLoader) applyOsEnvOverrides(environ []string) error {
|
||||||
} else {
|
} else {
|
||||||
l.cfg.Set(env.Key, val)
|
l.cfg.Set(env.Key, val)
|
||||||
}
|
}
|
||||||
} else if nestedKey != "" {
|
|
||||||
owner[nestedKey] = env.Value
|
|
||||||
} else {
|
} else {
|
||||||
// The container does not exist yet.
|
if nestedKey != "" {
|
||||||
l.cfg.Set(strings.ReplaceAll(env.Key, delim, "."), env.Value)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1419,3 +1419,118 @@ Home.
|
||||||
b.Assert(len(b.H.Sites), qt.Equals, 1)
|
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"})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/herrors"
|
"github.com/gohugoio/hugo/common/herrors"
|
||||||
|
"github.com/gohugoio/hugo/common/maps"
|
||||||
"github.com/niklasfasching/go-org/org"
|
"github.com/niklasfasching/go-org/org"
|
||||||
|
|
||||||
xml "github.com/clbanning/mxj/v2"
|
xml "github.com/clbanning/mxj/v2"
|
||||||
|
@ -90,7 +91,7 @@ func (d Decoder) UnmarshalStringTo(data string, typ any) (any, error) {
|
||||||
switch typ.(type) {
|
switch typ.(type) {
|
||||||
case string:
|
case string:
|
||||||
return data, nil
|
return data, nil
|
||||||
case map[string]any:
|
case map[string]any, maps.Params:
|
||||||
format := d.FormatFromContentString(data)
|
format := d.FormatFromContentString(data)
|
||||||
return d.UnmarshalToMap([]byte(data), format)
|
return d.UnmarshalToMap([]byte(data), format)
|
||||||
case []any:
|
case []any:
|
||||||
|
|
Loading…
Reference in a new issue