use crate::error::{CliError, CliErrorKind, KrikError, KrikResult};
use std::fs;
use std::path::{Path, PathBuf};
pub fn normalize_path<P: AsRef<Path>>(
path: P,
must_exist: bool,
context: &str,
) -> KrikResult<PathBuf> {
let p = path.as_ref();
if must_exist {
if !p.exists() {
return Err(KrikError::Cli(Box::new(CliError {
kind: CliErrorKind::PathDoesNotExist,
path: Some(p.to_path_buf()),
context: context.to_string(),
})));
}
match fs::canonicalize(p) {
Ok(abs) => Ok(abs),
Err(e) => Err(KrikError::Cli(Box::new(CliError {
kind: CliErrorKind::CanonicalizeFailed(e),
path: Some(p.to_path_buf()),
context: context.to_string(),
}))),
}
} else {
if p.exists() {
return fs::canonicalize(p).map_err(|e| {
KrikError::Cli(Box::new(CliError {
kind: CliErrorKind::CanonicalizeFailed(e),
path: Some(p.to_path_buf()),
context: context.to_string(),
}))
});
}
if let Some(parent) = p.parent() {
let base = if parent.exists() {
fs::canonicalize(parent).unwrap_or_else(|_| parent.to_path_buf())
} else {
std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."))
};
Ok(base.join(p.file_name().unwrap_or_default()))
} else {
Ok(std::env::current_dir()
.unwrap_or_else(|_| PathBuf::from("."))
.join(p))
}
}
}
pub fn validate_directory<P: AsRef<Path>>(path: P, context: &str) -> KrikResult<PathBuf> {
let p = path.as_ref();
if !p.exists() {
return Err(KrikError::Cli(Box::new(CliError {
kind: CliErrorKind::PathDoesNotExist,
path: Some(p.to_path_buf()),
context: context.to_string(),
})));
}
if !p.is_dir() {
return Err(KrikError::Cli(Box::new(CliError {
kind: CliErrorKind::NotADirectory,
path: Some(p.to_path_buf()),
context: context.to_string(),
})));
}
normalize_path(p, true, context)
}
pub fn ensure_directory<P: AsRef<Path>>(path: P, context: &str) -> KrikResult<PathBuf> {
let p = path.as_ref();
if p.exists() {
return validate_directory(p, context);
}
if let Err(e) = fs::create_dir_all(p) {
return Err(KrikError::Cli(Box::new(CliError {
kind: match e.kind() {
std::io::ErrorKind::PermissionDenied => CliErrorKind::PermissionDenied,
_ => CliErrorKind::CreateDirFailed(e),
},
path: Some(p.to_path_buf()),
context: context.to_string(),
})));
}
normalize_path(p, true, context)
}
pub fn parse_port(value: &str, context: &str) -> KrikResult<u16> {
match value.parse::<u16>() {
Ok(port) if port >= 1 => Ok(port),
_ => Err(KrikError::Cli(Box::new(CliError {
kind: CliErrorKind::InvalidPort(value.to_string()),
path: None,
context: context.to_string(),
}))),
}
}
pub fn validate_theme_dir<P: AsRef<Path>>(
opt_dir: Option<P>,
context: &str,
) -> KrikResult<Option<PathBuf>> {
match opt_dir {
Some(dir) => {
let p = dir.as_ref();
if !p.exists() {
return Err(KrikError::Cli(Box::new(CliError {
kind: CliErrorKind::ThemeNotFound,
path: Some(p.to_path_buf()),
context: context.to_string(),
})));
}
Ok(Some(normalize_path(p, true, context)?))
}
None => Ok(None),
}
}