fs-walk.js/lib/walk.js

129 lines
3.3 KiB
JavaScript
Raw Normal View History

2010-11-21 05:02:53 +00:00
(function () {
var fs = require('fs'),
Futures = require('futures'),
joinPath = require('path').join,
util = require('util'),
dir = process.argv[2];
function sortNodesByType(stats, o) {
if (stats.isFile()) {
o.files.push(stats);
} else if (stats.isDirectory()) {
o.dirs.push(stats);
} else if (stats.isBlockDevice()) {
o.blocks.push(stats);
} else if (stats.isCharacterDevice()) {
o.chars.push(stats);
} else if (stats.isSymbolicLink()) {
o.links.push(stats);
} else if (stats.isFIFO()) {
o.fifos.push(stats);
} else if (stats.isSocket()) {
o.sockets.push(stats);
} else {
util.debug(stats.node + 'is not of any node type');
}
}
/*
import os
from os.path import join, getsize
for root, dirs, files in os.walk('python/Lib/email'):
print root, "consumes",
print sum(getsize(join(root, name)) for name in files),
print "bytes in", len(files), "non-directory files"
if 'CVS' in dirs:
dirs.remove('CVS') # don't visit CVS directories
*/
/*
fs.walk(path, function ({ err, root, dirs, files }) {}, {
// currently ignored
topdown: boolean,
onerror: boolean, // ignored
followlinks: boolean // lstat or stat
});
*/
function walk(firstPath, options, callback) {
options = options || {};
var fstat = options.followlinks ? fs.stat : fs.lstat,
subscription = Futures.subscription();
if (callback) { subscription.subscribe(callback); }
function readDir(path) {
var p = Futures.promise();
fs.readdir(path, function (err, files) {
if (err) {
err.path = path;
subscription.deliver(err, path, undefined, undefined);
// Signal the completion of this readdir attempt
p.fulfill();
return;
}
// TODO fix futures sequence to not require a first function like this
var s = Futures.sequence(function(n){n();}),
nodes = [],
o = {
errors: [],
files: [],
dirs: [],
blocks: [],
chars: [],
links: [],
fifos: [],
sockets: []
};
files.forEach(function (file) {
s.then(function (next) {
fstat(joinPath(path, file), function (err, stats) {
stats = stats || {};
stats.name = file;
nodes.push(stats);
if (err) {
stats.err = err;
o.errors.push(stats);
} else {
sortNodesByType(stats, o);
}
next();
});
});
});
s.then(function (next) {
var s2 = Futures.sequence(function(n){n();});
subscription.deliver(undefined, path, nodes, o);
p.fulfill();
o.dirs.forEach(function (dir) {
s2.then(function (next2) {
readDir(joinPath(path, dir.name))
.when(function () { next2(); });
});
});
next();
});
});
return p.passable();
}
readDir(firstPath) //.whenever(callback);
return {
whenever: subscription.subscribe
}
}
module.exports = walk;
}());