Introduce swap journaling crash recovery system with tests.

- Added detailed journaling system (`SwapManager`) for crash recovery, including edit recording and replay.
- Integrated recovery prompts for handling swap files during file open flows.
- Implemented swap file cleanup, checkpointing, and compaction mechanisms.
- Added extensive unit tests for swap-related behaviors such as recovery prompts, file pruning, and corruption handling.
- Updated CMake to include new test files.
This commit is contained in:
2026-02-13 08:44:35 -08:00
parent 895e4ccb1e
commit 2a6ff2a862
19 changed files with 1697 additions and 144 deletions

View File

@@ -4,6 +4,7 @@
#pragma once
#include <cstddef>
#include <ctime>
#include <deque>
#include <string>
#include <vector>
@@ -497,6 +498,30 @@ public:
bool OpenFile(const std::string &path, std::string &err);
// Request that a file be opened. The request is processed by calling
// ProcessPendingOpens() (typically once per frontend frame).
void RequestOpenFile(const std::string &path, std::size_t line1 = 0);
// If no modal prompt is active, process queued open requests.
// Returns true if a file was opened during this call.
bool ProcessPendingOpens();
[[nodiscard]] bool HasPendingOpens() const;
// Swap recovery confirmation state. When non-None, a `PromptKind::Confirm`
// prompt is active and the user's answer should be routed to ResolveRecoveryPrompt().
enum class RecoveryPromptKind {
None = 0,
RecoverOrDiscard, // y = recover swap, else discard swap and open clean
DeleteCorruptSwap // y = delete corrupt swap, else keep it
};
[[nodiscard]] RecoveryPromptKind PendingRecoveryPrompt() const;
bool ResolveRecoveryPrompt(bool yes);
void CancelRecoveryPrompt();
// Buffer switching/closing
bool SwitchTo(std::size_t index);
@@ -550,6 +575,11 @@ public:
}
private:
struct PendingOpen {
std::string path;
std::size_t line1{0}; // 1-based; 0 = none
};
std::size_t rows_ = 0, cols_ = 0;
int mode_ = 0;
int kill_ = 0; // KILL CHAIN
@@ -593,6 +623,13 @@ private:
std::string prompt_text_;
std::string pending_overwrite_path_;
// Deferred open + swap recovery prompt state
std::deque<PendingOpen> pending_open_;
RecoveryPromptKind pending_recovery_prompt_ = RecoveryPromptKind::None;
PendingOpen pending_recovery_open_{};
std::string pending_recovery_swap_path_;
std::string pending_recovery_replay_err_;
// GUI-only state (safe no-op in terminal builds)
bool file_picker_visible_ = false;
std::string file_picker_dir_;