diff options
Diffstat (limited to 'commands/hugo.go')
-rw-r--r-- | commands/hugo.go | 169 |
1 files changed, 152 insertions, 17 deletions
diff --git a/commands/hugo.go b/commands/hugo.go index 3690c0ad5..4ca0eff69 100644 --- a/commands/hugo.go +++ b/commands/hugo.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Hugo Authors. All rights reserved. +// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,11 +18,16 @@ package commands import ( "fmt" "io/ioutil" - "os/signal" + "runtime/pprof" + "runtime/trace" "sort" "sync/atomic" + "github.com/gohugoio/hugo/hugofs" + + "github.com/gohugoio/hugo/resources/page" + "github.com/gohugoio/hugo/common/hugo" "github.com/pkg/errors" @@ -214,6 +219,7 @@ func initializeFlags(cmd *cobra.Command, cfg config.Provider) { "themesDir", "verbose", "verboseLog", + "duplicateTargetPaths", } // Will set a value even if it is the default. @@ -235,6 +241,7 @@ func initializeFlags(cmd *cobra.Command, cfg config.Provider) { // Set some "config aliases" setValueFromFlag(cmd.Flags(), "destination", cfg, "publishDir", false) setValueFromFlag(cmd.Flags(), "i18n-warnings", cfg, "logI18nWarnings", false) + setValueFromFlag(cmd.Flags(), "path-warnings", cfg, "logPathWarnings", false) } @@ -290,6 +297,7 @@ func (c *commandeer) fullBuild() error { } copyStaticFunc := func() error { + cnt, err := c.copyStatic() if err != nil { if !os.IsNotExist(err) { @@ -326,7 +334,7 @@ func (c *commandeer) fullBuild() error { } for _, s := range c.hugo.Sites { - s.ProcessingStats.Static = langCount[s.Language.Lang] + s.ProcessingStats.Static = langCount[s.Language().Lang] } if c.h.gc { @@ -344,9 +352,125 @@ func (c *commandeer) fullBuild() error { } +func (c *commandeer) initCPUProfile() (func(), error) { + if c.h.cpuprofile == "" { + return nil, nil + } + + f, err := os.Create(c.h.cpuprofile) + if err != nil { + return nil, errors.Wrap(err, "failed to create CPU profile") + } + if err := pprof.StartCPUProfile(f); err != nil { + return nil, errors.Wrap(err, "failed to start CPU profile") + } + return func() { + pprof.StopCPUProfile() + f.Close() + }, nil +} + +func (c *commandeer) initMemProfile() { + if c.h.memprofile == "" { + return + } + + f, err := os.Create(c.h.memprofile) + if err != nil { + c.logger.ERROR.Println("could not create memory profile: ", err) + } + defer f.Close() + runtime.GC() // get up-to-date statistics + if err := pprof.WriteHeapProfile(f); err != nil { + c.logger.ERROR.Println("could not write memory profile: ", err) + } +} + +func (c *commandeer) initTraceProfile() (func(), error) { + if c.h.traceprofile == "" { + return nil, nil + } + + f, err := os.Create(c.h.traceprofile) + if err != nil { + return nil, errors.Wrap(err, "failed to create trace file") + } + + if err := trace.Start(f); err != nil { + return nil, errors.Wrap(err, "failed to start trace") + } + + return func() { + trace.Stop() + f.Close() + }, nil +} + +func (c *commandeer) initMutexProfile() (func(), error) { + if c.h.mutexprofile == "" { + return nil, nil + } + + f, err := os.Create(c.h.mutexprofile) + if err != nil { + return nil, err + } + + runtime.SetMutexProfileFraction(1) + + return func() { + pprof.Lookup("mutex").WriteTo(f, 0) + f.Close() + }, nil + +} + +func (c *commandeer) initProfiling() (func(), error) { + stopCPUProf, err := c.initCPUProfile() + if err != nil { + return nil, err + } + + defer c.initMemProfile() + + stopMutexProf, err := c.initMutexProfile() + if err != nil { + return nil, err + } + + stopTraceProf, err := c.initTraceProfile() + if err != nil { + return nil, err + } + + return func() { + if stopCPUProf != nil { + stopCPUProf() + } + if stopMutexProf != nil { + stopMutexProf() + } + + if stopTraceProf != nil { + stopTraceProf() + } + }, nil +} + func (c *commandeer) build() error { defer c.timeTrack(time.Now(), "Total") + stopProfiling, err := c.initProfiling() + if err != nil { + return err + } + + defer func() { + if stopProfiling != nil { + stopProfiling() + } + }() + if err := c.fullBuild(); err != nil { return err } @@ -356,6 +480,13 @@ func (c *commandeer) build() error { fmt.Println() c.hugo.PrintProcessingStats(os.Stdout) fmt.Println() + + if createCounter, ok := c.destinationFs.(hugofs.DuplicatesReporter); ok { + dupes := createCounter.ReportDuplicates() + if dupes != "" { + c.logger.WARN.Println("Duplicate target paths:", dupes) + } + } } if c.h.buildWatch { @@ -369,7 +500,7 @@ func (c *commandeer) build() error { checkErr(c.Logger, err) defer watcher.Close() - var sigs = make(chan os.Signal) + var sigs = make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) <-sigs @@ -381,6 +512,17 @@ func (c *commandeer) build() error { func (c *commandeer) serverBuild() error { defer c.timeTrack(time.Now(), "Total") + stopProfiling, err := c.initProfiling() + if err != nil { + return err + } + + defer func() { + if stopProfiling != nil { + stopProfiling() + } + }() + if err := c.fullBuild(); err != nil { return err } @@ -474,11 +616,9 @@ func (c *commandeer) copyStaticTo(sourceFs *filesystems.SourceFilesystem) (uint6 } c.logger.INFO.Println("syncing static files to", publishDir) - var err error - // because we are using a baseFs (to get the union right). // set sync src to root - err = syncer.Sync(publishDir, helpers.FilePathSeparator) + err := syncer.Sync(publishDir, helpers.FilePathSeparator) if err != nil { return 0, err } @@ -619,13 +759,6 @@ func (c *commandeer) getDirList() ([]string, error) { return a, nil } -func (c *commandeer) resetAndBuildSites() (err error) { - if !c.h.quiet { - c.logger.FEEDBACK.Println("Started building sites ...") - } - return c.hugo.Build(hugolib.BuildCfg{ResetState: true}) -} - func (c *commandeer) buildSites() (err error) { return c.hugo.Build(hugolib.BuildCfg{}) } @@ -973,7 +1106,7 @@ func (c *commandeer) handleEvents(watcher *watcher.Batcher, navigate := c.Cfg.GetBool("navigateToChanged") // We have fetched the same page above, but it may have // changed. - var p *hugolib.Page + var p page.Page if navigate { if onePageName != "" { @@ -982,7 +1115,7 @@ func (c *commandeer) handleEvents(watcher *watcher.Batcher, } if p != nil { - livereload.NavigateToPathForPort(p.RelPermalink(), p.Site.ServerPort()) + livereload.NavigateToPathForPort(p.RelPermalink(), p.Site().ServerPort()) } else { livereload.ForceRefresh() } @@ -1044,9 +1177,11 @@ func (c *commandeer) isThemeVsHugoVersionMismatch(fs afero.Fs) (dir string, mism } b, err := afero.ReadFile(fs, path) + if err != nil { + continue + } tomlMeta, err := metadecoders.Default.UnmarshalToMap(b, metadecoders.TOML) - if err != nil { continue } |