use std::path::{Path, PathBuf};
use crate::error::Result;
use crate::settings::{Dirs, UPLOAD_DIR, VERSION_DIR};
#[derive(
Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, utoipa::ToSchema,
)]
#[serde(transparent)]
pub struct VersionedPath(String);
impl VersionedPath {
pub fn new(name: impl Into<String>) -> Self { Self(name.into()) }
pub fn logical(&self) -> &str { &self.0 }
pub fn resolve(&self, base_dir: &Path) -> std::io::Result<PathBuf> {
Self::find_latest(base_dir.join(&self.0).join(VERSION_DIR))
}
pub fn find_latest<P: AsRef<Path>>(dir: P) -> std::io::Result<PathBuf> {
let dir_path = dir.as_ref();
let mut entries: Vec<_> = std::fs::read_dir(dir_path)?
.filter_map(std::io::Result::ok)
.filter(|e| e.path().is_file())
.collect();
entries.sort_by_key(std::fs::DirEntry::file_name);
entries.last().map(std::fs::DirEntry::path).ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("No files found in directory: {}", dir_path.display()),
)
})
}
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, utoipa::ToSchema,
)]
#[serde(tag = "dir", content = "path", rename_all = "lowercase")]
pub enum RelativePath {
Cache(String),
Data(String),
Upload(VersionedPath),
}
impl RelativePath {
pub fn get(&self, base: Option<&Dirs>) -> std::io::Result<PathBuf> {
let dirs = base.unwrap_or(Dirs::get());
match self {
RelativePath::Cache(path) => Ok(dirs.cache.join(path)),
RelativePath::Data(path) => Ok(dirs.data.join(path)),
RelativePath::Upload(versioned) => {
versioned.resolve(&dirs.data.join(UPLOAD_DIR))
}
}
}
}
#[derive(
Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, utoipa::ToSchema,
)]
#[serde(untagged)]
pub enum UserDefinedPath {
Managed(RelativePath),
External(String),
}
impl UserDefinedPath {
pub fn resolve(&self, base: Option<&Dirs>) -> Result<PathBuf> {
match self {
UserDefinedPath::Managed(rel_path) => Ok(rel_path.get(base)?),
UserDefinedPath::External(path) => {
let expanded = super::utils::try_env_expand(path)?;
super::utils::normalize_path_to_cur_dir(expanded)
}
}
}
}