Just convert the pattern into a RegExp...

This commit is contained in:
Simon Engledew 2020-12-01 20:56:07 +00:00
parent 4d862616ce
commit 698e2a5487
No known key found for this signature in database
GPG key ID: 84302E7B02FE8BCE
9 changed files with 62 additions and 107 deletions

View file

@ -281,7 +281,9 @@ test("patternIsSuperset()", (t) => {
t.false(actionsutil.patternIsSuperset("feature-*", "**"));
t.false(actionsutil.patternIsSuperset("a/**/c", "a/**/d"));
t.false(actionsutil.patternIsSuperset("a/**/c", "a/**"));
t.true(actionsutil.patternIsSuperset("a/**", "a/**/c"));
t.true(actionsutil.patternIsSuperset("a/**/c", "a/main-**/c"));
t.false(actionsutil.patternIsSuperset("a/**/b/**/c", "a/**/d/**/c"));
t.false(actionsutil.patternIsSuperset("a/main-**/c", "a/**/c"));
t.true(
actionsutil.patternIsSuperset(

View file

@ -134,69 +134,36 @@ function isObject(o: unknown): o is object {
return o !== null && typeof o === "object";
}
const WORKSPACE_BRANCES_PATTERN = new RegExp("(\\*\\*?|/)");
const GLOB_PATTERN = new RegExp("(\\*\\*?)");
function tokenize(value: string): string[] {
return value.split(WORKSPACE_BRANCES_PATTERN).reduce(function (arr, cur) {
if (cur) {
arr.push(cur);
}
return arr;
}, [] as ReturnType<typeof tokenize>);
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}
function considerToken(
a: string,
b: string
): { advance: boolean; consume: boolean } {
switch (a) {
case "*":
return { advance: b === "/", consume: b !== "/" };
case "**":
return { advance: false, consume: true };
default:
return { advance: a === b, consume: a === b };
}
}
function tokensAreSuperset(tokensA: string[], tokensB: string[]) {
let indexA = 0;
let indexB = 0;
let advance;
let consume = true;
while (advance || consume) {
const currentA = tokensA[indexA];
const currentB = tokensB[indexB];
if (currentB === undefined) {
return true;
}
if (currentA === undefined) {
return false;
}
const next = considerToken(currentA, currentB);
advance = next.advance;
consume = next.consume;
if (consume) {
indexB += 1;
}
if (advance) {
indexA += 1;
}
}
return false;
function patternToRegExp(value) {
return new RegExp(
`^${value
.split(GLOB_PATTERN)
.reduce(function (arr, cur) {
if (cur) {
if (cur === "**") {
arr.push(".*?");
} else if (cur === "*") {
arr.push("[^/]*?");
} else {
arr.push(escapeRegExp(cur));
}
}
return arr;
}, [])
.join("")}$`
);
}
// this function should return true if patternA is a superset of patternB
// e.g: * is a superset of main-* but main-* is not a superset of *.
export function patternIsSuperset(patternA: string, patternB: string): boolean {
const tokensA = tokenize(patternA);
const tokensB = tokenize(patternB);
return tokensAreSuperset(tokensA, tokensB) && tokensAreSuperset(tokensA.reverse(), tokensB.reverse());
return patternToRegExp(patternA).test(patternB);
}
function branchesToArray(branches?: string | null | string[]): string[] | "**" {

View file

@ -101,7 +101,9 @@ async function run() {
// we do not want to worry users if linting is failing
// but we do want to send a status report containing this error code
// below
const userWorkflowErrors = workflowErrors.filter(o => o.code !== 'LintFailed');
const userWorkflowErrors = workflowErrors.filter(
(o) => o.code !== "LintFailed"
);
if (userWorkflowErrors.length > 0) {
core.warning(actionsUtil.formatWorkflowErrors(userWorkflowErrors));