use std::path::PathBuf;
use confium_registry::{Client, DEFAULT_REGISTRY_URL, Error, Fetcher};
pub const HOME_ENV: &str = "CONFium_HOME";
pub const REGISTRY_DIR_ENV: &str = "CONFium_REGISTRY_DIR";
pub const REGISTRY_URL_ENV: &str = "CONFium_REGISTRY_URL";
pub fn override_home() -> Option<PathBuf> {
std::env::var_os(HOME_ENV).map(PathBuf::from)
}
pub fn registry_client() -> Result<Client<FileFetcher>, Error> {
let base_url =
std::env::var(REGISTRY_URL_ENV).unwrap_or_else(|_| DEFAULT_REGISTRY_URL.to_string());
let root = std::env::var_os(REGISTRY_DIR_ENV).map(PathBuf::from);
let fetcher = FileFetcher::new(root);
Ok(Client::with_fetcher(base_url, fetcher))
}
pub struct FileFetcher {
root: Option<PathBuf>,
}
impl FileFetcher {
pub fn new(root: Option<PathBuf>) -> Self {
FileFetcher { root }
}
}
impl Fetcher for FileFetcher {
fn fetch(&self, path: &str) -> Result<Vec<u8>, Error> {
let Some(ref root) = self.root else {
return Err(Error::NotFound {
path: path.to_string(),
});
};
let relative = path.trim_start_matches('/');
let full = root.join(relative);
std::fs::read(&full).map_err(|e| Error::io(e, format!("failed to read {}", full.display())))
}
}
pub fn fail(err: Error) -> ! {
eprintln!("confium: {err}");
let code = match err {
Error::PluginNotFound { .. }
| Error::VersionNotFound { .. }
| Error::NotInstalled { .. }
| Error::NotFound { .. } => 64,
Error::UntrustedPlugin { .. } => 78,
Error::HashMismatch { .. } => 65,
_ => 70,
};
std::process::exit(code);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn override_home_reads_env() {
unsafe {
std::env::remove_var(HOME_ENV);
}
assert!(override_home().is_none());
unsafe {
std::env::set_var(HOME_ENV, "/tmp/example");
}
assert_eq!(override_home(), Some(PathBuf::from("/tmp/example")));
unsafe {
std::env::remove_var(HOME_ENV);
}
}
#[test]
fn empty_fetcher_returns_not_found() {
let fetcher = FileFetcher::new(None);
let err = fetcher.fetch("/index.toml").unwrap_err();
assert!(matches!(err, Error::NotFound { .. }));
}
}