|
2 | 2 |
|
3 | 3 | import rich |
4 | 4 | from rich.panel import Panel |
| 5 | +from rich.status import Status |
5 | 6 |
|
6 | 7 | from codegen import Codebase |
7 | 8 | from codegen.cli.auth.session import CodegenSession |
8 | | -from codegen.cli.git.patch import apply_patch |
9 | | -from codegen.cli.rich.codeblocks import format_command |
10 | | -from codegen.cli.rich.spinners import create_spinner |
11 | 9 | from codegen.cli.utils.function_finder import DecoratedFunction |
12 | 10 |
|
13 | 11 |
|
| 12 | +def parse_codebase(repo_root: Path) -> Codebase: |
| 13 | + """Parse the codebase at the given root. |
| 14 | +
|
| 15 | + Args: |
| 16 | + repo_root: Path to the repository root |
| 17 | +
|
| 18 | + Returns: |
| 19 | + Parsed Codebase object |
| 20 | + """ |
| 21 | + codebase = Codebase(repo_root) |
| 22 | + return codebase |
| 23 | + |
| 24 | + |
14 | 25 | def run_local( |
15 | 26 | session: CodegenSession, |
16 | 27 | function: DecoratedFunction, |
17 | | - apply_local: bool = False, |
18 | 28 | diff_preview: int | None = None, |
19 | 29 | ) -> None: |
20 | 30 | """Run a function locally against the codebase. |
21 | 31 |
|
22 | 32 | Args: |
23 | 33 | session: The current codegen session |
24 | | - function: The function to run (either a DecoratedFunction or Codemod) |
25 | | - apply_local: Whether to apply changes to the local filesystem |
| 34 | + function: The function to run |
26 | 35 | diff_preview: Number of lines of diff to preview (None for all) |
27 | 36 | """ |
28 | | - # Initialize codebase from git repo root |
| 37 | + # Parse codebase and run |
29 | 38 | repo_root = Path(session.git_repo.workdir) |
30 | 39 |
|
31 | | - with create_spinner("Parsing codebase...") as status: |
32 | | - codebase = Codebase(repo_root) |
33 | | - |
34 | | - try: |
35 | | - # Run the function |
36 | | - rich.print(f"Running {function.name} locally...") |
37 | | - result = function.run(codebase) |
38 | | - |
39 | | - if not result: |
40 | | - rich.print("\n[yellow]No changes were produced by this codemod[/yellow]") |
41 | | - return |
42 | | - |
43 | | - # Show diff preview if requested |
44 | | - if diff_preview: |
45 | | - rich.print("") # Add spacing |
46 | | - diff_lines = result.splitlines() |
47 | | - truncated = len(diff_lines) > diff_preview |
48 | | - limited_diff = "\n".join(diff_lines[:diff_preview]) |
49 | | - |
50 | | - if truncated: |
51 | | - if apply_local: |
52 | | - limited_diff += f"\n\n...\n\n[yellow]diff truncated to {diff_preview} lines, view the full change set in your local file system[/yellow]" |
53 | | - else: |
54 | | - limited_diff += f"\n\n...\n\n[yellow]diff truncated to {diff_preview} lines, view the full change set by running with --apply-local[/yellow]" |
55 | | - |
56 | | - panel = Panel(limited_diff, title="[bold]Diff Preview[/bold]", border_style="blue", padding=(1, 2), expand=False) |
57 | | - rich.print(panel) |
58 | | - |
59 | | - # Apply changes if requested |
60 | | - if apply_local: |
61 | | - try: |
62 | | - apply_patch(session.git_repo, f"\n{result}\n") |
63 | | - rich.print("") |
64 | | - rich.print("[green]✓ Changes have been applied to your local filesystem[/green]") |
65 | | - rich.print("[yellow]→ Don't forget to commit your changes:[/yellow]") |
66 | | - rich.print(format_command("git add .")) |
67 | | - rich.print(format_command("git commit -m 'Applied codemod changes'")) |
68 | | - except Exception as e: |
69 | | - rich.print("") |
70 | | - rich.print("[red]✗ Failed to apply changes locally[/red]") |
71 | | - rich.print("\n[yellow]This usually happens when you have uncommitted changes.[/yellow]") |
72 | | - rich.print("\nOption 1 - Save your changes:") |
73 | | - rich.print(" 1. [blue]git status[/blue] (check your working directory)") |
74 | | - rich.print(" 2. [blue]git add .[/blue] (stage your changes)") |
75 | | - rich.print(" 3. [blue]git commit -m 'msg'[/blue] (commit your changes)") |
76 | | - rich.print(" 4. Run this command again") |
77 | | - rich.print("\nOption 2 - Discard your changes:") |
78 | | - rich.print(" 1. [red]git reset --hard HEAD[/red] (⚠️ discards all uncommitted changes)") |
79 | | - rich.print(" 2. [red]git clean -fd[/red] (⚠️ removes all untracked files)") |
80 | | - rich.print(" 3. Run this command again\n") |
81 | | - raise RuntimeError("Failed to apply patch to local filesystem") from e |
82 | | - else: |
83 | | - rich.print("") |
84 | | - rich.print("To apply these changes locally:") |
85 | | - rich.print(format_command(f"codegen run {function.name} --apply-local")) |
86 | | - |
87 | | - except Exception as e: |
88 | | - rich.print(f"[red]Error running {function.name}:[/red] {e!s}") |
89 | | - raise |
| 40 | + with Status("[bold]Parsing codebase...", spinner="dots") as status: |
| 41 | + codebase = parse_codebase(repo_root) |
| 42 | + status.update("[bold green]✓ Parsed codebase") |
| 43 | + |
| 44 | + status.update("[bold]Running codemod...") |
| 45 | + function.run(codebase) # Run the function |
| 46 | + status.update("[bold green]✓ Completed codemod") |
| 47 | + |
| 48 | + # Get the diff from the codebase |
| 49 | + result = codebase.get_diff() |
| 50 | + |
| 51 | + # Handle no changes case |
| 52 | + if not result: |
| 53 | + rich.print("\n[yellow]No changes were produced by this codemod[/yellow]") |
| 54 | + return |
| 55 | + |
| 56 | + # Show diff preview if requested |
| 57 | + if diff_preview: |
| 58 | + rich.print("") # Add spacing |
| 59 | + diff_lines = result.splitlines() |
| 60 | + truncated = len(diff_lines) > diff_preview |
| 61 | + limited_diff = "\n".join(diff_lines[:diff_preview]) |
| 62 | + |
| 63 | + if truncated: |
| 64 | + limited_diff += f"\n\n...\n\n[yellow]diff truncated to {diff_preview} lines[/yellow]" |
| 65 | + |
| 66 | + panel = Panel(limited_diff, title="[bold]Diff Preview[/bold]", border_style="blue", padding=(1, 2), expand=False) |
| 67 | + rich.print(panel) |
| 68 | + |
| 69 | + # Apply changes |
| 70 | + rich.print("") |
| 71 | + rich.print("[green]✓ Changes have been applied to your local filesystem[/green]") |
0 commit comments