-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
101 lines (84 loc) · 2.55 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
var EventEmitter = require('events').EventEmitter
var debug = require('debug')('file-watch')
var inherits = require('util').inherits
var equal = require('array-equal')
var exclude = require('exclude')
var watch = require('fs').watch
var exists = require('fs').existsSync
module.exports = Watcher
inherits(Watcher, EventEmitter)
function Watcher() {
if (!(this instanceof Watcher)) return new Watcher()
this.onerror = this.onerror.bind(this)
// name -> files lookup
this.map = {}
// filename -> watcher lookup
this.watchers = {}
}
Watcher.prototype.watch = function (name, files) {
debug('watching %s: %s', name, files.join(', '))
var self = this
var map = this.map
var onerror = this.onerror
var watchers = this.watchers
// create a watcher for this file if not already
files.forEach(function (filename) {
// already watching
if (watchers[filename]) return
// watch the file
addWatcher()
function addWatcher() {
if (!exists(filename)) return debug('%s does not exist', filename)
watchers[filename] = watch(filename, {
persistent: true
}, function (event) {
// filename is not guaranteed to be emitted with fs.watch,
// so we make sure to emit `filename` ourselves.
debug('%s: %s', event, filename)
self.emit(name, filename)
self.emit('change', filename)
if (event === 'rename') readdWatcher()
}).on('error', function (err) {
onerror(err)
readdWatcher()
})
}
function readdWatcher() {
watchers[filename].close()
delete watchers[filename]
addWatcher()
}
})
var older = map[name]
if (older && !equal(files, older)) {
delete map[name]
var names = Object.keys(map)
debug('diffing %s against %s', files.join(', '), older.join(', '))
// remove files that we no longer care for
exclude(older, files).forEach(function (filename) {
// still has listeners, ignore
for (var i = 0; i < names.length; i++)
if (~map[names[i]].indexOf(filename))
return
debug('unwatching %s', filename)
// no more listeners, so just close it
watchers[filename].close()
delete watchers[filename]
})
}
map[name] = files
return this
}
Watcher.prototype.close =
Watcher.prototype.destroy = function () {
debug('destroyed')
Object.keys(this.watchers).forEach(function (filename) {
this.watchers[filename].close()
}, this)
this.map = {}
this.watchers = {}
return this
}
Watcher.prototype.onerror = function (err) {
if (err) this.emit('error', err)
}