refactor check logic.
This commit is contained in:
+66
-31
@@ -11,7 +11,7 @@ use std::time::Instant;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use clap::Parser;
|
||||
use meta::{DirSnapshot, FileMeta};
|
||||
use meta::{calc_xxh128, scan_dir_xxh128, DirSnapshot, FileMeta};
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let started = Instant::now();
|
||||
@@ -30,7 +30,6 @@ fn main() -> Result<()> {
|
||||
}
|
||||
|
||||
fn process_file(path: &Path) -> Result<()> {
|
||||
let meta = FileMeta::from_path(path)?;
|
||||
let meta_dir = path
|
||||
.parent()
|
||||
.map(Path::to_path_buf)
|
||||
@@ -39,8 +38,13 @@ fn process_file(path: &Path) -> Result<()> {
|
||||
fs::create_dir_all(&meta_dir)
|
||||
.with_context(|| format!("无法创建目录: {}", meta_dir.display()))?;
|
||||
|
||||
let save_path = meta_dir.join(format!("{}.json", meta.basename));
|
||||
let basename = path
|
||||
.file_name()
|
||||
.map(|n| n.to_string_lossy().to_string())
|
||||
.unwrap_or_else(|| "unknown".to_string());
|
||||
let save_path = meta_dir.join(format!("{basename}.json"));
|
||||
if !save_path.exists() {
|
||||
let meta = FileMeta::from_path(path)?;
|
||||
let json = meta.to_pretty_json()?;
|
||||
println!("{}", json);
|
||||
fs::write(&save_path, json)?;
|
||||
@@ -50,48 +54,79 @@ fn process_file(path: &Path) -> Result<()> {
|
||||
let existing = File::open(&save_path)
|
||||
.with_context(|| format!("无法读取历史元数据: {}", save_path.display()))?;
|
||||
let old_meta = FileMeta::from_reader(existing)?;
|
||||
if meta.matches(&old_meta) {
|
||||
let fast_hash = calc_xxh128(path)?;
|
||||
if fast_hash == old_meta.xxh128 {
|
||||
println!("校验通过.");
|
||||
} else {
|
||||
println!("校验失败!");
|
||||
println!("现校验文件:");
|
||||
println!("{}", meta.to_pretty_json()?);
|
||||
println!("原校验文件:");
|
||||
println!("{}", old_meta.to_pretty_json()?);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
println!("校验失败!");
|
||||
println!("现校验文件:");
|
||||
let meta = FileMeta::from_path(path)?;
|
||||
println!("{}", meta.to_pretty_json()?);
|
||||
println!("原校验文件:");
|
||||
println!("{}", old_meta.to_pretty_json()?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn process_dir(path: &Path) -> Result<()> {
|
||||
let save_path = path.join("meta.json");
|
||||
let old_path = path.join("meta-old.json");
|
||||
let has_old = save_path.exists();
|
||||
let meta_path = path.join("meta.json");
|
||||
let backup_path = path.join("meta-old.json");
|
||||
|
||||
if has_old {
|
||||
if old_path.exists() {
|
||||
fs::remove_file(&old_path)?;
|
||||
}
|
||||
fs::rename(&save_path, &old_path)
|
||||
.with_context(|| format!("无法备份旧文件: {}", save_path.display()))?;
|
||||
if !meta_path.exists() {
|
||||
let snapshot = DirSnapshot::build_root(path)?;
|
||||
let json = serde_json::to_string_pretty(&snapshot)?;
|
||||
let mut file = File::create(&meta_path)
|
||||
.with_context(|| format!("无法写入: {}", meta_path.display()))?;
|
||||
file.write_all(json.as_bytes())?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let snapshot = DirSnapshot::build_root(path)?;
|
||||
let json = serde_json::to_string_pretty(&snapshot)?;
|
||||
let mut file =
|
||||
File::create(&save_path).with_context(|| format!("无法写入: {}", save_path.display()))?;
|
||||
file.write_all(json.as_bytes())?;
|
||||
if backup_path.exists() {
|
||||
fs::remove_file(&backup_path)?;
|
||||
}
|
||||
|
||||
if has_old {
|
||||
let old_meta = FileMeta::from_path(&old_path)?;
|
||||
let new_meta = FileMeta::from_path(&save_path)?;
|
||||
if old_meta.matches(&new_meta) {
|
||||
println!("校验通过.");
|
||||
fs::remove_file(&old_path)?;
|
||||
fs::rename(&meta_path, &backup_path)
|
||||
.with_context(|| format!("无法重命名旧meta: {}", meta_path.display()))?;
|
||||
println!("发现旧元数据,已暂存为 meta-old.json,开始校验...");
|
||||
|
||||
let meta_file =
|
||||
File::open(&backup_path).with_context(|| format!("无法读取: {}", backup_path.display()))?;
|
||||
let snapshot = DirSnapshot::from_reader(meta_file)?;
|
||||
let mut stored = snapshot.collect_file_map(path);
|
||||
let current = scan_dir_xxh128(path)?;
|
||||
let mut issues = false;
|
||||
|
||||
for (file_path, hash) in current {
|
||||
if let Some(meta) = stored.remove(&file_path) {
|
||||
if hash != meta.xxh128 {
|
||||
println!(
|
||||
"校验失败: {}\n 期望: {}\n 当前: {}",
|
||||
file_path.display(),
|
||||
meta.xxh128,
|
||||
hash
|
||||
);
|
||||
issues = true;
|
||||
}
|
||||
} else {
|
||||
println!("校验失败!");
|
||||
println!("文件新增: {}", file_path.display());
|
||||
issues = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (missing_path, _) in stored {
|
||||
println!("文件缺失: {}", missing_path.display());
|
||||
issues = true;
|
||||
}
|
||||
|
||||
if issues {
|
||||
println!("校验存在异常,已保留 meta-old.json 供排查。");
|
||||
} else {
|
||||
println!("校验通过.");
|
||||
fs::rename(&backup_path, &meta_path)
|
||||
.with_context(|| format!("无法恢复meta: {}", meta_path.display()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user