feat(prune): R3 guarded deletion — confirm-to-delete + panel button
Extend BANK_PRUNE_FOLDER from report-only to dry-run→confirm-with-manifest→ delete exactly the pure-core orphan set (fresh recompute, stale entries skipped). Windows routes to Recycle Bin (SHFileOperation+FOF_ALLOWUNDO), else unlink. New pure prune_button module + footer button dispatching the action id. No ext-state write, no undo point (deletion is not REAPER-undoable).
This commit is contained in:
@@ -71,6 +71,26 @@ struct PruneReport {
|
||||
bool truncated = false;
|
||||
};
|
||||
|
||||
// The outcome of an actual prune DELETION (Phase R, Wave 3 — R3). The prune shell fills
|
||||
// this as it deletes the confirmed orphan set, reporting what it ACTUALLY reclaimed (not
|
||||
// what it intended to) so a locked/vanished file shows up as a skip, never a false claim.
|
||||
// REAPER-free / filesystem-free by design (the shell does the deletion; this is the
|
||||
// tallied outcome), so the count/byte aggregation is unit-testable outside the DAW.
|
||||
//
|
||||
// * reclaimedCount — number of files actually removed from disk (trash or unlink).
|
||||
// * reclaimedBytes — sum of the on-disk sizes of the files actually removed, in bytes.
|
||||
// * skippedCount — planned files that could NOT be removed (locked, disappeared, a
|
||||
// trash/unlink failure) OR that went stale between confirm and delete
|
||||
// (dropped by the delete-plan intersection). Never an error/crash.
|
||||
// * usedTrash — true iff the deletions were routed to the OS trash/recycle bin
|
||||
// (recoverable); false iff the platform fell back to hard unlink.
|
||||
struct PruneDeletionResult {
|
||||
std::size_t reclaimedCount = 0;
|
||||
std::uint64_t reclaimedBytes = 0;
|
||||
std::size_t skippedCount = 0;
|
||||
bool usedTrash = false;
|
||||
};
|
||||
|
||||
// Computes the prune orphan set: (owned ∩ present) − referenced.
|
||||
//
|
||||
// Returns the subset of `present` that is BOTH owned AND unreferenced, in the ORDER
|
||||
@@ -105,4 +125,24 @@ PruneReport buildPruneReport(const std::vector<std::string>& orphans,
|
||||
const std::unordered_map<std::string, std::uint64_t>& sizeByPath,
|
||||
std::size_t displayCap);
|
||||
|
||||
// Computes the confirm-time delete plan: the intersection of the set the user was SHOWN
|
||||
// and confirmed (`confirmed`) with a FRESH pure-core orphan output (`freshOrphans`) taken
|
||||
// at delete time. Returns exactly `confirmed ∩ freshOrphans`, in the order of `confirmed`
|
||||
// (deterministic — the same order the confirm listed).
|
||||
//
|
||||
// This is the R3 staleness guard, and it protects in BOTH directions so that "what was
|
||||
// shown is what is deleted" holds no matter what changed between confirm and delete:
|
||||
// * A confirmed path that is NO LONGER a fresh orphan — a file that vanished (gone from
|
||||
// `present`), or that some bank now references (gone from `− referenced`), or whose
|
||||
// ownership changed — is DROPPED (a skip, never an error, never a wrongful delete of a
|
||||
// now-referenced file). Because `freshOrphans` is itself a pure-core output, the plan
|
||||
// can never contain a referenced or hand-dropped file: the guard survives recompute.
|
||||
// * A path that became an orphan AFTER the confirm (in `freshOrphans` but not `confirmed`)
|
||||
// is NOT deleted — it was never shown, so it is never swept without its own confirm.
|
||||
//
|
||||
// PURE: no I/O, no REAPER. Duplicate spellings in `confirmed` are de-duplicated in the
|
||||
// result (mirrors pruneOrphans; a confirmed set from a real scan holds distinct names).
|
||||
std::vector<std::string> pruneDeletePlan(const std::vector<std::string>& confirmed,
|
||||
const std::vector<std::string>& freshOrphans);
|
||||
|
||||
} // namespace reasampler
|
||||
|
||||
Reference in New Issue
Block a user