use serde::{Deserialize, Serialize};
use std::env;
use std::path::{Path, PathBuf};
#[derive(Debug, Deserialize, Serialize, Default)]
#[serde(default)]
pub struct CellarConfig {
pub ml_cellar: MlCellarConfig,
pub aws: AWSConfig,
}
#[derive(Debug, Deserialize, Serialize, Default)]
#[serde(default)]
pub struct MlCellarConfig {
pub use_custom_transfer_agent: bool,
}
#[derive(Debug, Deserialize, Serialize, Default)]
#[serde(default)]
pub struct AWSConfig {
pub profile: Option<String>,
}
pub fn load_cellar_config(path: &Path) -> (CellarConfig, PathBuf) {
let relative_dir = if path.is_dir() {
path.to_path_buf()
} else {
path.parent().unwrap().to_path_buf()
};
let mut absolute_dir = if relative_dir.is_absolute() {
relative_dir
} else {
env::current_dir().unwrap().join(relative_dir)
};
loop {
let candidate = absolute_dir.join(".mlcellar.toml");
if candidate.is_file() {
log::info!("Loading config from {:?}", candidate);
let config_content = std::fs::read_to_string(&candidate).unwrap();
return (toml::from_str(&config_content).unwrap(), absolute_dir);
}
match absolute_dir.parent() {
Some(parent) => absolute_dir = parent.to_path_buf(),
None => {
log::error!(
".mlcellar.toml not found; reached filesystem root at {:?}\n\
Please ensure that .mlcellar.toml exists in the directory tree starting from the directory of the provided path.",
absolute_dir
);
panic!(
".mlcellar.toml not found in the directory tree starting from {:?}",
path
);
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
use toml::to_string_pretty;
#[test]
fn test_load_cellar_config() {
let temp = TempDir::new().unwrap();
let root_directory = temp.path();
let toml_str = to_string_pretty(&CellarConfig::default())
.expect("failed to serialize cellar config to TOML");
std::fs::write(root_directory.join(".mlcellar.toml"), toml_str)
.expect("failed to write .mlcellar.toml");
let (config, config_dir) = load_cellar_config(root_directory);
assert_eq!(config_dir, root_directory);
assert!(!config.ml_cellar.use_custom_transfer_agent);
}
}