refactor(review): streamline repo review logic and data handling

- Replaces manual path handling with `RepoCatalogState` abstraction
- Simplifies repo status checks and removes redundant imports
- Improves clarity and maintainability of interactive review process
This commit is contained in:
2025-05-11 14:38:44 +02:00
parent 9bff626f30
commit 68b3233fcb

View File

@@ -1,19 +1,15 @@
from typer import Typer, confirm, prompt from typer import Typer
from rich.console import Console from rich.console import Console
from rich.table import Table
from pathlib import Path
import shutil
from datetime import datetime
import typer
from rich.prompt import Prompt, Confirm from rich.prompt import Prompt, Confirm
from datetime import datetime
import shutil
import typer
from repocat.cli.move import move_command
from repocat.config import load_config from repocat.config import load_config
from repocat.models.config import RepoCategory from repocat.models.catalog import RepoCatalogState
from repocat.cli.move import move_command
from repocat.cli.archive import archive_repo from repocat.cli.archive import archive_repo
from repocat.cli.clean import get_dir_size, is_git_dirty, is_git_unpushed
app = Typer() app = Typer()
console = Console() console = Console()
@@ -23,48 +19,39 @@ def review():
""" """
Führt interaktiv durch alle Repositories im Review-Ordner. Führt interaktiv durch alle Repositories im Review-Ordner.
""" """
config = load_config() catalog = RepoCatalogState.from_config(load_config())
base = config.base_dir
archive_cat = next((c for c in config.categories if c.is_archive), None) archive_cat = next((c for c in catalog.categories if c.config.is_archive), None)
if not archive_cat: if not archive_cat:
console.print("[red]Keine Archiv-Kategorie in der Konfiguration gefunden.[/]") console.print("[red]Keine Archiv-Kategorie in der Konfiguration gefunden.[/]")
raise typer.Exit(1) raise typer.Exit(1)
archive_path = base / archive_cat.subdir
archive_path.mkdir(parents=True, exist_ok=True)
review_cat = catalog.get_category("review")
review_cat = next((c for c in config.categories if c.name == "review"), None)
if not review_cat: if not review_cat:
console.print("[red]Kein 'review'-Eintrag in der Konfiguration gefunden.[/]") console.print("[red]Kein 'review'-Eintrag in der Konfiguration gefunden.[/]")
raise typer.Exit(1) raise typer.Exit(1)
review_path = base / review_cat.subdir if not review_cat.repos:
if not review_path.exists():
console.print(f"[yellow]Hinweis:[/] Kein review-Ordner vorhanden unter {review_path}")
return
repos = [p for p in review_path.iterdir() if p.is_dir()]
if not repos:
console.print("[green]✓ Keine Repositories im Review-Ordner.[/]") console.print("[green]✓ Keine Repositories im Review-Ordner.[/]")
return return
for repo in sorted(repos): for repo in sorted(review_cat.repos, key=lambda r: r.name):
console.rule(f"[bold cyan]{repo.name}") console.rule(f"[bold cyan]{repo.name}")
age_days = (datetime.now() - datetime.fromtimestamp(repo.stat().st_mtime)).days console.print(f"[bold]Alter:[/] {repo.age_days} Tage")
size_mb = get_dir_size(repo) / 1024 / 1024 console.print(f"[bold]Größe:[/] {repo.size_mb:.1f} MB")
if repo.git:
status = [] status = []
if is_git_dirty(repo): if repo.git.dirty:
status.append("uncommitted") status.append("uncommitted")
if is_git_unpushed(repo): if repo.git.unpushed:
status.append("unpushed") status.append("unpushed")
if not status: if not status:
status.append("clean") status.append("clean")
else:
status = ["kein Git"]
console.print(f"[bold]Alter:[/] {age_days} Tage")
console.print(f"[bold]Größe:[/] {size_mb:.1f} MB")
console.print(f"[bold]Git:[/] {', '.join(status)}") console.print(f"[bold]Git:[/] {', '.join(status)}")
while True: while True:
@@ -81,17 +68,17 @@ def review():
raise typer.Exit() raise typer.Exit()
elif action in ("d", "delete"): elif action in ("d", "delete"):
if Confirm.ask(f"Bist du sicher, dass du [red]{repo.name}[/] löschen willst?"): if Confirm.ask(f"Bist du sicher, dass du [red]{repo.name}[/] löschen willst?"):
shutil.rmtree(repo) shutil.rmtree(repo.path)
console.print(f"[red]✓ Gelöscht:[/] {repo.name}") console.print(f"[red]✓ Gelöscht:[/] {repo.name}")
break break
elif action in ("m", "move"): elif action in ("m", "move"):
target_categories = [c.name for c in config.categories if c.name != "review" and not c.is_archive] target_categories = [c.config.name for c in catalog.categories if c.config.name != "review" and not c.config.is_archive]
target = Prompt.ask("Zielkategorie", choices=target_categories) target = Prompt.ask("Zielkategorie", choices=target_categories)
move_command(source=f"review/{repo.name}", target=target) move_command(source=f"review/{repo.name}", target=target)
break break
elif action in ("a", "archive"): elif action in ("a", "archive"):
try: try:
archive_file = archive_repo(repo, archive_path, dry_run=False) archive_file = archive_repo(repo.path, archive_cat.path, dry_run=False)
console.print(f"[green]✓ Archiviert:[/] {archive_file.name}") console.print(f"[green]✓ Archiviert:[/] {archive_file.name}")
break break
except Exception as e: except Exception as e: