Mtime-based fast-path for fingerprint checks. If the fingerprint file for *name* is NEWER than all source file mtimes in *dirs*, AND the stored status is "success", we can skip the expensive rglob + SHA-256 hash computation entirely. Returns True if the fas
(
self,
name: str,
*dirs: Path,
exts: frozenset[str] | None = None,
)
| 167 | return self._prev_fingerprints.get(name) |
| 168 | |
| 169 | def _mtime_fast_path( |
| 170 | self, |
| 171 | name: str, |
| 172 | *dirs: Path, |
| 173 | exts: frozenset[str] | None = None, |
| 174 | ) -> bool: |
| 175 | """ |
| 176 | Mtime-based fast-path for fingerprint checks. |
| 177 | |
| 178 | If the fingerprint file for *name* is NEWER than all source file mtimes in |
| 179 | *dirs*, AND the stored status is "success", we can skip the expensive |
| 180 | rglob + SHA-256 hash computation entirely. |
| 181 | |
| 182 | Returns True if the fast-path fired (fingerprint up-to-date, no change), |
| 183 | False if the full computation is needed. |
| 184 | |
| 185 | Side effects on True: populates _prev_fingerprints[name] and |
| 186 | _fingerprints[name] so that save_all() behaves correctly. |
| 187 | |
| 188 | Uses file-level mtime scanning (not directory-level) to correctly detect |
| 189 | content-only modifications. On NTFS/ext4, directory mtimes do NOT update |
| 190 | when a file's content changes (only on file create/delete), so the previous |
| 191 | directory-only approach could produce false "no change" results. |
| 192 | |
| 193 | Args: |
| 194 | name: Fingerprint cache name |
| 195 | *dirs: Directories to scan for source file changes |
| 196 | exts: File extensions to scan (default: _CPP_SOURCE_EXTS). |
| 197 | Pass _PY_SOURCE_EXTS for Python test fingerprinting. |
| 198 | |
| 199 | Overhead: ~20-70ms per call (file-level scanning of source files). |
| 200 | Savings: ~200-400ms vs full SHA-256 computation when no changes detected. |
| 201 | """ |
| 202 | fp_file = self._get_fingerprint_file(name) |
| 203 | if not fp_file.exists(): |
| 204 | return False |
| 205 | try: |
| 206 | fp_mtime = fp_file.stat().st_mtime |
| 207 | max_file_mtime = max( |
| 208 | (_get_max_source_file_mtime(d, exts=exts) for d in dirs), default=0.0 |
| 209 | ) |
| 210 | if max_file_mtime > fp_mtime: |
| 211 | return False # a source file was modified after fingerprint write |
| 212 | prev = self.read(name) |
| 213 | if prev is None or prev.status != "success": |
| 214 | return False # no previous result or previous run failed |
| 215 | # Fast-path fires: record the cached result without running the calculator |
| 216 | self._prev_fingerprints[name] = prev |
| 217 | self._fingerprints[name] = FingerprintResult(hash=prev.hash) |
| 218 | return True |
| 219 | except OSError: |
| 220 | return False |
| 221 | |
| 222 | def check_cpp(self, args: TestArgs) -> bool: |
| 223 | cwd = Path.cwd() |
no test coverage detected