sparse_profiles.py (2290B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5 import functools 6 from pathlib import Path 7 8 from gecko_taskgraph import GECKO 9 10 11 @functools.cache 12 def _get_taskgraph_sparse_profile(): 13 """ 14 Parse the taskgraph sparse profile and return the paths and globs it includes. 15 """ 16 17 # We need this nested function to handle %include directives recursively 18 def parse(profile_path): 19 paths = set() 20 globs = set() 21 22 full_path = Path(GECKO) / profile_path 23 if not full_path.exists(): 24 raise FileNotFoundError( 25 f"Sparse profile '{full_path.stem}' not found at {full_path}" 26 ) 27 28 for raw_line in full_path.read_text().splitlines(): 29 line = raw_line.strip() 30 if not line or line.startswith("#") or line.startswith("["): 31 continue 32 if line.startswith("%include "): 33 included_profile = line[len("%include ") :].strip() 34 included_paths, included_globs = parse(included_profile) 35 paths.update(included_paths) 36 globs.update(included_globs) 37 elif line.startswith("path:"): 38 path = line[len("path:") :].strip() 39 paths.add(Path(path)) 40 elif line.startswith("glob:"): 41 glob = line[len("glob:") :].strip() 42 globs.add(glob) 43 44 return paths, globs 45 46 return parse("build/sparse-profiles/taskgraph") 47 48 49 @functools.cache 50 def is_path_covered_by_taskgraph_sparse_profile(path): 51 """ 52 Check if a given path would be included in the taskgraph sparse checkout. 53 """ 54 profile_paths, profile_globs = _get_taskgraph_sparse_profile() 55 path = Path(path) 56 57 for profile_path in profile_paths: 58 if path == profile_path or profile_path in path.parents: 59 return True 60 61 # Path.match requires at least one directory for ** patterns to match 62 # root-level files, so we prepend a fake parent directory 63 path_with_parent = Path("_", path) 64 for pattern in profile_globs: 65 if path_with_parent.match(pattern): 66 return True 67 68 return False