Comparing version 1.1.0 to 1.2.0
@@ -0,1 +1,5 @@ | ||
# Chokidar 1.2.0 (1 October 2015) | ||
* Allow nested arrays of paths to be provided to `.watch()` and `.add()` | ||
* Add `awaitWriteFinish` option | ||
# Chokidar 1.1.0 (23 September 2015) | ||
@@ -2,0 +6,0 @@ * Dependency updates including fsevents@1.0.0, improving installation |
102
index.js
@@ -11,2 +11,3 @@ 'use strict'; | ||
var isAbsolute = require('path-is-absolute'); | ||
var flatten = require('lodash.flatten'); | ||
@@ -77,2 +78,12 @@ var NodeFsHandler = require('./lib/nodefs-handler'); | ||
if (undef('awaitWriteFinish')) opts.awaitWriteFinish = false; | ||
if (opts.awaitWriteFinish === true) opts.awaitWriteFinish = {}; | ||
var awf = opts.awaitWriteFinish; | ||
if (awf) { | ||
if (!awf.stabilityThreshold) awf.stabilityThreshold = 2000; | ||
if (!awf.pollInterval) awf.pollInterval = 100; | ||
this._pendingWrites = Object.create(null); | ||
} | ||
this._isntIgnored = function(path, stat) { | ||
@@ -116,2 +127,6 @@ return !this._isIgnored(path, stat); | ||
else if (val1 !== undefined) args.push(val1); | ||
var awf = this.options.awaitWriteFinish; | ||
if (awf && this._pendingWrites[path]) return this; | ||
if (this.options.atomic) { | ||
@@ -143,3 +158,15 @@ if (event === 'unlink') { | ||
if ( | ||
if (awf && event === 'add') { | ||
this._awaitWriteFinish(path, awf.stabilityThreshold, function(err, stats) { | ||
if (err) { | ||
event = args[0] = 'error'; | ||
args[1] = err; | ||
emitEvent(); | ||
} else if (stats) { | ||
// if stats doesn't exist the file must have been deleted | ||
args.push(stats); | ||
emitEvent(); | ||
} | ||
}); | ||
} else if ( | ||
this.options.alwaysStat && val1 === undefined && | ||
@@ -201,2 +228,54 @@ (event === 'add' || event === 'addDir' || event === 'change') | ||
// Private method: Awaits write operation to finish | ||
// | ||
// * path - string, path being acted upon | ||
// * threshold - int, time in milliseconds a file size must be fixed before | ||
// acknowledgeing write operation is finished | ||
// * callback - function, callback to call when write operation is finished | ||
// Polls a newly created file for size variations. When files size does not | ||
// change for 'threshold' milliseconds calls callback. | ||
FSWatcher.prototype._awaitWriteFinish = function(path, threshold, callback) { | ||
var timeoutHandler; | ||
(function awaitWriteFinish (prevStat) { | ||
fs.stat(path, function(err, curStat) { | ||
if (err) { | ||
// if the file have been erased, the file entry in _pendingWrites will | ||
// be deleted in the unlink event. | ||
if (err.code == 'ENOENT') return; | ||
return callback(err); | ||
} | ||
var now = new Date(); | ||
if (this._pendingWrites[path] === undefined) { | ||
this._pendingWrites[path] = { | ||
creationTime: now, | ||
cancelWait: function() { | ||
delete this._pendingWrites[path]; | ||
clearTimeout(timeoutHandler); | ||
return callback(); | ||
}.bind(this) | ||
} | ||
return timeoutHandler = setTimeout( | ||
awaitWriteFinish.bind(this, curStat), | ||
this.options.awaitWriteFinish.pollInterval | ||
); | ||
} | ||
if ( | ||
curStat.size == prevStat.size && | ||
now - this._pendingWrites[path].creationTime > threshold | ||
) { | ||
delete this._pendingWrites[path]; | ||
callback(null, curStat); | ||
} else { | ||
return timeoutHandler = setTimeout( | ||
awaitWriteFinish.bind(this, curStat), | ||
this.options.awaitWriteFinish.pollInterval | ||
); | ||
} | ||
}.bind(this)); | ||
}.bind(this))(); | ||
} | ||
// Private method: Determines whether user has asked to ignore this path | ||
@@ -376,2 +455,8 @@ // | ||
// If we wait for this file to be fully written, cancel the wait. | ||
if (this.options.awaitWriteFinish && this._pendingWrites[path]) { | ||
this._pendingWrites[path].cancelWait(); | ||
return; | ||
} | ||
// The Entry will either be a directory that just got removed | ||
@@ -395,4 +480,8 @@ // or a bogus entry to a file, in either case we have to remove it | ||
this.closed = false; | ||
paths = arrify(paths); | ||
paths = flatten(arrify(paths)); | ||
if (!paths.every(isString)) { | ||
throw new TypeError('Non-string provided as watch path'); | ||
} | ||
if (cwd) paths = paths.map(function(path) { | ||
@@ -454,3 +543,3 @@ if (isAbsolute(path)) { | ||
if (this.closed) return this; | ||
paths = arrify(paths); | ||
paths = flatten(arrify(paths)); | ||
@@ -465,3 +554,3 @@ paths.forEach(function(path) { | ||
path = sysPath.resolve(path); | ||
this._ignoredPaths[path] = true; | ||
@@ -507,2 +596,7 @@ if (path in this._watched) { | ||
// little isString util for use in Array.prototype.every | ||
function isString(maybeString) { | ||
return typeof maybeString === 'string' | ||
} | ||
// Export FSWatcher class | ||
@@ -509,0 +603,0 @@ exports.FSWatcher = FSWatcher; |
{ | ||
"name": "chokidar", | ||
"description": "A neat wrapper around node.js fs.watch / fs.watchFile / fsevents.", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"keywords": [ | ||
@@ -50,2 +50,3 @@ "fs", | ||
"is-glob": "^2.0.0", | ||
"lodash.flatten": "^3.0.2", | ||
"path-is-absolute": "^1.0.0", | ||
@@ -52,0 +53,0 @@ "readdirp": "^2.0.0" |
@@ -26,6 +26,2 @@ # Chokidar [![Mac/Linux Build Status](https://img.shields.io/travis/paulmillr/chokidar/master.svg?label=Mac%20OSX%20%26%20Linux)](https://travis-ci.org/paulmillr/chokidar) [![Windows Build status](https://img.shields.io/appveyor/ci/es128/chokidar/master.svg?label=Windows)](https://ci.appveyor.com/project/es128/chokidar/branch/master) [![Coverage Status](https://coveralls.io/repos/paulmillr/chokidar/badge.svg)](https://coveralls.io/r/paulmillr/chokidar) [![Join the chat at https://gitter.im/paulmillr/chokidar](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/paulmillr/chokidar?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||
Other node.js watching libraries: | ||
* Are not using ultra-fast non-polling fsevents watcher implementation on OS X | ||
Chokidar resolves these problems. | ||
@@ -45,8 +41,24 @@ | ||
## How? | ||
Chokidar does still rely on the Node.js core `fs` module, but when using | ||
`fs.watch` and `fs.watchFile` for watching, it normalizes the events it | ||
receives, often checking for truth by getting file stats and/or dir contents. | ||
On Mac OS X, chokidar by default uses a native extension exposing the Darwin | ||
`FSEvents` API. This provides very efficient recursive watching compared with | ||
implementations like `kqueue` available on most \*nix platforms. Chokidar still | ||
does have to do some work to normalize the events received that way as well. | ||
On other platforms, the `fs.watch`-based implementation is the default, which | ||
avoids polling and keeps CPU usage down. Be advised that chokidar will initiate | ||
watchers recursively for everything within scope of the paths that have been | ||
specified, so be judicious about not wasting system resources by watching much | ||
more than needed. | ||
## Getting started | ||
Install chokidar via node.js package manager: | ||
Install with npm: | ||
npm install chokidar | ||
npm install chokidar --save | ||
Then just require the package in your code: | ||
Then `require` and use it in your code: | ||
@@ -62,3 +74,5 @@ ```javascript | ||
// Example of a more typical implementation structure: | ||
// Initialize watcher | ||
var watcher = chokidar.watch('file, dir, or glob', { | ||
@@ -69,4 +83,6 @@ ignored: /[\/\\]\./, | ||
// something to use when events are received | ||
var log = console.log.bind(console); | ||
// Add event listeners | ||
watcher | ||
@@ -99,3 +115,3 @@ .on('add', function(path) { log('File', path, 'has been added'); }) | ||
// Full list of options. See below for descriptions. | ||
// Full list of options. See below for descriptions. (do not use this example) | ||
chokidar.watch('file', { | ||
@@ -110,5 +126,10 @@ persistent: true, | ||
usePolling: true, | ||
interval: 100, | ||
binaryInterval: 300, | ||
alwaysStat: false, | ||
depth: undefined, | ||
interval: 100, | ||
depth: 99, | ||
awaitWriteFinish: { | ||
stabilityThreshold: 2000, | ||
pollInterval: 100 | ||
}, | ||
@@ -123,4 +144,4 @@ ignorePermissionErrors: false, | ||
`chokidar.watch(paths, options)` — takes one or more paths (which may be paths to files, | ||
dirs to be watched recursively, or glob patterns) and options: | ||
`chokidar.watch(paths, options)` — takes one or more paths (which may be paths | ||
to files, dirs to be watched recursively, or glob patterns) and options: | ||
@@ -160,2 +181,7 @@ #### Persistence | ||
`useFsEvents` default. | ||
* _Polling-specific settings_ (effective when `usePolling: true`) | ||
* `interval` (default: `100`). Interval of file system polling. | ||
* `binaryInterval` (default: `300`). Interval of file system | ||
polling for binary files. | ||
([see list of binary extensions](https://github.com/sindresorhus/binary-extensions/blob/master/binary-extensions.json)) | ||
* `useFsEvents` (default: `true` on OS X). Whether to use the | ||
@@ -172,7 +198,19 @@ `fsevents` watching interface if available. When set to `true` explicitly | ||
subdirectories will be traversed. | ||
* _Polling-specific settings_ (effective when `usePolling: true`) | ||
* `interval` (default: `100`). Interval of file system polling. | ||
* `binaryInterval` (default: `300`). Interval of file system | ||
polling for binary files. | ||
([see list of binary extensions](https://github.com/sindresorhus/binary-extensions/blob/master/binary-extensions.json)) | ||
* `awaitWriteFinish` (default: `false`). | ||
By default, the `add` event will fire when a file first appear on disk, before | ||
the entire file has been written. Furthermore, in some cases some `change` | ||
events will be emitted while the file is being written. | ||
In some cases, especially when watching for large files there will be a need to | ||
wait for the write operation to finish before responding to the file creation. | ||
Setting `awaitWriteFinish` to `true` (or a truthy value) will poll a newly | ||
created file size, holding its `add` and `change` events until the size does not | ||
change for a configurable amount of time. The appropriate duration setting is | ||
heavily dependent on the OS and hardware. For accurate detection this parameter | ||
should be relatively high, making file watching much less responsive. | ||
Use with caution. | ||
* *`options.awaitWriteFinish` can be set to an object in order to adjust | ||
timing params:* | ||
* `awaitWriteFinish.stabilityThreshold` (default: 2000). Amount of time in | ||
milliseconds for a file size to remain constant before emitting its event. | ||
* `awaitWriteFinish.pollInterval` (default: 100). File size polling interval. | ||
@@ -194,5 +232,6 @@ #### Errors | ||
* `.on(event, callback)`: Listen for an FS event. | ||
Available events: `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `ready`, `raw`, `error`. | ||
Additionally `all` is available which gets emitted with the underlying event name | ||
and path for every event other than `ready`, `raw`, and `error`. | ||
Available events: `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `ready`, | ||
`raw`, `error`. | ||
Additionally `all` is available which gets emitted with the underlying event | ||
name and path for every event other than `ready`, `raw`, and `error`. | ||
* `.unwatch(path / paths)`: Stop watching files, directories, or glob patterns. | ||
@@ -204,3 +243,5 @@ Takes an array of strings or just one string. | ||
If you need a CLI interface for your file watching, check out [chokidar-cli](https://github.com/kimmobrunfeldt/chokidar-cli) which allows you to either execute a command on each change, or get a stdio stream of change events. | ||
If you need a CLI interface for your file watching, check out | ||
[chokidar-cli](https://github.com/kimmobrunfeldt/chokidar-cli), allowing you to | ||
execute a command on each change, or get a stdio stream of change events. | ||
@@ -207,0 +248,0 @@ ## Install Troubleshooting |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
69769
1248
273
10
+ Addedlodash.flatten@^3.0.2
+ Addedlodash._baseflatten@3.1.4(transitive)
+ Addedlodash._isiterateecall@3.0.9(transitive)
+ Addedlodash.flatten@3.0.2(transitive)
+ Addedlodash.isarguments@3.1.0(transitive)
+ Addedlodash.isarray@3.0.4(transitive)