Files
reasampler/src/shell/package/export_bank.h
T
daniel 454f67b3bc Close bank-export review findings: name-cap underflow, double overwrite prompt, test scope
Clamps insertSuffix's underflow, floors uniqueEntryName's validity guard, suppresses
the redundant overwrite confirm via a picker out-param, adds a PayloadBuffer
high-water mark, and corrects stale CLAUDE.md/CMake claims.
2026-08-02 17:19:30 -04:00

96 lines
4.1 KiB
C++

// shell/package/export_bank — the promptless bank-export verb: survey, digest,
// stream, commit. No prompts and no message boxes (shell/actions/
// package_export_action is the skin). The session arrives CONST, which is how "an
// export writes no ext state, opens no undo point and never bumps the bank
// generation" is enforced rather than remembered — those three acts
// (saveToActiveProject, bumpBankGeneration, writeAssignmentRequest) are exactly the
// session members that are non-const (session.h:113,108,147). Constness does not
// block every mutation, though: pruneReclaim (session.h:140-141) is const and is
// the system's sole file-deletion path — irrelevant to export, but not something a
// const session forbids in general. Blocking I/O: UI-thread actions only.
#pragma once
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
#include "core/package/bank_package.h"
#include "core/package/export_plan.h"
namespace reasampler {
class ReaSamplerSession;
struct ExportRequest {
std::string projectDir; // absolute; the root the index's relative paths hang off
std::string bankId;
std::string destAbsPath; // the .rsbank to write
std::int64_t exportTimestamp = 0; // manifest envelope; the caller's clock read
// Both default false and are set ONLY after the skin's explicit confirm: one
// lists what is absent, the other names the destination being replaced.
bool allowIncomplete = false;
bool allowOverwrite = false;
};
enum class ExportStatus {
Written,
NoSuchBank,
NoProjectDir,
RefusedIncomplete,
RefusedUnrepresentable,
RefusedDestinationExists,
SourceReadFailed, // a file the plan classified Present would not read, or is empty
SourceChanged, // a payload's bytes moved between the digest pass and the stream pass
EncodeFailed,
WriteFailed,
};
struct ExportOutcome {
ExportStatus status = ExportStatus::WriteFailed;
std::size_t entriesWritten = 0;
std::uint64_t bytesWritten = 0;
std::string bankDisplayName;
std::vector<package::ExcludedEntry> excluded;
std::string offendingName; // the entry a SourceReadFailed / SourceChanged names
};
struct ExportSurvey {
bool bankFound = false;
package::ExportPlan plan;
};
// Report-before-acting: the same plan exportBank recomputes, with nothing written.
// Read-only against both the project and the filesystem.
ExportSurvey surveyBankExport(const ReaSamplerSession& session,
const std::string& projectDir,
const std::string& bankId);
// Fills each manifest entry's byteLength and byteHash from its source file — the
// digest pass, one payload in memory at a time. False with `outFailedName` set when a
// source will not read or is empty; a zero-length entry cannot round-trip the
// format's own seam, so it is a failure here rather than an entry.
bool digestSources(package::PackageManifest& manifest,
const std::vector<std::string>& sourceAbsPaths,
std::string& outFailedName);
// Streams one package to `destAbsPath`: the encoded prefix, then each payload re-read
// from `sourceAbsPaths` (parallel to `manifest.entries`) and re-checked against the
// length and digest recorded for it before it is appended — so the digest the
// manifest claims describes the bytes actually written, not the bytes a concurrent
// edit replaced. Any failure abandons the writer, leaving the destination absent or
// holding its prior contents.
//
// Public because that atomicity is this function's property: proving it needs a
// failure injected mid-stream, which is a call to this seam, not to exportBank.
ExportOutcome writePackageFile(const package::EncodedPackage& encoded,
const package::PackageManifest& manifest,
const std::vector<std::string>& sourceAbsPaths,
const std::string& destAbsPath);
// The verb: plan, gate on the verdict and the destination, digest, encode, stream.
ExportOutcome exportBank(const ReaSamplerSession& session, const ExportRequest& req);
} // namespace reasampler