You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

167 lines
4.7 KiB

/**
* @fileoverview Util class to find config files.
* @author Aliaksei Shytkin
* @copyright 2014 Michael McLaughlin. All rights reserved.
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
var fs = require("fs"),
path = require("path");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Get the entries for a directory. Including a try-catch may be detrimental to
* function performance, so move it out here a separate function.
* @param {string} directory The directory to search in.
* @returns {string[]} The entries in the directory or an empty array on error.
* @private
*/
function getDirectoryEntries(directory) {
try {
return fs.readdirSync(directory);
} catch (ex) {
return [];
}
}
//------------------------------------------------------------------------------
// API
//------------------------------------------------------------------------------
/**
* FileFinder
* @constructor
* @param {...string} arguments The basename(s) of the file(s) to find.
*/
function FileFinder() {
this.fileNames = Array.prototype.slice.call(arguments);
this.cache = {};
}
/**
* Find one instance of a specified file name in directory or in a parent directory.
* Cache the results.
* Does not check if a matching directory entry is a file, and intentionally
* only searches for the first file name in this.fileNames.
* Is currently used by lib/ignored_paths.js to find an .eslintignore file.
* @param {string} directory The directory to start the search from.
* @returns {string} Path of the file found, or an empty string if not found.
*/
FileFinder.prototype.findInDirectoryOrParents = function (directory) {
var cache = this.cache,
child,
dirs,
filePath,
i,
name,
searched;
if (!directory) {
directory = process.cwd();
}
if (cache.hasOwnProperty(directory)) {
return cache[directory];
}
dirs = [];
searched = 0;
name = this.fileNames[0];
while (directory !== child) {
dirs[searched++] = directory;
if (getDirectoryEntries(directory).indexOf(name) !== -1 && fs.statSync(path.resolve(directory, name)).isFile()) {
filePath = path.resolve(directory, name);
break;
}
child = directory;
// Assign parent directory to directory.
directory = path.dirname(directory);
}
for (i = 0; i < searched; i++) {
cache[dirs[i]] = filePath;
}
return filePath || String();
};
/**
* Find all instances of files with the specified file names, in directory and
* parent directories. Cache the results.
* Does not check if a matching directory entry is a file.
* Searches for all the file names in this.fileNames.
* Is currently used by lib/config.js to find .eslintrc and package.json files.
* @param {string} directory The directory to start the search from.
* @returns {string[]} The file paths found.
*/
FileFinder.prototype.findAllInDirectoryAndParents = function (directory) {
var cache = this.cache,
child,
dirs,
name,
fileNames,
fileNamesCount,
filePath,
i,
j,
searched;
if (!directory) {
directory = process.cwd();
}
if (cache.hasOwnProperty(directory)) {
return cache[directory];
}
dirs = [];
searched = 0;
fileNames = this.fileNames;
fileNamesCount = fileNames.length;
do {
dirs[searched++] = directory;
cache[directory] = [];
for (i = 0; i < fileNamesCount; i++) {
name = fileNames[i];
if (getDirectoryEntries(directory).indexOf(name) !== -1 && fs.statSync(path.resolve(directory, name)).isFile()) {
filePath = path.resolve(directory, name);
// Add the file path to the cache of each directory searched.
for (j = 0; j < searched; j++) {
cache[dirs[j]].push(filePath);
}
}
}
child = directory;
// Assign parent directory to directory.
directory = path.dirname(directory);
if (directory === child) {
return cache[dirs[0]];
}
} while (!cache.hasOwnProperty(directory));
// Add what has been cached previously to the cache of each directory searched.
for (i = 0; i < searched; i++) {
dirs.push.apply(cache[dirs[i]], cache[directory]);
}
return cache[dirs[0]];
};
module.exports = FileFinder;