use std::path::{Path, PathBuf};
use crate::pack::{parse, PackManifest};
use super::error::TreeError;
pub trait PackLoader: Send + Sync {
fn load(&self, path: &Path) -> Result<PackManifest, TreeError>;
}
#[derive(Debug, Default)]
pub struct FsPackLoader;
impl FsPackLoader {
#[must_use]
pub const fn new() -> Self {
Self
}
}
impl PackLoader for FsPackLoader {
fn load(&self, path: &Path) -> Result<PackManifest, TreeError> {
let manifest_path = resolve_manifest_path(path);
if !manifest_path.is_file() {
return Err(TreeError::ManifestNotFound(manifest_path));
}
let raw = std::fs::read_to_string(&manifest_path)
.map_err(|e| TreeError::ManifestRead(format!("{}: {e}", manifest_path.display())))?;
parse(&raw)
.map_err(|e| TreeError::ManifestParse { path: manifest_path, detail: e.to_string() })
}
}
fn resolve_manifest_path(path: &Path) -> PathBuf {
if has_yaml_extension(path) {
path.to_path_buf()
} else {
path.join(".grex").join("pack.yaml")
}
}
fn has_yaml_extension(path: &Path) -> bool {
matches!(path.extension().and_then(|e| e.to_str()), Some("yaml" | "yml"))
}