gitdataai/libs/git/domain.rs
2026-04-15 09:08:09 +08:00

59 lines
1.8 KiB
Rust

use std::path::Path;
use std::sync::Arc;
use crate::GitError;
use git2::Repository;
use models::repos::repo;
#[derive(Clone)]
pub struct GitDomain {
pub(crate) repo: Arc<Repository>,
}
// SAFETY: git2's Repository uses internal locking for thread-safe operations.
// We additionally enforce exclusive access via Arc::get_mut in repo_mut().
// All mutable access is gated through the synchronous methods of HookMetaDataSync,
// which are called from a single blocking thread per sync cycle.
#[allow(unsafe_code)]
unsafe impl Send for GitDomain {}
#[allow(unsafe_code)]
unsafe impl Sync for GitDomain {}
impl GitDomain {
pub fn from_model(model: repo::Model) -> crate::GitResult<Self> {
let repo =
Repository::open(model.storage_path).map_err(|e| GitError::Internal(e.to_string()))?;
Ok(Self {
repo: Arc::new(repo),
})
}
pub fn open<P: AsRef<Path>>(path: P) -> crate::GitResult<Self> {
let repo = Repository::open(path).map_err(|e| GitError::Internal(e.to_string()))?;
Ok(Self {
repo: Arc::new(repo),
})
}
pub fn open_workdir<P: AsRef<Path>>(path: P) -> crate::GitResult<Self> {
let repo = Repository::open_bare(path).map_err(|e| GitError::Internal(e.to_string()))?;
Ok(Self {
repo: Arc::new(repo),
})
}
pub fn init_bare<P: AsRef<Path>>(path: P) -> crate::GitResult<Self> {
let repo = Repository::init_bare(path).map_err(|e| GitError::Internal(e.to_string()))?;
Ok(Self {
repo: Arc::new(repo),
})
}
pub fn repo(&self) -> &Repository {
&self.repo
}
pub fn repo_mut(&mut self) -> crate::GitResult<&mut Repository> {
Arc::get_mut(&mut self.repo)
.ok_or_else(|| GitError::Internal("GitDomain requires exclusive access".to_string()))
}
}