use std::{fs, io::ErrorKind, path::Path};
use strum_macros::Display;
use crate::{fs_path,
fs_path::{FsOpError, FsOpResult},
ok};
#[derive(Debug, Display, Default)]
pub enum MkdirOptions {
#[default]
CreateIntermediateDirectories,
CreateIntermediateDirectoriesOnlyIfNotExists,
CreateIntermediateDirectoriesAndPurgeExisting,
}
pub fn try_mkdir(new_path: impl AsRef<Path>, options: MkdirOptions) -> FsOpResult<()> {
let new_path = new_path.as_ref();
match options {
MkdirOptions::CreateIntermediateDirectories => { }
MkdirOptions::CreateIntermediateDirectoriesAndPurgeExisting => {
match fs::exists(new_path) {
Ok(true) => {
if let Err(err) = fs::remove_dir_all(new_path) {
return handle_err(err);
}
}
Err(err) => return handle_err(err),
_ => { }
}
}
MkdirOptions::CreateIntermediateDirectoriesOnlyIfNotExists => {
if let Ok(true) = fs::exists(new_path) {
let new_dir_display = fs_path::path_as_string(new_path);
return FsOpResult::Err(FsOpError::DirectoryAlreadyExists(
new_dir_display,
));
}
}
}
create_dir_all(new_path)
}
fn handle_err(err: std::io::Error) -> FsOpResult<()> {
match err.kind() {
ErrorKind::PermissionDenied => {
FsOpResult::Err(FsOpError::PermissionDenied(err.to_string()))
}
ErrorKind::InvalidInput => {
FsOpResult::Err(FsOpError::InvalidName(err.to_string()))
}
ErrorKind::ReadOnlyFilesystem => {
FsOpResult::Err(FsOpError::PermissionDenied(err.to_string()))
}
_ => FsOpResult::Err(FsOpError::IoError(err)),
}
}
fn create_dir_all(new_path: &Path) -> FsOpResult<()> {
match fs::create_dir_all(new_path) {
Ok(_) => ok!(),
Err(err) => handle_err(err),
}
}
#[cfg(test)]
mod tests_directory_create {
use super::*;
use crate::{directory_create::{try_mkdir, MkdirOptions::*},
fs_paths,
serial_preserve_pwd_test,
try_create_temp_dir};
serial_preserve_pwd_test!(test_try_mkdir, {
let root = try_create_temp_dir().unwrap();
let tmp_root_dir = fs_paths!(with_root: root => "test_create_clean_new_dir");
try_mkdir(&tmp_root_dir, CreateIntermediateDirectories).unwrap();
let new_dir = fs_paths!(with_root: tmp_root_dir => "new_dir");
try_mkdir(&new_dir, CreateIntermediateDirectories).unwrap();
assert!(new_dir.exists());
let result = try_mkdir(&new_dir, CreateIntermediateDirectoriesOnlyIfNotExists);
assert!(result.is_err());
assert!(matches!(result, Err(FsOpError::DirectoryAlreadyExists(_))));
let file_path = new_dir.join("test_file.txt");
fs::write(&file_path, "test").unwrap();
assert!(file_path.exists());
try_mkdir(&new_dir, CreateIntermediateDirectoriesAndPurgeExisting).unwrap();
assert!(new_dir.exists());
assert!(!file_path.exists());
});
}