Comparing version 0.8.2 to 0.8.3
105
index.js
@@ -6,2 +6,3 @@ 'use strict'; | ||
var sysPath = require('path'); | ||
var fsevents, recursiveReaddir; | ||
@@ -13,12 +14,4 @@ try { | ||
var __slice = [].slice; | ||
var createFSEventsInstance = function(path, callback) { | ||
var watcher = new fsevents.FSEvents(path); | ||
watcher.on('fsevent', callback); | ||
return watcher; | ||
}; | ||
var nodeVersion = process.versions.node.substring(0, 3); | ||
var directoryEndRe = /[\\\/]$/; | ||
var platform = os.platform(); | ||
var canUseFsEvents = platform === 'darwin' && fsevents; | ||
var isWindows = os.platform() === 'win32'; | ||
var canUseFsEvents = os.platform() === 'darwin' && !!fsevents; | ||
@@ -30,8 +23,6 @@ // To disable FSEvents completely. | ||
var _binExts = ['adp', 'au', 'mid', 'mp4a', 'mpga', 'oga', 's3m', 'sil', 'eol', 'dra', 'dts', 'dtshd', 'lvp', 'pya', 'ecelp4800', 'ecelp7470', 'ecelp9600', 'rip', 'weba', 'aac', 'aif', 'caf', 'flac', 'mka', 'm3u', 'wax', 'wma', 'wav', 'xm', 'flac', '3gp', '3g2', 'h261', 'h263', 'h264', 'jpgv', 'jpm', 'mj2', 'mp4', 'mpeg', 'ogv', 'qt', 'uvh', 'uvm', 'uvp', 'uvs', 'dvb', 'fvt', 'mxu', 'pyv', 'uvu', 'viv', 'webm', 'f4v', 'fli', 'flv', 'm4v', 'mkv', 'mng', 'asf', 'vob', 'wm', 'wmv', 'wmx', 'wvx', 'movie', 'smv', 'ts', 'bmp', 'cgm', 'g3', 'gif', 'ief', 'jpg', 'jpeg', 'ktx', 'png', 'btif', 'sgi', 'svg', 'tiff', 'psd', 'uvi', 'sub', 'djvu', 'dwg', 'dxf', 'fbs', 'fpx', 'fst', 'mmr', 'rlc', 'mdi', 'wdp', 'npx', 'wbmp', 'xif', 'webp', '3ds', 'ras', 'cmx', 'fh', 'ico', 'pcx', 'pic', 'pnm', 'pbm', 'pgm', 'ppm', 'rgb', 'tga', 'xbm', 'xpm', 'xwd', 'zip', 'rar', 'tar', 'bz2', 'eot', 'ttf', 'woff']; | ||
var binExts = Object.create(null); | ||
_binExts.forEach(function(ext) { binExts[ext] = true; }); | ||
_binExts.forEach(function(extension) { | ||
return binExts[extension] = true; | ||
}); | ||
var isBinary = function(extension) { | ||
@@ -70,2 +61,3 @@ if (extension === '') return false; | ||
this.watchers = []; | ||
this.closed = false; | ||
@@ -77,3 +69,3 @@ // Set up default options. | ||
if (opts.binaryInterval == null) opts.binaryInterval = 300; | ||
if (opts.usePolling == null) opts.usePolling = platform !== 'win32'; | ||
if (opts.usePolling == null) opts.usePolling = (!isWindows && !canUseFsEvents); | ||
if (opts.useFsEvents == null) { | ||
@@ -116,6 +108,7 @@ opts.useFsEvents = !opts.usePolling && canUseFsEvents; | ||
var directoryEndRegex = /[\\\/]$/; | ||
FSWatcher.prototype._getWatchedDir = function(directory) { | ||
var _base; | ||
var dir = directory.replace(directoryEndRe, ''); | ||
return (_base = this.watched)[dir] != null ? (_base = this.watched)[dir] : _base[dir] = []; | ||
var dir = directory.replace(directoryEndRegex, ''); | ||
if (this.watched[dir] == null) { this.watched[dir] = []; } | ||
return this.watched[dir]; | ||
}; | ||
@@ -163,10 +156,8 @@ | ||
// if it is not a directory, nestedDirectoryChildren will be empty array | ||
var fullPath, isDirectory, nestedDirectoryChildren, | ||
_this = this; | ||
fullPath = sysPath.join(directory, item); | ||
isDirectory = this.watched[fullPath]; | ||
var fullPath = sysPath.join(directory, item); | ||
var isDirectory = this.watched[fullPath]; | ||
// This will create a new entry in the watched object in either case | ||
// so we got to do the directory check beforehand | ||
nestedDirectoryChildren = this._getWatchedDir(fullPath).slice(); | ||
var nestedDirectoryChildren = this._getWatchedDir(fullPath).slice(); | ||
@@ -178,4 +169,4 @@ // Remove directory / file from watched list. | ||
nestedDirectoryChildren.forEach(function(nestedItem) { | ||
return _this._remove(fullPath, nestedItem); | ||
}); | ||
return this._remove(fullPath, nestedItem); | ||
}, this); | ||
@@ -191,2 +182,9 @@ if (this.options.usePolling) fs.unwatchFile(fullPath); | ||
// FS Events helper. | ||
var createFSEventsInstance = function(path, callback) { | ||
var watcher = new fsevents.FSEvents(path); | ||
watcher.on('fsevent', callback); | ||
return watcher; | ||
}; | ||
FSWatcher.prototype._watchWithFsEvents = function(path) { | ||
@@ -235,5 +233,3 @@ var _this = this; | ||
var basename, directory, options, parent, watcher; | ||
if (callback == null) { | ||
callback = (function() {}); | ||
} | ||
if (callback == null) callback = Function.prototype; // empty function | ||
directory = sysPath.dirname(item); | ||
@@ -248,3 +244,4 @@ basename = sysPath.basename(item); | ||
if (this.options.usePolling) { | ||
options.interval = this.enableBinaryInterval && isBinaryPath(basename) ? this.options.binaryInterval : this.options.interval; | ||
options.interval = this.enableBinaryInterval && isBinaryPath(basename) ? | ||
this.options.binaryInterval : this.options.interval; | ||
fs.watchFile(item, options, function(curr, prev) { | ||
@@ -263,2 +260,18 @@ if (curr.mtime.getTime() > prev.mtime.getTime()) { | ||
// Workaround for the "Windows rough edge" regarding the deletion of directories | ||
// (https://github.com/joyent/node/issues/4337) | ||
FSWatcher.prototype._emitError = function(error) { | ||
var emit = (function() { | ||
this.emit('error', error); | ||
}).bind(this); | ||
if (isWindows && error.code === 'EPERM') { | ||
fs.exists(item, function(exists) { | ||
if (exists) emit(); | ||
}); | ||
} else { | ||
emit(); | ||
} | ||
}; | ||
// Private: Emit `change` event once and watch file to emit it in the future | ||
@@ -293,3 +306,3 @@ // once the file is changed. | ||
return fs.readdir(directory, function(error, current) { | ||
if (error != null) return _this.emit('error', error); | ||
if (error != null) return _this._emitError(error); | ||
if (!current) return; | ||
@@ -336,7 +349,12 @@ | ||
if (this._isIgnored(item)) return; | ||
if (_this.closed) return; | ||
return fs.realpath(item, function(error, path) { | ||
if (_this.closed) return; | ||
if (error && error.code === 'ENOENT') return; | ||
if (error != null) return _this.emit('error', error); | ||
if (error != null) return _this._emitError(error); | ||
fs.stat(path, function(error, stats) { | ||
if (error != null) return _this.emit('error', error); | ||
if (_this.closed) return; | ||
if (error && error.code === 'ENOENT') return; | ||
if (error != null) return _this._emitError(error); | ||
if (_this.options.ignorePermissionErrors && (!_this._hasReadPermissions(stats))) { | ||
@@ -354,8 +372,9 @@ return; | ||
FSWatcher.prototype.emit = function() { | ||
var args, event; | ||
event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; | ||
EventEmitter.prototype.emit.apply(this, [event].concat(__slice.call(args))); | ||
if (event === 'add' || event === 'addDir' || event === 'change' || event === 'unlink' || event === 'unlinkDir') { | ||
return EventEmitter.prototype.emit.apply(this, ['all', event].concat(__slice.call(args))); | ||
FSWatcher.prototype.emit = function(event, arg1) { | ||
var data = arguments.length === 2 ? [arg1] : [].slice.call(arguments, 1); | ||
var args = [event].concat(data); | ||
EventEmitter.prototype.emit.apply(this, args); | ||
if (event === 'add' || event === 'addDir' || event === 'change' || | ||
event === 'unlink' || event === 'unlinkDir') { | ||
EventEmitter.prototype.emit.apply(this, ['all'].concat(args)); | ||
} | ||
@@ -372,7 +391,7 @@ }; | ||
fs.stat(file, function(error, stats) { | ||
if (error != null) return _this.emit('error', error); | ||
if (error != null) return _this._emitError(error); | ||
if (stats.isDirectory()) { | ||
recursiveReaddir(file, function(error, dirFiles) { | ||
if (error != null) return _this.emit('error', error); | ||
if (error != null) return _this._emitError(error); | ||
dirFiles.filter(function(path) { | ||
@@ -417,4 +436,10 @@ return !_this._isIgnored(path); | ||
FSWatcher.prototype.close = function() { | ||
if(this.closed) { | ||
return this; | ||
} | ||
var useFsEvents = this.options.useFsEvents; | ||
var method = useFsEvents ? 'stop' : 'close'; | ||
this.closed = true; | ||
this.watchers.forEach(function(watcher) { | ||
@@ -421,0 +446,0 @@ watcher[method](); |
{ | ||
"name": "chokidar", | ||
"description": "A neat wrapper around node.js fs.watch / fs.watchFile.", | ||
"version": "0.8.2", | ||
"version": "0.8.3", | ||
"keywords": [ | ||
@@ -10,2 +10,3 @@ "fs", | ||
"watcher", | ||
"watching", | ||
"file" | ||
@@ -12,0 +13,0 @@ ], |
@@ -9,4 +9,5 @@ # Chokidar | ||
* Doesn't report filenames on mac. | ||
* Doesn't report events at all when using editors like Sublime on mac. | ||
* Doesn't report filenames on OS X. | ||
* Doesn't report events at all when using editors like Sublime on OS X. | ||
* Doesn't use OS X internals for **fast low-CPU watching on OS X** (no other fs watch module does this!). | ||
* Sometimes reports events twice. | ||
@@ -13,0 +14,0 @@ * Has only one non-useful event: `rename`. |
136
test.js
@@ -36,2 +36,38 @@ 'use strict'; | ||
}); | ||
describe('close', function() { | ||
before(function() { | ||
try { | ||
fs.unlinkSync(getFixturePath('add.txt')); | ||
} catch(err) {} | ||
}); | ||
after(function() { | ||
this.watcher.close(); | ||
try { | ||
fs.unlinkSync(getFixturePath('add.txt')); | ||
} catch(err) {} | ||
}); | ||
it('should ignore further events on close', function(done) { | ||
this.watcher = chokidar.watch(fixturesPath, {}); | ||
var spy, watcher = this.watcher; | ||
spy = sinon.spy(); | ||
watcher.once('add', function() { | ||
watcher.once('add', function() { | ||
watcher.close().on('add', spy); | ||
delay(function() { | ||
spy.should.not.have.been.called; | ||
done(); | ||
}); | ||
}); | ||
}); | ||
fs.writeFileSync(getFixturePath('add.txt'), 'hello world'); | ||
}); | ||
}); | ||
describe('watch', function() { | ||
@@ -42,4 +78,4 @@ var options; | ||
this.watcher = chokidar.watch(fixturesPath, options); | ||
return delay(function() { | ||
return done(); | ||
delay(function() { | ||
done(); | ||
}); | ||
@@ -50,4 +86,4 @@ }); | ||
delete this.watcher; | ||
return delay(function() { | ||
return done(); | ||
delay(function() { | ||
done(); | ||
}); | ||
@@ -90,12 +126,48 @@ }); | ||
this.watcher.on('add', spy); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.not.have.been.called; | ||
fs.writeFileSync(testPath, 'hello'); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.have.been.calledOnce; | ||
spy.should.have.been.calledWith(testPath); | ||
return done(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it.skip('should emit single `add` event for single file added', function(done) { | ||
var spy, spy2, testPath, testPath2, _this = this; | ||
spy = sinon.spy(); | ||
spy2 = sinon.spy(); | ||
testPath = getFixturePath('add.txt'); | ||
testPath2 = getFixturePath('add2.txt'); | ||
this.watcher.on('add', spy); | ||
delay(function() { | ||
spy.should.not.have.been.called; | ||
fs.writeFileSync(testPath, 'hello'); | ||
delay(function() { | ||
spy.should.have.been.calledOnce; | ||
spy.should.have.been.calledWith(testPath); | ||
this.watcher.on('add', spy2); | ||
delay(function(){ | ||
spy2.should.not.have.been.called; | ||
fs.writeFileSync(testPath2, 'hello'); | ||
delay(function(){ | ||
spy2.should.have.been.calledOnce; | ||
spy2.should.have.been.calledWith(testPath2); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
it('should emit `addDir` event when directory was added', function(done) { | ||
@@ -107,9 +179,9 @@ var spy, testDir, | ||
this.watcher.on('addDir', spy); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.not.have.been.called; | ||
fs.mkdirSync(testDir, 0x1ed); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.have.been.calledOnce; | ||
spy.should.have.been.calledWith(testDir); | ||
return done(); | ||
done(); | ||
}); | ||
@@ -124,9 +196,9 @@ }); | ||
this.watcher.on('change', spy); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.not.have.been.called; | ||
fs.writeFileSync(testPath, 'c'); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.have.been.calledOnce; | ||
spy.should.have.been.calledWith(testPath); | ||
return done(); | ||
done(); | ||
}); | ||
@@ -141,9 +213,9 @@ }); | ||
this.watcher.on('unlink', spy); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.not.have.been.called; | ||
fs.unlinkSync(testPath); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.have.been.calledOnce; | ||
spy.should.have.been.calledWith(testPath); | ||
return done(); | ||
done(); | ||
}); | ||
@@ -158,8 +230,8 @@ }); | ||
this.watcher.on('unlinkDir', spy); | ||
return delay(function() { | ||
delay(function() { | ||
fs.rmdirSync(testDir); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.have.been.calledOnce; | ||
spy.should.have.been.calledWith(testDir); | ||
return done(); | ||
done(); | ||
}); | ||
@@ -181,10 +253,10 @@ }); | ||
this.watcher.add(testDir); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.not.have.been.callled; | ||
fs.mkdirSync(testDir, 0x1ed); | ||
fs.writeFileSync(testPath, 'hello'); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.have.been.calledOnce; | ||
spy.should.have.been.calledWith(testPath); | ||
return done(); | ||
done(); | ||
}); | ||
@@ -213,3 +285,3 @@ }); | ||
} catch (_error) {} | ||
return done(); | ||
done(); | ||
}); | ||
@@ -229,3 +301,3 @@ after(function(done) { | ||
} catch (_error) {} | ||
return done(); | ||
done(); | ||
}); | ||
@@ -238,6 +310,6 @@ it('should ignore inital add events', function(done) { | ||
watcher.on('add', spy); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.not.have.been.called; | ||
watcher.close(); | ||
return done(); | ||
done(); | ||
}); | ||
@@ -253,3 +325,3 @@ }); | ||
watcher.on('add', spy); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.not.have.been.called; | ||
@@ -259,6 +331,6 @@ fs.mkdirSync(testDir, 0x1ed); | ||
fs.writeFileSync(testPath, 'hello'); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.have.been.calledOnce; | ||
spy.should.have.been.calledWith(testPath); | ||
return done(); | ||
done(); | ||
}); | ||
@@ -288,6 +360,6 @@ }); | ||
fs.writeFileSync(testDir + '/dir/ignored.txt', ''); | ||
return delay(function() { | ||
delay(function() { | ||
spy.should.have.been.calledOnce; | ||
spy.should.have.been.calledWith(testDir + '/add.txt'); | ||
return done(); | ||
spy.should.have.been.calledWith(sysPath.join(testDir, 'add.txt')); | ||
done(); | ||
}); | ||
@@ -294,0 +366,0 @@ }); |
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
35016
726
123