mod git;
mod none;
mod svn;
pub use git::GitProvider;
pub use none::NoneProvider;
pub use svn::SvnProvider;
use std::path::{Path, PathBuf};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VcsKind {
Git,
Svn,
None,
}
impl std::fmt::Display for VcsKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Git => write!(f, "git"),
Self::Svn => write!(f, "svn"),
Self::None => write!(f, "none"),
}
}
}
#[derive(Debug, Clone)]
pub struct VcsCapabilities {
pub has_staging_area: bool,
pub has_client_hooks: bool,
pub has_worktree: bool,
pub has_branches: bool,
}
pub trait VcsProvider: Send + Sync {
fn kind(&self) -> VcsKind;
fn capabilities(&self) -> VcsCapabilities;
fn project_root(&self) -> &Path;
fn get_pending_files(&self) -> crate::Result<Vec<PathBuf>>;
fn get_modified_files(&self) -> crate::Result<Vec<PathBuf>>;
fn get_changed_files(&self, base: Option<&str>) -> crate::Result<Vec<PathBuf>>;
fn get_diff(&self, base: Option<&str>) -> crate::Result<String>;
fn stage_files(&self, files: &[PathBuf]) -> crate::Result<()>;
fn get_user_name(&self) -> Option<String>;
fn get_remote_url(&self) -> Option<String>;
fn current_branch(&self) -> Option<String>;
fn file_contributors(&self, file: &Path) -> Vec<String>;
fn hooks_dir(&self) -> Option<PathBuf>;
fn global_hooks_dir(&self) -> Option<PathBuf>;
fn create_worktree(&self, path: &Path, branch: &str) -> crate::Result<()>;
fn remove_worktree(&self, path: &Path) -> crate::Result<()>;
fn apply_diff_to(&self, diff: &str, target: &Path) -> crate::Result<()>;
}
pub fn detect_vcs() -> Box<dyn VcsProvider> {
if git::is_git_repo() {
Box::new(GitProvider::new())
} else if svn::is_svn_repo() {
Box::new(SvnProvider::new())
} else {
Box::new(NoneProvider::new())
}
}