feat(prune): R2 dry-run prune shell + persist wiring, report-only
Add ReaSamplerSession::pruneDryRun enumerating the resolved current bank folder, feeding the R1 core, and returning a PruneReport (count/bytes/list). New pure bankRelativeForName + buildPruneReport keep spelling and tally testable. Register forever-stable BANK_PRUNE_FOLDER action, report-only. No deletion.
This commit is contained in:
@@ -77,10 +77,13 @@
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "app_version.h"
|
||||
#include "capture_paths.h"
|
||||
#include "prune_reconcile.h"
|
||||
|
||||
#define REAPERAPI_MINIMAL
|
||||
#define REAPERAPI_WANT_EnumProjects
|
||||
@@ -243,6 +246,67 @@ bool ReaSamplerSession::saveToActiveProject() {
|
||||
|
||||
namespace {
|
||||
|
||||
// The dry-run file-list display cap: the orphan COUNT and reclaimed SIZE are always
|
||||
// exact (tallied over the full orphan set), but the enumerated file list handed to the
|
||||
// console is clipped to this many entries so a project with thousands of orphans does
|
||||
// not flood the report. PruneReport::truncated flags the clip. R3's confirm surface can
|
||||
// choose its own presentation; this is purely the Wave-2 dry-run readout ceiling.
|
||||
constexpr std::size_t kPruneListDisplayCap = 64;
|
||||
|
||||
} // namespace
|
||||
|
||||
PruneReport ReaSamplerSession::pruneDryRun() const {
|
||||
PruneReport report;
|
||||
|
||||
std::string rppPath;
|
||||
void* proj = readActiveProject(rppPath);
|
||||
if (!proj || rppPath.empty()) return report; // no active/saved project -> nothing
|
||||
|
||||
// Resolve the CURRENT bank folder the same way the index does (M4): project dir of
|
||||
// the live .rpp + the fixed bank subfolder. Never a stored absolute path, so a
|
||||
// Save-As relocation is followed automatically. resolveBankFile is the shared M4
|
||||
// arithmetic; feeding it the bank subfolder as the "relative path" yields the folder.
|
||||
const std::string projectDir = projectDirOf(rppPath);
|
||||
const std::string bankDir = resolveBankFile(projectDir, kBankSubfolder);
|
||||
if (bankDir.empty()) return report; // unresolvable (no project dir) -> nothing
|
||||
|
||||
std::error_code ec;
|
||||
if (!fs::exists(bankDir, ec) || !fs::is_directory(bankDir, ec)) {
|
||||
return report; // no bank folder captured yet -> nothing to reclaim
|
||||
}
|
||||
|
||||
// Enumerate the folder into project-relative index-spelled paths, spelled the SAME
|
||||
// way the capture path spelled them (bankRelativeForName == deriveBankPaths's
|
||||
// convention) so the pure core's exact-string match lines up with referencedPaths()
|
||||
// and the manifest. Non-recursive: the bank folder is flat (capture writes files
|
||||
// directly here); skip any subdirectory. Size is stat'd here and cached by relative
|
||||
// path so the report's byte tally reuses the same on-disk read.
|
||||
std::vector<std::string> present;
|
||||
std::unordered_map<std::string, std::uint64_t> sizeByRel;
|
||||
for (const auto& entry : fs::directory_iterator(bankDir, ec)) {
|
||||
if (ec) break;
|
||||
std::error_code fec;
|
||||
if (!entry.is_regular_file(fec)) continue; // skip subdirs / specials
|
||||
const std::string name = entry.path().filename().string();
|
||||
const std::string rel = bankRelativeForName(name);
|
||||
if (rel.empty()) continue;
|
||||
present.push_back(rel);
|
||||
const std::uintmax_t sz = entry.file_size(fec);
|
||||
sizeByRel[rel] = fec ? 0 : static_cast<std::uint64_t>(sz);
|
||||
}
|
||||
|
||||
// The decision lives in the pure core — read-only inputs from the session's book and
|
||||
// manifest (NO save, NO MarkProjectDirty, NO mutation). referencedPaths() unions
|
||||
// across the whole book (pool included); owned().paths() is the manifest set. The
|
||||
// count / byte-sum / display-truncation tally is the pure buildPruneReport, so this
|
||||
// shell only enumerates, resolves, and stats — no report logic re-implemented here.
|
||||
const std::vector<std::string> orphans =
|
||||
pruneOrphans(present, book_.referencedPaths(), owned_.paths());
|
||||
return buildPruneReport(orphans, sizeByRel, kPruneListDisplayCap);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Load the Design-View model from a project's view_state key, or return a fresh
|
||||
// default. An absent/empty key (older project with no view state) yields a
|
||||
// default-constructed model (Arrange + Design seeded, active = Arrange) — graceful,
|
||||
|
||||
Reference in New Issue
Block a user