From ab4166faf907b294cff7982ae759363e7c80d68a Mon Sep 17 00:00:00 2001 From: t14 Date: Sun, 6 Jan 2019 14:28:21 +0000 Subject: [PATCH 1/7] add ability to use config file with watcher --- README.md | 24 ++++++ cmd/watcher/README.md | 23 +++++ cmd/watcher/config/config.go | 135 ++++++++++++++++++++++++++++++ cmd/watcher/config/config_test.go | 62 ++++++++++++++ cmd/watcher/main.go | 40 ++++----- 5 files changed, 265 insertions(+), 19 deletions(-) create mode 100644 cmd/watcher/config/config.go create mode 100644 cmd/watcher/config/config_test.go diff --git a/README.md b/README.md index c0ef08b..2ee27df 100644 --- a/README.md +++ b/README.md @@ -170,3 +170,27 @@ watcher -cmd="python script.py" -pipe=true ``` Now when changes are detected, the event's info will be output from the running python script. + +#Config file +All of the command line flags can be set using a json config file like below. Any config values that are +not declared will use its default values instead. + +```json +{ + "recursive" : false, + "dotfiles": false, + "cmd": "python script.py", + "interval": "250ms", + "listfiles": true, + "pipe": true, + "keepalive": true +} + +``` +You can use the config file by supplying the full path and name of config file to `-config` comand line flag +like in the example below. + +```shell +watcher -config="watcher.json" +``` + diff --git a/cmd/watcher/README.md b/cmd/watcher/README.md index 0dc6740..cfcf0e7 100644 --- a/cmd/watcher/README.md +++ b/cmd/watcher/README.md @@ -56,3 +56,26 @@ watcher -cmd="python script.py" -pipe=true ``` Now when changes are detected, the event's info will be output from the running python script. + +#Config file +All of the command line flags can be set using a json config file like below. Any config values that are +not declared will use its default values instead. + +```json +{ + "recursive" : false, + "dotfiles": false, + "cmd": "python script.py", + "interval": "250ms", + "listfiles": true, + "pipe": true, + "keepalive": true +} + +``` +You can use the config file by supplying the full path and name of config file to `-config` comand line flag +like in the example below. + +```shell +watcher -config="watcher.json" +``` \ No newline at end of file diff --git a/cmd/watcher/config/config.go b/cmd/watcher/config/config.go new file mode 100644 index 0000000..3227160 --- /dev/null +++ b/cmd/watcher/config/config.go @@ -0,0 +1,135 @@ +package config + +import ( + "encoding/json" + "flag" + "io/ioutil" + "os" +) + +// Config values that can be used in a json file. +type Config struct { + Interval string `json:"interval"` + Recursive bool `json:"recursive"` + Dotfiles bool `json:"dotfiles"` + Cmd string `json:"cmd"` + Startcmd bool `json:"startcmd"` + ListFiles bool `json:"listfiles"` + StdinPipe bool `json:"pipe"` + Keepalive bool `json:"keepalive"` +} + +var c Config + +// GetConfig Checks for a user defined config file. If there is no config file the +// command line flags or their defaults are used. +func GetConfig() Config { + configFile := flag.String("config", "", "config file") + interval := flag.String("interval", "100ms", "watcher poll interval") + recursive := flag.Bool("recursive", true, "watch folders recursively") + dotfiles := flag.Bool("dotfiles", true, "watch dot files") + cmd := flag.String("cmd", "", "command to run when an event occurs") + startcmd := flag.Bool("startcmd", false, "run the command when watcher starts") + listFiles := flag.Bool("list", false, "list watched files on start") + stdinPipe := flag.Bool("pipe", false, "pipe event's info to command's stdin") + keepalive := flag.Bool("keepalive", false, "keep alive when a cmd returns code != 0") + + flag.Parse() + + // If the configfile flag is defined use its values. + if len(*configFile) > 0 { + jsonFile, err := os.Open(*configFile) + if err != nil { + panic(err) + } + + defer jsonFile.Close() + + byteValue, error := ioutil.ReadAll(jsonFile) + if error != nil { + panic(error) + } + + var data Config + json.Unmarshal(byteValue, &data) + // Set config values. If a value is not set in the config file + // the default value will be used. + c.setInterval(data.Interval) + c.setRecursive(data.Recursive) + c.setDotfiles(data.Dotfiles) + c.setCmd(data.Cmd) + c.setStartCmd(data.Startcmd) + c.setListFiles(data.ListFiles) + c.setPipe(data.StdinPipe) + c.setKeepAlive(data.Keepalive) + + } else { + //Use CLI values + c.Interval = *interval + c.Recursive = *recursive + c.Dotfiles = *dotfiles + c.Cmd = *cmd + c.Startcmd = *startcmd + c.ListFiles = *listFiles + c.StdinPipe = *stdinPipe + c.Keepalive = *keepalive + } + + return c +} + +func (c *Config) setInterval(interval string) { + c.Interval = "200ms" + if len(interval) > 0 { + c.Interval = interval + } +} + +func (c *Config) setRecursive(recursive bool) { + c.Recursive = true + if !recursive { + c.Recursive = false + } +} + +func (c *Config) setDotfiles(dotfiles bool) { + c.Dotfiles = true + if !dotfiles { + c.Dotfiles = false + } +} + +func (c *Config) setCmd(cmd string) { + c.Cmd = "" + if len(cmd) > 0 { + c.Cmd = cmd + } +} + +func (c *Config) setStartCmd(startCmd bool) { + c.Startcmd = false + if startCmd { + c.Startcmd = true + } +} + +func (c *Config) setListFiles(listFiles bool) { + c.ListFiles = false + if listFiles { + c.ListFiles = true + } +} + +func (c *Config) setPipe(pipe bool) { + c.StdinPipe = false + if pipe { + c.StdinPipe = true + } +} + +func (c *Config) setKeepAlive(keepAlive bool) { + c.Keepalive = false + if keepAlive { + c.Keepalive = true + } +} diff --git a/cmd/watcher/config/config_test.go b/cmd/watcher/config/config_test.go new file mode 100644 index 0000000..3775186 --- /dev/null +++ b/cmd/watcher/config/config_test.go @@ -0,0 +1,62 @@ +package config_test + +import ( + "testing" + + "github.com/t14/watcher/cmd/watcher/config" +) + +type Defaults = struct { + interval string + expected interface{} +} + +var c = config.GetConfig() + +func TestDefaultsInterval(t *testing.T) { + if c.Interval != "200ms" { + t.Error("Failed to set default Interval value") + } +} + +func TestDefaultRecursive(t *testing.T) { + if !c.Recursive { + t.Error("Failed to set default Recursive value") + } +} + +func TestDefaultDotFiles(t *testing.T) { + if !c.Dotfiles { + t.Error("Failed to set default Dot files value") + } +} + +func TestDefaultCmd(t *testing.T) { + if c.Cmd != "" { + t.Error("Failed to set default CMD value") + } +} + +func TestDefaultStartCmd(t *testing.T) { + if c.Startcmd { + t.Error("Failed to set default StartCmd value") + } +} + +func TestDefaultListFiles(t *testing.T) { + if c.ListFiles { + t.Error("Failed to set default Listfiles value") + } +} + +func TestDefaultStdinPipe(t *testing.T) { + if c.StdinPipe { + t.Error("Failed to set default StdinPipe value") + } +} + +func TestDefaultKeepAlive(t *testing.T) { + if c.Keepalive { + t.Error("Failed to set default KeepAlive value") + } +} diff --git a/cmd/watcher/main.go b/cmd/watcher/main.go index 6302b8a..579df54 100644 --- a/cmd/watcher/main.go +++ b/cmd/watcher/main.go @@ -11,18 +11,20 @@ import ( "time" "unicode" - "github.com/radovskyb/watcher" + "github.com/t14/watcher" + "github.com/t14/watcher/cmd/watcher/config" ) func main() { - interval := flag.String("interval", "100ms", "watcher poll interval") - recursive := flag.Bool("recursive", true, "watch folders recursively") - dotfiles := flag.Bool("dotfiles", true, "watch dot files") - cmd := flag.String("cmd", "", "command to run when an event occurs") - startcmd := flag.Bool("startcmd", false, "run the command when watcher starts") - listFiles := flag.Bool("list", false, "list watched files on start") - stdinPipe := flag.Bool("pipe", false, "pipe event's info to command's stdin") - keepalive := flag.Bool("keepalive", false, "keep alive when a cmd returns code != 0") + config := config.GetConfig() + interval := config.Interval + recursive := config.Recursive + dotfiles := config.Dotfiles + cmd := config.Cmd + startcmd := config.Startcmd + listFiles := config.ListFiles + stdinPipe := config.StdinPipe + keepalive := config.Keepalive flag.Parse() @@ -40,8 +42,8 @@ func main() { var cmdName string var cmdArgs []string - if *cmd != "" { - split := strings.FieldsFunc(*cmd, unicode.IsSpace) + if cmd != "" { + split := strings.FieldsFunc(cmd, unicode.IsSpace) cmdName = split[0] if len(split) > 1 { cmdArgs = split[1:] @@ -50,7 +52,7 @@ func main() { // Create a new Watcher with the specified options. w := watcher.New() - w.IgnoreHiddenFiles(!*dotfiles) + w.IgnoreHiddenFiles(!dotfiles) done := make(chan struct{}) go func() { @@ -63,9 +65,9 @@ func main() { fmt.Println(event) // Run the command if one was specified. - if *cmd != "" { + if cmd != "" { c := exec.Command(cmdName, cmdArgs...) - if *stdinPipe { + if stdinPipe { c.Stdin = strings.NewReader(event.String()) } else { c.Stdin = os.Stdin @@ -73,7 +75,7 @@ func main() { c.Stdout = os.Stdout c.Stderr = os.Stderr if err := c.Run(); err != nil { - if (c.ProcessState == nil || !c.ProcessState.Success()) && *keepalive { + if (c.ProcessState == nil || !c.ProcessState.Success()) && keepalive { log.Println(err) continue } @@ -94,7 +96,7 @@ func main() { // Add the files and folders specified. for _, file := range files { - if *recursive { + if recursive { if err := w.AddRecursive(file); err != nil { log.Fatalln(err) } @@ -106,7 +108,7 @@ func main() { } // Print a list of all of the files and folders being watched. - if *listFiles { + if listFiles { for path, f := range w.WatchedFiles() { fmt.Printf("%s: %s\n", path, f.Name()) } @@ -116,7 +118,7 @@ func main() { fmt.Printf("Watching %d files\n", len(w.WatchedFiles())) // Parse the interval string into a time.Duration. - parsedInterval, err := time.ParseDuration(*interval) + parsedInterval, err := time.ParseDuration(interval) if err != nil { log.Fatalln(err) } @@ -135,7 +137,7 @@ func main() { // Run the command before watcher starts if one was specified. go func() { - if *cmd != "" && *startcmd { + if cmd != "" && startcmd { c := exec.Command(cmdName, cmdArgs...) c.Stdin = os.Stdin c.Stdout = os.Stdout From 21311874b60b2dc27da0b5d014406a128ecf4816 Mon Sep 17 00:00:00 2001 From: TJ Date: Sun, 6 Jan 2019 14:31:27 +0000 Subject: [PATCH 2/7] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2ee27df..145cc53 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,7 @@ watcher -cmd="python script.py" -pipe=true Now when changes are detected, the event's info will be output from the running python script. #Config file + All of the command line flags can be set using a json config file like below. Any config values that are not declared will use its default values instead. From 51f56631b1574fe4ef8a874cb668e257c781b305 Mon Sep 17 00:00:00 2001 From: TJ Date: Sun, 6 Jan 2019 14:32:01 +0000 Subject: [PATCH 3/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 145cc53..8e21146 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,7 @@ watcher -cmd="python script.py" -pipe=true Now when changes are detected, the event's info will be output from the running python script. -#Config file +# Config file All of the command line flags can be set using a json config file like below. Any config values that are not declared will use its default values instead. From 1a1bbd224e57a127160240b7c862e13cce441350 Mon Sep 17 00:00:00 2001 From: TJ Date: Sun, 6 Jan 2019 14:32:35 +0000 Subject: [PATCH 4/7] Update README.md --- cmd/watcher/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/watcher/README.md b/cmd/watcher/README.md index cfcf0e7..37c9f50 100644 --- a/cmd/watcher/README.md +++ b/cmd/watcher/README.md @@ -57,7 +57,8 @@ watcher -cmd="python script.py" -pipe=true Now when changes are detected, the event's info will be output from the running python script. -#Config file +# Config file + All of the command line flags can be set using a json config file like below. Any config values that are not declared will use its default values instead. @@ -78,4 +79,4 @@ like in the example below. ```shell watcher -config="watcher.json" -``` \ No newline at end of file +``` From 7a1d8a6fd3f76db690fde8fba5e864b02d16ff69 Mon Sep 17 00:00:00 2001 From: t14 Date: Mon, 7 Jan 2019 10:36:10 +0000 Subject: [PATCH 5/7] correct imports --- cmd/watcher/config/config_test.go | 2 +- cmd/watcher/main.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/watcher/config/config_test.go b/cmd/watcher/config/config_test.go index 3775186..d42d63d 100644 --- a/cmd/watcher/config/config_test.go +++ b/cmd/watcher/config/config_test.go @@ -3,7 +3,7 @@ package config_test import ( "testing" - "github.com/t14/watcher/cmd/watcher/config" + "github.com/radovskyb/watcher/cmd/watcher/config" ) type Defaults = struct { diff --git a/cmd/watcher/main.go b/cmd/watcher/main.go index 579df54..b5e75c7 100644 --- a/cmd/watcher/main.go +++ b/cmd/watcher/main.go @@ -11,8 +11,8 @@ import ( "time" "unicode" - "github.com/t14/watcher" - "github.com/t14/watcher/cmd/watcher/config" + "github.com/radovskyb/watcher" + "github.com/radovskyb/watcher/cmd/watcher/config" ) func main() { From 3ae68325f1e43eb28059a1b73526f03244333f37 Mon Sep 17 00:00:00 2001 From: t14 Date: Mon, 7 Jan 2019 12:11:26 +0000 Subject: [PATCH 6/7] add ignore config --- cmd/watcher/config/config.go | 11 +++++++++++ cmd/watcher/config/config_test.go | 6 ++++++ cmd/watcher/main.go | 1 + 3 files changed, 18 insertions(+) diff --git a/cmd/watcher/config/config.go b/cmd/watcher/config/config.go index 3227160..e31da21 100644 --- a/cmd/watcher/config/config.go +++ b/cmd/watcher/config/config.go @@ -17,6 +17,7 @@ type Config struct { ListFiles bool `json:"listfiles"` StdinPipe bool `json:"pipe"` Keepalive bool `json:"keepalive"` + Ignore string `json:"ignore"` } var c Config @@ -33,6 +34,7 @@ func GetConfig() Config { listFiles := flag.Bool("list", false, "list watched files on start") stdinPipe := flag.Bool("pipe", false, "pipe event's info to command's stdin") keepalive := flag.Bool("keepalive", false, "keep alive when a cmd returns code != 0") + ignore := flag.String("ignore", "", "comma separated list of paths to ignore") flag.Parse() @@ -62,6 +64,7 @@ func GetConfig() Config { c.setListFiles(data.ListFiles) c.setPipe(data.StdinPipe) c.setKeepAlive(data.Keepalive) + c.setIgnore(data.Ignore) } else { //Use CLI values @@ -73,6 +76,7 @@ func GetConfig() Config { c.ListFiles = *listFiles c.StdinPipe = *stdinPipe c.Keepalive = *keepalive + c.Ignore = *ignore } return c @@ -133,3 +137,10 @@ func (c *Config) setKeepAlive(keepAlive bool) { c.Keepalive = true } } + +func (c *Config) setIgnore(ignore string) { + c.Ignore = "" + if len(ignore) > 0 { + c.Ignore = ignore + } +} diff --git a/cmd/watcher/config/config_test.go b/cmd/watcher/config/config_test.go index d42d63d..4c8330e 100644 --- a/cmd/watcher/config/config_test.go +++ b/cmd/watcher/config/config_test.go @@ -60,3 +60,9 @@ func TestDefaultKeepAlive(t *testing.T) { t.Error("Failed to set default KeepAlive value") } } + +func TestDefaultIgnore(t *testing.T) { + if c.Ignore != "" { + t.Error("Failed to set default file ignore value") + } +} diff --git a/cmd/watcher/main.go b/cmd/watcher/main.go index b5e75c7..ad9c944 100644 --- a/cmd/watcher/main.go +++ b/cmd/watcher/main.go @@ -25,6 +25,7 @@ func main() { listFiles := config.ListFiles stdinPipe := config.StdinPipe keepalive := config.Keepalive + ignore := config.ignore flag.Parse() From 5b6e106291c221009f25e73df4849befeffbab6d Mon Sep 17 00:00:00 2001 From: t14 Date: Mon, 7 Jan 2019 13:17:17 +0000 Subject: [PATCH 7/7] config ignore fix --- cmd/watcher/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/watcher/main.go b/cmd/watcher/main.go index aa96a86..5b6d0f6 100644 --- a/cmd/watcher/main.go +++ b/cmd/watcher/main.go @@ -25,7 +25,7 @@ func main() { listFiles := config.ListFiles stdinPipe := config.StdinPipe keepalive := config.Keepalive - ignore := config.ignore + ignore := config.Ignore flag.Parse()