dotfiles/src/utils.rs

89 lines
2.8 KiB
Rust
Raw Normal View History

use std::path::{Path, PathBuf};
2023-01-20 16:43:17 +01:00
fn get_dir_content_recursive<F>(p: &Path, filter: &F, pb: &indicatif::ProgressBar, dirs: &mut Vec<PathBuf>, files: &mut Vec<PathBuf>) -> bool
where F: Fn(&Path) -> bool {
let mut add = true;
for child in p.read_dir().unwrap() {
let child = child.unwrap();
let p = child.path();
if filter(&p) {
if child.file_type().unwrap().is_dir() {
add = get_dir_content_recursive(&child.path(), filter, pb, dirs, files) && add;
} else {
files.push(p);
pb.inc_length(1);
}
} else { add = false; }
2023-01-20 16:43:17 +01:00
}
if add {
dirs.push(p.to_path_buf());
pb.inc_length(1);
}
return add;
}
pub struct DirContent {
pub dirs: Vec<PathBuf>,
pub files: Vec<PathBuf>
}
pub fn get_dir_content_filtered(p: &Path, ignored: &[String], pb: &indicatif::ProgressBar) -> Result<DirContent, String> {
let base = p.canonicalize().map_err(|e| e.to_string())?;
let base_path_len = base.to_str().unwrap().len() + 1;
let path_filter = |p: &Path| {
let p = p.canonicalize().unwrap();
let p = p.to_string_lossy();
2023-01-20 16:43:17 +01:00
if p.len() < base_path_len { return false; }
let rel_path = p.split_at(base_path_len).1;
!ignored.iter().any(|i| rel_path.starts_with(i))
};
let mut dirs = Vec::<PathBuf>::new();
let mut files = Vec::<PathBuf>::new();
2023-01-20 16:43:17 +01:00
get_dir_content_recursive(&base, &path_filter, pb, &mut dirs, &mut files);
Ok(DirContent {
dirs,
files
})
}
2023-01-20 16:43:17 +01:00
pub fn copy_dir(src_dir: &Path, dst_dir: &Path, ignored: &[String], pb: &indicatif::ProgressBar) -> Result<(), String> {
let src_dir_len = src_dir.iter().count();
let trim_fn = |p: PathBuf| {
let new_path = p.into_iter().skip(src_dir_len).collect::<PathBuf>();
(new_path.iter().count() != 0).then_some(new_path).or_else(|| { pb.set_length(pb.length().unwrap() - 1); None })
2023-01-20 16:43:17 +01:00
};
let DirContent { dirs, files } = get_dir_content_filtered(src_dir, ignored, pb)?;
for dir in dirs.into_iter().filter_map(trim_fn) {
std::fs::create_dir_all(dst_dir.join(dir)).map_err(|e| e.to_string())?;
pb.inc(1);
}
for file in files.into_iter().filter_map(trim_fn) {
std::fs::copy(src_dir.join(&file), dst_dir.join(file)).map_err(|e| e.to_string())?;
pb.inc(1);
}
Ok(())
2023-01-20 16:43:17 +01:00
}
pub fn remove_dir(dir: &Path, ignored: &[String], pb: &indicatif::ProgressBar) -> Result<(), String> {
let to_remove = get_dir_content_filtered(dir, ignored, pb)?;
for file in to_remove.files {
std::fs::remove_file(file).map_err(|e| e.to_string())?;
pb.inc(1);
}
for dir in to_remove.dirs {
std::fs::remove_dir(dir).map_err(|e| e.to_string())?;
pb.inc(1);
2023-01-20 16:43:17 +01:00
}
2023-01-20 16:43:17 +01:00
Ok(())
}