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
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:
@@ -2,6 +2,8 @@ from typer import Typer, Option
|
|||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
from rich.table import Table
|
from rich.table import Table
|
||||||
import shutil
|
import shutil
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from repocat.config import load_config
|
from repocat.config import load_config
|
||||||
from repocat.models.catalog import RepoCatalogState
|
from repocat.models.catalog import RepoCatalogState
|
||||||
@@ -23,7 +25,16 @@ def clean_volatile(
|
|||||||
"""
|
"""
|
||||||
Löscht **bedingungslos** alle Repositories aus `volatile`-Kategorien (z.B. `scratches`).
|
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 = Table(title="Clean – Volatile (Zerstörung)")
|
||||||
table.add_column("Kategorie")
|
table.add_column("Kategorie")
|
||||||
@@ -33,6 +44,7 @@ def clean_volatile(
|
|||||||
|
|
||||||
deleted = 0
|
deleted = 0
|
||||||
skipped = 0
|
skipped = 0
|
||||||
|
snapshotted_categories = set()
|
||||||
|
|
||||||
for cat in catalog.categories:
|
for cat in catalog.categories:
|
||||||
if not cat.config.volatile:
|
if not cat.config.volatile:
|
||||||
@@ -40,23 +52,78 @@ def clean_volatile(
|
|||||||
if category and cat.config.name not in category:
|
if category and cat.config.name not in category:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for repo in cat.repos:
|
# If snapshots are enabled, we handle the whole category at once
|
||||||
size_mb = repo.size_mb
|
if use_snapshots:
|
||||||
|
if not cat.path.exists():
|
||||||
|
continue
|
||||||
|
|
||||||
if dry_run:
|
if dry_run:
|
||||||
action = "[yellow]Würde löschen[/]"
|
action = f"[yellow]Würde verschieben nach .snapshots/{timestamp}[/]"
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(repo.path)
|
# Create snapshot dir only if we actually have something to move
|
||||||
action = "[red]Gelöscht[/]"
|
if not current_snapshot_dir.exists():
|
||||||
deleted += 1
|
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:
|
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(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()
|
@app.command()
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ class RepoCategory(BaseModel):
|
|||||||
class RepoCatDefaults(BaseModel):
|
class RepoCatDefaults(BaseModel):
|
||||||
dry_run: bool = True
|
dry_run: bool = True
|
||||||
auto_create_directories: bool = True
|
auto_create_directories: bool = True
|
||||||
|
snapshots: bool = False
|
||||||
|
snapshot_count: int = 5
|
||||||
|
|
||||||
class RepoCatConfig(BaseModel):
|
class RepoCatConfig(BaseModel):
|
||||||
base_dir: Path = Field(default=Path("~/Repositories").expanduser())
|
base_dir: Path = Field(default=Path("~/Repositories").expanduser())
|
||||||
|
|||||||
Reference in New Issue
Block a user