UNPKG

3.3 kBtext/coffeescriptView Raw
1return if global.window
2
3fs = require 'fs'
4np = require 'path'
5util = require './utility'
6
7# watches a directory recursively for file changes
8# will call the listener once for each matching file
9# immediately and then whenever
10# files are changed, deleted or created
11exports.watchDirectory = (dirname, options, listener) ->
12 if not listener?
13 listener = options
14 options = {}
15 options.persistent ?= true
16 options.interval ?= 100
17 options.recursive ?= true
18 # change message for initial pass. Use false for no initial pass.
19 options.initial ?= 'initial'
20 options.exclude ?= util.defaultFileExclude
21
22 filter = (name) ->
23 if util.isMatch name, options.exclude, false
24 false
25 else
26 util.isMatch name, options.include, true
27
28 watchedFiles = {} # filename => bound listener
29
30 notifyListener = (filename, curr, prev, change, async=false) ->
31 if filter filename
32 if async
33 process.nextTick -> listener filename, curr, prev, change
34 else
35 listener filename, curr, prev, change
36
37 fsListener = (filename, depth, curr, prev) ->
38 change =
39 if curr.nlink is 0
40 'deleted'
41 else if prev.nlink is 0
42 'created'
43 else
44 'modified'
45 notifyListener filename, curr, prev, change
46 # we call watchFile again in case children were added
47 if change isnt 'deleted'
48 watchFile filename, depth, curr
49 else
50 unwatchFile filename
51
52 unwatchFile = (filename) ->
53 fs.unwatchFile filename, watchedFiles[filename]
54 delete watchedFiles[filename]
55 allWatchers[filename]--
56
57 watchFile = (filename, depth=0, stats) ->
58 if fs.existsSync filename
59 stats ?= fs.statSync filename
60 if stats.nlink > 0
61 if stats.isDirectory()
62 # also watch all children
63 # exclude directories in exclude list
64 if not util.isMatch filename, options.exclude, false
65 if depth is 0 or options.recursive
66 for child in fs.readdirSync filename
67 child = np.join filename, child
68 watchFile child, depth + 1
69
70 if not watchedFiles[filename]?
71 allWatchers[filename] ?= 0
72 allWatchers[filename]++
73
74 boundListener = fsListener.bind @, filename, depth
75 watchedFiles[filename] = boundListener
76 fs.watchFile filename, options, boundListener
77 if initial
78 notifyListener filename, stats, stats, initial, true
79 return
80
81 initial = options.initial
82 watchFile dirname
83 initial = 'created'
84
85 # console.log("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
86 # console.log(JSON.stringify(allWatchers, null, ' '))
87 # console.log("================" + fs.setMaxListeners)
88 # console.log("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
89
90 # return a function that will unwatch all watched files
91 ->
92 for key of watchedFiles
93 unwatchFile key
94
95allWatchers = {}
96