From f38a2fbd2e4de7f095a833b448cb8bc053955ce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Sun, 15 Jan 2023 18:45:51 +0100 Subject: [PATCH] Make hugo.toml the new config.toml Both will of course work, but hugo.toml will win if both are set. We should have done this a long time ago, of course, but the reason I'm picking this up now is that my VS Code setup by default picks up some JSON config schema from some random other software which also names its config files config.toml. Fixes #8979 --- commands/commands.go | 2 +- commands/new_site.go | 1 + config/configLoader.go | 14 ++++++-- hugolib/config.go | 37 +++++++++++++++------ hugolib/config_test.go | 52 ++++++++++++++++++++++++++++++ hugolib/integrationtest_builder.go | 15 ++++++--- modules/collect.go | 14 ++++---- 7 files changed, 111 insertions(+), 24 deletions(-) diff --git a/commands/commands.go b/commands/commands.go index b81b867f9..c1042459d 100644 --- a/commands/commands.go +++ b/commands/commands.go @@ -177,7 +177,7 @@ Complete documentation is available at https://gohugo.io/.`, }, }) - cc.cmd.PersistentFlags().StringVar(&cc.cfgFile, "config", "", "config file (default is path/config.yaml|json|toml)") + cc.cmd.PersistentFlags().StringVar(&cc.cfgFile, "config", "", "config file (default is hugo.yaml|json|toml)") cc.cmd.PersistentFlags().StringVar(&cc.cfgDir, "configDir", "config", "config dir") cc.cmd.PersistentFlags().BoolVar(&cc.quiet, "quiet", false, "build in quiet mode") diff --git a/commands/new_site.go b/commands/new_site.go index 438553ae7..fc4127f8b 100644 --- a/commands/new_site.go +++ b/commands/new_site.go @@ -83,6 +83,7 @@ func (n *newSiteCmd) doNewSite(fs *hugofs.Fs, basepath string, force bool) error return errors.New(basepath + " already exists and is not empty. See --force.") case !isEmpty && force: + // TODO(bep) eventually rename this to hugo. all := append(dirs, filepath.Join(basepath, "config."+n.configFormat)) for _, path := range all { if exists, _ := helpers.Exists(path, fs.Source); exists { diff --git a/config/configLoader.go b/config/configLoader.go index 6722c12fd..95594fc62 100644 --- a/config/configLoader.go +++ b/config/configLoader.go @@ -29,11 +29,22 @@ import ( ) var ( + // See issue #8979 for context. + // Hugo has always used config.toml etc. as the default config file name. + // But hugo.toml is a more descriptive name, but we need to check for both. + DefaultConfigNames = []string{"hugo", "config"} + + DefaultConfigNamesSet = make(map[string]bool) + ValidConfigFileExtensions = []string{"toml", "yaml", "yml", "json"} validConfigFileExtensionsMap map[string]bool = make(map[string]bool) ) func init() { + for _, name := range DefaultConfigNames { + DefaultConfigNamesSet[name] = true + } + for _, ext := range ValidConfigFileExtensions { validConfigFileExtensionsMap[ext] = true } @@ -142,8 +153,7 @@ func LoadConfigFromDir(sourceFs afero.Fs, configDir, environment string) (Provid } var keyPath []string - - if name != "config" { + if !DefaultConfigNamesSet[name] { // Can be params.jp, menus.en etc. name, lang := paths.FileAndExtNoDelimiter(name) diff --git a/hugolib/config.go b/hugolib/config.go index 8e73a35ec..059424e85 100644 --- a/hugolib/config.go +++ b/hugolib/config.go @@ -69,18 +69,35 @@ func LoadConfig(d ConfigSourceDescriptor, doWithConfig ...func(cfg config.Provid // use a partial configuration to do its job. defer l.deleteMergeStrategies() - for _, name := range d.configFilenames() { - var filename string - filename, err := l.loadConfig(name) - if err == nil { - configFiles = append(configFiles, filename) - } else if err != ErrNoConfigFile { - return nil, nil, l.wrapFileError(err, filename) + names := d.configFilenames() + + if names != nil { + for _, name := range names { + var filename string + filename, err := l.loadConfig(name) + if err == nil { + configFiles = append(configFiles, filename) + } else if err != ErrNoConfigFile { + return nil, nil, l.wrapFileError(err, filename) + } + } + } else { + for _, name := range config.DefaultConfigNames { + var filename string + filename, err := l.loadConfig(name) + if err == nil { + configFiles = append(configFiles, filename) + break + } else if err != ErrNoConfigFile { + return nil, nil, l.wrapFileError(err, filename) + } } } if d.AbsConfigDir != "" { + dcfg, dirnames, err := config.LoadConfigFromDir(l.Fs, d.AbsConfigDir, l.Environment) + if err == nil { if len(dirnames) > 0 { l.cfg.Set("", dcfg.Get("")) @@ -162,9 +179,9 @@ func LoadConfig(d ConfigSourceDescriptor, doWithConfig ...func(cfg config.Provid return l.cfg, configFiles, err } -// LoadConfigDefault is a convenience method to load the default "config.toml" config. +// LoadConfigDefault is a convenience method to load the default "hugo.toml" config. func LoadConfigDefault(fs afero.Fs) (config.Provider, error) { - v, _, err := LoadConfig(ConfigSourceDescriptor{Fs: fs, Filename: "config.toml"}) + v, _, err := LoadConfig(ConfigSourceDescriptor{Fs: fs}) return v, err } @@ -202,7 +219,7 @@ func (d ConfigSourceDescriptor) configFileDir() string { func (d ConfigSourceDescriptor) configFilenames() []string { if d.Filename == "" { - return []string{"config"} + return nil } return strings.Split(d.Filename, ",") } diff --git a/hugolib/config_test.go b/hugolib/config_test.go index 882d83c8d..37605b4c2 100644 --- a/hugolib/config_test.go +++ b/hugolib/config_test.go @@ -782,3 +782,55 @@ defaultMarkdownHandler = 'blackfriday' b.Assert(err.Error(), qt.Contains, "Configured defaultMarkdownHandler \"blackfriday\" not found. Did you mean to use goldmark? Blackfriday was removed in Hugo v0.100.0.") } + +// Issue 8979 +func TestHugoConfig(t *testing.T) { + filesTemplate := ` +-- hugo.toml -- +theme = "mytheme" +[params] +rootparam = "rootvalue" +-- config/_default/hugo.toml -- +[params] +rootconfigparam = "rootconfigvalue" +-- themes/mytheme/config/_default/hugo.toml -- +[params] +themeconfigdirparam = "themeconfigdirvalue" +-- themes/mytheme/hugo.toml -- +[params] +themeparam = "themevalue" +-- layouts/index.html -- +rootparam: {{ site.Params.rootparam }} +rootconfigparam: {{ site.Params.rootconfigparam }} +themeparam: {{ site.Params.themeparam }} +themeconfigdirparam: {{ site.Params.themeconfigdirparam }} + + +` + + for _, configName := range []string{"hugo.toml", "config.toml"} { + configName := configName + t.Run(configName, func(t *testing.T) { + t.Parallel() + + files := strings.ReplaceAll(filesTemplate, "hugo.toml", configName) + + b, err := NewIntegrationTestBuilder( + IntegrationTestConfig{ + T: t, + TxtarString: files, + }, + ).BuildE() + + b.Assert(err, qt.IsNil) + b.AssertFileContent("public/index.html", + "rootparam: rootvalue", + "rootconfigparam: rootconfigvalue", + "themeparam: themevalue", + "themeconfigdirparam: themeconfigdirvalue", + ) + + }) + } + +} diff --git a/hugolib/integrationtest_builder.go b/hugolib/integrationtest_builder.go index 9dcfe4830..5b457893d 100644 --- a/hugolib/integrationtest_builder.go +++ b/hugolib/integrationtest_builder.go @@ -301,13 +301,18 @@ func (s *IntegrationTestBuilder) initBuilder() error { s.Assert(afero.WriteFile(afs, filename, data, 0666), qt.IsNil) } + configDirFilename := filepath.Join(s.Cfg.WorkingDir, "config") + if _, err := afs.Stat(configDirFilename); err != nil { + configDirFilename = "" + } + cfg, _, err := LoadConfig( ConfigSourceDescriptor{ - WorkingDir: s.Cfg.WorkingDir, - Fs: afs, - Logger: logger, - Environ: []string{}, - Filename: "config.toml", + WorkingDir: s.Cfg.WorkingDir, + AbsConfigDir: configDirFilename, + Fs: afs, + Logger: logger, + Environ: []string{}, }, func(cfg config.Provider) error { return nil diff --git a/modules/collect.go b/modules/collect.go index ae6df9be9..fcde1d379 100644 --- a/modules/collect.go +++ b/modules/collect.go @@ -423,12 +423,14 @@ func (c *collector) applyThemeConfig(tc *moduleAdapter) error { err error ) - // Viper supports more, but this is the sub-set supported by Hugo. - for _, configFormats := range config.ValidConfigFileExtensions { - configFilename = filepath.Join(tc.Dir(), "config."+configFormats) - hasConfigFile, _ = afero.Exists(c.fs, configFilename) - if hasConfigFile { - break +LOOP: + for _, configBaseName := range config.DefaultConfigNames { + for _, configFormats := range config.ValidConfigFileExtensions { + configFilename = filepath.Join(tc.Dir(), configBaseName+"."+configFormats) + hasConfigFile, _ = afero.Exists(c.fs, configFilename) + if hasConfigFile { + break LOOP + } } }