Incremental update: re-parse changed + dependent files only.
(
repo_root: Path,
store: GraphStore,
base: str = "HEAD~1",
changed_files: list[str] | None = None,
)
| 917 | |
| 918 | |
| 919 | def incremental_update( |
| 920 | repo_root: Path, |
| 921 | store: GraphStore, |
| 922 | base: str = "HEAD~1", |
| 923 | changed_files: list[str] | None = None, |
| 924 | ) -> dict: |
| 925 | """Incremental update: re-parse changed + dependent files only.""" |
| 926 | parser = CodeParser(repo_root) |
| 927 | ignore_patterns = _load_ignore_patterns(repo_root) |
| 928 | |
| 929 | # Determine changed files |
| 930 | if changed_files is None: |
| 931 | changed_files = get_changed_files(repo_root, base) |
| 932 | |
| 933 | if not changed_files: |
| 934 | return { |
| 935 | "files_updated": 0, |
| 936 | "total_nodes": 0, |
| 937 | "total_edges": 0, |
| 938 | "changed_files": [], |
| 939 | "dependent_files": [], |
| 940 | } |
| 941 | |
| 942 | # Find dependent files (files that import from changed files) |
| 943 | dependent_files: set[str] = set() |
| 944 | for rel_path in changed_files: |
| 945 | full_path = str(repo_root / rel_path) |
| 946 | deps = find_dependents(store, full_path) |
| 947 | for d in deps: |
| 948 | # Convert back to relative path if needed |
| 949 | try: |
| 950 | dependent_files.add(str(Path(d).relative_to(repo_root))) |
| 951 | except ValueError: |
| 952 | dependent_files.add(d) |
| 953 | |
| 954 | # Combine changed + dependent |
| 955 | all_files = set(changed_files) | dependent_files |
| 956 | |
| 957 | total_nodes = 0 |
| 958 | total_edges = 0 |
| 959 | errors = [] |
| 960 | |
| 961 | # Separate deleted/unparseable files from files that need re-parsing |
| 962 | to_parse: list[str] = [] |
| 963 | removed_any = False |
| 964 | for rel_path in all_files: |
| 965 | if _should_ignore(rel_path, ignore_patterns): |
| 966 | continue |
| 967 | abs_path = repo_root / rel_path |
| 968 | if not abs_path.is_file(): |
| 969 | store.remove_file_data(str(abs_path)) |
| 970 | removed_any = True |
| 971 | continue |
| 972 | if parser.detect_language(abs_path) is None: |
| 973 | continue |
| 974 | # Quick hash check to skip unchanged files |
| 975 | try: |
| 976 | raw = abs_path.read_bytes() |