diff options
Diffstat (limited to 'hugolib/config.go')
-rw-r--r-- | hugolib/config.go | 145 |
1 files changed, 72 insertions, 73 deletions
diff --git a/hugolib/config.go b/hugolib/config.go index 73ba84686..dec5b870d 100644 --- a/hugolib/config.go +++ b/hugolib/config.go @@ -16,11 +16,14 @@ package hugolib import ( "errors" "fmt" - "path/filepath" + + "github.com/gohugoio/hugo/hugolib/paths" "io" "strings" + "github.com/gohugoio/hugo/langs" + "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/config/privacy" "github.com/gohugoio/hugo/config/services" @@ -81,6 +84,8 @@ func LoadConfigDefault(fs afero.Fs) (*viper.Viper, error) { return v, err } +var ErrNoConfigFile = errors.New("Unable to locate Config file. Perhaps you need to create a new site.\n Run `hugo help new` for details.\n") + // LoadConfig loads Hugo configuration into a new Viper and then adds // a set of defaults. func LoadConfig(d ConfigSourceDescriptor, doWithConfig ...func(cfg config.Provider) error) (*viper.Viper, []string, error) { @@ -100,41 +105,50 @@ func LoadConfig(d ConfigSourceDescriptor, doWithConfig ...func(cfg config.Provid v.SetConfigFile(configFilenames[0]) v.AddConfigPath(d.Path) + var configFileErr error + err := v.ReadInConfig() if err != nil { if _, ok := err.(viper.ConfigParseError); ok { return nil, configFiles, err } - return nil, configFiles, fmt.Errorf("Unable to locate Config file. Perhaps you need to create a new site.\n Run `hugo help new` for details. (%s)\n", err) + configFileErr = ErrNoConfigFile } - if cf := v.ConfigFileUsed(); cf != "" { - configFiles = append(configFiles, cf) - } + if configFileErr == nil { - for _, configFile := range configFilenames[1:] { - var r io.Reader - var err error - if r, err = fs.Open(configFile); err != nil { - return nil, configFiles, fmt.Errorf("Unable to open Config file.\n (%s)\n", err) + if cf := v.ConfigFileUsed(); cf != "" { + configFiles = append(configFiles, cf) } - if err = v.MergeConfig(r); err != nil { - return nil, configFiles, fmt.Errorf("Unable to parse/merge Config file (%s).\n (%s)\n", configFile, err) + + for _, configFile := range configFilenames[1:] { + var r io.Reader + var err error + if r, err = fs.Open(configFile); err != nil { + return nil, configFiles, fmt.Errorf("Unable to open Config file.\n (%s)\n", err) + } + if err = v.MergeConfig(r); err != nil { + return nil, configFiles, fmt.Errorf("Unable to parse/merge Config file (%s).\n (%s)\n", configFile, err) + } + configFiles = append(configFiles, configFile) } - configFiles = append(configFiles, configFile) + } if err := loadDefaultSettingsFor(v); err != nil { return v, configFiles, err } - themeConfigFile, err := loadThemeConfig(d, v) - if err != nil { - return v, configFiles, err - } + if configFileErr == nil { - if themeConfigFile != "" { - configFiles = append(configFiles, themeConfigFile) + themeConfigFiles, err := loadThemeConfig(d, v) + if err != nil { + return v, configFiles, err + } + + if len(themeConfigFiles) > 0 { + configFiles = append(configFiles, themeConfigFiles...) + } } // We create languages based on the settings, so we need to make sure that @@ -149,11 +163,11 @@ func LoadConfig(d ConfigSourceDescriptor, doWithConfig ...func(cfg config.Provid return v, configFiles, err } - return v, configFiles, nil + return v, configFiles, configFileErr } -func loadLanguageSettings(cfg config.Provider, oldLangs helpers.Languages) error { +func loadLanguageSettings(cfg config.Provider, oldLangs langs.Languages) error { defaultLang := cfg.GetString("defaultContentLanguage") @@ -182,14 +196,14 @@ func loadLanguageSettings(cfg config.Provider, oldLangs helpers.Languages) error } var ( - langs helpers.Languages - err error + languages2 langs.Languages + err error ) if len(languages) == 0 { - langs = append(langs, helpers.NewDefaultLanguage(cfg)) + languages2 = append(languages2, langs.NewDefaultLanguage(cfg)) } else { - langs, err = toSortedLanguages(cfg, languages) + languages2, err = toSortedLanguages(cfg, languages) if err != nil { return fmt.Errorf("Failed to parse multilingual config: %s", err) } @@ -201,10 +215,10 @@ func loadLanguageSettings(cfg config.Provider, oldLangs helpers.Languages) error // The validation below isn't complete, but should cover the most // important cases. var invalid bool - if langs.IsMultihost() != oldLangs.IsMultihost() { + if languages2.IsMultihost() != oldLangs.IsMultihost() { invalid = true } else { - if langs.IsMultihost() && len(langs) != len(oldLangs) { + if languages2.IsMultihost() && len(languages2) != len(oldLangs) { invalid = true } } @@ -213,10 +227,10 @@ func loadLanguageSettings(cfg config.Provider, oldLangs helpers.Languages) error return errors.New("language change needing a server restart detected") } - if langs.IsMultihost() { + if languages2.IsMultihost() { // We need to transfer any server baseURL to the new language for i, ol := range oldLangs { - nl := langs[i] + nl := languages2[i] nl.Set("baseURL", ol.GetString("baseURL")) } } @@ -225,7 +239,7 @@ func loadLanguageSettings(cfg config.Provider, oldLangs helpers.Languages) error // The defaultContentLanguage is something the user has to decide, but it needs // to match a language in the language definition list. langExists := false - for _, lang := range langs { + for _, lang := range languages2 { if lang.Lang == defaultLang { langExists = true break @@ -236,10 +250,10 @@ func loadLanguageSettings(cfg config.Provider, oldLangs helpers.Languages) error return fmt.Errorf("site config value %q for defaultContentLanguage does not match any language definition", defaultLang) } - cfg.Set("languagesSorted", langs) - cfg.Set("multilingual", len(langs) > 1) + cfg.Set("languagesSorted", languages2) + cfg.Set("multilingual", len(languages2) > 1) - multihost := langs.IsMultihost() + multihost := languages2.IsMultihost() if multihost { cfg.Set("defaultContentLanguageInSubdir", true) @@ -250,7 +264,7 @@ func loadLanguageSettings(cfg config.Provider, oldLangs helpers.Languages) error // The baseURL may be provided at the language level. If that is true, // then every language must have a baseURL. In this case we always render // to a language sub folder, which is then stripped from all the Permalink URLs etc. - for _, l := range langs { + for _, l := range languages2 { burl := l.GetLocal("baseURL") if burl == nil { return errors.New("baseURL must be set on all or none of the languages") @@ -262,49 +276,32 @@ func loadLanguageSettings(cfg config.Provider, oldLangs helpers.Languages) error return nil } -func loadThemeConfig(d ConfigSourceDescriptor, v1 *viper.Viper) (string, error) { +func loadThemeConfig(d ConfigSourceDescriptor, v1 *viper.Viper) ([]string, error) { + themesDir := paths.AbsPathify(d.WorkingDir, v1.GetString("themesDir")) + themes := config.GetStringSlicePreserveString(v1, "theme") - theme := v1.GetString("theme") - if theme == "" { - return "", nil + // CollectThemes(fs afero.Fs, themesDir string, themes []strin + themeConfigs, err := paths.CollectThemes(d.Fs, themesDir, themes) + if err != nil { + return nil, err } - - themesDir := helpers.AbsPathify(d.WorkingDir, v1.GetString("themesDir")) - configDir := filepath.Join(themesDir, theme) - - var ( - configPath string - exists bool - err error - ) - - // Viper supports more, but this is the sub-set supported by Hugo. - for _, configFormats := range []string{"toml", "yaml", "yml", "json"} { - configPath = filepath.Join(configDir, "config."+configFormats) - exists, err = helpers.Exists(configPath, d.Fs) - if err != nil { - return "", err - } - if exists { - break + v1.Set("allThemes", themeConfigs) + + var configFilenames []string + for _, tc := range themeConfigs { + if tc.ConfigFilename != "" { + configFilenames = append(configFilenames, tc.ConfigFilename) + if err := applyThemeConfig(v1, tc); err != nil { + return nil, err + } } } - if !exists { - // No theme config set. - return "", nil - } + return configFilenames, nil - v2 := viper.New() - v2.SetFs(d.Fs) - v2.AutomaticEnv() - v2.SetEnvPrefix("hugo") - v2.SetConfigFile(configPath) +} - err = v2.ReadInConfig() - if err != nil { - return "", err - } +func applyThemeConfig(v1 *viper.Viper, theme paths.ThemeConfig) error { const ( paramsKey = "params" @@ -312,11 +309,13 @@ func loadThemeConfig(d ConfigSourceDescriptor, v1 *viper.Viper) (string, error) menuKey = "menu" ) + v2 := theme.Cfg + for _, key := range []string{paramsKey, "outputformats", "mediatypes"} { mergeStringMapKeepLeft("", key, v1, v2) } - themeLower := strings.ToLower(theme) + themeLower := strings.ToLower(theme.Name) themeParamsNamespace := paramsKey + "." + themeLower // Set namespaced params @@ -371,11 +370,11 @@ func loadThemeConfig(d ConfigSourceDescriptor, v1 *viper.Viper) (string, error) } } - return v2.ConfigFileUsed(), nil + return nil } -func mergeStringMapKeepLeft(rootKey, key string, v1, v2 *viper.Viper) { +func mergeStringMapKeepLeft(rootKey, key string, v1, v2 config.Provider) { if !v2.IsSet(key) { return } |