UNPKG

2.65 kBJavaScriptView Raw
1(function () {
2 "use strict"
3
4 // Array.prototype.forEachAsync(next, item, i, collection)
5 require('futures/forEachAsync');
6
7 function noop() {}
8
9 var fs = require('fs'),
10 path = require('path'),
11 EventEmitter = require('events').EventEmitter,
12 TypeEmitter = require('./node-type-emitter');
13
14 // 2010-11-25 jorge@jorgechamorro.com
15 function create(pathname, cb) {
16 var emitter = new EventEmitter(),
17 q = [],
18 queue = [q],
19 curpath;
20
21 function walk() {
22 fs.readdir(curpath, function(err, files) {
23 if (err) {
24 emitter.emit('directoryError', curpath, { error: err }, noop);
25 //emitter.emit('error', curpath, { error: err });
26 }
27 // XXX bug was here. next() was omitted
28 if (!files || 0 == files.length) {
29 return next();
30 }
31
32 var fnodeGroups = TypeEmitter.createNodeGroups();
33
34 // TODO could allow user to selectively stat
35 // and don't stat if there are no stat listeners
36 emitter.emit('names', curpath, files, noop);
37 files.forEachAsync(function (cont, file) {
38 emitter.emit('name', curpath, file, noop);
39 fs.lstat(curpath + path.sep + file, function (err, stat) {
40 stat = stat || {};
41 stat.name = file;
42 if (err) {
43 stat.error = err;
44 //emitter.emit('error', curpath, stat);
45 emitter.emit('nodeError', curpath, stat, noop);
46 fnodeGroups.errors.push(stat);
47 cont();
48 } else {
49 TypeEmitter.sortFnodesByType(stat, fnodeGroups);
50 TypeEmitter.emitNodeType(emitter, curpath, stat, cont);
51 }
52 });
53 }).then(function () {
54 if (fnodeGroups.errors.length) {
55 emitter.emit('errors', curpath, fnodeGroups.errors, noop);
56 }
57 TypeEmitter.emitNodeTypeGroups(emitter, curpath, fnodeGroups, function () {
58 var dirs = [];
59 fnodeGroups.directories.forEach(function (stat) {
60 dirs.push(stat.name);
61 });
62 dirs.forEach(fullPath);
63 queue.push(q = dirs);
64 next();
65 });
66 });
67 });
68 }
69
70 function next() {
71 if (q.length) {
72 curpath = q.pop();
73 return walk();
74 }
75 if (queue.length -= 1) {
76 q = queue[queue.length-1];
77 return next();
78 }
79 emitter.emit('end');
80 }
81
82 function fullPath(v,i,o) {
83 o[i]= [curpath, path.sep, v].join('');
84 }
85
86 curpath = pathname;
87 walk();
88
89 return emitter;
90 }
91
92 module.exports = create;
93}());