import: a .rsbank lands as a new bank, whole or not at all
Four collisions answered explicitly: ids reminted, names never overwritten, content deduped before the write, bank name auto-suffixed. Degraded ledger refuses before the picker.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
// import_bank.cpp — see import_bank.h for the contract. The REAPER-facing half of the
|
||||
// import: the project directory, the minted bank id, the birth records, and the one
|
||||
// undo-batched persist. Every decision it makes is in import_landing / import_plan.
|
||||
//
|
||||
// main.cpp owns the API pointers; this TU gets them extern. DAW-verified, not unit tested.
|
||||
|
||||
#include "shell/package/import_bank.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "core/capture/capture_paths.h" // projectDirOfRpp
|
||||
#include "shell/bank_ops/bank_ops.h" // persistBankOp — one bank op is one Ctrl-Z
|
||||
#include "shell/persist/session.h"
|
||||
|
||||
#define REAPERAPI_MINIMAL
|
||||
#define REAPERAPI_WANT_EnumProjects
|
||||
#define REAPERAPI_WANT_genGuid
|
||||
#define REAPERAPI_WANT_guidToString
|
||||
#include "reaper_plugin_functions.h"
|
||||
|
||||
namespace reasampler {
|
||||
|
||||
namespace {
|
||||
|
||||
std::string activeProjectDir() {
|
||||
std::vector<char> buf(4096, '\0');
|
||||
EnumProjects(-1, buf.data(), static_cast<int>(buf.size()));
|
||||
return capture::projectDirOfRpp(std::string(buf.data()));
|
||||
}
|
||||
|
||||
// The model mints no ids (it stays pure and deterministic), so the shell does — the
|
||||
// same GUID pair bankOpCreate uses.
|
||||
std::string mintBankId() {
|
||||
GUID g{};
|
||||
genGuid(&g);
|
||||
char buf[64] = {0}; // guidToString needs >=64 chars (SDK contract)
|
||||
guidToString(&g, buf);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
void fillPlanCounts(ImportBankResult& out, const package::ImportPlan& plan) {
|
||||
out.bankDisplayName = plan.bankDisplayName;
|
||||
out.seedBankName = plan.seedBankName;
|
||||
out.bankNameAdjusted = plan.bankNameAdjusted;
|
||||
out.landedCount = plan.landCount;
|
||||
out.renamedCount = plan.renameCount;
|
||||
out.collapsedCount = plan.collapseCount;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ImportBankResult importBankPackage(ReaSamplerSession& session,
|
||||
const std::string& packageAbsPath) {
|
||||
ImportBankResult out;
|
||||
|
||||
// A per-import disambiguator, the same shape capture and ingest file under.
|
||||
const std::string uniqueTag =
|
||||
std::to_string(static_cast<std::int64_t>(std::time(nullptr)));
|
||||
|
||||
LandedFileJournal journal;
|
||||
const ImportLanding landing = landPackage(packageAbsPath, activeProjectDir(),
|
||||
session.book(), uniqueTag, journal);
|
||||
out.outcome = landing.outcome;
|
||||
out.header = landing.header;
|
||||
out.failedEntryName = landing.failedEntryName;
|
||||
out.rollback = landing.rollback;
|
||||
fillPlanCounts(out, landing.plan);
|
||||
if (landing.outcome != ImportOutcome::Landed) return out;
|
||||
|
||||
const bool applied = applyImportedBank(
|
||||
session.book(), mintBankId(), landing.plan,
|
||||
[&session](const model::Sample& s) {
|
||||
session.recordCreated(s, tracking::OriginKind::PackageImport);
|
||||
});
|
||||
if (!applied) {
|
||||
out.outcome = ImportOutcome::IndexRejected;
|
||||
out.rollback = journal.rollback();
|
||||
return out;
|
||||
}
|
||||
|
||||
// Generation bump + persist ride inside one undo block, so a Ctrl-Z takes the whole
|
||||
// import back out of the index. It does NOT un-write the files — the summary says so.
|
||||
persistBankOp(session, "ReaSampler: import bank package", /*bumpGeneration=*/true);
|
||||
// Only now: the files are referenced, so prune's self-cleanup carve-out no longer
|
||||
// covers them (see package_rollback.h).
|
||||
journal.markIndexCommitted();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace reasampler
|
||||
Reference in New Issue
Block a user