func build() { utils.CheckErr(copyStatic(), fmt.Sprintf("Error copying static files to %s", Config.GetAbsPath(Config.PublishDir))) utils.StopOnErr(buildSite()) if BuildWatch { fmt.Println("Watching for changes in", Config.GetAbsPath(Config.ContentDir)) fmt.Println("Press ctrl+c to stop") utils.CheckErr(NewWatcher(0)) } }
func build(watches ...bool) { utils.CheckErr(copyStatic(), fmt.Sprintf("Error copying static files to %s", Config.GetAbsPath(Config.PublishDir))) watch := false if len(watches) > 0 && watches[0] { watch = true } utils.StopOnErr(buildSite(BuildWatch || watch)) if BuildWatch { fmt.Println("Watching for changes in", Config.GetAbsPath(Config.ContentDir)) fmt.Println("Press ctrl+c to stop") utils.CheckErr(NewWatcher(0)) } }
func build(watches ...bool) { utils.CheckErr(copyStatic(), fmt.Sprintf("Error copying static files to %s", helpers.AbsPathify(viper.GetString("PublishDir")))) watch := false if len(watches) > 0 && watches[0] { watch = true } utils.StopOnErr(buildSite(BuildWatch || watch)) 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)) } }
func copyStatic() error { publishDir := helpers.AbsPathify(viper.GetString("PublishDir")) + "/" // If root, remove the second '/' if publishDir == "//" { publishDir = "/" } syncer := fsync.NewSyncer() syncer.NoTimes = viper.GetBool("notimes") syncer.SrcFs = hugofs.SourceFs syncer.DestFs = hugofs.DestinationFS themeDir, err := helpers.GetThemeStaticDirPath() if err != nil { jww.ERROR.Println(err) return nil } // Copy the theme's static directory if themeDir != "" { jww.INFO.Println("syncing from", themeDir, "to", publishDir) utils.CheckErr(syncer.Sync(publishDir, themeDir), fmt.Sprintf("Error copying static files of theme to %s", publishDir)) } // Copy the site's own static directory staticDir := helpers.AbsPathify(viper.GetString("StaticDir")) + "/" if _, err := os.Stat(staticDir); err == nil { jww.INFO.Println("syncing from", staticDir, "to", publishDir) return syncer.Sync(publishDir, staticDir) } else if os.IsNotExist(err) { jww.WARN.Println("Unable to find Static Directory:", staticDir) } return nil }
func build(watches ...bool) error { // Hugo writes the output to memory instead of the disk // This is only used for benchmark testing. Cause the content is only visible // in memory if renderToMemory { hugofs.DestinationFS = new(afero.MemMapFs) // Rendering to memoryFS, publish to Root regardless of publishDir. viper.Set("PublishDir", "/") } if err := copyStatic(); err != nil { return fmt.Errorf("Error copying static files to %s: %s", helpers.AbsPathify(viper.GetString("PublishDir")), err) } watch := false if len(watches) > 0 && watches[0] { watch = true } if err := buildSite(buildWatch || watch); err != nil { return fmt.Errorf("Error building site: %s", err) } 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)) } return nil }
func copyStatic() error { staticDir := helpers.AbsPathify(viper.GetString("StaticDir")) + "/" if _, err := os.Stat(staticDir); os.IsNotExist(err) { jww.ERROR.Println("Unable to find Static Directory:", viper.GetString("theme"), "in", staticDir) return nil } publishDir := helpers.AbsPathify(viper.GetString("PublishDir")) + "/" if themeSet() { themeDir := helpers.AbsPathify("themes/"+viper.GetString("theme")) + "/static/" if _, err := os.Stat(themeDir); os.IsNotExist(err) { jww.ERROR.Println("Unable to find static directory for theme :", viper.GetString("theme"), "in", themeDir) return nil } // Copy Static to Destination jww.INFO.Println("syncing from", themeDir, "to", publishDir) utils.CheckErr(fsync.Sync(publishDir, themeDir), fmt.Sprintf("Error copying static files of theme to %s", publishDir)) } // Copy Static to Destination jww.INFO.Println("syncing from", staticDir, "to", publishDir) return fsync.Sync(publishDir, staticDir) }
func copyStatic() error { staticDir := helpers.AbsPathify(viper.GetString("StaticDir")) + "/" if _, err := os.Stat(staticDir); os.IsNotExist(err) { jww.ERROR.Println("Unable to find Static Directory:", staticDir) return nil } publishDir := helpers.AbsPathify(viper.GetString("PublishDir")) + "/" syncer := fsync.NewSyncer() syncer.NoTimes = viper.GetBool("notimes") syncer.SrcFs = hugofs.SourceFs syncer.DestFs = hugofs.DestinationFS themeDir, err := helpers.GetThemeStaticDirPath() if err != nil { jww.ERROR.Println(err) return nil } if themeDir != "" { // Copy Static to Destination jww.INFO.Println("syncing from", themeDir, "to", publishDir) utils.CheckErr(syncer.Sync(publishDir, themeDir), fmt.Sprintf("Error copying static files of theme to %s", publishDir)) } // Copy Static to Destination jww.INFO.Println("syncing from", staticDir, "to", publishDir) return syncer.Sync(publishDir, staticDir) }
func watchChange(ev *fsnotify.FileEvent) { if strings.HasPrefix(ev.Name, Config.GetAbsPath(Config.StaticDir)) { fmt.Println("Static file changed, syncing\n") utils.CheckErr(copyStatic(), fmt.Sprintf("Error copying static files to %s", Config.GetAbsPath(Config.PublishDir))) } else { fmt.Println("Change detected, rebuilding site\n") utils.StopOnErr(buildSite()) } }
func watchConfig() { viper.WatchConfig() viper.OnConfigChange(func(e fsnotify.Event) { fmt.Println("Config file changed:", e.Name) utils.CheckErr(buildSite(true)) if !viper.GetBool("DisableLiveReload") { // Will block forever trying to write to a channel that nobody is reading if livereload isn't initialized livereload.ForceRefresh() } }) }
func watchChange(ev *fsnotify.FileEvent) { if strings.HasPrefix(ev.Name, Config.GetAbsPath(Config.StaticDir)) { fmt.Println("Static file changed, syncing\n") utils.CheckErr(copyStatic(), fmt.Sprintf("Error copying static files to %s", Config.GetAbsPath(Config.PublishDir))) } else { if !ev.IsRename() { // Rename is always accompanied by a create or modify // Ignoring temp files created by editors (vim) if !strings.HasSuffix(ev.Name, "~") && !strings.HasSuffix(ev.Name, ".swp") { fmt.Println("Change detected, rebuilding site\n") utils.StopOnErr(buildSite(true)) } } } }
func build(watches ...bool) error { if err := copyStatic(); err != nil { return fmt.Errorf("Error copying static files to %s: %s", helpers.AbsPathify(viper.GetString("PublishDir")), err) } watch := false if len(watches) > 0 && watches[0] { watch = true } if err := buildSite(BuildWatch || watch); err != nil { return fmt.Errorf("Error building site: %s", err) } 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)) } return nil }
// InitializeConfig initializes a config file with sensible default configuration flags. // A Hugo command that calls initCoreCommonFlags() can pass itself // as an argument to have its command-line flags processed here. func InitializeConfig(subCmdVs ...*cobra.Command) error { viper.SetConfigFile(cfgFile) // See https://github.com/spf13/viper/issues/73#issuecomment-126970794 if source == "" { viper.AddConfigPath(".") } else { viper.AddConfigPath(source) } err := viper.ReadInConfig() if err != nil { if _, ok := err.(viper.ConfigParseError); ok { return newSystemError(err) } else { return newSystemErrorF("Unable to locate Config file. Perhaps you need to create a new site.\n Run `hugo help new` for details. (%s)\n", err) } } viper.RegisterAlias("indexes", "taxonomies") LoadDefaultSettings() for _, cmdV := range append([]*cobra.Command{hugoCmdV}, subCmdVs...) { if flagChanged(cmdV.PersistentFlags(), "verbose") { viper.Set("Verbose", verbose) } if flagChanged(cmdV.PersistentFlags(), "logFile") { viper.Set("LogFile", logFile) } if flagChanged(cmdV.Flags(), "cleanDestinationDir") { viper.Set("cleanDestinationDir", cleanDestination) } if flagChanged(cmdV.Flags(), "buildDrafts") { viper.Set("BuildDrafts", draft) } if flagChanged(cmdV.Flags(), "buildFuture") { viper.Set("BuildFuture", future) } if flagChanged(cmdV.Flags(), "uglyURLs") { viper.Set("UglyURLs", uglyURLs) } if flagChanged(cmdV.Flags(), "canonifyURLs") { viper.Set("CanonifyURLs", canonifyURLs) } if flagChanged(cmdV.Flags(), "disableRSS") { viper.Set("DisableRSS", disableRSS) } if flagChanged(cmdV.Flags(), "disableSitemap") { viper.Set("DisableSitemap", disableSitemap) } if flagChanged(cmdV.Flags(), "disableRobotsTXT") { viper.Set("DisableRobotsTXT", disableRobotsTXT) } if flagChanged(cmdV.Flags(), "pluralizeListTitles") { viper.Set("PluralizeListTitles", pluralizeListTitles) } if flagChanged(cmdV.Flags(), "preserveTaxonomyNames") { viper.Set("PreserveTaxonomyNames", preserveTaxonomyNames) } 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 baseURL != "" { if !strings.HasSuffix(baseURL, "/") { baseURL = baseURL + "/" } viper.Set("BaseURL", baseURL) } if !viper.GetBool("RelativeURLs") && viper.GetString("BaseURL") == "" { jww.ERROR.Println("No 'baseurl' set in configuration or as a flag. Features like page menus will not work without one.") } if theme != "" { viper.Set("theme", theme) } if destination != "" { viper.Set("PublishDir", destination) } if source != "" { dir, _ := filepath.Abs(source) viper.Set("WorkingDir", dir) } else { dir, _ := os.Getwd() viper.Set("WorkingDir", dir) } if contentDir != "" { viper.Set("ContentDir", contentDir) } if layoutDir != "" { viper.Set("LayoutDir", layoutDir) } if cacheDir != "" { if helpers.FilePathSeparator != cacheDir[len(cacheDir)-1:] { cacheDir = cacheDir + helpers.FilePathSeparator } isDir, err := helpers.DirExists(cacheDir, hugofs.SourceFs) utils.CheckErr(err) if isDir == false { mkdir(cacheDir) } viper.Set("CacheDir", cacheDir) } else { viper.Set("CacheDir", helpers.GetTempDir("hugo_cache", hugofs.SourceFs)) } if verboseLog || logging || (viper.IsSet("LogFile") && viper.GetString("LogFile") != "") { if viper.IsSet("LogFile") && viper.GetString("LogFile") != "" { jww.SetLogFile(viper.GetString("LogFile")) } else { jww.UseTempLogFile("hugo") } } else { jww.DiscardLogging() } if viper.GetBool("verbose") { jww.SetStdoutThreshold(jww.LevelInfo) } if verboseLog { jww.SetLogThreshold(jww.LevelInfo) } jww.INFO.Println("Using config file:", viper.ConfigFileUsed()) themeDir := helpers.GetThemeDir() if themeDir != "" { if _, err := os.Stat(themeDir); os.IsNotExist(err) { return newSystemError("Unable to find theme Directory:", themeDir) } } themeVersionMismatch, minVersion := isThemeVsHugoVersionMismatch() if themeVersionMismatch { jww.ERROR.Printf("Current theme does not support Hugo version %s. Minimum version required is %s\n", helpers.HugoReleaseVersion(), minVersion) } return nil }
// NewWatcher creates a new watcher to watch filesystem events. func NewWatcher(port int) error { if runtime.GOOS == "darwin" { tweakLimit() } watcher, err := watcher.New(1 * time.Second) var wg sync.WaitGroup if err != nil { fmt.Println(err) return err } defer watcher.Close() wg.Add(1) for _, d := range getDirList() { if d != "" { _ = watcher.Add(d) } } go func() { for { select { case evs := <-watcher.Events: jww.INFO.Println("File System Event:", evs) staticChanged := false dynamicChanged := false staticFilesChanged := make(map[string]bool) for _, ev := range evs { ext := filepath.Ext(ev.Name) istemp := strings.HasSuffix(ext, "~") || (ext == ".swp") || (ext == ".swx") || (ext == ".tmp") || strings.HasPrefix(ext, ".goutputstream") if istemp { continue } // renames are always followed with Create/Modify if ev.Op&fsnotify.Rename == fsnotify.Rename { continue } isstatic := strings.HasPrefix(ev.Name, helpers.GetStaticDirPath()) || (len(helpers.GetThemesDirPath()) > 0 && strings.HasPrefix(ev.Name, helpers.GetThemesDirPath())) staticChanged = staticChanged || isstatic dynamicChanged = dynamicChanged || !isstatic if isstatic { if staticPath, err := helpers.MakeStaticPathRelative(ev.Name); err == nil { staticFilesChanged[staticPath] = true } } // add new directory to watch list if s, err := os.Stat(ev.Name); err == nil && s.Mode().IsDir() { if ev.Op&fsnotify.Create == fsnotify.Create { watcher.Add(ev.Name) } } } if staticChanged { jww.FEEDBACK.Printf("Static file changed, syncing\n\n") utils.StopOnErr(copyStatic(), fmt.Sprintf("Error copying static files to %s", helpers.AbsPathify(viper.GetString("PublishDir")))) if !BuildWatch && !viper.GetBool("DisableLiveReload") { // Will block forever trying to write to a channel that nobody is reading if livereload isn't initalized // force refresh when more than one file if len(staticFilesChanged) == 1 { for path := range staticFilesChanged { livereload.RefreshPath(path) } } else { livereload.ForceRefresh() } } } if dynamicChanged { fmt.Print("\nChange detected, rebuilding site\n") const layout = "2006-01-02 15:04 -0700" fmt.Println(time.Now().Format(layout)) utils.CheckErr(buildSite(true)) if !BuildWatch && !viper.GetBool("DisableLiveReload") { // Will block forever trying to write to a channel that nobody is reading if livereload isn't initalized livereload.ForceRefresh() } } case err := <-watcher.Errors: if err != nil { fmt.Println("error:", err) } } } }() if port > 0 { if !viper.GetBool("DisableLiveReload") { livereload.Initialize() http.HandleFunc("/livereload.js", livereload.ServeJS) http.HandleFunc("/livereload", livereload.Handler) } go serve(port) } wg.Wait() return nil }
// InitializeConfig initializes a config file with sensible default configuration flags. func InitializeConfig() { viper.SetConfigFile(CfgFile) viper.AddConfigPath(Source) err := viper.ReadInConfig() if err != nil { jww.ERROR.Println("Unable to locate Config file. Perhaps you need to create a new site. Run `hugo help new` for details") } viper.RegisterAlias("indexes", "taxonomies") LoadDefaultSettings() if hugoCmdV.PersistentFlags().Lookup("buildDrafts").Changed { viper.Set("BuildDrafts", Draft) } if hugoCmdV.PersistentFlags().Lookup("buildFuture").Changed { viper.Set("BuildFuture", Future) } if hugoCmdV.PersistentFlags().Lookup("uglyUrls").Changed { viper.Set("UglyURLs", UglyURLs) } if hugoCmdV.PersistentFlags().Lookup("disableRSS").Changed { viper.Set("DisableRSS", DisableRSS) } if hugoCmdV.PersistentFlags().Lookup("disableSitemap").Changed { viper.Set("DisableSitemap", DisableSitemap) } if hugoCmdV.PersistentFlags().Lookup("verbose").Changed { viper.Set("Verbose", Verbose) } if hugoCmdV.PersistentFlags().Lookup("pluralizeListTitles").Changed { viper.Set("PluralizeListTitles", PluralizeListTitles) } if hugoCmdV.PersistentFlags().Lookup("preserveTaxonomyNames").Changed { viper.Set("PreserveTaxonomyNames", PreserveTaxonomyNames) } if hugoCmdV.PersistentFlags().Lookup("editor").Changed { viper.Set("NewContentEditor", Editor) } if hugoCmdV.PersistentFlags().Lookup("logFile").Changed { viper.Set("LogFile", LogFile) } if BaseURL != "" { if !strings.HasSuffix(BaseURL, "/") { BaseURL = BaseURL + "/" } viper.Set("BaseURL", BaseURL) } if !viper.GetBool("RelativeURLs") && viper.GetString("BaseURL") == "" { jww.ERROR.Println("No 'baseurl' set in configuration or as a flag. Features like page menus will not work without one.") } if Theme != "" { viper.Set("theme", Theme) } if Destination != "" { viper.Set("PublishDir", Destination) } if Source != "" { viper.Set("WorkingDir", Source) } else { dir, _ := os.Getwd() viper.Set("WorkingDir", dir) } if hugoCmdV.PersistentFlags().Lookup("ignoreCache").Changed { viper.Set("IgnoreCache", IgnoreCache) } if CacheDir != "" { if helpers.FilePathSeparator != CacheDir[len(CacheDir)-1:] { CacheDir = CacheDir + helpers.FilePathSeparator } isDir, err := helpers.DirExists(CacheDir, hugofs.SourceFs) utils.CheckErr(err) if isDir == false { mkdir(CacheDir) } viper.Set("CacheDir", CacheDir) } else { viper.Set("CacheDir", helpers.GetTempDir("hugo_cache", hugofs.SourceFs)) } if VerboseLog || Logging || (viper.IsSet("LogFile") && viper.GetString("LogFile") != "") { if viper.IsSet("LogFile") && viper.GetString("LogFile") != "" { jww.SetLogFile(viper.GetString("LogFile")) } else { jww.UseTempLogFile("hugo") } } else { jww.DiscardLogging() } if viper.GetBool("verbose") { jww.SetStdoutThreshold(jww.LevelInfo) } if VerboseLog { jww.SetLogThreshold(jww.LevelInfo) } jww.INFO.Println("Using config file:", viper.ConfigFileUsed()) themeDir := helpers.GetThemeDir() if themeDir != "" { if _, err := os.Stat(themeDir); os.IsNotExist(err) { jww.FATAL.Fatalln("Unable to find theme Directory:", themeDir) } } themeVersionMismatch, minVersion := helpers.IsThemeVsHugoVersionMismatch() if themeVersionMismatch { jww.ERROR.Printf("Current theme does not support Hugo version %s. Minimum version required is %s\n", helpers.HugoReleaseVersion(), minVersion) } }
// InitializeConfig initializes a config file with sensible default configuration flags. func InitializeConfig(subCmdVs ...*cobra.Command) error { if err := hugolib.LoadGlobalConfig(source, cfgFile); err != nil { return err } for _, cmdV := range append([]*cobra.Command{hugoCmdV}, subCmdVs...) { if flagChanged(cmdV.PersistentFlags(), "verbose") { viper.Set("verbose", verbose) } if flagChanged(cmdV.PersistentFlags(), "logFile") { viper.Set("logFile", logFile) } if flagChanged(cmdV.Flags(), "cleanDestinationDir") { viper.Set("cleanDestinationDir", cleanDestination) } if flagChanged(cmdV.Flags(), "buildDrafts") { viper.Set("buildDrafts", draft) } if flagChanged(cmdV.Flags(), "buildFuture") { viper.Set("buildFuture", future) } if flagChanged(cmdV.Flags(), "buildExpired") { viper.Set("buildExpired", expired) } if flagChanged(cmdV.Flags(), "uglyURLs") { viper.Set("uglyURLs", uglyURLs) } if flagChanged(cmdV.Flags(), "canonifyURLs") { viper.Set("canonifyURLs", canonifyURLs) } if flagChanged(cmdV.Flags(), "disable404") { viper.Set("disable404", disable404) } if flagChanged(cmdV.Flags(), "disableRSS") { viper.Set("disableRSS", disableRSS) } if flagChanged(cmdV.Flags(), "disableSitemap") { viper.Set("disableSitemap", disableSitemap) } if flagChanged(cmdV.Flags(), "enableRobotsTXT") { viper.Set("enableRobotsTXT", enableRobotsTXT) } if flagChanged(cmdV.Flags(), "pluralizeListTitles") { viper.Set("pluralizeListTitles", pluralizeListTitles) } if flagChanged(cmdV.Flags(), "preserveTaxonomyNames") { viper.Set("preserveTaxonomyNames", preserveTaxonomyNames) } 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 baseURL != "" { if !strings.HasSuffix(baseURL, "/") { baseURL = baseURL + "/" } viper.Set("baseURL", baseURL) } if !viper.GetBool("relativeURLs") && viper.GetString("baseURL") == "" { jww.ERROR.Println("No 'baseurl' set in configuration or as a flag. Features like page menus will not work without one.") } if theme != "" { viper.Set("theme", theme) } if destination != "" { viper.Set("publishDir", destination) } var dir string if source != "" { dir, _ = filepath.Abs(source) } else { dir, _ = os.Getwd() } viper.Set("workingDir", dir) if contentDir != "" { viper.Set("contentDir", contentDir) } if layoutDir != "" { viper.Set("layoutDir", layoutDir) } if cacheDir != "" { viper.Set("cacheDir", cacheDir) } cacheDir = viper.GetString("cacheDir") if cacheDir != "" { if helpers.FilePathSeparator != cacheDir[len(cacheDir)-1:] { cacheDir = cacheDir + helpers.FilePathSeparator } isDir, err := helpers.DirExists(cacheDir, hugofs.Source()) utils.CheckErr(err) if isDir == false { mkdir(cacheDir) } viper.Set("cacheDir", cacheDir) } else { viper.Set("cacheDir", helpers.GetTempDir("hugo_cache", hugofs.Source())) } if verboseLog || logging || (viper.IsSet("logFile") && viper.GetString("logFile") != "") { if viper.IsSet("logFile") && viper.GetString("logFile") != "" { jww.SetLogFile(viper.GetString("logFile")) } else { jww.UseTempLogFile("hugo") } } else { jww.DiscardLogging() } if quiet { jww.SetStdoutThreshold(jww.LevelError) } else if viper.GetBool("verbose") { jww.SetStdoutThreshold(jww.LevelInfo) } if verboseLog { jww.SetLogThreshold(jww.LevelInfo) } jww.INFO.Println("Using config file:", viper.ConfigFileUsed()) // Init file systems. This may be changed at a later point. hugofs.InitDefaultFs() themeDir := helpers.GetThemeDir() if themeDir != "" { if _, err := hugofs.Source().Stat(themeDir); os.IsNotExist(err) { return newSystemError("Unable to find theme Directory:", themeDir) } } themeVersionMismatch, minVersion := isThemeVsHugoVersionMismatch() if themeVersionMismatch { jww.ERROR.Printf("Current theme does not support Hugo version %s. Minimum version required is %s\n", helpers.HugoReleaseVersion(), minVersion) } return nil }
func NewWatcher(port int) error { if runtime.GOOS == "darwin" { tweakLimit() } watcher, err := watcher.New(1 * time.Second) var wg sync.WaitGroup if err != nil { fmt.Println(err) return err } defer watcher.Close() wg.Add(1) for _, d := range getDirList() { if d != "" { _ = watcher.Watch(d) } } go func() { for { select { case evs := <-watcher.Event: if Verbose { fmt.Println(evs) } static_changed := false dynamic_changed := false for _, ev := range evs { ext := filepath.Ext(ev.Name) istemp := strings.HasSuffix(ext, "~") || (ext == ".swp") || (ext == ".tmp") if istemp { continue } // renames are always followed with Create/Modify if ev.IsRename() { continue } isstatic := strings.HasPrefix(ev.Name, Config.GetAbsPath(Config.StaticDir)) static_changed = static_changed || isstatic dynamic_changed = dynamic_changed || !isstatic // add new directory to watch list if s, err := os.Stat(ev.Name); err == nil && s.Mode().IsDir() { if ev.IsCreate() { watcher.Watch(ev.Name) } } } if static_changed { fmt.Print("Static file changed, syncing\n\n") utils.CheckErr(copyStatic(), fmt.Sprintf("Error copying static files to %s", Config.GetAbsPath(Config.PublishDir))) } if dynamic_changed { fmt.Print("Change detected, rebuilding site\n\n") utils.StopOnErr(buildSite(true)) } case err := <-watcher.Error: if err != nil { fmt.Println("error:", err) } } } }() if port > 0 { go serve(port) } wg.Wait() return nil }
// InitializeConfig initializes a config file with sensible default configuration flags. func InitializeConfig() { viper.SetConfigFile(CfgFile) viper.AddConfigPath(Source) err := viper.ReadInConfig() if err != nil { jww.ERROR.Println("Unable to locate Config file. Perhaps you need to create a new site. Run `hugo help new` for details") } viper.RegisterAlias("indexes", "taxonomies") viper.SetDefault("Watch", false) viper.SetDefault("MetaDataFormat", "toml") viper.SetDefault("DisableRSS", false) viper.SetDefault("DisableSitemap", false) viper.SetDefault("ContentDir", "content") viper.SetDefault("LayoutDir", "layouts") viper.SetDefault("StaticDir", "static") viper.SetDefault("ArchetypeDir", "archetypes") viper.SetDefault("PublishDir", "public") viper.SetDefault("DataDir", "data") viper.SetDefault("DefaultLayout", "post") viper.SetDefault("BuildDrafts", false) viper.SetDefault("BuildFuture", false) viper.SetDefault("UglyURLs", false) viper.SetDefault("Verbose", false) viper.SetDefault("IgnoreCache", false) viper.SetDefault("CanonifyURLs", false) viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"}) viper.SetDefault("Permalinks", make(hugolib.PermalinkOverrides, 0)) viper.SetDefault("Sitemap", hugolib.Sitemap{Priority: -1}) viper.SetDefault("PygmentsStyle", "monokai") viper.SetDefault("DefaultExtension", "html") viper.SetDefault("PygmentsUseClasses", false) viper.SetDefault("DisableLiveReload", false) viper.SetDefault("PluralizeListTitles", true) viper.SetDefault("FootnoteAnchorPrefix", "") viper.SetDefault("FootnoteReturnLinkContents", "") viper.SetDefault("NewContentEditor", "") viper.SetDefault("Paginate", 10) viper.SetDefault("PaginatePath", "page") viper.SetDefault("Blackfriday", helpers.NewBlackfriday()) if hugoCmdV.PersistentFlags().Lookup("buildDrafts").Changed { viper.Set("BuildDrafts", Draft) } if hugoCmdV.PersistentFlags().Lookup("buildFuture").Changed { viper.Set("BuildFuture", Future) } if hugoCmdV.PersistentFlags().Lookup("uglyUrls").Changed { viper.Set("UglyURLs", UglyURLs) } if hugoCmdV.PersistentFlags().Lookup("disableRSS").Changed { viper.Set("DisableRSS", DisableRSS) } if hugoCmdV.PersistentFlags().Lookup("disableSitemap").Changed { viper.Set("DisableSitemap", DisableSitemap) } if hugoCmdV.PersistentFlags().Lookup("verbose").Changed { viper.Set("Verbose", Verbose) } if hugoCmdV.PersistentFlags().Lookup("pluralizeListTitles").Changed { viper.Set("PluralizeListTitles", PluralizeListTitles) } if hugoCmdV.PersistentFlags().Lookup("editor").Changed { viper.Set("NewContentEditor", Editor) } if hugoCmdV.PersistentFlags().Lookup("logFile").Changed { viper.Set("LogFile", LogFile) } if BaseURL != "" { if !strings.HasSuffix(BaseURL, "/") { BaseURL = BaseURL + "/" } viper.Set("BaseURL", BaseURL) } if viper.GetString("BaseURL") == "" { jww.ERROR.Println("No 'baseurl' set in configuration or as a flag. Features like page menus will not work without one.") } if Theme != "" { viper.Set("theme", Theme) } if Destination != "" { viper.Set("PublishDir", Destination) } if Source != "" { viper.Set("WorkingDir", Source) } else { dir, _ := os.Getwd() viper.Set("WorkingDir", dir) } if hugoCmdV.PersistentFlags().Lookup("ignoreCache").Changed { viper.Set("IgnoreCache", IgnoreCache) } if CacheDir != "" { if helpers.FilePathSeparator != CacheDir[len(CacheDir)-1:] { CacheDir = CacheDir + helpers.FilePathSeparator } isDir, err := helpers.DirExists(CacheDir, hugofs.SourceFs) utils.CheckErr(err) if isDir == false { mkdir(CacheDir) } viper.Set("CacheDir", CacheDir) } else { viper.Set("CacheDir", helpers.GetTempDir("hugo_cache", hugofs.SourceFs)) } if VerboseLog || Logging || (viper.IsSet("LogFile") && viper.GetString("LogFile") != "") { if viper.IsSet("LogFile") && viper.GetString("LogFile") != "" { jww.SetLogFile(viper.GetString("LogFile")) } else { jww.UseTempLogFile("hugo") } } else { jww.DiscardLogging() } if viper.GetBool("verbose") { jww.SetStdoutThreshold(jww.LevelInfo) } if VerboseLog { jww.SetLogThreshold(jww.LevelInfo) } jww.INFO.Println("Using config file:", viper.ConfigFileUsed()) }
// NewWatcher creates a new watcher to watch filesystem events. func NewWatcher(port int) error { if runtime.GOOS == "darwin" { tweakLimit() } watcher, err := watcher.New(1 * time.Second) var wg sync.WaitGroup if err != nil { return err } defer watcher.Close() wg.Add(1) for _, d := range getDirList() { if d != "" { _ = watcher.Add(d) } } go func() { for { select { case evs := <-watcher.Events: jww.INFO.Println("File System Event:", evs) staticChanged := false dynamicChanged := false staticFilesChanged := make(map[string]bool) for _, ev := range evs { ext := filepath.Ext(ev.Name) istemp := strings.HasSuffix(ext, "~") || (ext == ".swp") || (ext == ".swx") || (ext == ".tmp") || strings.HasPrefix(ext, ".goutputstream") || strings.HasSuffix(ext, "jb_old___") || strings.HasSuffix(ext, "jb_bak___") if istemp { continue } // renames are always followed with Create/Modify if ev.Op&fsnotify.Rename == fsnotify.Rename { continue } // Write and rename operations are often followed by CHMOD. // There may be valid use cases for rebuilding the site on CHMOD, // but that will require more complex logic than this simple conditional. // On OS X this seems to be related to Spotlight, see: // https://github.com/go-fsnotify/fsnotify/issues/15 // A workaround is to put your site(s) on the Spotlight exception list, // but that may be a little mysterious for most end users. // So, for now, we skip reload on CHMOD. if ev.Op&fsnotify.Chmod == fsnotify.Chmod { continue } isstatic := strings.HasPrefix(ev.Name, helpers.GetStaticDirPath()) || (len(helpers.GetThemesDirPath()) > 0 && strings.HasPrefix(ev.Name, helpers.GetThemesDirPath())) staticChanged = staticChanged || isstatic dynamicChanged = dynamicChanged || !isstatic if isstatic { staticFilesChanged[ev.Name] = true } // add new directory to watch list if s, err := os.Stat(ev.Name); err == nil && s.Mode().IsDir() { if ev.Op&fsnotify.Create == fsnotify.Create { watcher.Add(ev.Name) } } } if staticChanged { jww.FEEDBACK.Printf("Static file changed, syncing\n") if viper.GetBool("ForceSyncStatic") { jww.FEEDBACK.Printf("Syncing all static files\n") err := copyStatic() if err != nil { fmt.Println(err) utils.StopOnErr(err, fmt.Sprintf("Error copying static files to %s", helpers.AbsPathify(viper.GetString("PublishDir")))) } } else { syncer := fsync.NewSyncer() syncer.NoTimes = viper.GetBool("notimes") syncer.SrcFs = hugofs.SourceFs syncer.DestFs = hugofs.DestinationFS publishDir := helpers.AbsPathify(viper.GetString("PublishDir")) + helpers.FilePathSeparator if publishDir == "//" || publishDir == helpers.FilePathSeparator { publishDir = "" } staticDir := helpers.GetStaticDirPath() themeStaticDir := helpers.GetThemesDirPath() jww.FEEDBACK.Printf("StaticDir '%s'\nThemeStaticDir '%s'\n", staticDir, themeStaticDir) for path := range staticFilesChanged { var publishPath string if strings.HasPrefix(path, staticDir) { publishPath = filepath.Join(publishDir, strings.TrimPrefix(path, staticDir)) } else if strings.HasPrefix(path, themeStaticDir) { publishPath = filepath.Join(publishDir, strings.TrimPrefix(path, themeStaticDir)) } jww.FEEDBACK.Printf("Syncing file '%s'", path) if _, err := os.Stat(path); err == nil { jww.INFO.Println("syncing from ", path, " to ", publishPath) err := syncer.Sync(publishPath, path) if err != nil { jww.FEEDBACK.Printf("Error on syncing file '%s'\n", path) } } } } if !BuildWatch && !viper.GetBool("DisableLiveReload") { // Will block forever trying to write to a channel that nobody is reading if livereload isn't initalized // force refresh when more than one file if len(staticFilesChanged) == 1 { for path := range staticFilesChanged { livereload.RefreshPath(path) } } else { livereload.ForceRefresh() } } } if dynamicChanged { fmt.Print("\nChange detected, rebuilding site\n") const layout = "2006-01-02 15:04 -0700" fmt.Println(time.Now().Format(layout)) utils.CheckErr(buildSite(true)) if !BuildWatch && !viper.GetBool("DisableLiveReload") { // Will block forever trying to write to a channel that nobody is reading if livereload isn't initalized livereload.ForceRefresh() } } case err := <-watcher.Errors: if err != nil { fmt.Println("error:", err) } } } }() if port > 0 { if !viper.GetBool("DisableLiveReload") { livereload.Initialize() http.HandleFunc("/livereload.js", livereload.ServeJS) http.HandleFunc("/livereload", livereload.Handler) } go serve(port) } wg.Wait() return nil }