1 | var EventEmitter = require('events').EventEmitter
|
2 | var watchDirs = require('./utils').watchDirs
|
3 | var readdir = require('recursive-readdir')
|
4 | var async = require('async-collection')
|
5 | var assert = require('assert')
|
6 | var path = require('path')
|
7 | var fs = require('fs')
|
8 |
|
9 | var READ_CONCURRENCY = 3
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | module.exports = Tracker
|
19 |
|
20 | function Tracker () {
|
21 | if (!(this instanceof Tracker)) return new Tracker()
|
22 | this._unwatch = null
|
23 | this.watching = false
|
24 | this.count = 0
|
25 | this.files = {}
|
26 | EventEmitter.call(this)
|
27 | }
|
28 | Tracker.prototype = Object.create(EventEmitter.prototype)
|
29 |
|
30 | Tracker.prototype.start = function (basedir, dirnames, opts) {
|
31 | var list = []
|
32 | var count = 0
|
33 | opts = opts || {}
|
34 | var watch = opts.watch === undefined ? false : opts.watch
|
35 |
|
36 | assert.equal(typeof basedir, 'string', 'lib/track-dir: basedir should be type string')
|
37 | assert.ok(Array.isArray(dirnames), 'lib/track-dir: basedir should be an Array')
|
38 | assert.equal(this.watching, false, 'lib/track-dir: already watching a set of directories')
|
39 |
|
40 |
|
41 | async.mapLimit(dirnames, 1, init, function (err) {
|
42 | if (err) return self.emit('error', err)
|
43 |
|
44 | async.mapLimit(list, READ_CONCURRENCY, wrap, function (err) {
|
45 | if (err) return self.emit('error', err)
|
46 | self.emit('progress', 100)
|
47 | self.emit('change')
|
48 | })
|
49 |
|
50 | function wrap (filename, done) {
|
51 | readFile(filename, function (err) {
|
52 | if (err) return done(err)
|
53 | self.emit('progress', Math.trunc((count / list.length) * 100))
|
54 | done()
|
55 | })
|
56 | }
|
57 | })
|
58 |
|
59 | var self = this
|
60 |
|
61 | if (watch) {
|
62 | var unwatch = watchDirs(basedir, dirnames, function (filePath) {
|
63 | readFile(filePath, function (err) {
|
64 | if (err) return self.emit('error', err)
|
65 | self.emit('change')
|
66 | })
|
67 | })
|
68 |
|
69 | this.watching = true
|
70 | this._unwatch = unwatch.bind(unwatch)
|
71 | }
|
72 |
|
73 |
|
74 | function init (dirname, done) {
|
75 | dirname = path.join(basedir, dirname)
|
76 | fs.access(dirname, function (err) {
|
77 | if (err) return done()
|
78 | readdir(dirname, function (err, _list) {
|
79 | if (err) return done(err)
|
80 | list = list.concat(_list)
|
81 | done()
|
82 | })
|
83 | })
|
84 | }
|
85 |
|
86 |
|
87 | function readFile (filePath, done) {
|
88 | fs.stat(filePath, function (err, stat) {
|
89 | if (err) {
|
90 | delete self.files[filePath]
|
91 | done()
|
92 | } else {
|
93 | self.files[filePath] = stat
|
94 | done()
|
95 | }
|
96 | })
|
97 | }
|
98 | }
|
99 |
|
100 | Tracker.prototype.unwatch = function () {
|
101 | if (!this.watching) return
|
102 | this._unwatch()
|
103 | }
|
104 |
|
105 | Tracker.prototype.size = function () {
|
106 | var self = this
|
107 | return Object.keys(this.files).reduce(function (size, filename) {
|
108 | var file = self.files[filename]
|
109 | return size + file.size
|
110 | }, 0)
|
111 | }
|
112 |
|
113 | Tracker.prototype.list = function () {
|
114 | return Object.keys(this.files)
|
115 | }
|