use super::recovery_error::RecoveryError;
use super::recovery_manual_steps::finish_by_hand_steps;
use std::path::Path;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RecordKind {
Preparing,
Landing,
IndexLock,
RefUpdated,
}
pub fn name_record_failure(error: RecoveryError, path: &Path, kind: RecordKind) -> RecoveryError {
let directory: &Path = path.parent().unwrap_or(path);
let transaction: String = directory
.file_name()
.map_or_else(|| { return String::from("(unnamed)"); }, |name| { return name.to_string_lossy().into_owned(); });
let way_out: String = match kind {
RecordKind::Preparing => format!(
"preparing.json is the first record of a transaction. If the directory holds no landing-<n>.json and no \
ref-updated.json, no commit was made: remove {}, and the next guarded command discards the transaction \
and goes on; if an index.lock file remains in the repository's Git directory after that and no Git \
command is running, remove it as well. If it holds either file, the commit may already be on the branch: run `git log` to check. {}",
path.display(),
finish_by_hand_steps(directory, None)
),
RecordKind::Landing => format!(
"A landing record names the post-index and the index lock the landing installs, and recovery cannot decide \
from the other records what to install. If you have a copy of this file, restore it at {} and the next \
guarded command recovers the transaction. Otherwise run `git log` to see whether the transaction's commit \
is on the branch. {}",
path.display(),
finish_by_hand_steps(directory, None)
),
RecordKind::IndexLock => format!(
"This record names the index.lock file the transaction created. Remove {}: the next guarded command then \
handles the transaction from its other records, but it cannot prove that an index.lock file on disk is \
the transaction's and leaves it. If index.lock still exists in the repository's Git directory (or the \
linked worktree's Git directory) and no Git command is running, remove it yourself.",
path.display()
),
RecordKind::RefUpdated => format!(
"This record is written after the branch moved. Remove {}: the next guarded command then looks in the \
branch's reflog for this transaction's entry to decide whether the commit landed, and finishes the \
transaction from its landing record.",
path.display()
),
};
return RecoveryError(format!(
"Cannot recover transaction {transaction}, so every guarded command stops with exit status 2 until it is \
resolved: {} cannot be read ({}). Recovery retained the transaction at {}. {way_out}",
path.display(),
error.0.trim_end_matches('.'),
directory.display()
));
}
#[cfg(test)]
#[path = "recovery_record_failure_tests.rs"]
mod tests;