mirror of
https://github.com/dorny/paths-filter.git
synced 2025-06-08 10:01:34 +00:00
Replace picomatch with micromatch
Using micromatch, removed `added|modified` rule to simplify the rules. The idea is to extend the output with things like `anyModified` or `anyDeleted` instead of putting that into the matcher rules to keep the matcher rules in sync with `micromatch` rules
This commit is contained in:
parent
1ec7035ff5
commit
6706fee383
5 changed files with 18279 additions and 795 deletions
|
@ -1,5 +1,5 @@
|
|||
import * as jsyaml from 'js-yaml'
|
||||
import picomatch from 'picomatch'
|
||||
import micromatch from 'micromatch'
|
||||
import {File, ChangeStatus} from './file'
|
||||
|
||||
// Type definition of object we expect to load from YAML
|
||||
|
@ -8,19 +8,18 @@ interface FilterYaml {
|
|||
}
|
||||
type FilterItemYaml =
|
||||
| string // Filename pattern, e.g. "path/to/*.js"
|
||||
| {[changeTypes: string]: string | string[]} // Change status and filename, e.g. added|modified: "path/to/*.js"
|
||||
| FilterItemYaml[] // Supports referencing another rule via YAML anchor
|
||||
|
||||
// Minimatch options used in all matchers
|
||||
const MatchOptions = {
|
||||
// Micromatch options used in all matchers
|
||||
const MatchOptions: micromatch.Options = {
|
||||
dot: true
|
||||
}
|
||||
|
||||
// Internal representation of one item in named filter rule
|
||||
// Created as simplified form of data in FilterItemYaml
|
||||
interface FilterRuleItem {
|
||||
status?: ChangeStatus[] // Required change status of the matched files
|
||||
isMatch: (str: string) => boolean // Matches the filename
|
||||
/** returns the list of matched files */
|
||||
matcher: (files: string[]) => string[]
|
||||
}
|
||||
|
||||
export interface FilterResults {
|
||||
|
@ -28,7 +27,7 @@ export interface FilterResults {
|
|||
}
|
||||
|
||||
export class Filter {
|
||||
rules: {[key: string]: FilterRuleItem[]} = {}
|
||||
rules: {[key: string]: string[]} = {}
|
||||
|
||||
// Creates instance of Filter and load rules from YAML if it's provided
|
||||
constructor(yaml?: string) {
|
||||
|
@ -49,49 +48,32 @@ export class Filter {
|
|||
}
|
||||
|
||||
for (const [key, item] of Object.entries(doc)) {
|
||||
this.rules[key] = this.parseFilterItemYaml(item)
|
||||
this.rules[key] = this.getPatterns(item)
|
||||
}
|
||||
}
|
||||
|
||||
match(files: File[]): FilterResults {
|
||||
const result: FilterResults = {}
|
||||
const filesMap = files.reduce((result, x) => {
|
||||
result.set(x.filename, x)
|
||||
return result
|
||||
}, new Map<string, File>())
|
||||
|
||||
for (const [key, patterns] of Object.entries(this.rules)) {
|
||||
result[key] = files.filter(file => this.isMatch(file, patterns))
|
||||
const matchingFileNames = micromatch([...filesMap.keys()], patterns, MatchOptions)
|
||||
result[key] = matchingFileNames.map(x => filesMap.get(x)).filter((x): x is File => !!x)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private isMatch(file: File, patterns: FilterRuleItem[]): boolean {
|
||||
return patterns.some(
|
||||
rule => (rule.status === undefined || rule.status.includes(file.status)) && rule.isMatch(file.filename)
|
||||
)
|
||||
}
|
||||
|
||||
private parseFilterItemYaml(item: FilterItemYaml): FilterRuleItem[] {
|
||||
private getPatterns(item: FilterItemYaml): string[] {
|
||||
if (Array.isArray(item)) {
|
||||
return flat(item.map(i => this.parseFilterItemYaml(i)))
|
||||
return flat(item.map(i => this.getPatterns(i)))
|
||||
}
|
||||
|
||||
if (typeof item === 'string') {
|
||||
return [{status: undefined, isMatch: picomatch(item, MatchOptions)}]
|
||||
}
|
||||
|
||||
if (typeof item === 'object') {
|
||||
return Object.entries(item).map(([key, pattern]) => {
|
||||
if (typeof key !== 'string' || (typeof pattern !== 'string' && !Array.isArray(pattern))) {
|
||||
this.throwInvalidFormatError(
|
||||
`Expected [key:string]= pattern:string | string[], but [${key}:${typeof key}]= ${pattern}:${typeof pattern} found`
|
||||
)
|
||||
}
|
||||
return {
|
||||
status: key
|
||||
.split('|')
|
||||
.map(x => x.trim())
|
||||
.filter(x => x.length > 0)
|
||||
.map(x => x.toLowerCase()) as ChangeStatus[],
|
||||
isMatch: picomatch(pattern, MatchOptions)
|
||||
}
|
||||
})
|
||||
return [item]
|
||||
}
|
||||
|
||||
this.throwInvalidFormatError(`Unexpected element type '${typeof item}'`)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue