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.

138 lines
3.8 KiB

/**
* @fileoverview Responsible for loading ignore config files and managing ignore patterns
* @author Jonathan Rajavuori
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
var fs = require("fs"),
debug = require("debug"),
minimatch = require("minimatch"),
FileFinder = require("./file-finder");
debug = debug("eslint:ignored-paths");
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
var ESLINT_IGNORE_FILENAME = ".eslintignore";
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Load and parse ignore patterns from the file at the given path
* @param {string} filepath Path to the ignore file.
* @returns {string[]} An array of ignore patterns or an empty array if no ignore file.
*/
function loadIgnoreFile(filepath) {
var ignorePatterns = [];
function nonEmpty(line) {
return line.trim() !== "" && line[0] !== "#";
}
if (filepath) {
try {
ignorePatterns = fs.readFileSync(filepath, "utf8").split(/\r?\n/).filter(nonEmpty);
} catch (e) {
e.message = "Cannot read ignore file: " + filepath + "\nError: " + e.message;
throw e;
}
}
return ["node_modules/**"].concat(ignorePatterns);
}
var ignoreFileFinder;
/**
* Find an ignore file in the current directory or a parent directory.
* @returns {string} Path of ignore file or an empty string.
*/
function findIgnoreFile() {
if (!ignoreFileFinder) {
ignoreFileFinder = new FileFinder(ESLINT_IGNORE_FILENAME);
}
return ignoreFileFinder.findInDirectoryOrParents();
}
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
/**
* IgnoredPaths
* @constructor
* @class IgnoredPaths
* @param {Array} patterns to be matched against file paths
*/
function IgnoredPaths(patterns) {
this.patterns = patterns;
}
/**
* IgnoredPaths initializer
* @param {Object} options object containing 'ignore' and 'ignorePath' properties
* @returns {IgnoredPaths} object, with patterns loaded from the ignore file
*/
IgnoredPaths.load = function (options) {
var patterns;
options = options || {};
if (options.ignore) {
patterns = loadIgnoreFile(options.ignorePath || findIgnoreFile());
} else {
patterns = [];
}
if (options.ignorePattern) {
patterns.push(options.ignorePattern);
}
return new IgnoredPaths(patterns);
};
/**
* Determine whether a file path is included in the configured ignore patterns
* @param {string} filepath Path to check
* @returns {boolean} true if the file path matches one or more patterns, false otherwise
*/
IgnoredPaths.prototype.contains = function (filepath) {
if (this.patterns === null) {
throw new Error("No ignore patterns loaded, call 'load' first");
}
filepath = filepath.replace("\\", "/");
filepath = filepath.replace(/^\.\//, "");
return this.patterns.reduce(function(ignored, pattern) {
var negated = pattern[0] === "!",
matches;
if (negated) {
pattern = pattern.slice(1);
}
// Remove leading "current folder" prefix
if (pattern.indexOf("./") === 0) {
pattern = pattern.slice(2);
}
matches = minimatch(filepath, pattern) || minimatch(filepath, pattern + "/**");
return matches ? !negated : ignored;
}, false);
};
module.exports = IgnoredPaths;