/* | |
MIT License http://www.opensource.org/licenses/mit-license.php | |
Author Tobias Koppers @sokra | |
*/ | |
"use strict"; | |
var watcherManager = require("./watcherManager"); | |
var EventEmitter = require("events").EventEmitter; | |
function Watchpack(options) { | |
EventEmitter.call(this); | |
if(!options) options = {}; | |
if(!options.aggregateTimeout) options.aggregateTimeout = 200; | |
this.options = options; | |
this.watcherOptions = { | |
ignored: options.ignored, | |
poll: options.poll | |
}; | |
this.fileWatchers = []; | |
this.dirWatchers = []; | |
this.mtimes = Object.create(null); | |
this.paused = false; | |
this.aggregatedChanges = []; | |
this.aggregatedRemovals = []; | |
this.aggregateTimeout = 0; | |
this._onTimeout = this._onTimeout.bind(this); | |
} | |
module.exports = Watchpack; | |
Watchpack.prototype = Object.create(EventEmitter.prototype); | |
Watchpack.prototype.watch = function watch(files, directories, startTime) { | |
this.paused = false; | |
var oldFileWatchers = this.fileWatchers; | |
var oldDirWatchers = this.dirWatchers; | |
this.fileWatchers = files.map(function(file) { | |
return this._fileWatcher(file, watcherManager.watchFile(file, this.watcherOptions, startTime)); | |
}, this); | |
this.dirWatchers = directories.map(function(dir) { | |
return this._dirWatcher(dir, watcherManager.watchDirectory(dir, this.watcherOptions, startTime)); | |
}, this); | |
oldFileWatchers.forEach(function(w) { | |
w.close(); | |
}, this); | |
oldDirWatchers.forEach(function(w) { | |
w.close(); | |
}, this); | |
}; | |
Watchpack.prototype.close = function resume() { | |
this.paused = true; | |
if(this.aggregateTimeout) | |
clearTimeout(this.aggregateTimeout); | |
this.fileWatchers.forEach(function(w) { | |
w.close(); | |
}, this); | |
this.dirWatchers.forEach(function(w) { | |
w.close(); | |
}, this); | |
this.fileWatchers.length = 0; | |
this.dirWatchers.length = 0; | |
}; | |
Watchpack.prototype.pause = function pause() { | |
this.paused = true; | |
if(this.aggregateTimeout) | |
clearTimeout(this.aggregateTimeout); | |
}; | |
function addWatchersToArray(watchers, array) { | |
watchers.forEach(function(w) { | |
if(array.indexOf(w.directoryWatcher) < 0) { | |
array.push(w.directoryWatcher); | |
addWatchersToArray(Object.keys(w.directoryWatcher.directories).reduce(function(a, dir) { | |
if(w.directoryWatcher.directories[dir] !== true) | |
a.push(w.directoryWatcher.directories[dir]); | |
return a; | |
}, []), array); | |
} | |
}); | |
} | |
Watchpack.prototype.getTimes = function() { | |
var directoryWatchers = []; | |
addWatchersToArray(this.fileWatchers.concat(this.dirWatchers), directoryWatchers); | |
var obj = Object.create(null); | |
directoryWatchers.forEach(function(w) { | |
var times = w.getTimes(); | |
Object.keys(times).forEach(function(file) { | |
obj[file] = times[file]; | |
}); | |
}); | |
return obj; | |
}; | |
Watchpack.prototype._fileWatcher = function _fileWatcher(file, watcher) { | |
watcher.on("change", function(mtime, type) { | |
this._onChange(file, mtime, file, type); | |
}.bind(this)); | |
watcher.on("remove", function(type) { | |
this._onRemove(file, file, type); | |
}.bind(this)); | |
return watcher; | |
}; | |
Watchpack.prototype._dirWatcher = function _dirWatcher(item, watcher) { | |
watcher.on("change", function(file, mtime, type) { | |
this._onChange(item, mtime, file, type); | |
}.bind(this)); | |
return watcher; | |
}; | |
Watchpack.prototype._onChange = function _onChange(item, mtime, file) { | |
file = file || item; | |
this.mtimes[file] = mtime; | |
if(this.paused) return; | |
this.emit("change", file, mtime); | |
if(this.aggregateTimeout) | |
clearTimeout(this.aggregateTimeout); | |
if(this.aggregatedChanges.indexOf(item) < 0) | |
this.aggregatedChanges.push(item); | |
this.aggregateTimeout = setTimeout(this._onTimeout, this.options.aggregateTimeout); | |
}; | |
Watchpack.prototype._onRemove = function _onRemove(item, file) { | |
file = file || item; | |
delete this.mtimes[item]; | |
if(this.paused) return; | |
this.emit("remove", item); | |
if(this.aggregateTimeout) | |
clearTimeout(this.aggregateTimeout); | |
if(this.aggregatedRemovals.indexOf(item) < 0) | |
this.aggregatedRemovals.push(item); | |
this.aggregateTimeout = setTimeout(this._onTimeout, this.options.aggregateTimeout); | |
}; | |
Watchpack.prototype._onTimeout = function _onTimeout() { | |
this.aggregateTimeout = 0; | |
var changes = this.aggregatedChanges; | |
var removals = this.aggregatedRemovals; | |
this.aggregatedChanges = []; | |
this.aggregatedRemovals = []; | |
this.emit("aggregated", changes, removals); | |
}; |