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.

106 lines
3.1 KiB

/**
* @fileoverview Simple directory traversal logic.
* @author Nicholas C. Zakas
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
var fs = require("fs"),
path = require("path"),
debug = require("debug");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
debug = debug("eslint:traverse");
/**
* Walks a path recursively calling the callback on each file.
* @param {string} name The file or directory path.
* @param {string[]} extensions The file extensions that should cause the callback
* to be called.
* @param {Function} exclude The function to check if file/path should be excluded.
* @param {Function} callback The function to call on each file.
* @returns {void}
* @private
*/
function walk(name, extensions, exclude, callback) {
var stat, basename;
stat = fs.statSync(name);
function traverse(dir, stack) {
stack.push(dir);
fs.readdirSync(path.join.apply(path, stack)).forEach(function(file) {
var filePath, fileStat;
// skip all hidded things (dirs, files, links)
if (file[0] === ".") {
return;
}
filePath = path.join.apply(path, stack.concat([file]));
fileStat = fs.statSync(filePath);
// if this file or directory is excluded from linting, skip over it.
if (exclude && exclude(filePath)) {
// console.log("Ignoring " + filePath);
debug("Ignoring " + filePath);
return;
}
// only call callback for files with correct extensions
if (fileStat.isFile() && extensions.indexOf(path.extname(filePath)) > -1) {
callback(filePath);
} else if (fileStat.isDirectory()) {
traverse(file, stack);
}
});
stack.pop();
}
basename = path.basename(name);
// don't ignore cases like 'eslint ./'
if ((basename !== "." && basename !== ".." && basename[0] === ".") ||
(exclude && exclude(name))) {
debug("Ignoring " + name);
return;
}
// always call callback for any files that are passed on the command line
if (stat.isFile()) {
callback(name);
} else {
traverse(name, []);
}
}
/**
* Traverses multiple directories and calls a callback on each file.
* @param {Object} options The option for the traversal.
* param {string[]} options.files An array of file and directory paths to traverse.
* param {Function} options.exclude The function to check if file/path should be excluded.
* @param {Function} callback A function to call for each file.
* @returns {void}
*/
module.exports = function traverse(options, callback) {
var files = options.files,
exclude = options.exclude,
extensions = options.extensions;
files.forEach(function(file) {
walk(file, extensions, exclude, callback);
});
};