1
|
/*
|
2
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
Author Tobias Koppers @sokra
|
4
|
*/
|
5
|
"use strict";
|
6
|
|
7
|
var watcherManager = require("./watcherManager");
|
8
|
var EventEmitter = require("events").EventEmitter;
|
9
|
|
10
|
function Watchpack(options) {
|
11
|
EventEmitter.call(this);
|
12
|
if(!options) options = {};
|
13
|
if(!options.aggregateTimeout) options.aggregateTimeout = 200;
|
14
|
this.options = options;
|
15
|
this.watcherOptions = {
|
16
|
ignored: options.ignored,
|
17
|
poll: options.poll
|
18
|
};
|
19
|
this.fileWatchers = [];
|
20
|
this.dirWatchers = [];
|
21
|
this.mtimes = Object.create(null);
|
22
|
this.paused = false;
|
23
|
this.aggregatedChanges = [];
|
24
|
this.aggregatedRemovals = [];
|
25
|
this.aggregateTimeout = 0;
|
26
|
this._onTimeout = this._onTimeout.bind(this);
|
27
|
}
|
28
|
|
29
|
module.exports = Watchpack;
|
30
|
|
31
|
Watchpack.prototype = Object.create(EventEmitter.prototype);
|
32
|
|
33
|
Watchpack.prototype.watch = function watch(files, directories, startTime) {
|
34
|
this.paused = false;
|
35
|
var oldFileWatchers = this.fileWatchers;
|
36
|
var oldDirWatchers = this.dirWatchers;
|
37
|
this.fileWatchers = files.map(function(file) {
|
38
|
return this._fileWatcher(file, watcherManager.watchFile(file, this.watcherOptions, startTime));
|
39
|
}, this);
|
40
|
this.dirWatchers = directories.map(function(dir) {
|
41
|
return this._dirWatcher(dir, watcherManager.watchDirectory(dir, this.watcherOptions, startTime));
|
42
|
}, this);
|
43
|
oldFileWatchers.forEach(function(w) {
|
44
|
w.close();
|
45
|
}, this);
|
46
|
oldDirWatchers.forEach(function(w) {
|
47
|
w.close();
|
48
|
}, this);
|
49
|
};
|
50
|
|
51
|
Watchpack.prototype.close = function resume() {
|
52
|
this.paused = true;
|
53
|
if(this.aggregateTimeout)
|
54
|
clearTimeout(this.aggregateTimeout);
|
55
|
this.fileWatchers.forEach(function(w) {
|
56
|
w.close();
|
57
|
}, this);
|
58
|
this.dirWatchers.forEach(function(w) {
|
59
|
w.close();
|
60
|
}, this);
|
61
|
this.fileWatchers.length = 0;
|
62
|
this.dirWatchers.length = 0;
|
63
|
};
|
64
|
|
65
|
Watchpack.prototype.pause = function pause() {
|
66
|
this.paused = true;
|
67
|
if(this.aggregateTimeout)
|
68
|
clearTimeout(this.aggregateTimeout);
|
69
|
};
|
70
|
|
71
|
function addWatchersToArray(watchers, array) {
|
72
|
watchers.forEach(function(w) {
|
73
|
if(array.indexOf(w.directoryWatcher) < 0) {
|
74
|
array.push(w.directoryWatcher);
|
75
|
addWatchersToArray(Object.keys(w.directoryWatcher.directories).reduce(function(a, dir) {
|
76
|
if(w.directoryWatcher.directories[dir] !== true)
|
77
|
a.push(w.directoryWatcher.directories[dir]);
|
78
|
return a;
|
79
|
}, []), array);
|
80
|
}
|
81
|
});
|
82
|
}
|
83
|
|
84
|
Watchpack.prototype.getTimes = function() {
|
85
|
var directoryWatchers = [];
|
86
|
addWatchersToArray(this.fileWatchers.concat(this.dirWatchers), directoryWatchers);
|
87
|
var obj = Object.create(null);
|
88
|
directoryWatchers.forEach(function(w) {
|
89
|
var times = w.getTimes();
|
90
|
Object.keys(times).forEach(function(file) {
|
91
|
obj[file] = times[file];
|
92
|
});
|
93
|
});
|
94
|
return obj;
|
95
|
};
|
96
|
|
97
|
Watchpack.prototype._fileWatcher = function _fileWatcher(file, watcher) {
|
98
|
watcher.on("change", function(mtime, type) {
|
99
|
this._onChange(file, mtime, file, type);
|
100
|
}.bind(this));
|
101
|
watcher.on("remove", function(type) {
|
102
|
this._onRemove(file, file, type);
|
103
|
}.bind(this));
|
104
|
return watcher;
|
105
|
};
|
106
|
|
107
|
Watchpack.prototype._dirWatcher = function _dirWatcher(item, watcher) {
|
108
|
watcher.on("change", function(file, mtime, type) {
|
109
|
this._onChange(item, mtime, file, type);
|
110
|
}.bind(this));
|
111
|
return watcher;
|
112
|
};
|
113
|
|
114
|
Watchpack.prototype._onChange = function _onChange(item, mtime, file) {
|
115
|
file = file || item;
|
116
|
this.mtimes[file] = mtime;
|
117
|
if(this.paused) return;
|
118
|
this.emit("change", file, mtime);
|
119
|
if(this.aggregateTimeout)
|
120
|
clearTimeout(this.aggregateTimeout);
|
121
|
if(this.aggregatedChanges.indexOf(item) < 0)
|
122
|
this.aggregatedChanges.push(item);
|
123
|
this.aggregateTimeout = setTimeout(this._onTimeout, this.options.aggregateTimeout);
|
124
|
};
|
125
|
|
126
|
Watchpack.prototype._onRemove = function _onRemove(item, file) {
|
127
|
file = file || item;
|
128
|
delete this.mtimes[item];
|
129
|
if(this.paused) return;
|
130
|
this.emit("remove", item);
|
131
|
if(this.aggregateTimeout)
|
132
|
clearTimeout(this.aggregateTimeout);
|
133
|
if(this.aggregatedRemovals.indexOf(item) < 0)
|
134
|
this.aggregatedRemovals.push(item);
|
135
|
this.aggregateTimeout = setTimeout(this._onTimeout, this.options.aggregateTimeout);
|
136
|
};
|
137
|
|
138
|
Watchpack.prototype._onTimeout = function _onTimeout() {
|
139
|
this.aggregateTimeout = 0;
|
140
|
var changes = this.aggregatedChanges;
|
141
|
var removals = this.aggregatedRemovals;
|
142
|
this.aggregatedChanges = [];
|
143
|
this.aggregatedRemovals = [];
|
144
|
this.emit("aggregated", changes, removals);
|
145
|
};
|