shithub: hugo

Download patch

ref: 87ca0d0cbea19dd2c0aac44dc2731e6247a82ece
parent: bd0176a5487b0d8c368a14b3f283b9029f51d619
author: Bjørn Erik Pedersen <[email protected]>
date: Fri Feb 5 13:41:40 EST 2016

Clean flags

* Reduce the amount of global flags
* Unexport all flag vars and commands vars
* Some other minor flag cleaning

--- a/commands/benchmark.go
+++ b/commands/benchmark.go
@@ -19,9 +19,11 @@
 	"runtime/pprof"
 )
 
-var cpuProfilefile string
-var memProfilefile string
-var benchmarkTimes int
+var (
+	benchmarkTimes int
+	cpuProfilefile string
+	memProfilefile string
+)
 
 var benchmarkCmd = &cobra.Command{
 	Use:   "benchmark",
@@ -31,7 +33,7 @@
 }
 
 func init() {
-	initCoreCommonFlags(benchmarkCmd)
+	initHugoBuilderFlags(benchmarkCmd)
 
 	benchmarkCmd.Flags().StringVar(&cpuProfilefile, "cpuprofile", "", "path/filename for the CPU profile file")
 	benchmarkCmd.Flags().StringVar(&memProfilefile, "memprofile", "", "path/filename for the memory profile file")
--- a/commands/check.go
+++ b/commands/check.go
@@ -26,7 +26,7 @@
 }
 
 func init() {
-	initCoreCommonFlags(checkCmd)
+	initHugoBuilderFlags(checkCmd)
 	checkCmd.RunE = check
 }
 
--- a/commands/hugo.go
+++ b/commands/hugo.go
@@ -27,6 +27,7 @@
 	"time"
 
 	"github.com/spf13/hugo/parser"
+	flag "github.com/spf13/pflag"
 
 	"regexp"
 
@@ -92,7 +93,7 @@
 
 // HugoCmd is Hugo's root command.
 // Every other command attached to HugoCmd is a child command to it.
-var HugoCmd = &cobra.Command{
+var hugoCmd = &cobra.Command{
 	Use:   "hugo",
 	Short: "hugo builds your site",
 	Long: `hugo is the main command, used to build your Hugo site.
@@ -106,7 +107,7 @@
 			return err
 		}
 
-		if BuildWatch {
+		if buildWatch {
 			viper.Set("DisableLiveReload", true)
 			watchConfig()
 		}
@@ -118,18 +119,37 @@
 var hugoCmdV *cobra.Command
 
 // Flags that are to be added to commands.
-var BuildWatch, IgnoreCache, Draft, Future, UglyURLs, CanonifyURLs, Verbose, Logging, VerboseLog, DisableRSS, DisableSitemap, DisableRobotsTXT, PluralizeListTitles, PreserveTaxonomyNames, NoTimes, ForceSync, CleanDestination bool
-var Source, CacheDir, Destination, Theme, BaseURL, CfgFile, LogFile, Editor string
+var (
+	canonifyURLs          bool
+	cleanDestination      bool
+	disableRobotsTXT      bool
+	disableRSS            bool
+	disableSitemap        bool
+	draft                 bool
+	future                bool
+	ignoreCache           bool
+	logging               bool
+	noTimes               bool
+	pluralizeListTitles   bool
+	preserveTaxonomyNames bool
+	uglyURLs              bool
+	verbose               bool
+	verboseLog            bool
+	buildWatch            bool
+)
 
+var forceSync bool
+var Source, CacheDir, Destination, Theme, BaseURL, CfgFile, LogFile string
+
 // Execute adds all child commands to the root command HugoCmd and sets flags appropriately.
 func Execute() {
-	HugoCmd.SetGlobalNormalizationFunc(helpers.NormalizeHugoFlags)
+	hugoCmd.SetGlobalNormalizationFunc(helpers.NormalizeHugoFlags)
 
-	HugoCmd.SilenceUsage = true
+	hugoCmd.SilenceUsage = true
 
 	AddCommands()
 
-	if c, err := HugoCmd.ExecuteC(); err != nil {
+	if c, err := hugoCmd.ExecuteC(); err != nil {
 		if isUserError(err) {
 			c.Println("")
 			c.Println(c.UsageString())
@@ -141,46 +161,34 @@
 
 // AddCommands adds child commands to the root command HugoCmd.
 func AddCommands() {
-	HugoCmd.AddCommand(serverCmd)
-	HugoCmd.AddCommand(versionCmd)
-	HugoCmd.AddCommand(configCmd)
-	HugoCmd.AddCommand(checkCmd)
-	HugoCmd.AddCommand(benchmarkCmd)
-	HugoCmd.AddCommand(convertCmd)
-	HugoCmd.AddCommand(newCmd)
-	HugoCmd.AddCommand(listCmd)
-	HugoCmd.AddCommand(undraftCmd)
-	HugoCmd.AddCommand(importCmd)
+	hugoCmd.AddCommand(serverCmd)
+	hugoCmd.AddCommand(versionCmd)
+	hugoCmd.AddCommand(configCmd)
+	hugoCmd.AddCommand(checkCmd)
+	hugoCmd.AddCommand(benchmarkCmd)
+	hugoCmd.AddCommand(convertCmd)
+	hugoCmd.AddCommand(newCmd)
+	hugoCmd.AddCommand(listCmd)
+	hugoCmd.AddCommand(undraftCmd)
+	hugoCmd.AddCommand(importCmd)
 
-	HugoCmd.AddCommand(genCmd)
+	hugoCmd.AddCommand(genCmd)
 	genCmd.AddCommand(genautocompleteCmd)
 	genCmd.AddCommand(gendocCmd)
 	genCmd.AddCommand(genmanCmd)
 }
 
+// initHugoBuilderFlags initializes all common flags, typically used by the
+// core build commands.
+func initHugoBuilderFlags(cmd *cobra.Command) {
+	initCoreCommonFlags(cmd)
+	initHugoBuildCommonFlags(cmd)
+}
+
 // initCoreCommonFlags initializes common flags used by Hugo core commands
 // such as hugo itself, server, check, config and benchmark.
 func initCoreCommonFlags(cmd *cobra.Command) {
-	cmd.Flags().BoolVar(&CleanDestination, "cleanDestinationDir", false, "Remove files from destination not found in static directories")
-	cmd.Flags().BoolVarP(&Draft, "buildDrafts", "D", false, "include content marked as draft")
-	cmd.Flags().BoolVarP(&Future, "buildFuture", "F", false, "include content with publishdate in the future")
-	cmd.Flags().BoolVar(&DisableRSS, "disableRSS", false, "Do not build RSS files")
-	cmd.Flags().BoolVar(&DisableSitemap, "disableSitemap", false, "Do not build Sitemap file")
-	cmd.Flags().BoolVar(&DisableRobotsTXT, "disableRobotsTXT", false, "Do not build Robots TXT file")
-	cmd.Flags().StringVarP(&Source, "source", "s", "", "filesystem path to read files relative from")
-	cmd.Flags().StringVarP(&CacheDir, "cacheDir", "", "", "filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/")
-	cmd.Flags().BoolVarP(&IgnoreCache, "ignoreCache", "", false, "Ignores the cache directory for reading but still writes to it")
-	cmd.Flags().StringVarP(&Destination, "destination", "d", "", "filesystem path to write files to")
-	cmd.Flags().StringVarP(&Theme, "theme", "t", "", "theme to use (located in /themes/THEMENAME/)")
-	cmd.Flags().BoolVar(&UglyURLs, "uglyURLs", false, "if true, use /filename.html instead of /filename/")
-	cmd.Flags().BoolVar(&CanonifyURLs, "canonifyURLs", false, "if true, all relative URLs will be canonicalized using baseURL")
-	cmd.Flags().StringVarP(&BaseURL, "baseURL", "b", "", "hostname (and path) to the root, e.g. http://spf13.com/")
 	cmd.Flags().StringVar(&CfgFile, "config", "", "config file (default is path/config.yaml|json|toml)")
-	cmd.Flags().StringVar(&Editor, "editor", "", "edit new content with this editor, if provided")
-	cmd.Flags().BoolVar(&nitro.AnalysisOn, "stepAnalysis", false, "display memory and timing of different steps of the program")
-	cmd.Flags().BoolVar(&PluralizeListTitles, "pluralizeListTitles", true, "Pluralize titles in lists using inflect")
-	cmd.Flags().BoolVar(&PreserveTaxonomyNames, "preserveTaxonomyNames", false, `Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu")`)
-	cmd.Flags().BoolVarP(&ForceSync, "forceSyncStatic", "", false, "Copy all files when static is changed.")
 	// For bash-completion
 	validConfigFilenames := []string{"json", "js", "yaml", "yml", "toml", "tml"}
 	cmd.Flags().SetAnnotation("config", cobra.BashCompFilenameExt, validConfigFilenames)
@@ -190,21 +198,45 @@
 	cmd.Flags().SetAnnotation("theme", cobra.BashCompSubdirsInDir, []string{"themes"})
 }
 
+// initial flags related to the Hugo build
+func initHugoBuildCommonFlags(cmd *cobra.Command) {
+	cmd.Flags().BoolVar(&cleanDestination, "cleanDestinationDir", false, "Remove files from destination not found in static directories")
+	cmd.Flags().BoolVarP(&draft, "buildDrafts", "D", false, "include content marked as draft")
+	cmd.Flags().BoolVarP(&future, "buildFuture", "F", false, "include content with publishdate in the future")
+	cmd.Flags().BoolVar(&disableRSS, "disableRSS", false, "Do not build RSS files")
+	cmd.Flags().BoolVar(&disableSitemap, "disableSitemap", false, "Do not build Sitemap file")
+	cmd.Flags().BoolVar(&disableRobotsTXT, "disableRobotsTXT", false, "Do not build Robots TXT file")
+	cmd.Flags().StringVarP(&Source, "source", "s", "", "filesystem path to read files relative from")
+	cmd.Flags().StringVarP(&CacheDir, "cacheDir", "", "", "filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/")
+	cmd.Flags().BoolVarP(&ignoreCache, "ignoreCache", "", false, "Ignores the cache directory for reading but still writes to it")
+	cmd.Flags().StringVarP(&Destination, "destination", "d", "", "filesystem path to write files to")
+	cmd.Flags().StringVarP(&Theme, "theme", "t", "", "theme to use (located in /themes/THEMENAME/)")
+	cmd.Flags().BoolVar(&uglyURLs, "uglyURLs", false, "if true, use /filename.html instead of /filename/")
+	cmd.Flags().BoolVar(&canonifyURLs, "canonifyURLs", false, "if true, all relative URLs will be canonicalized using baseURL")
+	cmd.Flags().StringVarP(&BaseURL, "baseURL", "b", "", "hostname (and path) to the root, e.g. http://spf13.com/")
+
+	cmd.Flags().BoolVar(&nitro.AnalysisOn, "stepAnalysis", false, "display memory and timing of different steps of the program")
+	cmd.Flags().BoolVar(&pluralizeListTitles, "pluralizeListTitles", true, "Pluralize titles in lists using inflect")
+	cmd.Flags().BoolVar(&preserveTaxonomyNames, "preserveTaxonomyNames", false, `Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu")`)
+	cmd.Flags().BoolVarP(&forceSync, "forceSyncStatic", "", false, "Copy all files when static is changed.")
+	cmd.Flags().BoolVarP(&noTimes, "noTimes", "", false, "Don't sync modification time of files")
+
+}
+
 // init initializes flags.
 func init() {
-	HugoCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
-	HugoCmd.PersistentFlags().BoolVar(&Logging, "log", false, "Enable Logging")
-	HugoCmd.PersistentFlags().StringVar(&LogFile, "logFile", "", "Log File path (if set, logging enabled automatically)")
-	HugoCmd.PersistentFlags().BoolVar(&VerboseLog, "verboseLog", false, "verbose logging")
+	hugoCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output")
+	hugoCmd.PersistentFlags().BoolVar(&logging, "log", false, "Enable Logging")
+	hugoCmd.PersistentFlags().StringVar(&LogFile, "logFile", "", "Log File path (if set, logging enabled automatically)")
+	hugoCmd.PersistentFlags().BoolVar(&verboseLog, "verboseLog", false, "verbose logging")
 
-	initCoreCommonFlags(HugoCmd)
+	initHugoBuilderFlags(hugoCmd)
 
-	HugoCmd.Flags().BoolVarP(&BuildWatch, "watch", "w", false, "watch filesystem for changes and recreate as needed")
-	HugoCmd.Flags().BoolVarP(&NoTimes, "noTimes", "", false, "Don't sync modification time of files")
-	hugoCmdV = HugoCmd
+	hugoCmd.Flags().BoolVarP(&buildWatch, "watch", "w", false, "watch filesystem for changes and recreate as needed")
+	hugoCmdV = hugoCmd
 
 	// For bash-completion
-	HugoCmd.PersistentFlags().SetAnnotation("logFile", cobra.BashCompFilenameExt, []string{})
+	hugoCmd.PersistentFlags().SetAnnotation("logFile", cobra.BashCompFilenameExt, []string{})
 }
 
 func LoadDefaultSettings() {
@@ -278,57 +310,54 @@
 
 	LoadDefaultSettings()
 
-	if hugoCmdV.PersistentFlags().Lookup("verbose").Changed {
-		viper.Set("Verbose", Verbose)
-	}
-	if hugoCmdV.PersistentFlags().Lookup("logFile").Changed {
-		viper.Set("LogFile", LogFile)
-	}
-
 	for _, cmdV := range append([]*cobra.Command{hugoCmdV}, subCmdVs...) {
-		if cmdV.Flags().Lookup("cleanDestinationDir").Changed {
-			viper.Set("cleanDestinationDir", CleanDestination)
+
+		if flagChanged(cmdV.PersistentFlags(), "verbose") {
+			viper.Set("Verbose", verbose)
 		}
-		if cmdV.Flags().Lookup("buildDrafts").Changed {
-			viper.Set("BuildDrafts", Draft)
+		if flagChanged(cmdV.PersistentFlags(), "logFile") {
+			viper.Set("LogFile", LogFile)
 		}
-		if cmdV.Flags().Lookup("buildFuture").Changed {
-			viper.Set("BuildFuture", Future)
+		if flagChanged(cmdV.Flags(), "cleanDestinationDir") {
+			viper.Set("cleanDestinationDir", cleanDestination)
 		}
-		if cmdV.Flags().Lookup("uglyURLs").Changed {
-			viper.Set("UglyURLs", UglyURLs)
+		if flagChanged(cmdV.Flags(), "buildDrafts") {
+			viper.Set("BuildDrafts", draft)
 		}
-		if cmdV.Flags().Lookup("canonifyURLs").Changed {
-			viper.Set("CanonifyURLs", CanonifyURLs)
+		if flagChanged(cmdV.Flags(), "buildFuture") {
+			viper.Set("BuildFuture", future)
 		}
-		if cmdV.Flags().Lookup("disableRSS").Changed {
-			viper.Set("DisableRSS", DisableRSS)
+		if flagChanged(cmdV.Flags(), "uglyURLs") {
+			viper.Set("UglyURLs", uglyURLs)
 		}
-		if cmdV.Flags().Lookup("disableSitemap").Changed {
-			viper.Set("DisableSitemap", DisableSitemap)
+		if flagChanged(cmdV.Flags(), "canonifyURLs") {
+			viper.Set("CanonifyURLs", canonifyURLs)
 		}
-		if cmdV.Flags().Lookup("disableRobotsTXT").Changed {
-			viper.Set("DisableRobotsTXT", DisableRobotsTXT)
+		if flagChanged(cmdV.Flags(), "disableRSS") {
+			viper.Set("DisableRSS", disableRSS)
 		}
-		if cmdV.Flags().Lookup("pluralizeListTitles").Changed {
-			viper.Set("PluralizeListTitles", PluralizeListTitles)
+		if flagChanged(cmdV.Flags(), "disableSitemap") {
+			viper.Set("DisableSitemap", disableSitemap)
 		}
-		if cmdV.Flags().Lookup("preserveTaxonomyNames").Changed {
-			viper.Set("PreserveTaxonomyNames", PreserveTaxonomyNames)
+		if flagChanged(cmdV.Flags(), "disableRobotsTXT") {
+			viper.Set("DisableRobotsTXT", disableRobotsTXT)
 		}
-		if cmdV.Flags().Lookup("forceSyncStatic").Changed {
-			viper.Set("ForceSyncStatic", ForceSync)
+		if flagChanged(cmdV.Flags(), "pluralizeListTitles") {
+			viper.Set("PluralizeListTitles", pluralizeListTitles)
 		}
-		if cmdV.Flags().Lookup("editor").Changed {
-			viper.Set("NewContentEditor", Editor)
+		if flagChanged(cmdV.Flags(), "preserveTaxonomyNames") {
+			viper.Set("PreserveTaxonomyNames", preserveTaxonomyNames)
 		}
-		if cmdV.Flags().Lookup("ignoreCache").Changed {
-			viper.Set("IgnoreCache", IgnoreCache)
+		if flagChanged(cmdV.Flags(), "ignoreCache") {
+			viper.Set("IgnoreCache", ignoreCache)
 		}
-	}
+		if flagChanged(cmdV.Flags(), "forceSyncStatic") {
+			viper.Set("ForceSyncStatic", forceSync)
+		}
+		if flagChanged(cmdV.Flags(), "noTimes") {
+			viper.Set("NoTimes", noTimes)
+		}
 
-	if hugoCmdV.Flags().Lookup("noTimes").Changed {
-		viper.Set("NoTimes", NoTimes)
 	}
 
 	if BaseURL != "" {
@@ -372,7 +401,7 @@
 		viper.Set("CacheDir", helpers.GetTempDir("hugo_cache", hugofs.SourceFs))
 	}
 
-	if VerboseLog || Logging || (viper.IsSet("LogFile") && viper.GetString("LogFile") != "") {
+	if verboseLog || logging || (viper.IsSet("LogFile") && viper.GetString("LogFile") != "") {
 		if viper.IsSet("LogFile") && viper.GetString("LogFile") != "" {
 			jww.SetLogFile(viper.GetString("LogFile"))
 		} else {
@@ -386,7 +415,7 @@
 		jww.SetStdoutThreshold(jww.LevelInfo)
 	}
 
-	if VerboseLog {
+	if verboseLog {
 		jww.SetLogThreshold(jww.LevelInfo)
 	}
 
@@ -409,6 +438,14 @@
 	return nil
 }
 
+func flagChanged(flags *flag.FlagSet, key string) bool {
+	flag := flags.Lookup(key)
+	if flag == nil {
+		return false
+	}
+	return flag.Changed
+}
+
 func watchConfig() {
 	viper.WatchConfig()
 	viper.OnConfigChange(func(e fsnotify.Event) {
@@ -430,11 +467,11 @@
 	if len(watches) > 0 && watches[0] {
 		watch = true
 	}
-	if err := buildSite(BuildWatch || watch); err != nil {
+	if err := buildSite(buildWatch || watch); err != nil {
 		return fmt.Errorf("Error building site: %s", err)
 	}
 
-	if BuildWatch {
+	if buildWatch {
 		jww.FEEDBACK.Println("Watching for changes in", helpers.AbsPathify(viper.GetString("ContentDir")))
 		jww.FEEDBACK.Println("Press Ctrl+C to stop")
 		utils.CheckErr(NewWatcher(0))
@@ -787,7 +824,7 @@
 						}
 					}
 
-					if !BuildWatch && !viper.GetBool("DisableLiveReload") {
+					if !buildWatch && !viper.GetBool("DisableLiveReload") {
 						// Will block forever trying to write to a channel that nobody is reading if livereload isn't initialized
 
 						// force refresh when more than one file
@@ -810,7 +847,7 @@
 
 					rebuildSite(dynamicEvents)
 
-					if !BuildWatch && !viper.GetBool("DisableLiveReload") {
+					if !buildWatch && !viper.GetBool("DisableLiveReload") {
 						// Will block forever trying to write to a channel that nobody is reading if livereload isn't initialized
 						livereload.ForceRefresh()
 					}
--- a/commands/new.go
+++ b/commands/new.go
@@ -30,11 +30,14 @@
 	"github.com/spf13/viper"
 )
 
-var siteType string
-var configFormat string
-var contentType string
-var contentFormat string
-var contentFrontMatter string
+var (
+	configFormat       string
+	contentEditor      string
+	contentFormat      string
+	contentFrontMatter string
+	contentType        string
+	siteType           string
+)
 
 func init() {
 	newSiteCmd.Flags().StringVarP(&configFormat, "format", "f", "toml", "config & frontmatter format")
@@ -43,8 +46,11 @@
 	newCmd.Flags().StringVarP(&contentType, "kind", "k", "", "Content type to create")
 	newCmd.PersistentFlags().StringVarP(&Source, "source", "s", "", "filesystem path to read files relative from")
 	newCmd.PersistentFlags().SetAnnotation("source", cobra.BashCompSubdirsInDir, []string{})
+	newCmd.Flags().StringVar(&contentEditor, "editor", "", "edit new content with this editor, if provided")
+
 	newCmd.AddCommand(newSiteCmd)
 	newCmd.AddCommand(newThemeCmd)
+
 }
 
 var newCmd = &cobra.Command{
@@ -85,8 +91,12 @@
 		return err
 	}
 
-	if cmd.Flags().Lookup("format").Changed {
+	if flagChanged(cmd.Flags(), "format") {
 		viper.Set("MetaDataFormat", configFormat)
+	}
+
+	if flagChanged(cmd.Flags(), "editor") {
+		viper.Set("NewContentEditor", contentEditor)
 	}
 
 	if len(args) < 1 {
--- a/commands/server.go
+++ b/commands/server.go
@@ -32,12 +32,14 @@
 	"github.com/spf13/viper"
 )
 
-var serverPort int
-var serverInterface string
-var serverWatch bool
-var serverAppend bool
-var disableLiveReload bool
-var renderToDisk bool
+var (
+	disableLiveReload bool
+	renderToDisk      bool
+	serverAppend      bool
+	serverInterface   string
+	serverPort        int
+	serverWatch       bool
+)
 
 //var serverCmdV *cobra.Command
 
@@ -81,7 +83,8 @@
 }
 
 func init() {
-	initCoreCommonFlags(serverCmd)
+	initHugoBuilderFlags(serverCmd)
+
 	serverCmd.Flags().IntVarP(&serverPort, "port", "p", 1313, "port on which the server will listen")
 	serverCmd.Flags().StringVarP(&serverInterface, "bind", "", "127.0.0.1", "interface to which the server will bind")
 	serverCmd.Flags().BoolVarP(&serverWatch, "watch", "w", true, "watch filesystem for changes and recreate as needed")
@@ -88,7 +91,6 @@
 	serverCmd.Flags().BoolVarP(&serverAppend, "appendPort", "", true, "append port to baseurl")
 	serverCmd.Flags().BoolVar(&disableLiveReload, "disableLiveReload", false, "watch without enabling live browser reload on rebuild")
 	serverCmd.Flags().BoolVar(&renderToDisk, "renderToDisk", false, "render to Destination path (default is render to memory & serve from there)")
-	serverCmd.Flags().BoolVarP(&NoTimes, "noTimes", "", false, "Don't sync modification time of files")
 	serverCmd.Flags().String("memstats", "", "log memory usage to this file")
 	serverCmd.Flags().Int("meminterval", 100, "interval to poll memory usage (requires --memstats)")
 	serverCmd.RunE = server
@@ -146,10 +148,6 @@
 		hugofs.DestinationFS = new(afero.MemMapFs)
 		// Rendering to memoryFS, publish to Root regardless of publishDir.
 		viper.Set("PublishDir", "/")
-	}
-
-	if serverCmd.Flags().Lookup("noTimes").Changed {
-		viper.Set("NoTimes", NoTimes)
 	}
 
 	if err := build(serverWatch); err != nil {