diff --git a/README.md b/README.md index 045dce2..30e1efb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Liver -A recursive file watcher that works by attaching itself to processes +A dead simple recursive file watcher that works by attaching itself to processes ## Installation diff --git a/internal/process/manager.go b/internal/process/manager.go index 6dc139f..de04d16 100644 --- a/internal/process/manager.go +++ b/internal/process/manager.go @@ -1,111 +1,74 @@ package process import ( - "fmt" "log" "strings" "sync" ) type ProcessManager struct { - root *trie - procs []*process + procs map[string][]*process mu *sync.Mutex } func NewProcessManager() *ProcessManager { - rootNode := &trieNode{ - children: make(map[string]*trieNode), - } - - rootNode.children["/"] = newNode() - return &ProcessManager{ - root: &trie{ - node: rootNode, - }, - procs: make([]*process, 0), + procs: make(map[string][]*process), mu: &sync.Mutex{}, } } -func (pm *ProcessManager) Add(path, command string) error { +func (pm *ProcessManager) Add(path, command string) { p := newProcess(command) - chars := strings.Split(path, "") - if chars[0] != "/" { - return fmt.Errorf("expected UNIX filesystem absolute path starting with '/', got %s", path) + if _, ok := pm.procs[path]; !ok { + pm.procs[path] = make([]*process, 0) } - chars = chars[1:] - - curr := pm.root.node - - for _, c := range chars { - if _, ok := curr.children[c]; !ok { - curr.children[c] = newNode() - } - - curr = curr.children[c] - } - - curr.proc = p - - pm.procs = append(pm.procs, p) - - return nil + pm.procs[path] = append(pm.procs[path], p) } -func (pm *ProcessManager) Start() error { +func (pm *ProcessManager) StartAll() error { pm.mu.Lock() defer pm.mu.Unlock() - for _, p := range pm.procs { - err := p.start() - if err != nil { - return err + for _, procs := range pm.procs { + for _, p := range procs { + err := p.Start() + if err != nil { + return err + } } } return nil } -func (pm *ProcessManager) Stop() error { +func (pm *ProcessManager) StopAll() error { pm.mu.Lock() defer pm.mu.Unlock() - for _, p := range pm.procs { - err := p.kill() - if err != nil { - log.Println(err) + for _, procs := range pm.procs { + for _, p := range procs { + err := p.Kill() + if err != nil { + log.Println(err) + } } } return nil } -func (pm *ProcessManager) Valid(path string) bool { - chars := strings.Split(path, "") - - if chars[0] != "/" { - return false - } - - chars = chars[1:] - - curr := pm.root.node - - for _, c := range chars { - if curr.isLeaf() { - return true - } +func (pm *ProcessManager) GetProcs(path string) []*process { + pm.mu.Lock() + defer pm.mu.Unlock() - if _, ok := curr.children[c]; !ok { - return false + for procPath, procs := range pm.procs { + if strings.HasPrefix(path, procPath) { + return procs } - - curr = curr.children[c] } - return curr.isLeaf() + return []*process{} } diff --git a/internal/process/process.go b/internal/process/process.go index 580e8c8..6816aea 100644 --- a/internal/process/process.go +++ b/internal/process/process.go @@ -23,7 +23,7 @@ func newProcess(command string) *process { } } -func (p *process) start() error { +func (p *process) Start() error { if p == nil { return nil } @@ -41,7 +41,7 @@ func (p *process) start() error { return p.internalProcessCmd.Start() } -func (p *process) kill() error { +func (p *process) Kill() error { if p == nil || p.internalProcessCmd == nil || p.internalProcessCmd.Process == nil { return nil } diff --git a/internal/process/trie.go b/internal/process/trie.go deleted file mode 100644 index 1b8c645..0000000 --- a/internal/process/trie.go +++ /dev/null @@ -1,20 +0,0 @@ -package process - -type trieNode struct { - children map[string]*trieNode - proc *process -} - -type trie struct { - node *trieNode -} - -func newNode() *trieNode { - return &trieNode{ - children: make(map[string]*trieNode), - } -} - -func (n *trieNode) isLeaf() bool { - return n.proc != nil -} diff --git a/main.go b/main.go index 98d54f2..574af0e 100644 --- a/main.go +++ b/main.go @@ -56,10 +56,7 @@ func main() { for path, commands := range c.Procs { for _, c := range commands { - err = pm.Add(path, c) - if err != nil { - log.Fatalf("error adding process for path %s: %v\n", path, err) - } + pm.Add(path, c) } } @@ -77,7 +74,7 @@ func main() { log.Println("starting all processes") - err := pm.Start() + err := pm.StartAll() if err != nil { log.Fatalf("error starting processes: %v\n", err) sig <- os.Interrupt @@ -92,7 +89,10 @@ func main() { if !ok { sig <- os.Interrupt return - } else if !pm.Valid(event.Name) { + } + + procs := pm.GetProcs(event.Name) + if len(procs) == 0 { continue } @@ -102,21 +102,25 @@ func main() { if !ok { t = time.AfterFunc(math.MaxInt64, func() { - log.Println("stopping all processes") + log.Println("stopping processes") - err := pm.Stop() - if err != nil { - log.Fatalf("error stopping processes: %v\n", err) + for _, p := range procs { + err := p.Kill() + if err != nil { + log.Fatalf("error stopping processes: %v\n", err) + } } - log.Println("restarting all processes") + log.Println("restarting processes") - err = pm.Start() - if err != nil { - log.Fatalf("error starting processes: %v\n", err) + for _, p := range procs { + err = p.Start() + if err != nil { + log.Fatalf("error starting processes: %v\n", err) + } } - log.Println("restarted all processes") + log.Println("restarted processes") mu.Lock() delete(timers, event.Name) @@ -145,7 +149,7 @@ func main() { log.Println("stopping all processes") - err = pm.Stop() + err = pm.StopAll() if err != nil { log.Fatalf("error stopping processes: %v\n", err) }