import (
"fmt"
- "github.com/howeyc/fsnotify"
"github.com/mostafah/fsync"
"github.com/spf13/cobra"
"github.com/spf13/hugo/hugolib"
"github.com/spf13/hugo/utils"
+ "github.com/spf13/hugo/watcher"
"github.com/spf13/nitro"
"os"
"path/filepath"
}
func NewWatcher(port int) error {
- watcher, err := fsnotify.NewWatcher()
+ watcher, err := watcher.New(1 * time.Second)
var wg sync.WaitGroup
if err != nil {
defer watcher.Close()
wg.Add(1)
+
+ for _, d := range getDirList() {
+ if d != "" {
+ _ = watcher.Watch(d)
+ }
+ }
+
go func() {
for {
select {
- case ev := <-watcher.Event:
+ case evs := <-watcher.Event:
if Verbose {
- fmt.Println(ev)
+ 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.Println("Static file changed, syncing\n")
+ utils.CheckErr(copyStatic(), fmt.Sprintf("Error copying static files to %s", Config.GetAbsPath(Config.PublishDir)))
+ }
+
+ if dynamic_changed {
+ fmt.Println("Change detected, rebuilding site\n")
+ utils.StopOnErr(buildSite(true))
}
- watchChange(ev)
- // TODO add newly created directories to the watch list
case err := <-watcher.Error:
if err != nil {
fmt.Println("error:", err)
}
}()
- for _, d := range getDirList() {
- if d != "" {
- _ = watcher.Watch(d)
- }
- }
-
if port > 0 {
go serve(port)
}
wg.Wait()
return nil
}
-
-func watchChange(ev *fsnotify.FileEvent) {
- ext := filepath.Ext(ev.Name)
- // ignore temp files
- istemp := strings.HasSuffix(ext, "~") || (ext == ".swp") || (ext == ".tmp")
- if istemp {
- return
- }
-
- 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
- fmt.Println("Change detected, rebuilding site\n")
- utils.StopOnErr(buildSite(true))
- }
- }
-}
--- /dev/null
+package watcher\r
+\r
+import (\r
+ "github.com/howeyc/fsnotify"\r
+ "time"\r
+)\r
+\r
+type Batcher struct {\r
+ *fsnotify.Watcher\r
+ interval time.Duration\r
+ done chan struct{}\r
+\r
+ Event chan []*fsnotify.FileEvent // Events are returned on this channel\r
+}\r
+\r
+func New(interval time.Duration) (*Batcher, error) {\r
+ watcher, err := fsnotify.NewWatcher()\r
+\r
+ batcher := &Batcher{}\r
+ batcher.Watcher = watcher\r
+ batcher.interval = interval\r
+ batcher.done = make(chan struct{}, 1)\r
+ batcher.Event = make(chan []*fsnotify.FileEvent, 1)\r
+\r
+ if err == nil {\r
+ go batcher.run()\r
+ }\r
+\r
+ return batcher, err\r
+}\r
+\r
+func (b *Batcher) run() {\r
+ tick := time.Tick(b.interval)\r
+ evs := make([]*fsnotify.FileEvent, 0)\r
+OuterLoop:\r
+ for {\r
+ select {\r
+ case ev := <-b.Watcher.Event:\r
+ evs = append(evs, ev)\r
+ case <-tick:\r
+ if len(evs) == 0 {\r
+ continue\r
+ }\r
+ b.Event <- evs\r
+ evs = make([]*fsnotify.FileEvent, 0)\r
+ case <-b.done:\r
+ break OuterLoop\r
+ }\r
+ }\r
+ close(b.done)\r
+}\r
+\r
+func (b *Batcher) Close() {\r
+ b.done <- struct{}{}\r
+ b.Watcher.Close()\r
+}\r