|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
| 3 | +import glob |
3 | 4 | import json |
4 | 5 | import os |
5 | 6 | import pathlib |
| 7 | +import re |
6 | 8 | import typing |
7 | 9 | import uuid |
8 | 10 |
|
|
21 | 23 | GITHUB_ACTIONS_SCOPES_OUTPUT_NAME = "scopes" |
22 | 24 |
|
23 | 25 |
|
| 26 | +# NOTE: We convert the pattern to a compiled regex using `glob.translate`, |
| 27 | +# in order to avoid any potential inconsistency that could arise from |
| 28 | +# running `glob.glob` or pathlib.PurePath.full_match` on a different OS. |
| 29 | +def convert_pattern_to_regex(pattern: str) -> re.Pattern[str]: |
| 30 | + return re.compile( |
| 31 | + glob.translate( |
| 32 | + pattern, |
| 33 | + recursive=True, |
| 34 | + include_hidden=True, |
| 35 | + seps=["/", "\\"], |
| 36 | + ), |
| 37 | + ) |
| 38 | + |
| 39 | + |
24 | 40 | def match_scopes( |
25 | 41 | files: abc.Iterable[str], |
26 | 42 | filters: dict[config.ScopeName, config.FileFilters], |
27 | 43 | ) -> tuple[set[str], dict[str, list[str]]]: |
28 | 44 | scopes_hit: set[str] = set() |
29 | 45 | per_scope: dict[str, list[str]] = {s: [] for s in filters} |
30 | 46 | for f in files: |
31 | | - # NOTE(sileht): we use pathlib.full_match to support **, as fnmatch does not |
32 | | - p = pathlib.PurePosixPath(f) |
33 | 47 | for scope, scope_config in filters.items(): |
34 | 48 | if not scope_config.include and not scope_config.exclude: |
35 | 49 | continue |
36 | 50 |
|
37 | 51 | # Check if file matches any include |
38 | 52 | if scope_config.include: |
39 | 53 | matches_positive = any( |
40 | | - p.full_match(pat) for pat in scope_config.include |
| 54 | + convert_pattern_to_regex(pat).fullmatch(f) |
| 55 | + for pat in scope_config.include |
41 | 56 | ) |
42 | 57 | else: |
43 | 58 | matches_positive = True |
44 | 59 |
|
45 | 60 | # Check if file matches any exclude |
46 | | - matches_negative = any(p.full_match(pat) for pat in scope_config.exclude) |
| 61 | + matches_negative = any( |
| 62 | + convert_pattern_to_regex(pat).fullmatch(f) |
| 63 | + for pat in scope_config.exclude |
| 64 | + ) |
47 | 65 |
|
48 | 66 | # File matches the scope if it matches positive patterns and doesn't match negative patterns |
49 | 67 | if matches_positive and not matches_negative: |
|
0 commit comments