very very very asynchronous now
This commit is contained in:
parent
106bd60d9b
commit
6bcf64a422
|
@ -0,0 +1,156 @@
|
|||
(function (undefined) {
|
||||
var fs = require('fs'),
|
||||
upath = require('path'),
|
||||
util = require('util'),
|
||||
Futures = require('futures'),
|
||||
events = require('events');
|
||||
|
||||
function create(path, options) {
|
||||
// TODO add types by listener dynamically
|
||||
var emitter = new events.EventEmitter(),
|
||||
oneNodeEvents = [
|
||||
"file",
|
||||
"directory",
|
||||
"blockDevice",
|
||||
"characterDevice",
|
||||
"symbolicLink",
|
||||
"FIFO",
|
||||
"socket"
|
||||
],
|
||||
oneNodeTypes = [
|
||||
"isFile",
|
||||
"isDirectory",
|
||||
"isBlockDevice",
|
||||
"isCharacterDevice",
|
||||
"isSymbolicLink",
|
||||
"isFIFO",
|
||||
"isSocket"
|
||||
],
|
||||
multiNodeEvents = [
|
||||
// multiple
|
||||
"files",
|
||||
"directories",
|
||||
"blockDevices",
|
||||
"characterDevices",
|
||||
"symbolicLinks",
|
||||
"FIFOs",
|
||||
"sockets"
|
||||
],
|
||||
fstat = (options||{}).followLinks ? fs.stat : fs.lstat;
|
||||
|
||||
function normalize(path) {
|
||||
return path;
|
||||
var index;
|
||||
|
||||
path = upath.normalize(path);
|
||||
index = path.length - 1;
|
||||
if (index > 0 && '/' === path[index]) {
|
||||
path = path.substr(0, index);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
function sortNodesByType(path, stats, nodes, next) {
|
||||
// This could easily be unrolled
|
||||
// but in this case concise was more readable for me
|
||||
oneNodeTypes.forEach(function (isType, i) {
|
||||
if (stats[isType]()) {
|
||||
if (stats.type) { throw new Error("is_" + type + " and " + isType); }
|
||||
stats.type = oneNodeEvents[i];
|
||||
nodes[multiNodeEvents[i]].push(stats);
|
||||
// TODO throw to break;
|
||||
}
|
||||
});
|
||||
if (!stats.type) { throw new Error(upath.join(path, stats.name) + ' isAnUndefinedType'); }
|
||||
function emitSingleEvents(stats, next) {
|
||||
var num;
|
||||
|
||||
// get the current number of listeners (may change)
|
||||
num = 1 + emitter.listeners(stats.type).length + emitter.listeners("node").length;
|
||||
|
||||
function nextWhenReady() {
|
||||
num -= 1;
|
||||
if (0 === num) { next(); }
|
||||
}
|
||||
nextWhenReady();
|
||||
|
||||
// Total number of listeners
|
||||
emitter.emit(stats.type, path, stats, function () {
|
||||
nextWhenReady();
|
||||
});
|
||||
|
||||
emitter.emit("node", path, stats, function () {
|
||||
nextWhenReady();
|
||||
});
|
||||
} // emitSingleEvents
|
||||
emitSingleEvents(stats, next);
|
||||
}
|
||||
|
||||
function getStats(path, files, walkDirs) {
|
||||
var nodes = [], o = {};
|
||||
|
||||
// TODO unroll for better readability
|
||||
multiNodeEvents.forEach(function (eventType) {
|
||||
o[eventType] = [];
|
||||
});
|
||||
|
||||
function nextFile() {
|
||||
var file = files.pop(), dirs = [], fnames = [];
|
||||
|
||||
if (undefined === file) {
|
||||
o.directories.forEach(function (dir) {
|
||||
dirs.push(dir.name);
|
||||
});
|
||||
return walkDirs(dirs);
|
||||
}
|
||||
|
||||
fstat(upath.join(path, file), function (err, stats) {
|
||||
//console.log("`stat`ed file " + file);
|
||||
stats = stats || {};
|
||||
stats.name = file;
|
||||
nodes.push(stats);
|
||||
|
||||
if (err) {
|
||||
stats.error = err
|
||||
// TODO single error emittor
|
||||
o.errors.push(stats);
|
||||
util.debug("[Error 1] " + util.inspect(err));
|
||||
return nextFile();
|
||||
}
|
||||
sortNodesByType(path, stats, o, nextFile);
|
||||
});
|
||||
}
|
||||
nextFile();
|
||||
}
|
||||
|
||||
function walk(path, next) {
|
||||
fs.readdir(path, function (err, nodes) {
|
||||
if (err) { return next(); /*TODO*/ throw err; }
|
||||
getStats(path, nodes, function (dirs) {
|
||||
walkDirs(path, dirs, function () {
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function walkDirs(path, dirs, cb) {
|
||||
function nextDir() {
|
||||
var dir = dirs.pop();
|
||||
if (undefined === dir) {
|
||||
delete dirs;
|
||||
return cb();
|
||||
}
|
||||
walk(upath.join(path, dir), nextDir);
|
||||
}
|
||||
nextDir();
|
||||
}
|
||||
|
||||
walk(normalize(path), function () {
|
||||
//throw Error("hey");
|
||||
//console.log("Utterly Done!");
|
||||
});
|
||||
return emitter;
|
||||
}
|
||||
module.exports = create;
|
||||
}());
|
Loading…
Reference in New Issue