var EventEmitter = require('events').EventEmitter, _fs = require('fs'), _path = require('path'), sep = _path.sep||'/';// 0.6.x module.exports = walkdir; walkdir.find = walkdir.walk = walkdir; walkdir.sync = function(path,options,eventHandler){ if(typeof options == 'function') cb = options; options = options || {}; options.sync = true; return walkdir(path,options,eventHandler); }; // return promise. walkdir.async = function(path,options,eventHandler){ return new Promise((resolve,reject)=>{ if(typeof options == 'function') cb = options; options = options || {}; let emitter = walkdir(path,options,eventHandler) emitter.on('error',reject) emitter.on('fail',(path,err)=>{ err.message = 'Error walking": '+path+' '+err.message if(err) reject(err) }) let allPaths = {} emitter.on('path',(path,stat)=>{ if(options.no_return !== true) allPaths[path] = stat; }) emitter.on('end',()=>{ if(options.no_return !== true){ return resolve(options.return_object?allPaths:Object.keys(allPaths)) } resolve() }) }) } function walkdir(path,options,cb){ if(typeof options == 'function') cb = options; options = options || {}; if(options.find_links === undefined){ options.find_links = true; } var fs = options.fs || _fs; var emitter = new EventEmitter(), dontTraverse = [], allPaths = (options.return_object?{}:[]), resolved = false, inos = {}, stop = 0, pause = null, ended = 0, jobs=0, job = function(value) { jobs += value; if(value < 1 && !tick) { tick = 1; process.nextTick(function(){ tick = 0; if(jobs <= 0 && !ended) { ended = 1; emitter.emit('end'); } }); } }, tick = 0; emitter.ignore = function(path){ if(Array.isArray(path)) dontTraverse.push.apply(dontTraverse,path) else dontTraverse.push(path) return this } //mapping is stat functions to event names. var statIs = [['isFile','file'],['isDirectory','directory'],['isSymbolicLink','link'],['isSocket','socket'],['isFIFO','fifo'],['isBlockDevice','blockdevice'],['isCharacterDevice','characterdevice']]; var statter = function (path,first,depth) { job(1); var statAction = function fn(err,stat,data) { job(-1); if(stop) return; // in sync mode i found that node will sometimes return a null stat and no error =( // this is reproduceable in file descriptors that no longer exist from this process // after a readdir on /proc/3321/task/3321/ for example. Where 3321 is this pid // node @ v0.6.10 if(err || !stat) { emitter.emit('fail',path,err); return; } //if i have evented this inode already dont again. var fileName = _path.basename(path); var fileKey = stat.dev + '-' + stat.ino + '-' + fileName; if(options.track_inodes !== false) { if(inos[fileKey] && stat.ino) return; inos[fileKey] = 1; } if (first && stat.isDirectory()) { emitter.emit('targetdirectory',path,stat,depth); return; } emitter.emit('path', path, stat, depth); var i,name; for(var j=0,k=statIs.length;j= options.max_depth){ emitter.emit('maxdepth',path,stat,depth); return; } if(dontTraverse.length){ for(var i=0;i{ job(-1) for(var i=0,j=files.length;i