use std::{
fs::{self, File},
io::Write,
path::Path,
};
use toml::Value;
use walkdir::WalkDir;
use crate::errors::*;
pub fn cp_r(src: &Path, dst: &Path) -> Result<()> {
for e in WalkDir::new(src) {
let e = e.chain_err(|| {
format!(
"intermittent IO error while iterating directory `{}`",
src.display()
)
})?;
let src_file = e.path();
let relative_path = src_file.strip_prefix(src).chain_err(|| {
format!(
"Could not retrieve relative path of child directory or \
file `{}` with regards to parent directory `{}`",
src_file.display(),
src.display()
)
})?;
let dst_file = dst.join(relative_path);
let ft = e.file_type();
if ft.is_dir() {
fs::create_dir_all(&dst_file)
.chain_err(|| format!("Could not create directory `{}`", dst_file.display()))?;
} else {
fs::copy(src_file, &dst_file).chain_err(|| {
format!(
"copying files from `{}` to `{}` failed",
src_file.display(),
dst_file.display()
)
})?;
}
}
Ok(())
}
pub fn mkdir(path: &Path) -> Result<()> {
fs::create_dir(path).chain_err(|| format!("couldn't create directory {}", path.display()))
}
pub fn parse(path: &Path) -> Result<Value> {
Ok(toml::from_str(&read(path)?)
.map_err(|e| format!("{} is not valid TOML: {}", path.display(), e))?)
}
pub fn read(path: &Path) -> Result<String> {
fs::read_to_string(path).chain_err(|| format!("couldn't read {}", path.display()))
}
pub fn search<'p>(mut path: &'p Path, file: &str) -> Option<&'p Path> {
loop {
if path.join(file).exists() {
return Some(path);
}
if let Some(p) = path.parent() {
path = p;
} else {
return None;
}
}
}
pub fn write(path: &Path, contents: &str) -> Result<()> {
let p = path.display();
File::create(path)
.chain_err(|| format!("couldn't open {}", p))?
.write_all(contents.as_bytes())
.chain_err(|| format!("couldn't write to {}", p))
}