Improve watching search and configuration by improving default ignore

Now it will ignore by default hidden files and folders, test files and vendor
This commit is contained in:
Max Claus Nunes 2018-07-22 10:30:30 -03:00
parent 586c834cb9
commit a75eac8490
5 changed files with 133 additions and 44 deletions

View File

@ -49,9 +49,9 @@ GLOBAL OPTIONS:
--build-args value arguments used on building the program
--program-args value arguments used on executing the program
--verbose turns on the verbose messages from gaper
--disable-default-ignore turns off default ignore for hidden files and folders, "*_test.go" files, and vendor folder
--watch value, -w value list of folders or files to watch for changes
--ignore value, -i value list of folders or files to ignore for changes
(always ignores all hidden files and directories)
--poll-interval value, -p value how often in milliseconds to poll watched files for changes (default: 500)
--extensions value, -e value a comma-delimited list of file extensions to watch for changes (default: "go")
--no-restart-on value, -n value don't automatically restart the supervised program if it ends:
@ -62,10 +62,26 @@ GLOBAL OPTIONS:
--version, -v print the version
```
Since in most projects there is no need to watch changes of:
* hidden files and folders
* test files (`*_test.go`)
* vendor folder
Gaper by default ignores those cases already. Although, if you need Gaper to watch those files anyway it is possible to disable this setting with `--disable-default-ignore` argument.
### Examples
Using all defaults provided by Gaper:
```
gaper
```
Ignore watch over all test files:
> no need for this in case you are not using `--disable-default-ignore`
```
--ignore './**/*_test.go'
```

View File

@ -17,16 +17,17 @@ var logger = gaper.NewLogger("gaper")
func main() {
parseArgs := func(c *cli.Context) *gaper.Config {
return &gaper.Config{
BinName: c.String("bin-name"),
BuildPath: c.String("build-path"),
BuildArgsMerged: c.String("build-args"),
ProgramArgsMerged: c.String("program-args"),
Verbose: c.Bool("verbose"),
WatchItems: c.StringSlice("watch"),
IgnoreItems: c.StringSlice("ignore"),
PollInterval: c.Int("poll-interval"),
Extensions: c.StringSlice("extensions"),
NoRestartOn: c.String("no-restart-on"),
BinName: c.String("bin-name"),
BuildPath: c.String("build-path"),
BuildArgsMerged: c.String("build-args"),
ProgramArgsMerged: c.String("program-args"),
Verbose: c.Bool("verbose"),
DisableDefaultIgnore: c.Bool("disable-default-ignore"),
WatchItems: c.StringSlice("watch"),
IgnoreItems: c.StringSlice("ignore"),
PollInterval: c.Int("poll-interval"),
Extensions: c.StringSlice("extensions"),
NoRestartOn: c.String("no-restart-on"),
}
}
@ -74,6 +75,10 @@ func main() {
Name: "verbose",
Usage: "turns on the verbose messages from gaper",
},
cli.BoolFlag{
Name: "disable-default-ignore",
Usage: "turns off default ignore for hidden files and folders, \"*_test.go\" files, and vendor folder",
},
cli.StringSliceFlag{
Name: "watch, w",
Usage: "list of folders or files to watch for changes",

View File

@ -37,19 +37,20 @@ var exitStatusError = 1
// Config contains all settings supported by gaper
type Config struct {
BinName string
BuildPath string
BuildArgs []string
BuildArgsMerged string
ProgramArgs []string
ProgramArgsMerged string
WatchItems []string
IgnoreItems []string
PollInterval int
Extensions []string
NoRestartOn string
Verbose bool
WorkingDirectory string
BinName string
BuildPath string
BuildArgs []string
BuildArgsMerged string
ProgramArgs []string
ProgramArgsMerged string
WatchItems []string
IgnoreItems []string
PollInterval int
Extensions []string
NoRestartOn string
Verbose bool
DisableDefaultIgnore bool
WorkingDirectory string
}
// Run starts the whole gaper process watching for file changes or exit codes
@ -61,9 +62,17 @@ func Run(cfg *Config, chOSSiginal chan os.Signal) error {
return err
}
wCfg := WatcherConfig{
DefaultIgnore: !cfg.DisableDefaultIgnore,
PollInterval: cfg.PollInterval,
WatchItems: cfg.WatchItems,
IgnoreItems: cfg.IgnoreItems,
Extensions: cfg.Extensions,
}
builder := NewBuilder(cfg.BuildPath, cfg.BinName, cfg.WorkingDirectory, cfg.BuildArgs)
runner := NewRunner(os.Stdout, os.Stderr, filepath.Join(cfg.WorkingDirectory, builder.Binary()), cfg.ProgramArgs)
watcher, err := NewWatcher(cfg.PollInterval, cfg.WatchItems, cfg.IgnoreItems, cfg.Extensions)
watcher, err := NewWatcher(wCfg)
if err != nil {
return fmt.Errorf("watcher error: %v", err)
}

View File

@ -20,6 +20,7 @@ type Watcher interface {
// watcher is a interface for the watch process
type watcher struct {
defaultIgnore bool
pollInterval int
watchItems map[string]bool
ignoreItems map[string]bool
@ -28,27 +29,36 @@ type watcher struct {
errors chan error
}
// WatcherConfig defines the settings available for the watcher
type WatcherConfig struct {
DefaultIgnore bool
PollInterval int
WatchItems []string
IgnoreItems []string
Extensions []string
}
// NewWatcher creates a new watcher
func NewWatcher(pollInterval int, watchItems []string, ignoreItems []string, extensions []string) (Watcher, error) {
if pollInterval == 0 {
pollInterval = DefaultPoolInterval
func NewWatcher(cfg WatcherConfig) (Watcher, error) {
if cfg.PollInterval == 0 {
cfg.PollInterval = DefaultPoolInterval
}
if len(extensions) == 0 {
extensions = DefaultExtensions
if len(cfg.Extensions) == 0 {
cfg.Extensions = DefaultExtensions
}
allowedExts := make(map[string]bool)
for _, ext := range extensions {
for _, ext := range cfg.Extensions {
allowedExts["."+ext] = true
}
watchPaths, err := resolvePaths(watchItems, allowedExts)
watchPaths, err := resolvePaths(cfg.WatchItems, allowedExts)
if err != nil {
return nil, err
}
ignorePaths, err := resolvePaths(ignoreItems, allowedExts)
ignorePaths, err := resolvePaths(cfg.IgnoreItems, allowedExts)
if err != nil {
return nil, err
}
@ -58,7 +68,8 @@ func NewWatcher(pollInterval int, watchItems []string, ignoreItems []string, ext
return &watcher{
events: make(chan string),
errors: make(chan error),
pollInterval: pollInterval,
defaultIgnore: cfg.DefaultIgnore,
pollInterval: cfg.PollInterval,
watchItems: watchPaths,
ignoreItems: ignorePaths,
allowedExtensions: allowedExts,
@ -105,12 +116,7 @@ func (w *watcher) scanChange(watchPath string) (string, error) {
var fileChanged string
err := filepath.Walk(watchPath, func(path string, info os.FileInfo, err error) error {
// always ignore hidden files and directories
if dir := filepath.Base(path); dir[0] == '.' && dir != "." {
return skipFile(info)
}
if _, ignored := w.ignoreItems[path]; ignored {
if w.ignoreFile(path, info) {
return skipFile(info)
}
@ -130,6 +136,31 @@ func (w *watcher) scanChange(watchPath string) (string, error) {
return fileChanged, nil
}
func (w *watcher) ignoreFile(path string, info os.FileInfo) bool {
// check if preset ignore is enabled
if w.defaultIgnore {
// check for hidden files and directories
if name := info.Name(); name[0] == '.' && name != "." {
return true
}
// check if it is a Go testing file
if strings.HasSuffix(path, "_test.go") {
return true
}
// check if it is the vendor folder
if info.IsDir() && info.Name() == "vendor" {
return true
}
}
if _, ignored := w.ignoreItems[path]; ignored {
return true
}
return false
}
func resolvePaths(paths []string, extensions map[string]bool) (map[string]bool, error) {
result := map[string]bool{}

View File

@ -16,7 +16,14 @@ func TestWatcherDefaultValues(t *testing.T) {
var ignoreItems []string
var extensions []string
wt, err := NewWatcher(pollInterval, watchItems, ignoreItems, extensions)
wCfg := WatcherConfig{
DefaultIgnore: true,
PollInterval: pollInterval,
WatchItems: watchItems,
IgnoreItems: ignoreItems,
Extensions: extensions,
}
wt, err := NewWatcher(wCfg)
expectedPath := "testdata/server"
if runtime.GOOS == OSWindows {
@ -37,7 +44,14 @@ func TestWatcherGlobPath(t *testing.T) {
ignoreItems := []string{"./testdata/**/*_test.go"}
var extensions []string
wt, err := NewWatcher(pollInterval, watchItems, ignoreItems, extensions)
wCfg := WatcherConfig{
DefaultIgnore: true,
PollInterval: pollInterval,
WatchItems: watchItems,
IgnoreItems: ignoreItems,
Extensions: extensions,
}
wt, err := NewWatcher(wCfg)
assert.Nil(t, err, "wacher error")
w := wt.(*watcher)
assert.Equal(t, map[string]bool{"testdata/server/main_test.go": true}, w.ignoreItems)
@ -49,7 +63,14 @@ func TestWatcherRemoveOverlapdPaths(t *testing.T) {
ignoreItems := []string{"./testdata/**/*", "./testdata/server"}
var extensions []string
wt, err := NewWatcher(pollInterval, watchItems, ignoreItems, extensions)
wCfg := WatcherConfig{
DefaultIgnore: true,
PollInterval: pollInterval,
WatchItems: watchItems,
IgnoreItems: ignoreItems,
Extensions: extensions,
}
wt, err := NewWatcher(wCfg)
assert.Nil(t, err, "wacher error")
w := wt.(*watcher)
assert.Equal(t, map[string]bool{"./testdata/server": true}, w.ignoreItems)
@ -69,7 +90,14 @@ func TestWatcherWatchChange(t *testing.T) {
ignoreItems := []string{testfile}
extensions := []string{"go"}
w, err := NewWatcher(pollInterval, watchItems, ignoreItems, extensions)
wCfg := WatcherConfig{
DefaultIgnore: true,
PollInterval: pollInterval,
WatchItems: watchItems,
IgnoreItems: ignoreItems,
Extensions: extensions,
}
w, err := NewWatcher(wCfg)
assert.Nil(t, err, "wacher error")
go w.Watch()