Synchronously indexes a repository in a given context.
(path: str, context: Optional[str] = None)
| 295 | |
| 296 | |
| 297 | def index_helper(path: str, context: Optional[str] = None): |
| 298 | """Synchronously indexes a repository in a given context.""" |
| 299 | time_start = time.time() |
| 300 | path_obj = Path(path).resolve() |
| 301 | # Normalize to forward slashes for cross-platform DB consistency. |
| 302 | # The graph DB always stores paths via Path.resolve().as_posix(), |
| 303 | # so Cypher queries must also use forward slashes on Windows. |
| 304 | repo_path_str = path_obj.as_posix() |
| 305 | index_cwd = path_obj if path_obj.is_dir() else path_obj.parent |
| 306 | services = _initialize_services(context, cwd=index_cwd) |
| 307 | if not all(services[:3]): |
| 308 | _fail_services_init() |
| 309 | |
| 310 | db_manager, graph_builder, code_finder, ctx = services |
| 311 | |
| 312 | if not path_obj.exists(): |
| 313 | console.print(f"[red]Error: Path does not exist: {path_obj}[/red]") |
| 314 | db_manager.close_driver() |
| 315 | raise typer.Exit(code=1) |
| 316 | |
| 317 | indexed_repos = code_finder.list_indexed_repositories() |
| 318 | repo_exists = any_repo_matches_path(indexed_repos, path_obj) |
| 319 | |
| 320 | if repo_exists: |
| 321 | # Check if the repository actually has files (not just an empty node from interrupted indexing) |
| 322 | # Use variable-length path to handle both flat (Repository->File) and |
| 323 | # hierarchical (Repository->Directory->...->File) graph structures |
| 324 | try: |
| 325 | with db_manager.get_driver().session() as session: |
| 326 | result = session.run( |
| 327 | "MATCH (r:Repository {path: $path})-[:CONTAINS*]->(f:File) RETURN count(DISTINCT f) as file_count", |
| 328 | path=repo_path_str |
| 329 | ) |
| 330 | record = result.single() |
| 331 | file_count = record["file_count"] if record else 0 |
| 332 | |
| 333 | if file_count > 0: |
| 334 | console.print(f"[yellow]Repository '{path}' is already indexed with {file_count} files. Skipping.[/yellow]") |
| 335 | console.print("[dim]💡 Tip: Use 'cgc index --force' to re-index[/dim]") |
| 336 | db_manager.close_driver() |
| 337 | return |
| 338 | else: |
| 339 | console.print(f"[yellow]Repository '{path}' exists but has no files (likely interrupted). Re-indexing...[/yellow]") |
| 340 | except Exception as e: |
| 341 | console.print(f"[yellow]Warning: Could not check file count: {e}. Proceeding with indexing...[/yellow]") |
| 342 | |
| 343 | if context and ctx.mode == "named": |
| 344 | if not register_repo_in_context(context, str(path_obj), auto_create=False): |
| 345 | db_manager.close_driver() |
| 346 | raise typer.Exit(code=1) |
| 347 | |
| 348 | console.print(f"Starting indexing for: {path_obj}") |
| 349 | |
| 350 | try: |
| 351 | asyncio.run(_run_index_with_progress(graph_builder, path_obj, is_dependency=False, cgcignore_path=ctx.cgcignore_path)) |
| 352 | time_end = time.time() |
| 353 | elapsed = time_end - time_start |
| 354 | _print_call_resolution_diagnostics(graph_builder) |
no test coverage detected