commands: Make sure the hugo field is always initialized before it's used

Wrap the field to make it accessible after initialization.

Fixes #6193
This commit is contained in:
HyeonGyu Lee 2019-08-15 16:33:47 +09:00 committed by Bjørn Erik Pedersen
parent 37f5929803
commit ea9261e856
8 changed files with 54 additions and 40 deletions

View file

@ -52,8 +52,9 @@ import (
type commandeerHugoState struct { type commandeerHugoState struct {
*deps.DepsCfg *deps.DepsCfg
hugo *hugolib.HugoSites hugoSites *hugolib.HugoSites
fsCreate sync.Once fsCreate sync.Once
created chan struct{}
} }
type commandeer struct { type commandeer struct {
@ -97,6 +98,17 @@ type commandeer struct {
buildErr error buildErr error
} }
func newCommandeerHugoState() *commandeerHugoState {
return &commandeerHugoState{
created: make(chan struct{}),
}
}
func (c *commandeerHugoState) hugo() *hugolib.HugoSites {
<-c.created
return c.hugoSites
}
func (c *commandeer) errCount() int { func (c *commandeer) errCount() int {
return int(c.logger.ErrorCounter.Count()) return int(c.logger.ErrorCounter.Count())
} }
@ -154,7 +166,7 @@ func newCommandeer(mustHaveConfigFile, running bool, h *hugoBuilderCommon, f fla
c := &commandeer{ c := &commandeer{
h: h, h: h,
ftch: f, ftch: f,
commandeerHugoState: &commandeerHugoState{}, commandeerHugoState: newCommandeerHugoState(),
doWithCommandeer: doWithCommandeer, doWithCommandeer: doWithCommandeer,
visitedURLs: types.NewEvictingStringQueue(10), visitedURLs: types.NewEvictingStringQueue(10),
debounce: rebuildDebouncer, debounce: rebuildDebouncer,
@ -373,13 +385,15 @@ func (c *commandeer) loadConfig(mustHaveConfigFile, running bool) error {
err = c.initFs(fs) err = c.initFs(fs)
if err != nil { if err != nil {
close(c.created)
return return
} }
var h *hugolib.HugoSites var h *hugolib.HugoSites
h, err = hugolib.NewHugoSites(*c.DepsCfg) h, err = hugolib.NewHugoSites(*c.DepsCfg)
c.hugo = h c.hugoSites = h
close(c.created)
}) })

View file

@ -58,7 +58,7 @@ documentation.
if err != nil { if err != nil {
return err return err
} }
deployer, err := deploy.New(comm.Cfg, comm.hugo.PathSpec.PublishFs) deployer, err := deploy.New(comm.Cfg, comm.hugo().PathSpec.PublishFs)
if err != nil { if err != nil {
return err return err
} }

View file

@ -92,7 +92,7 @@ func Execute(args []string) Response {
if c == cmd && hugoCmd.c != nil { if c == cmd && hugoCmd.c != nil {
// Root command executed // Root command executed
resp.Result = hugoCmd.c.hugo resp.Result = hugoCmd.c.hugo()
} }
if err == nil { if err == nil {
@ -338,16 +338,16 @@ func (c *commandeer) fullBuild() error {
} }
} }
for _, s := range c.hugo.Sites { for _, s := range c.hugo().Sites {
s.ProcessingStats.Static = langCount[s.Language().Lang] s.ProcessingStats.Static = langCount[s.Language().Lang]
} }
if c.h.gc { if c.h.gc {
count, err := c.hugo.GC() count, err := c.hugo().GC()
if err != nil { if err != nil {
return err return err
} }
for _, s := range c.hugo.Sites { for _, s := range c.hugo().Sites {
// We have no way of knowing what site the garbage belonged to. // We have no way of knowing what site the garbage belonged to.
s.ProcessingStats.Cleaned = uint64(count) s.ProcessingStats.Cleaned = uint64(count)
} }
@ -483,7 +483,7 @@ func (c *commandeer) build() error {
// TODO(bep) Feedback? // TODO(bep) Feedback?
if !c.h.quiet { if !c.h.quiet {
fmt.Println() fmt.Println()
c.hugo.PrintProcessingStats(os.Stdout) c.hugo().PrintProcessingStats(os.Stdout)
fmt.Println() fmt.Println()
if createCounter, ok := c.destinationFs.(hugofs.DuplicatesReporter); ok { if createCounter, ok := c.destinationFs.(hugofs.DuplicatesReporter); ok {
@ -539,7 +539,7 @@ func (c *commandeer) serverBuild() error {
// TODO(bep) Feedback? // TODO(bep) Feedback?
if !c.h.quiet { if !c.h.quiet {
fmt.Println() fmt.Println()
c.hugo.PrintProcessingStats(os.Stdout) c.hugo().PrintProcessingStats(os.Stdout)
fmt.Println() fmt.Println()
} }
@ -558,7 +558,7 @@ func (c *commandeer) doWithPublishDirs(f func(sourceFs *filesystems.SourceFilesy
langCount := make(map[string]uint64) langCount := make(map[string]uint64)
staticFilesystems := c.hugo.BaseFs.SourceFilesystems.Static staticFilesystems := c.hugo().BaseFs.SourceFilesystems.Static
if len(staticFilesystems) == 0 { if len(staticFilesystems) == 0 {
c.logger.INFO.Println("No static directories found to sync") c.logger.INFO.Println("No static directories found to sync")
@ -610,7 +610,7 @@ func chmodFilter(dst, src os.FileInfo) bool {
} }
func (c *commandeer) copyStaticTo(sourceFs *filesystems.SourceFilesystem) (uint64, error) { func (c *commandeer) copyStaticTo(sourceFs *filesystems.SourceFilesystem) (uint64, error) {
publishDir := c.hugo.PathSpec.PublishDir publishDir := c.hugo().PathSpec.PublishDir
// If root, remove the second '/' // If root, remove the second '/'
if publishDir == "//" { if publishDir == "//" {
publishDir = helpers.FilePathSeparator publishDir = helpers.FilePathSeparator
@ -655,7 +655,7 @@ func (c *commandeer) copyStaticTo(sourceFs *filesystems.SourceFilesystem) (uint6
} }
func (c *commandeer) firstPathSpec() *helpers.PathSpec { func (c *commandeer) firstPathSpec() *helpers.PathSpec {
return c.hugo.Sites[0].PathSpec return c.hugo().Sites[0].PathSpec
} }
func (c *commandeer) timeTrack(start time.Time, name string) { func (c *commandeer) timeTrack(start time.Time, name string) {
@ -689,7 +689,7 @@ func (c *commandeer) getDirList() ([]string, error) {
} }
watchDirs := c.hugo.PathSpec.BaseFs.WatchDirs() watchDirs := c.hugo().PathSpec.BaseFs.WatchDirs()
for _, watchDir := range watchDirs { for _, watchDir := range watchDirs {
w := hugofs.NewWalkway(hugofs.WalkwayConfig{Logger: c.logger, Info: watchDir, WalkFn: walkFn}) w := hugofs.NewWalkway(hugofs.WalkwayConfig{Logger: c.logger, Info: watchDir, WalkFn: walkFn})
@ -704,7 +704,7 @@ func (c *commandeer) getDirList() ([]string, error) {
} }
func (c *commandeer) buildSites() (err error) { func (c *commandeer) buildSites() (err error) {
return c.hugo.Build(hugolib.BuildCfg{}) return c.hugo().Build(hugolib.BuildCfg{})
} }
func (c *commandeer) handleBuildErr(err error, msg string) { func (c *commandeer) handleBuildErr(err error, msg string) {
@ -726,16 +726,16 @@ func (c *commandeer) rebuildSites(events []fsnotify.Event) error {
// Make sure we always render the home pages // Make sure we always render the home pages
for _, l := range c.languages { for _, l := range c.languages {
langPath := c.hugo.PathSpec.GetLangSubDir(l.Lang) langPath := c.hugo().PathSpec.GetLangSubDir(l.Lang)
if langPath != "" { if langPath != "" {
langPath = langPath + "/" langPath = langPath + "/"
} }
home := c.hugo.PathSpec.PrependBasePath("/"+langPath, false) home := c.hugo().PathSpec.PrependBasePath("/"+langPath, false)
visited[home] = true visited[home] = true
} }
} }
return c.hugo.Build(hugolib.BuildCfg{RecentlyVisited: visited}, events...) return c.hugo().Build(hugolib.BuildCfg{RecentlyVisited: visited}, events...)
} }
func (c *commandeer) partialReRender(urls ...string) error { func (c *commandeer) partialReRender(urls ...string) error {
@ -744,7 +744,7 @@ func (c *commandeer) partialReRender(urls ...string) error {
for _, url := range urls { for _, url := range urls {
visited[url] = true visited[url] = true
} }
return c.hugo.Build(hugolib.BuildCfg{RecentlyVisited: visited, PartialReRender: true}) return c.hugo().Build(hugolib.BuildCfg{RecentlyVisited: visited, PartialReRender: true})
} }
func (c *commandeer) fullRebuild(changeType string) { func (c *commandeer) fullRebuild(changeType string) {
@ -775,7 +775,7 @@ func (c *commandeer) fullRebuild(changeType string) {
defer c.timeTrack(time.Now(), "Total") defer c.timeTrack(time.Now(), "Total")
c.commandeerHugoState = &commandeerHugoState{} c.commandeerHugoState = newCommandeerHugoState()
err := c.loadConfig(true, true) err := c.loadConfig(true, true)
if err != nil { if err != nil {
// Set the processing on pause until the state is recovered. // Set the processing on pause until the state is recovered.
@ -951,7 +951,7 @@ func (c *commandeer) handleEvents(watcher *watcher.Batcher,
filtered := []fsnotify.Event{} filtered := []fsnotify.Event{}
for _, ev := range evs { for _, ev := range evs {
// Check the most specific first, i.e. files. // Check the most specific first, i.e. files.
contentMapped := c.hugo.ContentChanges.GetSymbolicLinkMappings(ev.Name) contentMapped := c.hugo().ContentChanges.GetSymbolicLinkMappings(ev.Name)
if len(contentMapped) > 0 { if len(contentMapped) > 0 {
for _, mapped := range contentMapped { for _, mapped := range contentMapped {
filtered = append(filtered, fsnotify.Event{Name: mapped, Op: ev.Op}) filtered = append(filtered, fsnotify.Event{Name: mapped, Op: ev.Op})
@ -963,7 +963,7 @@ func (c *commandeer) handleEvents(watcher *watcher.Batcher,
dir, name := filepath.Split(ev.Name) dir, name := filepath.Split(ev.Name)
contentMapped = c.hugo.ContentChanges.GetSymbolicLinkMappings(dir) contentMapped = c.hugo().ContentChanges.GetSymbolicLinkMappings(dir)
if len(contentMapped) == 0 { if len(contentMapped) == 0 {
filtered = append(filtered, ev) filtered = append(filtered, ev)
@ -997,7 +997,7 @@ func (c *commandeer) handleEvents(watcher *watcher.Batcher,
if istemp { if istemp {
continue continue
} }
if c.hugo.Deps.SourceSpec.IgnoreFile(ev.Name) { if c.hugo().Deps.SourceSpec.IgnoreFile(ev.Name) {
continue continue
} }
// Sometimes during rm -rf operations a '"": REMOVE' is triggered. Just ignore these // Sometimes during rm -rf operations a '"": REMOVE' is triggered. Just ignore these
@ -1073,7 +1073,7 @@ func (c *commandeer) handleEvents(watcher *watcher.Batcher,
// force refresh when more than one file // force refresh when more than one file
if len(staticEvents) == 1 { if len(staticEvents) == 1 {
ev := staticEvents[0] ev := staticEvents[0]
path := c.hugo.BaseFs.SourceFilesystems.MakeStaticPathRelative(ev.Name) path := c.hugo().BaseFs.SourceFilesystems.MakeStaticPathRelative(ev.Name)
path = c.firstPathSpec().RelURL(helpers.ToSlashTrimLeading(path), false) path = c.firstPathSpec().RelURL(helpers.ToSlashTrimLeading(path), false)
livereload.RefreshPath(path) livereload.RefreshPath(path)
} else { } else {
@ -1119,7 +1119,7 @@ func (c *commandeer) handleEvents(watcher *watcher.Batcher,
if navigate { if navigate {
if onePageName != "" { if onePageName != "" {
p = c.hugo.GetContentPage(onePageName) p = c.hugo().GetContentPage(onePageName)
} }
} }

View file

@ -157,7 +157,7 @@ Also note that if you configure a positive maxAge for the "modules" file cache,
return err return err
} }
_, err = com.hugo.FileCaches.ModulesCache().Prune(true) _, err = com.hugo().FileCaches.ModulesCache().Prune(true)
return err return err
}, },
@ -176,7 +176,7 @@ func (c *modCmd) withModsClient(failOnMissingConfig bool, f func(*modules.Client
return err return err
} }
return f(com.hugo.ModulesClient) return f(com.hugo().ModulesClient)
} }
func (c *modCmd) initConfig(failOnNoConfig bool) (*commandeer, error) { func (c *modCmd) initConfig(failOnNoConfig bool) (*commandeer, error) {

View file

@ -85,13 +85,13 @@ func (n *newCmd) newContent(cmd *cobra.Command, args []string) error {
var kind string var kind string
createPath, kind = newContentPathSection(c.hugo, createPath) createPath, kind = newContentPathSection(c.hugo(), createPath)
if n.contentType != "" { if n.contentType != "" {
kind = n.contentType kind = n.contentType
} }
return create.NewContent(c.hugo, kind, createPath) return create.NewContent(c.hugo(), kind, createPath)
} }
func mkdir(x ...string) { func mkdir(x ...string) {

View file

@ -63,7 +63,7 @@ func (n *newThemeCmd) newTheme(cmd *cobra.Command, args []string) error {
return newUserError("theme name needs to be provided") return newUserError("theme name needs to be provided")
} }
createpath := c.hugo.PathSpec.AbsPathify(filepath.Join(c.Cfg.GetString("themesDir"), args[0])) createpath := c.hugo().PathSpec.AbsPathify(filepath.Join(c.Cfg.GetString("themesDir"), args[0]))
jww.FEEDBACK.Println("Creating theme at", createpath) jww.FEEDBACK.Println("Creating theme at", createpath)
cfg := c.DepsCfg cfg := c.DepsCfg

View file

@ -244,7 +244,7 @@ func (sc *serverCmd) server(cmd *cobra.Command, args []string) error {
return err return err
} }
for _, s := range c.hugo.Sites { for _, s := range c.hugo().Sites {
s.RegisterMediaTypes() s.RegisterMediaTypes()
} }
@ -303,9 +303,9 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, erro
publishDir = filepath.Join(publishDir, root) publishDir = filepath.Join(publishDir, root)
} }
absPublishDir := f.c.hugo.PathSpec.AbsPathify(publishDir) absPublishDir := f.c.hugo().PathSpec.AbsPathify(publishDir)
jww.FEEDBACK.Printf("Environment: %q", f.c.hugo.Deps.Site.Hugo().Environment) jww.FEEDBACK.Printf("Environment: %q", f.c.hugo().Deps.Site.Hugo().Environment)
if i == 0 { if i == 0 {
if f.s.renderToDisk { if f.s.renderToDisk {
@ -398,7 +398,7 @@ func removeErrorPrefixFromLog(content string) string {
} }
func (c *commandeer) serve(s *serverCmd) error { func (c *commandeer) serve(s *serverCmd) error {
isMultiHost := c.hugo.IsMultihost() isMultiHost := c.hugo().IsMultihost()
var ( var (
baseURLs []string baseURLs []string
@ -406,17 +406,17 @@ func (c *commandeer) serve(s *serverCmd) error {
) )
if isMultiHost { if isMultiHost {
for _, s := range c.hugo.Sites { for _, s := range c.hugo().Sites {
baseURLs = append(baseURLs, s.BaseURL.String()) baseURLs = append(baseURLs, s.BaseURL.String())
roots = append(roots, s.Language().Lang) roots = append(roots, s.Language().Lang)
} }
} else { } else {
s := c.hugo.Sites[0] s := c.hugo().Sites[0]
baseURLs = []string{s.BaseURL.String()} baseURLs = []string{s.BaseURL.String()}
roots = []string{""} roots = []string{""}
} }
templ, err := c.hugo.TextTmpl.Parse("__default_server_error", buildErrorTemplate) templ, err := c.hugo().TextTmpl.Parse("__default_server_error", buildErrorTemplate)
if err != nil { if err != nil {
return err return err
} }

View file

@ -33,14 +33,14 @@ func newStaticSyncer(c *commandeer) (*staticSyncer, error) {
} }
func (s *staticSyncer) isStatic(filename string) bool { func (s *staticSyncer) isStatic(filename string) bool {
return s.c.hugo.BaseFs.SourceFilesystems.IsStatic(filename) return s.c.hugo().BaseFs.SourceFilesystems.IsStatic(filename)
} }
func (s *staticSyncer) syncsStaticEvents(staticEvents []fsnotify.Event) error { func (s *staticSyncer) syncsStaticEvents(staticEvents []fsnotify.Event) error {
c := s.c c := s.c
syncFn := func(sourceFs *filesystems.SourceFilesystem) (uint64, error) { syncFn := func(sourceFs *filesystems.SourceFilesystem) (uint64, error) {
publishDir := c.hugo.PathSpec.PublishDir publishDir := c.hugo().PathSpec.PublishDir
// If root, remove the second '/' // If root, remove the second '/'
if publishDir == "//" { if publishDir == "//" {
publishDir = helpers.FilePathSeparator publishDir = helpers.FilePathSeparator