use crate::migration::MigrationConfig;
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
pub struct Config {
pub migration: MigrationConfig,
}
impl Config {
pub fn new() -> Self {
Self::default()
}
pub fn load() -> Result<Self> {
Self::load_from(Path::new("Toasty.toml"))
}
pub fn load_from(path: &Path) -> Result<Self> {
let contents = fs::read_to_string(path).with_context(|| {
format!(
"failed to read Toasty config file at `{}` — check that the file exists \
at this path relative to the working directory (a common cause in Docker \
multi-stage builds is forgetting to copy it into the final image)",
path.display()
)
})?;
let config: Config = toml::from_str(&contents).with_context(|| {
format!("failed to parse Toasty config file at `{}`", path.display())
})?;
Ok(config)
}
pub fn load_or_default(project_root: &Path) -> Result<Self> {
let path = project_root.join("Toasty.toml");
if path.exists() {
Self::load_from(&path)
} else {
let config = Self::default();
let toml = toml::to_string_pretty(&config)?;
fs::write(&path, toml)?;
Ok(config)
}
}
pub fn migration(mut self, migration: MigrationConfig) -> Self {
self.migration = migration;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;
#[test]
fn load_or_default_creates_toasty_toml_when_missing() {
let dir = tempdir().unwrap();
let path = dir.path().join("Toasty.toml");
assert!(!path.exists());
Config::load_or_default(dir.path()).unwrap();
assert!(path.exists(), "Toasty.toml should be created on first load");
let contents = fs::read_to_string(&path).unwrap();
let reparsed: Config = toml::from_str(&contents).unwrap();
let default = Config::default();
assert_eq!(reparsed, default);
}
#[test]
fn load_from_missing_file_reports_path() {
let dir = tempdir().unwrap();
let path = dir.path().join("Toasty.toml");
let err = Config::load_from(&path).unwrap_err();
let message = format!("{err:#}");
assert!(
message.contains(&path.display().to_string()),
"error message should mention the missing path: {message}"
);
}
}