mod cargo;
use crate::config::{Configuration, models::ConfigModel};
use anyhow::bail;
use std::{
fs::File,
io::BufReader,
path::{Path, PathBuf},
};
pub enum Source {
File(PathBuf),
Manifest { file: PathBuf },
}
const CANDIDATES: &[&str] = &[
"Trunk.toml",
".trunk.toml",
"Trunk.yaml",
".trunk.yaml",
"Trunk.json",
".trunk.json",
];
impl Source {
pub fn find(path: &Path) -> anyhow::Result<Source> {
for name in CANDIDATES {
if let Some(file) = check_path(path, name) {
return Ok(Source::File(file));
}
}
if let Some(file) = check_path(path, "Cargo.toml") {
Ok(Source::Manifest { file })
} else {
bail!("Unable to find any Trunk configuration");
}
}
pub async fn load(self) -> anyhow::Result<Configuration> {
match self {
Self::File(file) => load_from(&file),
Self::Manifest { file } => cargo::from_manifest(file).await,
}
.and_then(|mut cfg| {
cfg.migrate()?;
Ok(cfg)
})
}
}
fn load_from(file: &Path) -> anyhow::Result<Configuration> {
match file.extension().map(|s| s.to_string_lossy()).as_deref() {
Some("toml") => Ok(toml::from_str(&String::from_utf8(std::fs::read(file)?)?)?),
Some("yaml") => Ok(serde_yaml::from_reader(BufReader::new(File::open(file)?))?),
Some("json") => Ok(serde_json::from_reader(BufReader::new(File::open(file)?))?),
Some(n) => {
bail!("Unsupported configuration file type: {n}");
}
None => {
bail!("Missing configuration file extension");
}
}
}
fn check_path(path: &Path, name: &str) -> Option<PathBuf> {
let path = path.join(name);
if path.is_file() { Some(path) } else { None }
}