-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwatchfile.go
87 lines (76 loc) · 2.01 KB
/
watchfile.go
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
package args
import (
"time"
"sync"
"github.com/fsnotify/fsnotify"
)
func WatchFile(path string, interval time.Duration, callBack func(error)) (WatchCancelFunc, error) {
var isRunning sync.WaitGroup
fsWatch, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}
if err := fsWatch.Add(path); err != nil {
return nil, err
}
// Check for write events at this interval
tick := time.Tick(interval)
done := make(chan struct{}, 1)
once := sync.Once{}
isRunning.Add(1)
go func() {
var lastWriteEvent *fsnotify.Event
var checkFile *fsnotify.Event
for {
once.Do(func() { isRunning.Done() }) // Notify we are watching
select {
case event := <-fsWatch.Events:
//fmt.Printf("Event %s\n", event.String())
// If it was a write event
if event.Op&fsnotify.Write == fsnotify.Write {
lastWriteEvent = &event
}
// VIM apparently renames a file before writing
if event.Op&fsnotify.Rename == fsnotify.Rename {
checkFile = &event
}
// If we see a Remove event, This is probably ConfigMap updating the config symlink
if event.Op&fsnotify.Remove == fsnotify.Remove {
checkFile = &event
}
case <-tick:
// If the file was renamed or removed; maybe it re-appears after our duration?
if checkFile != nil {
// Since the file was removed, we must
// re-register the file to be watched
fsWatch.Remove(checkFile.Name)
if err := fsWatch.Add(checkFile.Name); err != nil {
// Nothing left to watch
callBack(err)
return
}
lastWriteEvent = checkFile
checkFile = nil
continue
}
// No events during this interval
if lastWriteEvent == nil {
continue
}
// Execute the callback
callBack(nil)
// Reset the last event
lastWriteEvent = nil
case <-done:
return
}
}
}()
// Wait until the go-routine is running before we return, this ensures we
// pickup any file changes after we leave this function
isRunning.Wait()
return func() {
close(done)
fsWatch.Close()
}, err
}