diff --git a/CHANGELOG.md b/CHANGELOG.md index 93766073..7f3a7af3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## v3.0.2 +- [Add config parameter for predicate quantifier](https://github.com/dorny/paths-filter/pull/224) + ## v3.0.1 - [Compare base and ref when token is empty](https://github.com/dorny/paths-filter/pull/133) diff --git a/dist/index.js b/dist/index.js index b47bb03b..cc7d7d43 100644 --- a/dist/index.js +++ b/dist/index.js @@ -53,16 +53,53 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.Filter = void 0; +exports.Filter = exports.isPredicateQuantifier = exports.SUPPORTED_PREDICATE_QUANTIFIERS = exports.PredicateQuantifier = void 0; const jsyaml = __importStar(__nccwpck_require__(1917)); const picomatch_1 = __importDefault(__nccwpck_require__(8569)); // Minimatch options used in all matchers const MatchOptions = { dot: true }; +/** + * Enumerates the possible logic quantifiers that can be used when determining + * if a file is a match or not with multiple patterns. + * + * The YAML configuration property that is parsed into one of these values is + * 'predicate-quantifier' on the top level of the configuration object of the + * action. + * + * The default is to use 'some' which used to be the hardcoded behavior prior to + * the introduction of the new mechanism. + * + * @see https://en.wikipedia.org/wiki/Quantifier_(logic) + */ +var PredicateQuantifier; +(function (PredicateQuantifier) { + /** + * When choosing 'every' in the config it means that files will only get matched + * if all the patterns are satisfied by the path of the file, not just at least one of them. + */ + PredicateQuantifier["EVERY"] = "every"; + /** + * When choosing 'some' in the config it means that files will get matched as long as there is + * at least one pattern that matches them. This is the default behavior if you don't + * specify anything as a predicate quantifier. + */ + PredicateQuantifier["SOME"] = "some"; +})(PredicateQuantifier || (exports.PredicateQuantifier = PredicateQuantifier = {})); +/** + * An array of strings (at runtime) that contains the valid/accepted values for + * the configuration parameter 'predicate-quantifier'. + */ +exports.SUPPORTED_PREDICATE_QUANTIFIERS = Object.values(PredicateQuantifier); +function isPredicateQuantifier(x) { + return exports.SUPPORTED_PREDICATE_QUANTIFIERS.includes(x); +} +exports.isPredicateQuantifier = isPredicateQuantifier; class Filter { // Creates instance of Filter and load rules from YAML if it's provided - constructor(yaml) { + constructor(yaml, filterConfig) { + this.filterConfig = filterConfig; this.rules = {}; if (yaml) { this.load(yaml); @@ -89,7 +126,16 @@ class Filter { return result; } isMatch(file, patterns) { - return patterns.some(rule => (rule.status === undefined || rule.status.includes(file.status)) && rule.isMatch(file.filename)); + var _a; + const aPredicate = (rule) => { + return (rule.status === undefined || rule.status.includes(file.status)) && rule.isMatch(file.filename); + }; + if (((_a = this.filterConfig) === null || _a === void 0 ? void 0 : _a.predicateQuantifier) === 'every') { + return patterns.every(aPredicate); + } + else { + return patterns.some(aPredicate); + } } parseFilterItemYaml(item) { if (Array.isArray(item)) { @@ -528,11 +574,18 @@ async function run() { const filtersYaml = isPathInput(filtersInput) ? getConfigFileContent(filtersInput) : filtersInput; const listFiles = core.getInput('list-files', { required: false }).toLowerCase() || 'none'; const initialFetchDepth = parseInt(core.getInput('initial-fetch-depth', { required: false })) || 10; + const predicateQuantifier = core.getInput('predicate-quantifier', { required: false }) || filter_1.PredicateQuantifier.SOME; if (!isExportFormat(listFiles)) { core.setFailed(`Input parameter 'list-files' is set to invalid value '${listFiles}'`); return; } - const filter = new filter_1.Filter(filtersYaml); + if (!(0, filter_1.isPredicateQuantifier)(predicateQuantifier)) { + const predicateQuantifierInvalidErrorMsg = `Input parameter 'predicate-quantifier' is set to invalid value ` + + `'${predicateQuantifier}'. Valid values: ${filter_1.SUPPORTED_PREDICATE_QUANTIFIERS.join(', ')}`; + throw new Error(predicateQuantifierInvalidErrorMsg); + } + const filterConfig = { predicateQuantifier }; + const filter = new filter_1.Filter(filtersYaml, filterConfig); const files = await getChangedFiles(token, base, ref, initialFetchDepth); core.info(`Detected ${files.length} changed files`); const results = filter.match(files); diff --git a/src/filter.ts b/src/filter.ts index 2b201fb2..1947ef88 100644 --- a/src/filter.ts +++ b/src/filter.ts @@ -73,7 +73,7 @@ export class Filter { rules: {[key: string]: FilterRuleItem[]} = {} // Creates instance of Filter and load rules from YAML if it's provided - constructor(yaml?: string, public readonly filterConfig?: FilterConfig) { + constructor(yaml?: string, readonly filterConfig?: FilterConfig) { if (yaml) { this.load(yaml) } @@ -104,7 +104,7 @@ export class Filter { } private isMatch(file: File, patterns: FilterRuleItem[]): boolean { - const aPredicate = (rule: Readonly) => { + const aPredicate = (rule: Readonly): boolean => { return (rule.status === undefined || rule.status.includes(file.status)) && rule.isMatch(file.filename) } if (this.filterConfig?.predicateQuantifier === 'every') {