gitee.com/mirrors/Hugo-Go@v0.47.1/commands/commands.go (about) 1 // Copyright 2017 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package commands 15 16 import ( 17 "os" 18 19 "github.com/gohugoio/hugo/config" 20 "github.com/gohugoio/hugo/helpers" 21 "github.com/spf13/cobra" 22 jww "github.com/spf13/jwalterweatherman" 23 24 "github.com/spf13/nitro" 25 ) 26 27 type commandsBuilder struct { 28 hugoBuilderCommon 29 30 commands []cmder 31 } 32 33 func newCommandsBuilder() *commandsBuilder { 34 return &commandsBuilder{} 35 } 36 37 func (b *commandsBuilder) addCommands(commands ...cmder) *commandsBuilder { 38 b.commands = append(b.commands, commands...) 39 return b 40 } 41 42 func (b *commandsBuilder) addAll() *commandsBuilder { 43 b.addCommands( 44 b.newServerCmd(), 45 newVersionCmd(), 46 newEnvCmd(), 47 newConfigCmd(), 48 newCheckCmd(), 49 b.newBenchmarkCmd(), 50 newConvertCmd(), 51 newNewCmd(), 52 newListCmd(), 53 newImportCmd(), 54 newGenCmd(), 55 createReleaser(), 56 ) 57 58 return b 59 } 60 61 func (b *commandsBuilder) build() *hugoCmd { 62 h := b.newHugoCmd() 63 addCommands(h.getCommand(), b.commands...) 64 return h 65 } 66 67 func addCommands(root *cobra.Command, commands ...cmder) { 68 for _, command := range commands { 69 cmd := command.getCommand() 70 if cmd == nil { 71 continue 72 } 73 root.AddCommand(cmd) 74 } 75 } 76 77 type baseCmd struct { 78 cmd *cobra.Command 79 } 80 81 var _ commandsBuilderGetter = (*baseBuilderCmd)(nil) 82 83 // Used in tests. 84 type commandsBuilderGetter interface { 85 getCmmandsBuilder() *commandsBuilder 86 } 87 type baseBuilderCmd struct { 88 *baseCmd 89 *commandsBuilder 90 } 91 92 func (b *baseBuilderCmd) getCmmandsBuilder() *commandsBuilder { 93 return b.commandsBuilder 94 } 95 96 func (c *baseCmd) getCommand() *cobra.Command { 97 return c.cmd 98 } 99 100 func newBaseCmd(cmd *cobra.Command) *baseCmd { 101 return &baseCmd{cmd: cmd} 102 } 103 104 func (b *commandsBuilder) newBuilderCmd(cmd *cobra.Command) *baseBuilderCmd { 105 bcmd := &baseBuilderCmd{commandsBuilder: b, baseCmd: &baseCmd{cmd: cmd}} 106 bcmd.hugoBuilderCommon.handleFlags(cmd) 107 return bcmd 108 } 109 110 func (c *baseCmd) flagsToConfig(cfg config.Provider) { 111 initializeFlags(c.cmd, cfg) 112 } 113 114 type hugoCmd struct { 115 *baseBuilderCmd 116 117 // Need to get the sites once built. 118 c *commandeer 119 } 120 121 var _ cmder = (*nilCommand)(nil) 122 123 type nilCommand struct { 124 } 125 126 func (c *nilCommand) getCommand() *cobra.Command { 127 return nil 128 } 129 130 func (c *nilCommand) flagsToConfig(cfg config.Provider) { 131 132 } 133 134 func (b *commandsBuilder) newHugoCmd() *hugoCmd { 135 cc := &hugoCmd{} 136 137 cc.baseBuilderCmd = b.newBuilderCmd(&cobra.Command{ 138 Use: "hugo", 139 Short: "hugo builds your site", 140 Long: `hugo is the main command, used to build your Hugo site. 141 142 Hugo is a Fast and Flexible Static Site Generator 143 built with love by spf13 and friends in Go. 144 145 Complete documentation is available at http://gohugo.io/.`, 146 RunE: func(cmd *cobra.Command, args []string) error { 147 cfgInit := func(c *commandeer) error { 148 if cc.buildWatch { 149 c.Set("disableLiveReload", true) 150 } 151 return nil 152 } 153 154 c, err := initializeConfig(true, cc.buildWatch, &cc.hugoBuilderCommon, cc, cfgInit) 155 if err != nil { 156 return err 157 } 158 cc.c = c 159 160 return c.build() 161 }, 162 }) 163 164 cc.cmd.PersistentFlags().StringVar(&cc.cfgFile, "config", "", "config file (default is path/config.yaml|json|toml)") 165 cc.cmd.PersistentFlags().BoolVar(&cc.quiet, "quiet", false, "build in quiet mode") 166 167 // Set bash-completion 168 validConfigFilenames := []string{"json", "js", "yaml", "yml", "toml", "tml"} 169 _ = cc.cmd.PersistentFlags().SetAnnotation("config", cobra.BashCompFilenameExt, validConfigFilenames) 170 171 cc.cmd.PersistentFlags().BoolVarP(&cc.verbose, "verbose", "v", false, "verbose output") 172 cc.cmd.PersistentFlags().BoolVarP(&cc.debug, "debug", "", false, "debug output") 173 cc.cmd.PersistentFlags().BoolVar(&cc.logging, "log", false, "enable Logging") 174 cc.cmd.PersistentFlags().StringVar(&cc.logFile, "logFile", "", "log File path (if set, logging enabled automatically)") 175 cc.cmd.PersistentFlags().BoolVar(&cc.verboseLog, "verboseLog", false, "verbose logging") 176 177 cc.cmd.Flags().BoolVarP(&cc.buildWatch, "watch", "w", false, "watch filesystem for changes and recreate as needed") 178 179 cc.cmd.Flags().Bool("renderToMemory", false, "render to memory (only useful for benchmark testing)") 180 cc.cmd.Flags().Bool("minify", false, "minify any supported output format (HTML, XML etc.)") 181 182 // Set bash-completion 183 _ = cc.cmd.PersistentFlags().SetAnnotation("logFile", cobra.BashCompFilenameExt, []string{}) 184 185 cc.cmd.SetGlobalNormalizationFunc(helpers.NormalizeHugoFlags) 186 cc.cmd.SilenceUsage = true 187 188 return cc 189 } 190 191 type hugoBuilderCommon struct { 192 source string 193 baseURL string 194 195 buildWatch bool 196 197 gc bool 198 199 // TODO(bep) var vs string 200 logging bool 201 verbose bool 202 verboseLog bool 203 debug bool 204 quiet bool 205 206 cfgFile string 207 logFile string 208 } 209 210 func (cc *hugoBuilderCommon) handleFlags(cmd *cobra.Command) { 211 cmd.Flags().Bool("cleanDestinationDir", false, "remove files from destination not found in static directories") 212 cmd.Flags().BoolP("buildDrafts", "D", false, "include content marked as draft") 213 cmd.Flags().BoolP("buildFuture", "F", false, "include content with publishdate in the future") 214 cmd.Flags().BoolP("buildExpired", "E", false, "include expired content") 215 cmd.Flags().StringVarP(&cc.source, "source", "s", "", "filesystem path to read files relative from") 216 cmd.Flags().StringP("contentDir", "c", "", "filesystem path to content directory") 217 cmd.Flags().StringP("layoutDir", "l", "", "filesystem path to layout directory") 218 cmd.Flags().StringP("cacheDir", "", "", "filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/") 219 cmd.Flags().BoolP("ignoreCache", "", false, "ignores the cache directory") 220 cmd.Flags().StringP("destination", "d", "", "filesystem path to write files to") 221 cmd.Flags().StringP("theme", "t", "", "theme to use (located in /themes/THEMENAME/)") 222 cmd.Flags().StringP("themesDir", "", "", "filesystem path to themes directory") 223 cmd.Flags().Bool("uglyURLs", false, "(deprecated) if true, use /filename.html instead of /filename/") 224 cmd.Flags().Bool("canonifyURLs", false, "(deprecated) if true, all relative URLs will be canonicalized using baseURL") 225 cmd.Flags().StringVarP(&cc.baseURL, "baseURL", "b", "", "hostname (and path) to the root, e.g. http://spf13.com/") 226 cmd.Flags().Bool("enableGitInfo", false, "add Git revision, date and author info to the pages") 227 cmd.Flags().BoolVar(&cc.gc, "gc", false, "enable to run some cleanup tasks (remove unused cache files) after the build") 228 229 cmd.Flags().BoolVar(&nitro.AnalysisOn, "stepAnalysis", false, "display memory and timing of different steps of the program") 230 cmd.Flags().Bool("templateMetrics", false, "display metrics about template executions") 231 cmd.Flags().Bool("templateMetricsHints", false, "calculate some improvement hints when combined with --templateMetrics") 232 cmd.Flags().Bool("pluralizeListTitles", true, "(deprecated) pluralize titles in lists using inflect") 233 cmd.Flags().Bool("preserveTaxonomyNames", false, `(deprecated) preserve taxonomy names as written ("GĂ©rard Depardieu" vs "gerard-depardieu")`) 234 cmd.Flags().BoolP("forceSyncStatic", "", false, "copy all files when static is changed.") 235 cmd.Flags().BoolP("noTimes", "", false, "don't sync modification time of files") 236 cmd.Flags().BoolP("noChmod", "", false, "don't sync permission mode of files") 237 cmd.Flags().BoolP("i18n-warnings", "", false, "print missing translations") 238 239 cmd.Flags().StringSlice("disableKinds", []string{}, "disable different kind of pages (home, RSS etc.)") 240 241 // Set bash-completion. 242 // Each flag must first be defined before using the SetAnnotation() call. 243 _ = cmd.Flags().SetAnnotation("source", cobra.BashCompSubdirsInDir, []string{}) 244 _ = cmd.Flags().SetAnnotation("cacheDir", cobra.BashCompSubdirsInDir, []string{}) 245 _ = cmd.Flags().SetAnnotation("destination", cobra.BashCompSubdirsInDir, []string{}) 246 _ = cmd.Flags().SetAnnotation("theme", cobra.BashCompSubdirsInDir, []string{"themes"}) 247 } 248 249 func checkErr(logger *jww.Notepad, err error, s ...string) { 250 if err == nil { 251 return 252 } 253 if len(s) == 0 { 254 logger.CRITICAL.Println(err) 255 return 256 } 257 for _, message := range s { 258 logger.ERROR.Println(message) 259 } 260 logger.ERROR.Println(err) 261 } 262 263 func stopOnErr(logger *jww.Notepad, err error, s ...string) { 264 if err == nil { 265 return 266 } 267 268 defer os.Exit(-1) 269 270 if len(s) == 0 { 271 newMessage := err.Error() 272 // Printing an empty string results in a error with 273 // no message, no bueno. 274 if newMessage != "" { 275 logger.CRITICAL.Println(newMessage) 276 } 277 } 278 for _, message := range s { 279 if message != "" { 280 logger.CRITICAL.Println(message) 281 } 282 } 283 }