shama / gaze

:crystal_ball: A globbing fs.watch wrapper built from the best parts of other fine watch libs.
MIT License
1.16k stars 168 forks source link

How to ignore/negate patterns #109

Open cristiandouce opened 10 years ago

cristiandouce commented 10 years ago

Hi,

I've not been able to use negate patterns even though isaacs/minimatch allow those.

I want this approach because there are times I just don't want to watch changes in node_modules for example, but I do from any other folder/file in the project.

Is there a correct way to do this with the current version of gaze?

shama commented 10 years ago

Could you post the patterns that you've tried?

The patterns are order dependent where the next pattern takes precedence over the previous. Also negate patterns work just like regular patterns but to the opposite effect. Which sometimes gets confusing because each pattern expands to a list of files to compare, rather than using logic on the actual patterns.

cristiandouce commented 10 years ago

I have tried the following:

['!node_modules']
['!node_modules*']
['!node_modules/*']
['!node_modules/**/*']

None seemed to work.

Is there a working example of this I could use to see if I'm doing something wrong?

I've seen minimatch has this tested. But not globule.

cristiandouce commented 10 years ago

Well, seeing this: https://github.com/shama/gaze/blob/master/test/patterns_test.js#L30

I'm using node@0.10.26 btw.

4ok commented 10 years ago

I also can't use negate the pattern.

This problem has already been raised, then it decided instead of using glob module fileset. 5578985. Now the module is used globule, which apparently does not support the "negate pattern"

4ok commented 10 years ago

Turned out!

// This pattern has earned: 
['dir-a/**', '!dir-a/dir-b/**']
// But this pattern does not work, so he thought that no support
['dir-a/**', '!dir-a/dir-b']
shama commented 10 years ago

globule does support the negate pattern and so does gaze. We both have tests for it https://github.com/cowboy/node-globule/blob/master/test/globule_test.js#L188 and https://github.com/shama/gaze/blob/master/test/patterns_test.js#L28

Consider the patterns ['**/*', '!**/node_modules/**']. This will first get a list of every file in your cwd, then exclude every file within a node_modules folder. Likely if your node_module folder matches the first pattern, it is going to take a long time to sort through all of those files. A better strategy is to limit the matching pattern to the specific files you need and avoid matching the node_modules at all.

I've even considered excluding the node_modules folder by default because this is very common to accidentally match every file within it. I am guessing that is what is happening.

bclinkinbeard commented 10 years ago

+1 for ignoring node_modules by default. My guess is that the vast majority of projects want to watch their entire source tree, and nobody (sane) wants to watch nodemodules. Would be killer to be able to just pass */_ and be done with it.

thejohnfreeman commented 10 years ago

Consider the patterns ['*/', '!/node_modules/']. This will first get a list of every file in your cwd, then exclude every file within a node_modules folder.

This behavior is cost prohibitive in all but small and acyclic directory trees. Is there any better way to prune branches from the search tree?

shama commented 10 years ago

Is there any better way to prune branches from the search tree?

Don't include patterns that match in the first place. AFAIK, there isn't a mechanism or library that can negate patterns without first retrieving files from each and filtering. If so, please open a PR on https://github.com/cowboy/node-globule because that would be a great feature (and is the library this one uses).

thejohnfreeman commented 10 years ago

Don't include patterns that match in the first place.

This is not a very good answer. It ignores the common situation where enumerating every specific inclusion is more onerous and error prone than enumerating every specific exclusion.

AFAIK, there isn't a mechanism or library that can negate patterns without first retrieving files from each and filtering.

Sounds like the authors should have consulted the algorithm for find. The mechanism is very simple: do not descend into a branch of the filesystem that matches an exclusion.

shama commented 10 years ago

@thejohnfreeman Awesome, glad to hear it is very simple. Looking forward to your patch. :)

thejohnfreeman commented 10 years ago

I must be the only one capable.

vojtajina commented 10 years ago

Couldn't gaze.remove() take patterns and ignore those?

Right now, you have to glob existing files yourself and add the ones that are ignored (gaze.remove()) and keep doing that for every new file.

Chokidar has a ignore callback (for every new file discovered, the callback can decide whether it is ignored or not). That works pretty well too.

schmod commented 10 years ago

Ideally, we'd want to bake this functionality into globule, so that we never even bother traversing excluded folders (basically echoing what @shama said above).

The ignore callback strikes me as a sub-optimal solution, because it means that we're watching files that never should have been watched in the first place.

shama commented 10 years ago

Couldn't gaze.remove() take patterns and ignore those?

+1 as it would make it a bit more consistent with the add() api. Created #143

As @schmod said, the initial glob would still have ran and time spent. Ideally it needs to happen in globule to be more efficient than it is now. I'll work on ignoring node_modules by default though as that is the most common area to ignore.

thejohnfreeman commented 10 years ago

Here's a module I wrote that provides a subset of GNU find's excellent interface, including the "prune" operator. I'm happy to work with anyone who wants to use it.

https://github.com/thejohnfreeman/node-find

shama commented 10 years ago

@thejohnfreeman Nice! I'll give it a try. Thanks!