GooDrive/backend/drive/trash_cleanup.py
Louis Mazin d94a36d9a7 parfait
2026-10-14 18:09:57 +02:00

47 lines
2.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Permanent deletion shared by the trash API and scheduled retention cleanup."""
from django.db import transaction
from .models import DriveItem, UploadSession
from .services import descendant_files
from .storage_layout import disk_path, file_location
def has_active_uploads_in_tree(item):
"""Do not purge directories while a resumable upload targets a descendant."""
if not item.is_folder:
return False
pending = [item.pk]
while pending:
batch, pending = pending[:250], pending[250:]
if UploadSession.objects.filter(parent_id__in=batch).exists():
return True
pending.extend(DriveItem.objects.filter(parent_id__in=batch, is_folder=True).values_list('pk', flat=True))
return False
def delete_trashed_item(item):
"""Delete the SQL tree, then its tracked files after commit.
Untracked files and directories are not erased. Failures resolving a stored
path abort before the SQL delete; missing physical files are tolerated.
"""
if item.trashed_at is None:
raise ValueError('L’élément doit être dans la corbeille.')
if has_active_uploads_in_tree(item):
raise ValueError('Un transfert est encore en cours dans ce dossier.')
files = [disk_path(key) for key in descendant_files(item)]
folder = disk_path(file_location(item.space, item.parent, item.name)) if item.is_folder else None
with transaction.atomic():
item.delete()
def remove_files():
for path in files:
path.unlink(missing_ok=True)
if folder and folder.is_dir() and not folder.is_symlink():
# Only remove empty directories, never user data untracked by SQL.
for candidate in sorted(folder.rglob('*'), key=lambda p:len(p.parts), reverse=True):
if candidate.is_dir() and not candidate.is_symlink():
try: candidate.rmdir()
except OSError: pass
try: folder.rmdir()
except OSError: pass
transaction.on_commit(remove_files)