refactor check logic.
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::file::FileMeta;
|
||||
use super::file::{calc_xxh128, FileMeta};
|
||||
use crate::constants::META_VERSION;
|
||||
use crate::utils::{basename, should_skip_dir, should_skip_file};
|
||||
|
||||
@@ -24,6 +25,10 @@ impl DirSnapshot {
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
pub fn from_reader<R: std::io::Read>(reader: R) -> Result<Self> {
|
||||
Ok(serde_json::from_reader(reader)?)
|
||||
}
|
||||
|
||||
fn build_node(path: &Path) -> Result<Self> {
|
||||
let dir_name = path
|
||||
.file_name()
|
||||
@@ -73,4 +78,61 @@ impl DirSnapshot {
|
||||
v: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn collect_file_map(&self, root: &Path) -> BTreeMap<PathBuf, FileMeta> {
|
||||
let mut map = BTreeMap::new();
|
||||
self.collect_into(root.to_path_buf(), &mut map);
|
||||
map
|
||||
}
|
||||
|
||||
fn collect_into(&self, current: PathBuf, map: &mut BTreeMap<PathBuf, FileMeta>) {
|
||||
for file in &self.files {
|
||||
map.insert(current.join(&file.basename), file.clone());
|
||||
}
|
||||
|
||||
for dir in &self.dirs {
|
||||
let next = current.join(&dir.dir_name);
|
||||
dir.collect_into(next, map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scan_dir_xxh128(path: &Path) -> Result<BTreeMap<PathBuf, String>> {
|
||||
let mut map = BTreeMap::new();
|
||||
walk_dir(path, &mut map)?;
|
||||
Ok(map)
|
||||
}
|
||||
|
||||
fn walk_dir(path: &Path, map: &mut BTreeMap<PathBuf, String>) -> Result<()> {
|
||||
let mut entries = fs::read_dir(path)
|
||||
.with_context(|| format!("无法遍历目录: {}", path.display()))?
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.with_context(|| format!("读取目录失败: {}", path.display()))?;
|
||||
entries.sort_by(|a, b| a.file_name().cmp(&b.file_name()));
|
||||
|
||||
for entry in entries {
|
||||
let file_name = entry.file_name();
|
||||
let name = file_name.to_string_lossy().to_string();
|
||||
let full_path = entry.path();
|
||||
let file_type = entry
|
||||
.file_type()
|
||||
.with_context(|| format!("无法读取类型: {}", full_path.display()))?;
|
||||
|
||||
if file_type.is_dir() {
|
||||
if should_skip_dir(&name) {
|
||||
continue;
|
||||
}
|
||||
walk_dir(&full_path, map)?;
|
||||
continue;
|
||||
}
|
||||
|
||||
if should_skip_file(&name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let hash = calc_xxh128(&full_path)?;
|
||||
map.insert(full_path, hash);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user