From 49fedbc51cafa64e4eb0eae9fb79ccbe2d4c6774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Tue, 29 Jun 2021 09:38:05 +0200 Subject: [PATCH] config: Fix handling of invalid OS env config overrides Fixes #8709 --- config/defaultConfigProvider.go | 13 ++- hugolib/config_test.go | 135 +++++++++++++++++++------------- 2 files changed, 93 insertions(+), 55 deletions(-) diff --git a/config/defaultConfigProvider.go b/config/defaultConfigProvider.go index 80353664..9f1c44ee 100644 --- a/config/defaultConfigProvider.go +++ b/config/defaultConfigProvider.go @@ -169,6 +169,9 @@ func (c *defaultConfigProvider) Set(k string, v interface{}) { } key, m := c.getNestedKeyAndMap(k, true) + if m == nil { + return + } if existing, found := m[key]; found { if p1, ok := existing.(maps.Params); ok { @@ -289,6 +292,9 @@ func (c *defaultConfigProvider) Merge(k string, v interface{}) { } key, m := c.getNestedKeyAndMap(k, true) + if m == nil { + return + } if existing, found := m[key]; found { if p1, ok := existing.(maps.Params); ok { @@ -422,7 +428,12 @@ func (c *defaultConfigProvider) getNestedKeyAndMap(key string, create bool) (str return "", nil } } - current = next.(maps.Params) + var ok bool + current, ok = next.(maps.Params) + if !ok { + // E.g. a string, not a map that we can store values in. + return "", nil + } } return parts[len(parts)-1], current } diff --git a/hugolib/config_test.go b/hugolib/config_test.go index c5e77c94..810ab18f 100644 --- a/hugolib/config_test.go +++ b/hugolib/config_test.go @@ -576,9 +576,10 @@ anchor = "smart" quality = 75 ` - b := newTestSitesBuilder(t).WithConfigFile("toml", baseConfig) + newB := func(t testing.TB) *sitesBuilder { + b := newTestSitesBuilder(t).WithConfigFile("toml", baseConfig) - b.WithSourceFile("themes/mytheme/config.toml", ` + b.WithSourceFile("themes/mytheme/config.toml", ` [outputFormats] [outputFormats.oftheme] @@ -595,64 +596,90 @@ theme_param="themevalue2" `) - b.WithEnviron( - "HUGO_ENVIRONMENT", "test", - "HUGO_NEW", "new", // key not in config.toml - "HUGO_ENABLEGITINFO", "false", - "HUGO_IMAGING_ANCHOR", "top", - "HUGO_IMAGING_RESAMPLEFILTER", "CatmullRom", - "HUGO_STRINGSLICE", `["c", "d"]`, - "HUGO_INTSLICE", `[5, 8, 9]`, - "HUGO_FLOATSLICE", `[5.32]`, - // Issue #7829 - "HUGOxPARAMSxAPI_CONFIGxAPI_KEY", "new_key", - // Delimiters are case sensitive. - "HUGOxPARAMSxAPI_CONFIGXANOTHER_KEY", "another_key", - // Issue #8346 - "HUGOxPARAMSxMYTHEME_SECTIONxTHEME_PARAM", "themevalue_changed", - "HUGOxPARAMSxMYTHEME_SECTION2xTHEME_PARAM", "themevalue2_changed", - "HUGO_PARAMS_EMPTY", ``, - "HUGO_PARAMS_HTML", ``, - // Issue #8618 - "HUGO_SERVICES_GOOGLEANALYTICS_ID", `gaid`, - "HUGO_PARAMS_A_B_C", "abc", - ) + return b + } - b.Build(BuildCfg{}) + c.Run("Variations", func(c *qt.C) { - cfg := b.H.Cfg - s := b.H.Sites[0] - scfg := s.siteConfigConfig.Services + b := newB(c) - c.Assert(cfg.Get("environment"), qt.Equals, "test") - c.Assert(cfg.GetBool("enablegitinfo"), qt.Equals, false) - c.Assert(cfg.Get("new"), qt.Equals, "new") - c.Assert(cfg.Get("imaging.anchor"), qt.Equals, "top") - c.Assert(cfg.Get("imaging.quality"), qt.Equals, int64(75)) - c.Assert(cfg.Get("imaging.resamplefilter"), qt.Equals, "CatmullRom") - c.Assert(cfg.Get("stringSlice"), qt.DeepEquals, []interface{}{"c", "d"}) - c.Assert(cfg.Get("floatSlice"), qt.DeepEquals, []interface{}{5.32}) - c.Assert(cfg.Get("intSlice"), qt.DeepEquals, []interface{}{5, 8, 9}) - c.Assert(cfg.Get("params.api_config.api_key"), qt.Equals, "new_key") - c.Assert(cfg.Get("params.api_config.another_key"), qt.Equals, "default another_key") - c.Assert(cfg.Get("params.mytheme_section.theme_param"), qt.Equals, "themevalue_changed") - c.Assert(cfg.Get("params.mytheme_section.theme_param_nooverride"), qt.Equals, "nooverride") - c.Assert(cfg.Get("params.mytheme_section2.theme_param"), qt.Equals, "themevalue2_changed") - c.Assert(cfg.Get("params.empty"), qt.Equals, ``) - c.Assert(cfg.Get("params.html"), qt.Equals, ``) + b.WithEnviron( + "HUGO_ENVIRONMENT", "test", + "HUGO_NEW", "new", // key not in config.toml + "HUGO_ENABLEGITINFO", "false", + "HUGO_IMAGING_ANCHOR", "top", + "HUGO_IMAGING_RESAMPLEFILTER", "CatmullRom", + "HUGO_STRINGSLICE", `["c", "d"]`, + "HUGO_INTSLICE", `[5, 8, 9]`, + "HUGO_FLOATSLICE", `[5.32]`, + // Issue #7829 + "HUGOxPARAMSxAPI_CONFIGxAPI_KEY", "new_key", + // Delimiters are case sensitive. + "HUGOxPARAMSxAPI_CONFIGXANOTHER_KEY", "another_key", + // Issue #8346 + "HUGOxPARAMSxMYTHEME_SECTIONxTHEME_PARAM", "themevalue_changed", + "HUGOxPARAMSxMYTHEME_SECTION2xTHEME_PARAM", "themevalue2_changed", + "HUGO_PARAMS_EMPTY", ``, + "HUGO_PARAMS_HTML", ``, + // Issue #8618 + "HUGO_SERVICES_GOOGLEANALYTICS_ID", `gaid`, + "HUGO_PARAMS_A_B_C", "abc", + ) + + b.Build(BuildCfg{}) + + cfg := b.H.Cfg + s := b.H.Sites[0] + scfg := s.siteConfigConfig.Services + + c.Assert(cfg.Get("environment"), qt.Equals, "test") + c.Assert(cfg.GetBool("enablegitinfo"), qt.Equals, false) + c.Assert(cfg.Get("new"), qt.Equals, "new") + c.Assert(cfg.Get("imaging.anchor"), qt.Equals, "top") + c.Assert(cfg.Get("imaging.quality"), qt.Equals, int64(75)) + c.Assert(cfg.Get("imaging.resamplefilter"), qt.Equals, "CatmullRom") + c.Assert(cfg.Get("stringSlice"), qt.DeepEquals, []interface{}{"c", "d"}) + c.Assert(cfg.Get("floatSlice"), qt.DeepEquals, []interface{}{5.32}) + c.Assert(cfg.Get("intSlice"), qt.DeepEquals, []interface{}{5, 8, 9}) + c.Assert(cfg.Get("params.api_config.api_key"), qt.Equals, "new_key") + c.Assert(cfg.Get("params.api_config.another_key"), qt.Equals, "default another_key") + c.Assert(cfg.Get("params.mytheme_section.theme_param"), qt.Equals, "themevalue_changed") + c.Assert(cfg.Get("params.mytheme_section.theme_param_nooverride"), qt.Equals, "nooverride") + c.Assert(cfg.Get("params.mytheme_section2.theme_param"), qt.Equals, "themevalue2_changed") + c.Assert(cfg.Get("params.empty"), qt.Equals, ``) + c.Assert(cfg.Get("params.html"), qt.Equals, ``) + + params := cfg.Get("params").(maps.Params) + c.Assert(params["paramwithnoenvoverride"], qt.Equals, "nooverride") + c.Assert(cfg.Get("params.paramwithnoenvoverride"), qt.Equals, "nooverride") + c.Assert(scfg.GoogleAnalytics.ID, qt.Equals, "gaid") + c.Assert(cfg.Get("params.a.b"), qt.DeepEquals, maps.Params{ + "c": "abc", + }) + + ofBase, _ := s.outputFormatsConfig.GetByName("ofbase") + ofTheme, _ := s.outputFormatsConfig.GetByName("oftheme") + + c.Assert(ofBase.MediaType, qt.Equals, media.TextType) + c.Assert(ofTheme.MediaType, qt.Equals, media.TextType) - params := cfg.Get("params").(maps.Params) - c.Assert(params["paramwithnoenvoverride"], qt.Equals, "nooverride") - c.Assert(cfg.Get("params.paramwithnoenvoverride"), qt.Equals, "nooverride") - c.Assert(scfg.GoogleAnalytics.ID, qt.Equals, "gaid") - c.Assert(cfg.Get("params.a.b"), qt.DeepEquals, maps.Params{ - "c": "abc", }) - ofBase, _ := s.outputFormatsConfig.GetByName("ofbase") - ofTheme, _ := s.outputFormatsConfig.GetByName("oftheme") + // Issue #8709 + c.Run("Set in string", func(c *qt.C) { + b := newB(c) - c.Assert(ofBase.MediaType, qt.Equals, media.TextType) - c.Assert(ofTheme.MediaType, qt.Equals, media.TextType) + b.WithEnviron( + // imaging.anchor is a string, and it's not possible + // to set a child attribute. + "HUGO_IMAGING_ANCHOR_FOO", "top", + ) + + b.Build(BuildCfg{}) + + cfg := b.H.Cfg + c.Assert(cfg.Get("imaging.anchor"), qt.Equals, "smart") + + }) }