-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathwatch.go
More file actions
110 lines (96 loc) · 2.44 KB
/
Copy pathwatch.go
File metadata and controls
110 lines (96 loc) · 2.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package reload
import (
"errors"
"io/fs"
"path"
"path/filepath"
"strings"
"time"
"github.com/bep/debounce"
"github.com/fsnotify/fsnotify"
)
// WatchDirectories listens for changes in directories and
// broadcasts on write.
func (reload *Reloader) WatchDirectories() {
if len(reload.directories) == 0 {
reload.logError("no directories provided (reload.Directories is empty)\n")
return
}
w, err := fsnotify.NewWatcher()
if err != nil {
reload.logError("error initializing fsnotify watcher: %s\n", err)
}
defer w.Close()
for _, path := range reload.directories {
directories, err := recursiveWalk(path)
if err != nil {
var pathErr *fs.PathError
if errors.As(err, &pathErr) {
reload.logError("directory doesn't exist: %s\n", pathErr.Path)
} else {
reload.logError("error walking directories: %s\n", err)
}
return
}
for _, dir := range directories {
// Path is converted to absolute path, so that fsnotify.Event also contains
// absolute paths
absPath, err := filepath.Abs(dir)
if err != nil {
reload.logError("Failed to convert path to absolute path: %s\n", err)
continue
}
w.Add(absPath)
}
}
reload.logDebug("watching %s for changes\n", strings.Join(reload.directories, ","))
debounce := debounce.New(100 * time.Millisecond)
callback := func(path string) func() {
return func() {
reload.logDebug("Edit %s\n", path)
if reload.OnReload != nil {
reload.OnReload()
}
reload.cond.Broadcast()
}
}
for {
select {
case err := <-w.Errors:
reload.logError("error watching: %s \n", err)
case e := <-w.Events:
switch {
case e.Has(fsnotify.Create):
dir := filepath.Dir(e.Name)
// Watch any created directory
if err := w.Add(dir); err != nil {
reload.logError("error watching %s: %s\n", e.Name, err)
continue
}
debounce(callback(path.Base(e.Name)))
case e.Has(fsnotify.Write):
debounce(callback(path.Base(e.Name)))
case e.Has(fsnotify.Rename), e.Has(fsnotify.Remove):
// a renamed file might be outside the specified paths
directories, _ := recursiveWalk(e.Name)
for _, v := range directories {
w.Remove(v)
}
w.Remove(e.Name)
}
}
}
}
func recursiveWalk(path string) ([]string, error) {
var res []string
err := filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
res = append(res, path)
}
return nil
})
return res, err
}