Skip to main content

auths_infra_git/
repo.rs

1use auths_core::ports::storage::StorageError;
2use git2::Repository;
3use std::path::{Path, PathBuf};
4use std::sync::Mutex;
5
6/// Newtype wrapper around `git2::Repository`.
7///
8/// Wraps the repository in a `Mutex` to satisfy `Send + Sync` bounds
9/// required by the storage port traits, since `git2::Repository` is
10/// not `Sync` by default.
11///
12/// Usage:
13/// ```ignore
14/// use auths_infra_git::GitRepo;
15///
16/// let repo = GitRepo::open("/path/to/repo")?;
17/// ```
18pub struct GitRepo {
19    inner: Mutex<Repository>,
20    path: PathBuf,
21}
22
23impl GitRepo {
24    /// Opens an existing Git repository at the given path.
25    ///
26    /// Args:
27    /// * `path`: Filesystem path to the repository root.
28    ///
29    /// Usage:
30    /// ```ignore
31    /// let repo = GitRepo::open("/home/user/.auths")?;
32    /// ```
33    pub fn open(path: impl AsRef<Path>) -> Result<Self, StorageError> {
34        let path = path.as_ref().to_path_buf();
35        let inner = Repository::open(&path).map_err(|e| StorageError::Io(e.to_string()))?;
36        Ok(Self {
37            inner: Mutex::new(inner),
38            path,
39        })
40    }
41
42    /// Initializes a new Git repository at the given path.
43    ///
44    /// Args:
45    /// * `path`: Filesystem path where the repository will be created.
46    ///
47    /// Usage:
48    /// ```ignore
49    /// let repo = GitRepo::init("/tmp/new-repo")?;
50    /// ```
51    pub fn init(path: impl AsRef<Path>) -> Result<Self, StorageError> {
52        let path = path.as_ref().to_path_buf();
53        let inner = Repository::init(&path).map_err(|e| StorageError::Io(e.to_string()))?;
54        Ok(Self {
55            inner: Mutex::new(inner),
56            path,
57        })
58    }
59
60    pub(crate) fn with_repo<T>(
61        &self,
62        f: impl FnOnce(&Repository) -> Result<T, StorageError>,
63    ) -> Result<T, StorageError> {
64        let repo = self
65            .inner
66            .lock()
67            .map_err(|e| StorageError::Io(format!("mutex poisoned: {}", e)))?;
68        f(&repo)
69    }
70
71    pub fn path(&self) -> &Path {
72        &self.path
73    }
74}