exlab_wizard.sync.run_delete#

Keep-local-aware, symlink-safe deletion of a run’s staging copy.

Operator-free per-file NAS sync design (2026-05-21). Both the automatic cleanup reaper (exlab_wizard.sync.nas_client.NASSyncClient._delete_local()) and the operator-facing “Clear” actions (exlab_wizard.orchestrator.staging_clear.clear_run_dir()) must delete a run’s staging copy with identical semantics:

  • files flagged keep_local in sync_state.json survive (the spec’s keep-local guarantee: “excluded from cleanup deletion”);

  • the .exlab-wizard/ metadata subtree survives so a cleared run still renders its files as “On NAS” tombstones;

  • directory symlinks are never descended into or removed – a staged run containing a symlink to an external directory must not have files deleted outside the run tree.

This module is the single shared implementation. It is a pure filesystem helper – no SyncStateWriter / api / orchestrator imports – so it can be imported from anywhere without circular-import risk. The callers own reading the keep_local set and stamping cleared_at.

Functions

collect_cleanup_candidates(run_path, *, ...)

Return the run-relative files cleanup would remove.

delete_run_files(run_path, *, keep_local, ...)

Delete run_path data files honoring retain_cache and keep_local.

Classes

CleanupCandidates(delete[, retained_ignored])

Run-relative files selected or retained by cleanup planning.

class exlab_wizard.sync.run_delete.CleanupCandidates(delete, retained_ignored=())[source]#

Bases: object

Run-relative files selected or retained by cleanup planning.

Parameters:
delete: tuple[str, ...]#
retained_ignored: tuple[str, ...]#
exlab_wizard.sync.run_delete.collect_cleanup_candidates(run_path, *, keep_local, ignore_globs=(), delete_ignored=False)[source]#

Return the run-relative files cleanup would remove.

The walk matches delete_run_files(): the cache subtree and directory symlinks are not descended into, keep_local files are retained, and ignored files are retained unless delete_ignored explicitly opts into local discard.

Parameters:
Return type:

CleanupCandidates

exlab_wizard.sync.run_delete.delete_run_files(run_path, *, keep_local, retain_cache, delete_only=None, ignore_globs=(), delete_ignored=False)[source]#

Delete run_path data files honoring retain_cache and keep_local.

keep_local is a set of run-relative POSIX paths (possibly nested) that must survive the sweep. retain_cache keeps the .exlab-wizard/ subtree when True. delete_only constrains deletion to a pre-proved set of run-relative files; in that mode no whole-tree recursive data delete is used, so files that appear after the proof survive.

The whole-run shutil.rmtree fast path is used only when retain_cache is False and there are no keep_local files; any kept file (or a retained cache) forces the per-file walk so it survives. The walk does not follow directory symlinks – a symlinked directory inside the run is left entirely untouched (neither its contents deleted nor the link removed).

Idempotent: a missing run_path is a no-op.

Parameters:
Return type:

None