From 7e223b3baaef68d6e6f99e28f162362c81deffba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Tue, 24 Nov 2020 14:11:42 +0100 Subject: Allow setting the delimiter used for setting config via OS env, e.g. HUGO_ Fixes #7829 --- hugolib/config.go | 62 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 23 deletions(-) (limited to 'hugolib/config.go') diff --git a/hugolib/config.go b/hugolib/config.go index 72b51272b..9acb7d701 100644 --- a/hugolib/config.go +++ b/hugolib/config.go @@ -18,6 +18,8 @@ import ( "path/filepath" "strings" + "github.com/gohugoio/hugo/common/types" + "github.com/gobwas/glob" hglob "github.com/gohugoio/hugo/hugofs/glob" @@ -166,45 +168,59 @@ func LoadConfig(d ConfigSourceDescriptor, doWithConfig ...func(cfg config.Provid } } + 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. -- cgit v1.2.3