UNPKG

2.45 kBJavaScriptView Raw
1'use strict';
2
3var fs = require('fs')
4 , path = require('path')
5 , readdirp = require('readdirp')
6 , utl = require('./utl')
7 , log = require('./log')
8 , watchers = {}
9 , watchedDirs = {}
10 ;
11
12function dateEqual(d1, d2) {
13 return d1.toGMTString() === d2.toGMTString();
14}
15
16function watchFile(entry, eventName, startedWatching, update) {
17 var fullPath = entry.fullPath;
18
19 if (watchers[fullPath]) return;
20 startedWatching(entry);
21
22 fs.watch(fullPath, { persistent: false }, function (event) {
23 if (event !== eventName) return;
24
25 var prevStat = watchers[fullPath].stat
26 , entry = watchers[fullPath].entry
27
28 fs.stat(fullPath, function (err, stat) {
29 if (err) return log.error('watcher', err);
30
31 // ignore atime changes (read access)
32 if ( prevStat
33 && dateEqual(prevStat.mtime, stat.mtime)
34 && dateEqual(prevStat.ctime, stat.ctime)) return;
35
36 watchers[fullPath].stat = stat
37 update(entry);
38 });
39 });
40}
41
42function watchTree(options, addedWatch, update, watching) {
43
44 function startedWatching(entry) {
45 watchers[entry.fullPath] = { lastChange: new Date(), entry: entry };
46 addedWatch({ entry: entry, all: watchers });
47 }
48
49 function watchDir(fullPath) {
50 if (watchedDirs[fullPath]) return;
51 watchedDirs[fullPath] = true;
52
53 fs.watch(fullPath, { persistent: false }, function (event) {
54 if (event !== 'rename') return;
55 var cloned = utl.shallowClone(options);
56
57 cloned.depth = 0;
58 cloned.root = fullPath;
59
60 readdirp(cloned)
61 .on('warn', log.error)
62 .on('error', log.error)
63 .on('data', function (entry) {
64 try {
65 watchFile(entry, 'change', startedWatching, update);
66 } catch(e) {
67 log.error('Not watching: ' + entry.path);
68 }
69 });
70 });
71 }
72
73 readdirp(options)
74 .on('warn', log.error)
75 .on('error', log.error)
76 .on('data', function (entry) {
77 try {
78 watchFile(entry, 'change', startedWatching, update);
79 watchDir(entry.fullParentDir, utl.shallowClone(options), watching, update);
80 } catch(e) {
81 log.error('Not watching: ' + entry.path);
82 }
83 })
84 .on('end', function () {
85 watchDir(options.root, utl.shallowClone(options), watching, update);
86 if (watching) watching(watchers);
87 });
88}
89
90module.exports = {
91 watchFile: watchFile
92 , watchTree: watchTree
93};