use std::io::Error as IoError;
use std::io::ErrorKind;
use std::path::Path;
use tracing::{debug, error, trace};
pub fn prepare_file_path(path: &Path) -> Result<(), IoError> {
match std::fs::remove_file(path) {
Ok(()) => trace!("Removed existing file: {}", path.display()),
Err(e) if e.kind() == ErrorKind::NotFound => {
trace!("Nothing to remove at: {}", path.display());
}
Err(e) => {
error!("Failed to remove existing file: {}", path.display());
return Err(IoError::new(
e.kind(),
format!("Failed to remove existing file: {}", path.display()),
));
}
}
if let Some(parent) = path.parent()
&& !parent.exists()
{
match std::fs::create_dir_all(parent) {
Ok(_) => {}
Err(e) => {
error!("Failed to create parent directories: {}", path.display());
return Err(IoError::new(
e.kind(),
format!("Failed to create parent directories: {}", path.display()),
));
}
};
debug!("Created directory: {}", path.display());
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
#[test]
fn test_prepare_file_path_accepts_a_path_with_no_file() {
let dir = std::env::temp_dir().join("optionstratlib_prepare_file_path");
fs::create_dir_all(&dir).expect("the temp directory is writable");
let path = dir.join("absent.html");
let _ = fs::remove_file(&path);
prepare_file_path(&path).expect("an absent file is already prepared");
fs::write(&path, b"contents").expect("the temp directory is writable");
prepare_file_path(&path).expect("an existing file is removed");
assert!(!path.exists());
prepare_file_path(&path).expect("preparing twice is not an error");
assert!(!path.exists());
}
#[test]
fn test_prepare_file_path_creates_missing_parents() {
let dir = std::env::temp_dir().join("optionstratlib_prepare_file_path/nested/deeper");
let _ = fs::remove_dir_all(
std::env::temp_dir().join("optionstratlib_prepare_file_path/nested"),
);
let path = dir.join("target.html");
prepare_file_path(&path).expect("the parents are created");
assert!(dir.exists());
}
}