use std::path::PathBuf;
use crate::domain::usecases::init::WorkspaceInitializer;
use crate::infra::driven::fs::config::CURRENT_SCHEMA_VERSION;
pub struct FsWorkspaceInitializer {
pub root: PathBuf,
}
fn default_config() -> String {
format!(
r#"version = {CURRENT_SCHEMA_VERSION}
[decisions]
types = ["adr"]
[decisions.adr]
dir = "docs/adr"
[issues]
dir = "docs/issues"
"#
)
}
impl WorkspaceInitializer for FsWorkspaceInitializer {
fn config_exists(&self) -> bool {
self.root.join("cartulary.toml").exists()
}
fn write_default_config(&self) -> anyhow::Result<std::path::PathBuf> {
let path = self.root.join("cartulary.toml");
std::fs::write(&path, default_config())
.map_err(|e| anyhow::anyhow!("failed to write {}: {e}", path.display()))?;
Ok(path)
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
#[test]
fn config_exists_returns_false_for_empty_dir() {
let tmp = TempDir::new().unwrap();
let adapter = FsWorkspaceInitializer {
root: tmp.path().to_path_buf(),
};
assert!(!adapter.config_exists());
}
#[test]
fn config_exists_returns_true_when_file_present() {
let tmp = TempDir::new().unwrap();
std::fs::write(tmp.path().join("cartulary.toml"), "[decisions]\n").unwrap();
let adapter = FsWorkspaceInitializer {
root: tmp.path().to_path_buf(),
};
assert!(adapter.config_exists());
}
#[test]
fn write_default_config_creates_file_with_correct_content() {
let tmp = TempDir::new().unwrap();
let adapter = FsWorkspaceInitializer {
root: tmp.path().to_path_buf(),
};
let path = adapter.write_default_config().unwrap();
let content = std::fs::read_to_string(tmp.path().join("cartulary.toml")).unwrap();
assert!(
content.contains("[decisions]"),
"missing [decisions] in {content}"
);
assert!(
content.contains("[issues]"),
"missing [issues] in {content}"
);
assert!(path.ends_with("cartulary.toml"));
}
#[test]
fn write_default_config_embeds_current_schema_version() {
let tmp = TempDir::new().unwrap();
let adapter = FsWorkspaceInitializer {
root: tmp.path().to_path_buf(),
};
adapter.write_default_config().unwrap();
let content = std::fs::read_to_string(tmp.path().join("cartulary.toml")).unwrap();
let expected = format!("version = {CURRENT_SCHEMA_VERSION}");
assert!(
content.contains(&expected),
"expected `{expected}` in fresh workspace, got:\n{content}"
);
}
}