Spaces:
Sleeping
Sleeping
| var fs = require('fs'), | |
| Path = require('path'), | |
| util = require('util'), | |
| EE = require('events').EventEmitter; | |
| function fsExists(file, cb) { | |
| if (!fs.access) return fs.exists(file, cb); | |
| fs.access(file, function(err) { | |
| cb(err ? false : true); | |
| }); | |
| } | |
| function fsExistsSync(file) { | |
| if (!fs.accessSync) return fs.existsSync(file); | |
| try { | |
| fs.accessSync(file); | |
| } catch(err) { | |
| return false; | |
| } | |
| return true; | |
| } | |
| module.exports = function(dir, iterator, options, callback){ | |
| return FindUp(dir, iterator, options, callback); | |
| }; | |
| function FindUp(dir, iterator, options, callback){ | |
| if (!(this instanceof FindUp)) { | |
| return new FindUp(dir, iterator, options, callback); | |
| } | |
| if(typeof options === 'function'){ | |
| callback = options; | |
| options = {}; | |
| } | |
| options = options || {}; | |
| EE.call(this); | |
| this.found = false; | |
| this.stopPlease = false; | |
| var self = this; | |
| if(typeof iterator === 'string'){ | |
| var file = iterator; | |
| iterator = function(dir, cb){ | |
| return fsExists(Path.join(dir, file), cb); | |
| }; | |
| } | |
| if(callback) { | |
| this.on('found', function(dir){ | |
| if(options.verbose) console.log(('found '+ dir )); | |
| callback(null, dir); | |
| self.stop(); | |
| }); | |
| this.on('end', function(){ | |
| if(options.verbose) console.log('end'); | |
| if(!self.found) callback(new Error('not found')); | |
| }); | |
| this.on('error', function(err){ | |
| if(options.verbose) console.log('error', err); | |
| callback(err); | |
| }); | |
| } | |
| this._find(dir, iterator, options, callback); | |
| } | |
| util.inherits(FindUp, EE); | |
| FindUp.prototype._find = function(dir, iterator, options, callback, currentDepth){ | |
| var self = this; | |
| if (typeof currentDepth !== 'number') currentDepth = 0; | |
| iterator(dir, function(exists){ | |
| if(options.verbose) console.log(('traverse '+ dir)); | |
| if (typeof options.maxdepth === 'number' && options.maxdepth >= 0 && currentDepth > options.maxdepth) { | |
| return self.emit('end'); | |
| } | |
| currentDepth++; | |
| if(exists) { | |
| self.found = true; | |
| self.emit('found', dir); | |
| } | |
| var parentDir = Path.join(dir, '..'); | |
| if (self.stopPlease) return self.emit('end'); | |
| if (dir === parentDir) return self.emit('end'); | |
| if(dir.indexOf('../../') !== -1 ) return self.emit('error', new Error(dir + ' is not correct.')); | |
| self._find(parentDir, iterator, options, callback, currentDepth); | |
| }); | |
| }; | |
| FindUp.prototype.stop = function(){ | |
| this.stopPlease = true; | |
| }; | |
| module.exports.FindUp = FindUp; | |
| module.exports.sync = function(dir, iteratorSync, options){ | |
| if(typeof iteratorSync === 'string'){ | |
| var file = iteratorSync; | |
| iteratorSync = function(dir){ | |
| return fsExistsSync(Path.join(dir, file)); | |
| }; | |
| } | |
| options = options || {}; | |
| var initialDir = dir; | |
| var currentDepth = 0; | |
| while(dir !== Path.join(dir, '..')){ | |
| if (typeof options.maxdepth === 'number' && options.maxdepth >= 0 && currentDepth > options.maxdepth) { | |
| break; | |
| } | |
| currentDepth++; | |
| if(dir.indexOf('../../') !== -1 ) throw new Error(initialDir + ' is not correct.'); | |
| if(iteratorSync(dir)) return dir; | |
| dir = Path.join(dir, '..'); | |
| } | |
| throw new Error('not found'); | |
| }; | |