cartulary 0.3.0-alpha.1

The knowledge layer of your project — decisions, issues, docs, all in one place.
Documentation
/// Port: abstracts writing the initial configuration file.
///
/// The template content lives in the infra adapter — the schema version
/// embedded in it is an on-disk-format concern, not a domain concern.
pub trait WorkspaceInitializer {
    /// Returns `true` if a configuration file already exists at the target location.
    fn config_exists(&self) -> bool;

    /// Write the default configuration file and return its path.
    fn write_default_config(&self) -> anyhow::Result<std::path::PathBuf>;
}

/// Initialise a cartulary workspace by creating a default `cartulary.toml`.
///
/// Returns the path of the created file on success.
/// Returns an error if the configuration file already exists.
pub fn init_workspace(
    initializer: &impl WorkspaceInitializer,
) -> anyhow::Result<std::path::PathBuf> {
    if initializer.config_exists() {
        anyhow::bail!("cartulary.toml already exists in this directory");
    }
    initializer.write_default_config()
}

#[cfg(test)]
mod tests {
    use super::*;

    struct StubInitializer {
        exists: bool,
    }

    impl WorkspaceInitializer for StubInitializer {
        fn config_exists(&self) -> bool {
            self.exists
        }

        fn write_default_config(&self) -> anyhow::Result<std::path::PathBuf> {
            Ok(std::path::PathBuf::from("cartulary.toml"))
        }
    }

    #[test]
    fn init_workspace_succeeds_when_no_config_exists() {
        let result = init_workspace(&StubInitializer { exists: false });
        assert!(result.is_ok());
        assert_eq!(result.unwrap(), std::path::Path::new("cartulary.toml"));
    }

    #[test]
    fn init_workspace_fails_when_config_already_exists() {
        let result = init_workspace(&StubInitializer { exists: true });
        assert!(result.is_err());
        let msg = result.unwrap_err().to_string();
        assert!(msg.contains("already exists"), "got: {msg}");
    }
}