ref: 8d80f9b39e42dd5b61af052979a7c04dc8edf851
parent: 1979f7d9c7d047340c9205f0d3e6d8393d498f9c
author: Egon Elbre <egonelbre@gmail.com>
date: Sun Dec 15 12:19:22 EST 2013
Added batching behavior for page building. Quite often file watcher gets many changes and each change triggered a build. One build per second should be sufficient. Also added tracking for new folders.
--- a/commands/hugo.go
+++ b/commands/hugo.go
@@ -15,11 +15,11 @@
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"
@@ -155,7 +155,7 @@
}
func NewWatcher(port int) error {- watcher, err := fsnotify.NewWatcher()
+ watcher, err := watcher.New(1 * time.Second)
var wg sync.WaitGroup
if err != nil {@@ -166,15 +166,56 @@
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)
}
- watchChange(ev)
- // TODO add newly created directories to the watch list
+
+ 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))
+ }
case err := <-watcher.Error:
if err != nil { fmt.Println("error:", err)@@ -183,12 +224,6 @@
}
}()
- for _, d := range getDirList() {- if d != "" {- _ = watcher.Watch(d)
- }
- }
-
if port > 0 {go serve(port)
}
@@ -195,23 +230,4 @@
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
+++ b/watcher/batcher.go
@@ -1,0 +1,56 @@
+package watcher
+
+import (
+ "github.com/howeyc/fsnotify"
+ "time"
+)
+
+type Batcher struct {
+ *fsnotify.Watcher
+ interval time.Duration
+ done chan struct{}
+
+ Event chan []*fsnotify.FileEvent // Events are returned on this channel
+}
+
+func New(interval time.Duration) (*Batcher, error) {
+ watcher, err := fsnotify.NewWatcher()
+
+ batcher := &Batcher{}
+ batcher.Watcher = watcher
+ batcher.interval = interval
+ batcher.done = make(chan struct{}, 1)
+ batcher.Event = make(chan []*fsnotify.FileEvent, 1)
+
+ if err == nil {
+ go batcher.run()
+ }
+
+ return batcher, err
+}
+
+func (b *Batcher) run() {
+ tick := time.Tick(b.interval)
+ evs := make([]*fsnotify.FileEvent, 0)
+OuterLoop:
+ for {
+ select {
+ case ev := <-b.Watcher.Event:
+ evs = append(evs, ev)
+ case <-tick:
+ if len(evs) == 0 {
+ continue
+ }
+ b.Event <- evs
+ evs = make([]*fsnotify.FileEvent, 0)
+ case <-b.done:
+ break OuterLoop
+ }
+ }
+ close(b.done)
+}
+
+func (b *Batcher) Close() {
+ b.done <- struct{}{}
+ b.Watcher.Close()
+}
--
⑨