Initial commit
This commit is contained in:
+75
@@ -0,0 +1,75 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
type Watcher struct {
|
||||
w *fsnotify.Watcher
|
||||
g *Generator
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
func NewWatcher(dir string, g *Generator) (*Watcher, error) {
|
||||
w, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := w.Add(dir); err != nil {
|
||||
w.Close()
|
||||
return nil, err
|
||||
}
|
||||
return &Watcher{w: w, g: g, done: make(chan struct{})}, nil
|
||||
}
|
||||
|
||||
// Watch blocks, watching for changes and triggering rebuilds.
|
||||
// Rapid events (e.g. scp writing an image then its sidecar) are debounced
|
||||
// with a 500 ms window so only one rebuild fires per logical upload.
|
||||
func (w *Watcher) Watch() {
|
||||
var timer *time.Timer
|
||||
rebuild := func() {
|
||||
if err := w.g.Build(); err != nil {
|
||||
log.Printf("rebuild: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-w.w.Events:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if !isRelevant(event.Name) {
|
||||
continue
|
||||
}
|
||||
if event.Has(fsnotify.Create) || event.Has(fsnotify.Write) || event.Has(fsnotify.Remove) {
|
||||
if timer != nil {
|
||||
timer.Stop()
|
||||
}
|
||||
timer = time.AfterFunc(500*time.Millisecond, rebuild)
|
||||
}
|
||||
case err, ok := <-w.w.Errors:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
log.Printf("watcher: %v", err)
|
||||
case <-w.done:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Watcher) Close() {
|
||||
close(w.done)
|
||||
w.w.Close()
|
||||
}
|
||||
|
||||
func isRelevant(name string) bool {
|
||||
ext := strings.ToLower(filepath.Ext(name))
|
||||
return ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".toml"
|
||||
}
|
||||
Reference in New Issue
Block a user