const REGEX_SPECIAL = /[.+^${}()|[\]\\]/g;
/** Glob matching for ref and path filters: `*` matches within a segment, `**` across segments, `?` one char. */
export function globToRegExp(pattern: string): RegExp {
let source = "";
for (let index = 0; index < pattern.length; index++) {
const char = pattern[index];
if (char === "*") {
if (pattern[index + 1] === "*") {
source += ".*";
index++;
if (pattern[index + 1] === "/") index++;
} else {
source += "[^/]*";
}
} else if (char === "?") {
source += "[^/]";
} else {
source += char.replace(REGEX_SPECIAL, "\\$&");
}
}
return new RegExp(`^${source}$`);
}
export function matchesGlob(pattern: string, value: string): boolean {
return globToRegExp(pattern).test(value);
}
/** GitHub-style filters: patterns prefixed with `!` exclude; the last matching pattern wins. */
export function matchesFilters(patterns: string[], value: string): boolean {
let matched = false;
for (const pattern of patterns) {
if (pattern.startsWith("!")) {
if (matchesGlob(pattern.slice(1), value)) matched = false;
} else if (matchesGlob(pattern, value)) {
matched = true;
}
}
return matched;
}