mirror of
https://github.com/kevinveenbirkenbach/docker-volume-backup-cleanup.git
synced 2026-01-19 05:32:58 +00:00
fix: apply --force-keep to timestamp subdirectories instead of backup folders
- Change --force-keep semantics to skip the last N subdirectories inside each backup-docker-to-local folder - Remove old behavior that skipped entire backup folders in --all mode - Update CLI help text to reflect the new behavior - Align unit and E2E tests with timestamp-based force-keep semantics https://chatgpt.com/share/695d1ed9-44f0-800f-a236-e903c61036cb
This commit is contained in:
@@ -40,6 +40,20 @@ class ValidationResult:
|
||||
stdout: str
|
||||
|
||||
|
||||
def _sorted_timestamp_subdirs(path: Path) -> List[Path]:
|
||||
# Timestamp-like folder names sort correctly lexicographically.
|
||||
# We keep it simple: sort by name.
|
||||
return sorted([p for p in path.iterdir() if p.is_dir()], key=lambda p: p.name)
|
||||
|
||||
|
||||
def _apply_force_keep(subdirs: List[Path], force_keep: int) -> List[Path]:
|
||||
if force_keep <= 0:
|
||||
return subdirs
|
||||
if len(subdirs) <= force_keep:
|
||||
return []
|
||||
return subdirs[:-force_keep]
|
||||
|
||||
|
||||
def discover_target_subdirs(
|
||||
backups_root: Path, backup_id: Optional[str], all_mode: bool, force_keep: int
|
||||
) -> List[Path]:
|
||||
@@ -47,6 +61,8 @@ def discover_target_subdirs(
|
||||
Return a list of subdirectories to validate:
|
||||
- If backup_id is given: <root>/<id>/backup-docker-to-local/* (dirs only)
|
||||
- If --all: for each <root>/* that has backup-docker-to-local, include its subdirs
|
||||
force_keep:
|
||||
- Skips the last N timestamp subdirectories inside each backup-docker-to-local folder.
|
||||
"""
|
||||
targets: List[Path] = []
|
||||
if force_keep < 0:
|
||||
@@ -56,26 +72,25 @@ def discover_target_subdirs(
|
||||
raise FileNotFoundError(f"Backups root does not exist: {backups_root}")
|
||||
|
||||
if all_mode:
|
||||
backup_folders = sorted(p for p in backups_root.iterdir() if p.is_dir())
|
||||
|
||||
# Skip the last N backup folders (by sorted name order).
|
||||
# This is intentionally simple: timestamp-like folder names sort correctly.
|
||||
if force_keep:
|
||||
if len(backup_folders) <= force_keep:
|
||||
return []
|
||||
backup_folders = backup_folders[:-force_keep]
|
||||
|
||||
backup_folders = sorted(
|
||||
[p for p in backups_root.iterdir() if p.is_dir()],
|
||||
key=lambda p: p.name,
|
||||
)
|
||||
for backup_folder in backup_folders:
|
||||
candidate = backup_folder / "backup-docker-to-local"
|
||||
if candidate.is_dir():
|
||||
targets.extend(sorted([p for p in candidate.iterdir() if p.is_dir()]))
|
||||
subdirs = _sorted_timestamp_subdirs(candidate)
|
||||
subdirs = _apply_force_keep(subdirs, force_keep)
|
||||
targets.extend(subdirs)
|
||||
else:
|
||||
if not backup_id:
|
||||
raise ValueError("Either --id or --all must be provided.")
|
||||
base = backups_root / backup_id / "backup-docker-to-local"
|
||||
if not base.is_dir():
|
||||
raise FileNotFoundError(f"Directory does not exist: {base}")
|
||||
targets = sorted([p for p in base.iterdir() if p.is_dir()])
|
||||
subdirs = _sorted_timestamp_subdirs(base)
|
||||
subdirs = _apply_force_keep(subdirs, force_keep)
|
||||
targets = subdirs
|
||||
|
||||
return targets
|
||||
|
||||
@@ -257,7 +272,7 @@ def parse_args(argv: Optional[List[str]] = None) -> argparse.Namespace:
|
||||
"--force-keep",
|
||||
type=int,
|
||||
default=0,
|
||||
help="In --all mode: keep (skip) the last N backup folders under --backups-root (default: 0).",
|
||||
help="Keep (skip) the last N timestamp subdirectories inside each backup-docker-to-local folder (default: 0).",
|
||||
)
|
||||
return parser.parse_args(argv)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user