-
-
Notifications
You must be signed in to change notification settings - Fork 171
/
filewatch.go
99 lines (82 loc) · 2.05 KB
/
filewatch.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
88
89
90
91
92
93
94
95
96
97
98
99
package serv
import (
"fmt"
"os"
"path"
"path/filepath"
"syscall"
"time"
"github.com/fsnotify/fsnotify"
"github.com/kardianos/osext"
"github.com/pkg/errors"
)
func startConfigWatcher(s1 *Service) error {
var watcher *fsnotify.Watcher
var err error
binary, err := osext.Executable()
if err != nil {
return err
}
var paths []string
if s1.cpath == "" || s1.cpath == "./" {
paths = []string{"./config"}
} else {
paths = []string{s1.cpath}
}
if watcher, err = fsnotify.NewWatcher(); err != nil {
return fmt.Errorf("cannot setup watcher: %w", err)
}
defer watcher.Close() // nolint: errcheck
var dirs []string
for _, p := range paths {
path, err := filepath.Abs(p)
if err != nil {
return fmt.Errorf("cannot get absolute path to %q: %w", p, err)
}
s, err := os.Stat(path)
if err != nil {
return errors.Wrap(err, "os.Stat")
}
if !s.IsDir() {
return fmt.Errorf("not a directory: %q; can only watch directories", p)
}
dirs = append(dirs, path)
}
for _, d := range dirs {
if err := watcher.Add(d); err != nil {
return fmt.Errorf("cannot add %q to watcher: %w", d, err)
}
}
for {
s := s1.Load().(*service)
select {
case err := <-watcher.Errors:
// Standard logger doesn't have anything other than Print,
// Panic, and Fatal :-/ Printf() is probably best.
s.log.Infof("reload error: %v", err)
case event := <-watcher.Events:
// Ensure that we use the correct events, as they are not uniform across
// platforms. See https://github.com/fsnotify/fsnotify/issues/74
if s.conf == nil {
continue
}
ext := path.Ext(event.Name)
if ext != ".json" && ext != ".toml" && ext != ".yaml" && ext != ".yml" {
continue
}
if s.conf.Serv.Production {
continue
}
if event.Op != fsnotify.Create && event.Op != fsnotify.Write {
continue
}
// Wait for writes to finish.
s.log.Infof("reloading, config file changed: %s", event.Name)
time.Sleep(500 * time.Millisecond)
err := syscall.Exec(binary, os.Args, os.Environ())
if err != nil {
s.log.Fatal(err)
}
}
}
}