testsAndMisc/python_pkg/wsg_grabber/_prune.py
Krzysztof kuhy Rudnicki 33f0fee342
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (mypy, mypy) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (pylint, pylint) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (rest, ) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (shellcheck, shellcheck) (push) Waiting to run
Python tests / test (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / lib-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
wsg_grabber: keep to the cloud folder, cap trash at 200 passes
Kept videos land in ~/data/cloud/Media/<year>/wsg (~/Downloads without the
cloud folder); trash/ keeps only the newest 200 passes and marks the rest
purged. Legacy keep/ is migrated once. Undo follows a keep through every
place it can end up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F8G3BNETGmbr6aM5cc18g4
2026-09-28 10:44:00 +02:00

57 lines
2.0 KiB
Python

"""Keeping ``trash/`` bounded.
A pass used to be a move into a directory nobody ever emptied; 23k files and
77 GB later that was clearly wrong. The trail is now capped at the newest
``TRASH_RETAIN`` passes, which is still far more than anyone undoes. Runs at
startup and after every pass, so the directory never drifts above the cap.
The survivor set comes from the index, not from mtimes: a verdict's
``reviewed_at`` is the fact, the file's timestamp is a side-effect of it.
Anything in ``trash/`` the index does not vouch for -- orphans from before the
``reviewed_name`` column existed -- is deleted along with the old passes.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
from python_pkg.wsg_grabber import files, logs, paths, store_verdicts
from python_pkg.wsg_grabber.constants import TRASH_RETAIN
if TYPE_CHECKING:
import sqlite3
def prune_trash(conn: sqlite3.Connection, retain: int = TRASH_RETAIN) -> int:
"""Delete every trashed file except the *retain* most recent passes.
Files go first, rows second: a crash in between leaves rows that still say
``PASSED`` for files that are gone, which undo already copes with by
forgetting the verdict. The reverse order would leave undoable-looking
files the index had already written off.
Args:
conn: Open connection.
retain: How many passes stay on disk and undoable.
Returns:
int: Files deleted.
"""
trash = paths.trash_dir()
survivors = store_verdicts.recent_passed_names(conn, retain)
removed = 0
if trash.is_dir():
for entry in trash.iterdir():
if entry.name in survivors or not entry.is_file():
continue
removed += files.remove(entry)
purged = store_verdicts.purge_older_passes(conn, retain)
if removed or purged:
logs.event(
"trash.pruned",
removed=removed,
purged_rows=purged,
retained=len(survivors),
)
return removed