use std::collections::HashMap;
use std::sync::Mutex;
use crate::ports::git_config::{GitConfigError, GitConfigProvider};
#[derive(Debug, Clone)]
pub struct GitConfigSetCall {
pub key: String,
pub value: String,
}
pub struct FakeGitConfigProvider {
configs: Mutex<HashMap<String, String>>,
set_calls: Mutex<Vec<GitConfigSetCall>>,
fail_on_set: Mutex<Option<String>>,
}
impl Default for FakeGitConfigProvider {
fn default() -> Self {
Self::new()
}
}
impl FakeGitConfigProvider {
pub fn new() -> Self {
Self {
configs: Mutex::new(HashMap::new()),
set_calls: Mutex::new(Vec::new()),
fail_on_set: Mutex::new(None),
}
}
pub fn with_config(self, key: &str, value: &str) -> Self {
self.configs
.lock()
.unwrap_or_else(|e| e.into_inner())
.insert(key.into(), value.into());
self
}
pub fn set_fails_with(self, msg: &str) -> Self {
*self.fail_on_set.lock().unwrap_or_else(|e| e.into_inner()) = Some(msg.into());
self
}
pub fn set_calls(&self) -> Vec<GitConfigSetCall> {
self.set_calls
.lock()
.unwrap_or_else(|e| e.into_inner())
.clone()
}
pub fn get(&self, key: &str) -> Option<String> {
self.configs
.lock()
.unwrap_or_else(|e| e.into_inner())
.get(key)
.cloned()
}
}
impl GitConfigProvider for FakeGitConfigProvider {
fn set(&self, key: &str, value: &str) -> Result<(), GitConfigError> {
if let Some(msg) = self
.fail_on_set
.lock()
.unwrap_or_else(|e| e.into_inner())
.as_ref()
{
return Err(GitConfigError::CommandFailed(msg.clone()));
}
self.set_calls
.lock()
.unwrap_or_else(|e| e.into_inner())
.push(GitConfigSetCall {
key: key.into(),
value: value.into(),
});
self.configs
.lock()
.unwrap_or_else(|e| e.into_inner())
.insert(key.into(), value.into());
Ok(())
}
fn unset(&self, key: &str) -> Result<(), GitConfigError> {
self.configs
.lock()
.unwrap_or_else(|e| e.into_inner())
.remove(key);
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::testing::fakes::git_config::FakeGitConfigProvider;
crate::git_config_provider_contract_tests!(fake, { (FakeGitConfigProvider::new(), ()) },);
}