diff options
-rw-r--r-- | commands/hugo.go | 78 | ||||
-rw-r--r-- | watcher/batcher.go | 56 |
2 files changed, 103 insertions, 31 deletions
diff --git a/commands/hugo.go b/commands/hugo.go index 8cfbc734f..ee1d6f27a 100644 --- a/commands/hugo.go +++ b/commands/hugo.go @@ -15,11 +15,11 @@ package commands 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 buildSite(watching ...bool) (err error) { } 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 @@ func NewWatcher(port int) error { 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) @@ -183,12 +224,6 @@ func NewWatcher(port int) error { } }() - for _, d := range getDirList() { - if d != "" { - _ = watcher.Watch(d) - } - } - if port > 0 { go serve(port) } @@ -196,22 +231,3 @@ func NewWatcher(port int) error { 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)) - } - } -} diff --git a/watcher/batcher.go b/watcher/batcher.go new file mode 100644 index 000000000..a22ad8b41 --- /dev/null +++ b/watcher/batcher.go @@ -0,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()
+}
|