Check if full test suite result is cached (stdlib only, no ci.* imports). Verifies that: 1. Full run cache file exists 2. Last run result was "pass" 3. build.ninja hasn't been modified 4. Source files (src/, tests/, and optionally examples/) haven't changed Mirrors
(
build_dir: Path, include_examples: bool = False
)
| 280 | |
| 281 | |
| 282 | def full_run_cache( |
| 283 | build_dir: Path, include_examples: bool = False |
| 284 | ) -> tuple[int, int, float] | None: |
| 285 | """Check if full test suite result is cached (stdlib only, no ci.* imports). |
| 286 | |
| 287 | Verifies that: |
| 288 | 1. Full run cache file exists |
| 289 | 2. Last run result was "pass" |
| 290 | 3. build.ninja hasn't been modified |
| 291 | 4. Source files (src/, tests/, and optionally examples/) haven't changed |
| 292 | |
| 293 | Mirrors ci/meson/cache_utils.check_full_run_cache() without importing |
| 294 | that module. |
| 295 | |
| 296 | Args: |
| 297 | build_dir: Meson build directory. |
| 298 | include_examples: If True, also check examples/ for changes. |
| 299 | |
| 300 | Returns: |
| 301 | Tuple of (num_passed, num_tests, duration) on cache hit, else None. |
| 302 | """ |
| 303 | cache_file = build_dir / ".full_run_cache.json" |
| 304 | if not cache_file.exists(): |
| 305 | return None |
| 306 | try: |
| 307 | with open(cache_file, "r", encoding="utf-8") as f: |
| 308 | saved = json.load(f) |
| 309 | if saved.get("result") != "pass": |
| 310 | return None |
| 311 | build_ninja = build_dir / "build.ninja" |
| 312 | if not build_ninja.exists(): |
| 313 | return None |
| 314 | if ( |
| 315 | abs(build_ninja.stat().st_mtime - saved.get("build_ninja_mtime", -1.0)) |
| 316 | > 0.001 |
| 317 | ): |
| 318 | return None |
| 319 | # Check meson.build files (detects build config changes) |
| 320 | _meson_files = [ |
| 321 | Path("meson.build"), |
| 322 | Path("tests/meson.build"), |
| 323 | Path("ci/meson/native/meson.build"), |
| 324 | Path("ci/meson/wasm/meson.build"), |
| 325 | Path("examples/meson.build"), |
| 326 | ] |
| 327 | _meson_max = 0.0 |
| 328 | for mf in _meson_files: |
| 329 | try: |
| 330 | _meson_max = max(_meson_max, mf.stat().st_mtime) |
| 331 | except OSError: |
| 332 | pass |
| 333 | if _meson_max > saved.get("meson_max_file_mtime", -1.0) + 0.001: |
| 334 | return None |
| 335 | # Check src/ max source file mtime (detects src/ code changes). |
| 336 | # Previously used libfastled.a mtime as a proxy, but libfastled.a is only |
| 337 | # updated AFTER ninja runs. Scanning src/ files directly is correct. |
| 338 | src_max = max_file_mtime(Path("src")) |
| 339 | if src_max > saved.get("src_max_file_mtime", -1.0) + 0.001: |
no test coverage detected