"path/filepath"
"strings"
+ "github.com/gohugoio/hugo/common/types"
+
"github.com/gobwas/glob"
hglob "github.com/gohugoio/hugo/hugofs/glob"
}
}
+ const delim = "__env__delim"
+
// Apply environment overrides
if len(d.Environ) > 0 {
- // Extract all that start with the HUGO_ prefix
- const hugoEnvPrefix = "HUGO_"
- var hugoEnv []string
+ // Extract all that start with the HUGO prefix.
+ // The delimiter is the following rune, usually "_".
+ const hugoEnvPrefix = "HUGO"
+ var hugoEnv []types.KeyValueStr
for _, v := range d.Environ {
key, val := config.SplitEnvVar(v)
if strings.HasPrefix(key, hugoEnvPrefix) {
- hugoEnv = append(hugoEnv, strings.ToLower(strings.TrimPrefix(key, hugoEnvPrefix)), val)
+ delimiterAndKey := strings.TrimPrefix(key, hugoEnvPrefix)
+ if len(delimiterAndKey) < 2 {
+ continue
+ }
+ // Allow delimiters to be case sensitive.
+ // It turns out there isn't that many allowed special
+ // chars in environment variables when used in Bash and similar,
+ // so variables on the form HUGOxPARAMSxFOO=bar is one option.
+ key := strings.ReplaceAll(delimiterAndKey[1:], delimiterAndKey[:1], delim)
+ key = strings.ToLower(key)
+ hugoEnv = append(hugoEnv, types.KeyValueStr{
+ Key: key,
+ Value: val,
+ })
+
}
}
- if len(hugoEnv) > 0 {
- for i := 0; i < len(hugoEnv); i += 2 {
- key, valStr := strings.ToLower(hugoEnv[i]), hugoEnv[i+1]
+ for _, env := range hugoEnv {
+ existing, nestedKey, owner, err := maps.GetNestedParamFn(env.Key, delim, v.Get)
+ if err != nil {
+ return v, configFiles, err
+ }
- existing, nestedKey, owner, err := maps.GetNestedParamFn(key, "_", v.Get)
+ if existing != nil {
+ val, err := metadecoders.Default.UnmarshalStringTo(env.Value, existing)
if err != nil {
- return v, configFiles, err
+ continue
}
- if existing != nil {
- val, err := metadecoders.Default.UnmarshalStringTo(valStr, existing)
- if err != nil {
- continue
- }
-
- if owner != nil {
- owner[nestedKey] = val
- } else {
- v.Set(key, val)
- }
- } else if nestedKey != "" {
- owner[nestedKey] = valStr
+ if owner != nil {
+ owner[nestedKey] = val
} else {
- v.Set(key, valStr)
+ v.Set(env.Key, val)
}
+ } else if nestedKey != "" {
+ owner[nestedKey] = env.Value
+ } else {
+ v.Set(env.Key, env.Value)
}
}
+
}
// We made this a Glob pattern in Hugo 0.75, we don't need both.
floatSlice = [3.14, 5.19]
stringSlice = ["a", "b"]
+[params]
+[params.api_config]
+api_key="default_key"
+another_key="default another_key"
+
[imaging]
anchor = "smart"
quality = 75
"HUGO_STRINGSLICE", `["c", "d"]`,
"HUGO_INTSLICE", `[5, 8, 9]`,
"HUGO_FLOATSLICE", `[5.32]`,
+ // https://github.com/gohugoio/hugo/issues/7829
+ "HUGOxPARAMSxAPI_CONFIGxAPI_KEY", "new_key",
+ // Delimiters are case sensitive.
+ "HUGOxPARAMSxAPI_CONFIGXANOTHER_KEY", "another_key",
)
b.Build(BuildCfg{})
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")
}