Skip to content

Commit

Permalink
v2.3.4. Bugfix. Improvement.
Browse files Browse the repository at this point in the history
- v2.3.4 January 8, 2013
	- Better handling and detection of failed watching operations
	- Better handling of duplicated events
	- Watching is now an atomic operation
		- If watching fails for a descendant, we will close everything related to that watch operation of the eve
	- We now prefer the `watch` method over the `watchFile` method
		- This offers great reliability and way less CPU and memory foot print
		- If you still wish to prefer `watchFile`, then set the new configuration option `preferredMethod` to `watchFile`
	- Closes [issue #30](#30) thanks to [Howard Tyson](https://github.com/tizzo)
  • Loading branch information
balupton committed Feb 5, 2013
1 parent a1fe761 commit 770cd65
Show file tree
Hide file tree
Showing 11 changed files with 495 additions and 267 deletions.
7 changes: 5 additions & 2 deletions .travis.yml
@@ -1,12 +1,15 @@
language: node_js
before_script: "make test-prepare"
install: "npm install"
before_script: "./node_modules/.bin/cake test-prepare"
script: "./node_modules/.bin/cake test"
node_js:
- 0.4
- 0.6
- 0.8
- 0.9
notifications:
irc:
- "irc.freenode.org#bevry"
- "irc.freenode.org#bevry-dev"
email:
recipients:
- watchr@bevry.me
132 changes: 132 additions & 0 deletions Cakefile
@@ -0,0 +1,132 @@
# This file was originally created by Benjamin Lupton <b@lupton.cc> (http://balupton.com)
# and is currently licensed under the Creative Commons Zero (http://creativecommons.org/publicdomain/zero/1.0/)
# making it public domain so you can do whatever you wish with it without worry (you can even remove this notice!)
#
# If you change something here, be sure to reflect the changes in:
# - the scripts section of the package.json file
# - the .travis.yml file


# -----------------
# Variables

WINDOWS = process.platform.indexOf('win') is 0
NODE = process.execPath
NPM = if WINDOWS then process.execPath.replace('node.exe','npm.cmd') else 'npm'
EXT = (if WINDOWS then '.cmd' else '')
APP = process.cwd()
BIN = "#{APP}/node_modules/.bin"
CAKE = "#{BIN}/cake#{EXT}"
COFFEE = "#{BIN}/coffee#{EXT}"
OUT = "#{APP}/out"
SRC = "#{APP}/src"


# -----------------
# Requires

pathUtil = require('path')
{exec,spawn} = require('child_process')
safe = (next,fn) ->
return (err) ->
return next(err) if err
return fn()


# -----------------
# Actions

clean = (opts,next) ->
(next = opts; opts = {}) unless next?
args = [
'-Rf'
OUT
pathUtil.join(APP,'node_modules')
pathUtil.join(APP,'*out')
pathUtil.join(APP,'*log')
]
spawn('rm', args, {stdio:'inherit',cwd:APP}).on('exit',next)

compile = (opts,next) ->
(next = opts; opts = {}) unless next?
spawn(COFFEE, ['-co', OUT, SRC], {stdio:'inherit',cwd:APP}).on('exit',next)

example = (opts,next) ->
(next = opts; opts = {}) unless next?
compile opts, safe next, ->
command = pathUtil.resolve("#{__dirname}/bin/watchr")
spawn(command, [], {stdio:'inherit',cwd:APP,env:process.env}).on('exit',next)

watch = (opts,next) ->
(next = opts; opts = {}) unless next?
spawn(COFFEE, ['-wco', OUT, SRC], {stdio:'inherit',cwd:APP}).on('exit',next)

install = (opts,next) ->
(next = opts; opts = {}) unless next?
spawn(NPM, ['install'], {stdio:'inherit',cwd:APP}).on('exit',next)

reset = (opts,next) ->
(next = opts; opts = {}) unless next?
clean opts, safe next, ->
install opts, safe next, ->
compile opts, next

setup = (opts,next) ->
(next = opts; opts = {}) unless next?
install opts, safe next, ->
compile opts, next

test = (opts,next) ->
(next = opts; opts = {}) unless next?
spawn(NPM, ['test'], {stdio:'inherit',cwd:APP}).on('exit',next)

finish = (err) ->
throw err if err
console.log('OK')


# -----------------
# Commands

# clean
task 'clean', 'clean up instance', ->
clean finish

# compile
task 'compile', 'compile our files', ->
compile finish

# dev/watch
task 'dev', 'watch and recompile our files', ->
watch finish
task 'watch', 'watch and recompile our files', ->
watch finish

# example
task 'example', 'run the example file', ->
example finish

# install
task 'install', 'install dependencies', ->
install finish

# reset
task 'reset', 'reset instance', ->
reset finish

# setup
task 'setup', 'setup for development', ->
setup finish

# test
task 'test', 'run our tests', ->
test finish

# test-debug
task 'test-debug', 'run our tests in debug mode', ->
test {debug:true}, finish

# test-prepare
task 'test-prepare', 'prepare out tests', ->
setup finish

10 changes: 10 additions & 0 deletions History.md
@@ -1,5 +1,15 @@
## History

- v2.3.4 January 8, 2013
- Better handling and detection of failed watching operations
- Better handling of duplicated events
- Watching is now an atomic operation
- If watching fails for a descendant, we will close everything related to that watch operation of the eve
- We now prefer the `watch` method over the `watchFile` method
- This offers great reliability and way less CPU and memory foot print
- If you still wish to prefer `watchFile`, then set the new configuration option `preferredMethod` to `watchFile`
- Closes [issue #30](https://github.com/bevry/watchr/issues/30) thanks to [Howard Tyson](https://github.com/tizzo)

- v2.3.3 January 8, 2013
- Added `outputLog` option
- Added `ignorePaths` option
Expand Down
66 changes: 0 additions & 66 deletions Makefile

This file was deleted.

29 changes: 21 additions & 8 deletions README.md
Expand Up @@ -16,13 +16,14 @@ You install it via `npm install watchr` and use it via `require('watchr').watch(
- when using the `path` configuration option: `err, watcherInstance`
- when using the `paths` configuration option: `err, [watcherInstance,...]`
- `stat` (optional, defaults to `null`) a file stat object to use for the path, instead of fetching a new one
- `interval` (optional, defaults to `100`) for systems that poll to detect file changes, how often should it poll in millseconds
- `persistent` (optional, defaults to `true`) whether or not we should keep the node process alive for as long as files are still being watched
- `duplicateDelay` (optional, defaults to `1000`) sometimes events will fire really fast, this delay is set in place so we don't fire the same event within the timespan
- `preferredMethod` (optional, defaults to `watch`) which watching method should try first? `watch` or `watchFile`
- `ignorePaths` (optional, defaults to `false`) an array of full paths to ignore
- `ignoreHiddenFiles` (optional, defaults to `false`) whether or not to ignored files which filename starts with a `.`
- `ignoreCommonPatterns` (optional, defaults to `true`) whether or not to ignore common undesirable file patterns (e.g. `.svn`, `.git`, `.DS_Store`, `thumbs.db`, etc)
- `ignoreCustomPatterns` (optional, defaults to `null`) any custom ignore patterns that you would also like to ignore along with the common patterns
- `interval` (optional, defaults to `100`) for systems that poll to detect file changes, how often should it poll in millseconds
- `persistent` (optional, defaults to `true`) whether or not we should keep the node process alive for as long as files are still being watched


The following events are available to your via the listeners:

Expand All @@ -39,7 +40,7 @@ To wrap it all together, it would look like this:

``` javascript
// Require
var watchr = require('watchr')
var watchr = require('watchr');

// Watch a directory or file
console.log('Watch our paths');
Expand All @@ -53,15 +54,22 @@ watchr.watch({
console.log('an error occured:', err);
},
watching: function(err,watcherInstance,isWatching){
console.log('a new watcher instance finished setting up', arguments);
if (err) {
console.log("watching the path " + watcherInstance.path + " failed with error", err);
} else {
console.log("watching the path " + watcherInstance.path + " completed");
}
},
change: function(changeType,filePath,fileCurrentStat,filePreviousStat){
console.log('a change event occured:',arguments);
}
},
next: function(err,watchers){
// Watching all setup
console.log('Now watching our paths', arguments);
if (err) {
return console.log("watching everything failed with error", err);
} else {
console.log('watching everything completed', watchers);
}

// Close watchers after 10 seconds
setTimeout(function(){
Expand All @@ -75,7 +83,12 @@ watchr.watch({
});
```

You can test the above code snippet by installing watchr globally by running `npm install -g watchr` to install watchr, then `watchr <pathToWatch>` to watchr a particular path, and performing some file system modifications on that path.
You can test the above code snippet by running the following:

```
npm install watchr
./node_modules/.bin/watchr
```


## Support
Expand Down
43 changes: 42 additions & 1 deletion bin/watchr
@@ -1,2 +1,43 @@
#!/usr/bin/env node
require(__dirname+'/../out/bin/watchr');
// Require
var watchr = require(__dirname+'/../out/lib/watchr');

// Watch a directory or file
console.log('Watch our paths');
watchr.watch({
paths: [process.cwd()],
listeners: {
log: function(logLevel){
console.log('a log message occured:', arguments);
},
error: function(err){
console.log('an error occured:', err);
},
watching: function(err,watcherInstance,isWatching){
if (err) {
console.log("watching the path " + watcherInstance.path + " failed with error", err);
} else {
console.log("watching the path " + watcherInstance.path + " completed");
}
},
change: function(changeType,filePath,fileCurrentStat,filePreviousStat){
console.log('a change event occured:',arguments);
}
},
next: function(err,watchers){
if (err) {
return console.log("watching everything failed with error", err);
} else {
console.log('watching everything completed', watchers);
}

// Close watchers after 10 seconds
setTimeout(function(){
var i;
console.log('Stop watching our paths');
for ( i=0; i<watchers.length; i++ ) {
watchers[i].close();
}
},10*1000);
}
});
35 changes: 0 additions & 35 deletions example.js

This file was deleted.

0 comments on commit 770cd65

Please sign in to comment.