use std::path::Path;
use obj::{Db, IntegrityFailure, IntegrityReport};
pub(crate) fn run(path: &Path) -> i32 {
let db = match Db::open(path) {
Ok(db) => db,
Err(err) => {
print_open_failure(path, &err);
return open_exit_code(&err);
}
};
let report = match db.integrity_check() {
Ok(r) => r,
Err(err) => {
eprintln!("error: integrity_check failed: {err}");
return 2;
}
};
if report.is_ok() {
print_ok(&report);
0
} else {
print_failures(&report);
1
}
}
fn print_ok(report: &IntegrityReport) {
let millis = report.elapsed.as_millis();
println!("ok: {} pages, {millis} ms", report.pages_checked);
}
fn print_failures(report: &IntegrityReport) {
let millis = report.elapsed.as_millis();
eprintln!(
"failed: {} pages checked, {millis} ms, {} failure(s):",
report.pages_checked,
report.failures.len(),
);
for failure in &report.failures {
eprintln!(" - {}", format_failure(failure));
}
}
fn format_failure(failure: &IntegrityFailure) -> String {
format!("{failure:?}")
}
fn print_open_failure(path: &Path, err: &obj::Error) {
eprintln!("error: failed to open {}: {err}", path.display());
}
fn open_exit_code(err: &obj::Error) -> i32 {
match err {
obj::Error::Corruption { .. } | obj::Error::BTreeDepthExceeded { .. } => 1,
_ => 2,
}
}