From 60a2cdf72db31d746da21ab2e32b6c51830b5fd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Tue, 13 Jun 2023 18:01:23 +0200 Subject: [PATCH] Fix config merge regression with root slices (e.g. disableKinds) Fixes #11089 --- config/allconfig/allconfig.go | 18 ++++++++++ hugolib/config_test.go | 68 +++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/config/allconfig/allconfig.go b/config/allconfig/allconfig.go index ade9607dded..08792d870d9 100644 --- a/config/allconfig/allconfig.go +++ b/config/allconfig/allconfig.go @@ -191,6 +191,22 @@ type configCompiler interface { func (c Config) cloneForLang() *Config { x := c x.C = nil + copyStringSlice := func(in []string) []string { + if in == nil { + return nil + } + out := make([]string, len(in)) + copy(out, in) + return out + } + + // Copy all the slices to avoid sharing. + x.DisableKinds = copyStringSlice(x.DisableKinds) + x.DisableLanguages = copyStringSlice(x.DisableLanguages) + x.MainSections = copyStringSlice(x.MainSections) + x.IgnoreErrors = copyStringSlice(x.IgnoreErrors) + x.IgnoreFiles = copyStringSlice(x.IgnoreFiles) + x.Theme = copyStringSlice(x.Theme) // Collapse all static dirs to one. x.StaticDir = x.staticDirs() @@ -787,12 +803,14 @@ func fromLoadConfigResult(fs afero.Fs, logger loggers.Logger, res config.LoadCon // Create a copy of the complete config and replace the root keys with the language specific ones. clone := all.cloneForLang() + if err := decodeConfigFromParams(fs, bcfg, mergedConfig, clone, differentRootKeys); err != nil { return nil, fmt.Errorf("failed to decode config for language %q: %w", k, err) } if err := clone.CompileConfig(logger); err != nil { return nil, err } + langConfigMap[k] = clone case maps.ParamsMergeStrategy: default: diff --git a/hugolib/config_test.go b/hugolib/config_test.go index 7f278f00a8c..5a308720752 100644 --- a/hugolib/config_test.go +++ b/hugolib/config_test.go @@ -750,6 +750,74 @@ author: {{ site.Author }} } +// Issue #11089 +func TestHugoConfigSliceOverrides(t *testing.T) { + t.Parallel() + + filesTemplate := ` +-- hugo.toml -- +disableKinds = ["section"] +[languages] +[languages.en] +disableKinds = [] +title = "English" +weigHt = WEIGHT_EN +[languages.sv] +title = "Swedish" +wEight = WEIGHT_SV +disableKinds = ["page"] +-- layouts/index.html -- +Home: {{ .Lang}}|{{ len site.RegularPages }}| +-- layouts/_default/single.html -- +Single. +-- content/p1.en.md -- +-- content/p2.en.md -- +-- content/p1.sv.md -- +-- content/p2.sv.md -- + +` + + t.Run("En first", func(t *testing.T) { + files := strings.ReplaceAll(filesTemplate, "WEIGHT_EN", "1") + files = strings.ReplaceAll(files, "WEIGHT_SV", "2") + + cfg := config.New() + b, err := NewIntegrationTestBuilder( + IntegrationTestConfig{ + T: t, + TxtarString: files, + BaseCfg: cfg, + }, + ).BuildE() + + b.Assert(err, qt.IsNil) + b.AssertFileContent("public/index.html", "Home: en|2|") + b.AssertFileContent("public/sv/index.html", "Home: sv|0|") + + }) + + t.Run("Sv first", func(t *testing.T) { + files := strings.ReplaceAll(filesTemplate, "WEIGHT_EN", "2") + files = strings.ReplaceAll(files, "WEIGHT_SV", "1") + + for i := 0; i < 20; i++ { + cfg := config.New() + b, err := NewIntegrationTestBuilder( + IntegrationTestConfig{ + T: t, + TxtarString: files, + BaseCfg: cfg, + }, + ).BuildE() + + b.Assert(err, qt.IsNil) + b.AssertFileContent("public/index.html", "Home: en|2|") + b.AssertFileContent("public/sv/index.html", "Home: sv|0|") + } + }) + +} + func TestConfigOutputFormatDefinedInTheme(t *testing.T) { t.Parallel()