forked from adamveld12/gowatch
/
main.go
143 lines (115 loc) · 3.6 KB
/
main.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package main
import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"time"
gwl "github.com/adamveld12/gowatch/log"
"github.com/adamveld12/gowatch/project"
"github.com/adamveld12/gowatch/watch"
"github.com/fatih/color"
"github.com/hashicorp/logutils"
)
var (
debug = flag.Bool("debug", false, "")
wait = flag.Duration("wait", time.Second*2, "")
ignore = flag.String("ignore", ".git/*,node_modules/*", "")
restartOnExit = flag.Bool("onexit", true, "")
restartOnError = flag.Bool("onerror", true, "")
appArgs = flag.String("args", "", "")
shouldTest = flag.Bool("test", true, "")
shouldLint = flag.Bool("lint", true, "")
)
func init() {
flag.Usage = func() {
fmt.Printf("%s options\n%s\n", os.Args[0], strings.Join([]string{
color.GreenString(" -args") + "=\"\": arguments to pass to the underlying app",
color.GreenString(" -debug") + "=false: enabled debug print statements",
color.GreenString(" -ignore") + "=\".git/*,node_modules/*\": comma delimited paths to ignore in the file watcher",
color.GreenString(" -lint") + "=true: run go lint on reload",
color.GreenString(" -onerror") + "=true: If the app should restart if a lint/test/build/non-zero exit code occurs",
color.GreenString(" -onexit") + "=true: If the app sould restart on exit, regardless of exit code",
color.GreenString(" -test") + "=true: run go test on reload",
color.GreenString(" -wait") + "=2s: # seconds to wait before restarting",
}, "\n"))
}
}
func main() {
flag.Parse()
setupLogging()
projectPath := getAbsPathToProject()
gwl.LogDebug("watching", projectPath)
handleWatch(projectPath, setupIgnorePaths(projectPath))
}
func handleWatch(projectPath string, ignorePaths []string) {
watchHandle := watch.StartWatch(projectPath, ignorePaths)
for {
gwl.LogDebug("---Starting app monitor---")
time.Sleep(*wait)
execHandle := project.ExecuteBuildSteps(projectPath, *appArgs, *shouldTest, *shouldLint)
gwl.LogDebug("---Setting up watch cb---")
watchHandle.Subscribe(func(fileName string) {
if !execHandle.Halted() {
gwl.LogError("attempting to kill process")
execHandle.Kill(nil)
gwl.LogDebug("exiting file watch routine in main")
}
})
gwl.LogDebug("waiting on app to exit")
err := execHandle.Error()
gwl.LogDebug("---App exited---")
watchHandle.Subscribe(nil)
exitedSuccessfully := err == nil || err == project.ErrorAppKilled
if exitedSuccessfully {
color.Green("exited successfully\n")
} else {
color.Red("%s\n", err.Error())
}
sync := make(chan bool)
if (!exitedSuccessfully && !*restartOnError) || (!*restartOnExit && err != project.ErrorAppKilled) {
watchHandle.Subscribe(func(fileName string) {
close(sync)
watchHandle.Subscribe(nil)
})
gwl.LogDebug("waiting on file notification")
<-sync
}
}
}
func getAbsPathToProject() string {
pwd := "."
if flag.Arg(0) != "" {
pwd = flag.Arg(0)
}
directoryPath, err := filepath.Abs(pwd)
if err != nil {
log.Fatal("[ERROR]", err)
}
return directoryPath
}
func setupLogging() {
minLevel := logutils.LogLevel("ERROR")
if *debug {
minLevel = logutils.LogLevel("DEBUG")
}
filter := &logutils.LevelFilter{
Levels: []logutils.LogLevel{"DEBUG", "INFO", "ERROR"},
MinLevel: minLevel,
Writer: os.Stderr,
}
log.SetOutput(filter)
}
func setupIgnorePaths(root string) []string {
gwl.LogDebug("Ignore globs.")
paths := strings.Split(*ignore, ",")
expandedPaths := []string{}
for _, path := range paths {
abs := filepath.Join(root, path)
gwl.LogDebug("\t%s\n", abs)
expandedPaths = append(expandedPaths, abs)
}
return expandedPaths
}