mirror of
https://github.com/nodejs/node.git
synced 2024-12-01 16:10:02 +01:00
d91e10b3bd
PR-URL: https://github.com/nodejs/io.js/pull/2072 Reviewed-By: Yosuke Furukawa <yosuke.furukawa@gmail.com> Reviewed-by: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Alex Kocharin <alex@kocharin.ru>
168 lines
4.7 KiB
JavaScript
168 lines
4.7 KiB
JavaScript
/**
|
|
* @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;
|