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 + } } }