use std::path::Path;
use rskit_errors::{AppError, AppResult, ErrorCode};
use crate::types::DirEntry;
pub fn create_all(path: &Path) -> AppResult<()> {
std::fs::create_dir_all(path).map_err(|error| create_dir_error(path, error))
}
pub fn exists(path: &Path) -> AppResult<bool> {
match std::fs::symlink_metadata(path) {
Ok(metadata) => Ok(metadata.is_dir() && !metadata.file_type().is_symlink()),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(false),
Err(error) => Err(inspect_dir_error(path, error)),
}
}
pub fn list(path: &Path) -> AppResult<Vec<DirEntry>> {
std::fs::read_dir(path)
.map_err(|error| read_dir_error(path, error))?
.map(|entry| {
let entry = entry.map_err(read_dir_entry_error)?;
let path = entry.path();
let file_name = entry.file_name();
let file_type = entry
.file_type()
.map_err(|error| inspect_dir_entry_error(&path, error))?;
Ok(DirEntry {
path,
file_name,
is_file: file_type.is_file(),
is_dir: file_type.is_dir(),
is_symlink: file_type.is_symlink(),
})
})
.collect()
}
pub fn is_empty(path: &Path) -> AppResult<bool> {
Ok(list(path)?.is_empty())
}
pub fn remove(path: &Path) -> AppResult<()> {
std::fs::remove_dir(path).map_err(|error| remove_dir_error(path, error))
}
pub fn remove_if_exists(path: &Path) -> AppResult<bool> {
match std::fs::remove_dir(path) {
Ok(()) => Ok(true),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(false),
Err(error) => Err(remove_dir_error(path, error)),
}
}
pub fn remove_all(path: &Path) -> AppResult<()> {
std::fs::remove_dir_all(path).map_err(|error| remove_tree_error(path, error))
}
pub fn remove_all_if_exists(path: &Path) -> AppResult<bool> {
match std::fs::remove_dir_all(path) {
Ok(()) => Ok(true),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(false),
Err(error) => Err(remove_tree_error(path, error)),
}
}
fn create_dir_error(path: &Path, error: std::io::Error) -> AppError {
AppError::new(
ErrorCode::Internal,
format!("failed to create directory '{}': {error}", path.display()),
)
.with_cause(error)
}
fn inspect_dir_error(path: &Path, error: std::io::Error) -> AppError {
AppError::new(
ErrorCode::Internal,
format!("failed to inspect directory '{}': {error}", path.display()),
)
.with_cause(error)
}
fn read_dir_error(path: &Path, error: std::io::Error) -> AppError {
AppError::new(
ErrorCode::Internal,
format!("failed to read directory '{}': {error}", path.display()),
)
.with_cause(error)
}
fn read_dir_entry_error(error: std::io::Error) -> AppError {
AppError::new(
ErrorCode::Internal,
format!("failed to read directory entry: {error}"),
)
.with_cause(error)
}
fn inspect_dir_entry_error(path: &Path, error: std::io::Error) -> AppError {
AppError::new(
ErrorCode::Internal,
format!(
"failed to inspect directory entry '{}': {error}",
path.display()
),
)
.with_cause(error)
}
fn remove_dir_error(path: &Path, error: std::io::Error) -> AppError {
AppError::new(
ErrorCode::Internal,
format!("failed to remove directory '{}': {error}", path.display()),
)
.with_cause(error)
}
fn remove_tree_error(path: &Path, error: std::io::Error) -> AppError {
AppError::new(
ErrorCode::Internal,
format!(
"failed to remove directory tree '{}': {error}",
path.display()
),
)
.with_cause(error)
}