Fallback: detect changed files by comparing mtime with generation timestamp.
(
repo_path: Path,
metadata: Dict[str, Any],
)
| 190 | |
| 191 | |
| 192 | def _detect_via_mtime( |
| 193 | repo_path: Path, |
| 194 | metadata: Dict[str, Any], |
| 195 | ) -> Optional[Dict[str, Any]]: |
| 196 | """Fallback: detect changed files by comparing mtime with generation timestamp.""" |
| 197 | timestamp_str = metadata.get("generation_info", {}).get("timestamp") |
| 198 | if not timestamp_str: |
| 199 | return None |
| 200 | |
| 201 | try: |
| 202 | from datetime import datetime |
| 203 | prev_time = datetime.fromisoformat(timestamp_str).timestamp() |
| 204 | except (ValueError, TypeError): |
| 205 | return None |
| 206 | |
| 207 | # Language extensions recognized by CodeWiki |
| 208 | source_extensions = { |
| 209 | ".py", ".java", ".js", ".jsx", ".ts", ".tsx", |
| 210 | ".c", ".h", ".cpp", ".hpp", ".cc", ".hh", |
| 211 | ".cs", ".kt", ".kts", |
| 212 | } |
| 213 | |
| 214 | changed: list[str] = [] |
| 215 | for dirpath, dirnames, filenames in os.walk(repo_path): |
| 216 | # Skip hidden dirs and common non-source dirs |
| 217 | dirnames[:] = [ |
| 218 | d for d in dirnames |
| 219 | if not d.startswith(".") and d not in ("node_modules", "__pycache__", "venv", ".venv") |
| 220 | ] |
| 221 | for filename in filenames: |
| 222 | filepath = Path(dirpath) / filename |
| 223 | if filepath.suffix.lower() not in source_extensions: |
| 224 | continue |
| 225 | try: |
| 226 | if filepath.stat().st_mtime > prev_time: |
| 227 | rel_path = filepath.relative_to(repo_path).as_posix() |
| 228 | changed.append(rel_path) |
| 229 | except OSError: |
| 230 | continue |
| 231 | |
| 232 | return {"changed_files": changed, "method": "mtime"} |
| 233 | |
| 234 | |
| 235 | def _find_affected_modules( |