feat(clean): add snapshot support for volatile repo cleanup
Some checks failed
Auto Changelog & Release / detect-version-change (push) Successful in 3s
Auto Changelog & Release / release (push) Has been skipped
Auto Changelog & Release / changelog-only (push) Failing after 6s
Build and Publish nightly package / build-and-publish (push) Successful in 33s

This commit is contained in:
2025-11-27 18:21:20 +01:00
parent 801c8e24a1
commit 7f629fd752
2 changed files with 80 additions and 11 deletions

View File

@@ -2,6 +2,8 @@ from typer import Typer, Option
from rich.console import Console
from rich.table import Table
import shutil
import os
from datetime import datetime
from repocat.config import load_config
from repocat.models.catalog import RepoCatalogState
@@ -23,7 +25,16 @@ def clean_volatile(
"""
Löscht **bedingungslos** alle Repositories aus `volatile`-Kategorien (z.B. `scratches`).
"""
catalog = RepoCatalogState.from_config(load_config())
config = load_config()
catalog = RepoCatalogState.from_config(config)
# Snapshot configuration
use_snapshots = config.defaults.snapshots if config.defaults else False
snapshot_count = config.defaults.snapshot_count if config.defaults else 5
snapshot_root = config.base_dir / ".snapshots"
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
current_snapshot_dir = snapshot_root / timestamp
table = Table(title="Clean – Volatile (Zerstörung)")
table.add_column("Kategorie")
@@ -33,6 +44,7 @@ def clean_volatile(
deleted = 0
skipped = 0
snapshotted_categories = set()
for cat in catalog.categories:
if not cat.config.volatile:
@@ -40,23 +52,78 @@ def clean_volatile(
if category and cat.config.name not in category:
continue
for repo in cat.repos:
size_mb = repo.size_mb
# If snapshots are enabled, we handle the whole category at once
if use_snapshots:
if not cat.path.exists():
continue
if dry_run:
action = "[yellow]Würde löschen[/]"
action = f"[yellow]Würde verschieben nach .snapshots/{timestamp}[/]"
else:
try:
shutil.rmtree(repo.path)
action = "[red]Gelöscht[/]"
deleted += 1
# Create snapshot dir only if we actually have something to move
if not current_snapshot_dir.exists():
current_snapshot_dir.mkdir(parents=True, exist_ok=True)
target_dir = current_snapshot_dir / cat.config.subdir
# Ensure parent of target exists (if subdir is nested)
target_dir.parent.mkdir(parents=True, exist_ok=True)
# Move the whole category folder
# Note: shutil.move(src, dst) where dst does not exist moves src to dst.
# If dst exists, it moves src inside dst.
# We want to rename cat.path to target_dir.
shutil.move(str(cat.path), str(target_dir))
# Recreate the empty category folder
cat.path.mkdir(parents=True, exist_ok=True)
action = f"[green]Verschoben nach .snapshots/{timestamp}[/]"
snapshotted_categories.add(cat.config.name)
except Exception as e:
action = f"[red]Fehler: {e}[/]"
action = f"[red]Fehler beim Verschieben: {e}[/]"
table.add_row(cat.config.name, repo.name, f"{size_mb:.1f}", action)
# Add rows for all repos in this category to show what happened to them
if cat.repos:
for repo in cat.repos:
table.add_row(cat.config.name, repo.name, f"{repo.size_mb:.1f}", action)
deleted += 1 # Count as "processed/removed from volatile"
else:
# If no repos but folder existed (and maybe had other files), show a generic row
table.add_row(cat.config.name, "(Alle Dateien)", "-", action)
else:
# Old behavior: Delete individual repos
for repo in cat.repos:
size_mb = repo.size_mb
if dry_run:
action = "[yellow]Würde löschen[/]"
else:
try:
shutil.rmtree(repo.path)
action = "[red]Gelöscht[/]"
deleted += 1
except Exception as e:
action = f"[red]Fehler: {e}[/]"
table.add_row(cat.config.name, repo.name, f"{size_mb:.1f}", action)
console.print(table)
console.print(f"\n[green]✓ Volatile-Clean abgeschlossen[/] – {deleted} gelöscht, {skipped} übersprungen")
# Prune old snapshots
if use_snapshots and not dry_run and snapshot_root.exists():
try:
snapshots = sorted([p for p in snapshot_root.iterdir() if p.is_dir()], key=lambda p: p.name)
if len(snapshots) > snapshot_count:
to_delete = snapshots[:-snapshot_count]
for snap in to_delete:
shutil.rmtree(snap)
console.print(f"[dim]Alte Snapshots bereinigt: {len(to_delete)} gelöscht[/]")
except Exception as e:
console.print(f"[red]Fehler beim Bereinigen der Snapshots: {e}[/]")
console.print(f"\n[green]✓ Volatile-Clean abgeschlossen[/] – {deleted} Repositories verarbeitet")
@app.command()