Files
fomod-manager/src/utils.rs

66 lines
1.6 KiB
Rust

use std::{
fs::{self, DirEntry},
io,
path::{Path, PathBuf},
};
pub fn walk_files_recursive(
root: impl AsRef<Path>,
) -> std::io::Result<impl Iterator<Item = DirEntry>> {
fn visit(dir: &Path, out: &mut Vec<DirEntry>) -> std::io::Result<()> {
for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
let file_type = entry.file_type()?;
if file_type.is_dir() {
visit(&path, out)?;
} else if file_type.is_file() {
out.push(entry);
}
}
Ok(())
}
let mut files = Vec::new();
visit(root.as_ref(), &mut files)?;
Ok(files.into_iter())
}
pub fn path_to_lowercase(path: impl AsRef<Path>) -> PathBuf {
PathBuf::from(path.as_ref().to_string_lossy().to_lowercase())
}
pub fn resolve_case_insensitive(
base: impl AsRef<Path>,
rel: impl AsRef<Path>,
) -> io::Result<Option<PathBuf>> {
let mut current = base.as_ref().to_path_buf();
for part in rel.as_ref().iter() {
let target = part.to_string_lossy();
let mut found = None;
for entry in fs::read_dir(&current)? {
let entry = entry?;
let name = entry.file_name();
let name = name.to_string_lossy();
if name.eq_ignore_ascii_case(&target) {
found = Some(entry.path());
break;
}
}
match found {
Some(path) => current = path,
None => {
return Ok(None);
}
}
}
Ok(Some(current))
}