use auths_core::ports::storage::StorageError;
use git2::Repository;
use std::path::{Path, PathBuf};
use std::sync::Mutex;
pub struct GitRepo {
inner: Mutex<Repository>,
path: PathBuf,
}
impl GitRepo {
pub fn open(path: impl AsRef<Path>) -> Result<Self, StorageError> {
let path = path.as_ref().to_path_buf();
let inner = Repository::open(&path).map_err(|e| StorageError::Io(e.to_string()))?;
Ok(Self {
inner: Mutex::new(inner),
path,
})
}
pub fn init(path: impl AsRef<Path>) -> Result<Self, StorageError> {
let path = path.as_ref().to_path_buf();
let inner = Repository::init(&path).map_err(|e| StorageError::Io(e.to_string()))?;
disable_gc(&inner)?;
Ok(Self {
inner: Mutex::new(inner),
path,
})
}
pub(crate) fn with_repo<T>(
&self,
f: impl FnOnce(&Repository) -> Result<T, StorageError>,
) -> Result<T, StorageError> {
let repo = self
.inner
.lock()
.map_err(|e| StorageError::Io(format!("mutex poisoned: {}", e)))?;
f(&repo)
}
pub fn path(&self) -> &Path {
&self.path
}
}
fn disable_gc(repo: &Repository) -> Result<(), StorageError> {
let mut cfg = repo.config().map_err(|e| StorageError::Io(e.to_string()))?;
cfg.set_i32("gc.auto", 0)
.map_err(|e| StorageError::Io(e.to_string()))?;
cfg.set_str("gc.pruneExpire", "never")
.map_err(|e| StorageError::Io(e.to_string()))?;
Ok(())
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
#[test]
fn init_disables_gc() {
let dir = tempfile::tempdir().unwrap();
let repo = GitRepo::init(dir.path()).unwrap();
repo.with_repo(|r| {
let cfg = r.config().map_err(|e| StorageError::Io(e.to_string()))?;
assert_eq!(cfg.get_i32("gc.auto").unwrap(), 0);
assert_eq!(cfg.get_string("gc.pruneExpire").unwrap(), "never");
Ok(())
})
.unwrap();
}
}