Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-vcs/src/lib.rs')
| -rw-r--r-- | helix-vcs/src/lib.rs | 69 |
1 files changed, 43 insertions, 26 deletions
diff --git a/helix-vcs/src/lib.rs b/helix-vcs/src/lib.rs index 4c5f2036..7225c38e 100644 --- a/helix-vcs/src/lib.rs +++ b/helix-vcs/src/lib.rs @@ -1,7 +1,3 @@ -//! `helix_vcs` provides types for working with diffs from a Version Control System (VCS). -//! Currently `git` is the only supported provider for diffs, but this architecture allows -//! for other providers to be added in the future. - use anyhow::{anyhow, bail, Result}; use arc_swap::ArcSwap; use std::{ @@ -10,6 +6,11 @@ use std::{ }; #[cfg(feature = "git")] +pub use git::Git; +#[cfg(not(feature = "git"))] +pub use Dummy as Git; + +#[cfg(feature = "git")] mod git; mod diff; @@ -20,16 +21,39 @@ mod status; pub use status::FileChange; -/// Contains all active diff providers. Diff providers are compiled in via features. Currently -/// only `git` is supported. +#[doc(hidden)] +#[derive(Clone, Copy)] +pub struct Dummy; +impl Dummy { + fn get_diff_base(&self, _file: &Path) -> Result<Vec<u8>> { + bail!("helix was compiled without git support") + } + + fn get_current_head_name(&self, _file: &Path) -> Result<Arc<ArcSwap<Box<str>>>> { + bail!("helix was compiled without git support") + } + + fn for_each_changed_file( + &self, + _cwd: &Path, + _f: impl Fn(Result<FileChange>) -> bool, + ) -> Result<()> { + bail!("helix was compiled without git support") + } +} + +impl From<Dummy> for DiffProvider { + fn from(value: Dummy) -> Self { + DiffProvider::Dummy(value) + } +} + #[derive(Clone)] pub struct DiffProviderRegistry { providers: Vec<DiffProvider>, } impl DiffProviderRegistry { - /// Get the given file from the VCS. This provides the unedited document as a "base" - /// for a diff to be created. pub fn get_diff_base(&self, file: &Path) -> Option<Vec<u8>> { self.providers .iter() @@ -43,7 +67,6 @@ impl DiffProviderRegistry { }) } - /// Get the current name of the current [HEAD](https://stackoverflow.com/questions/2304087/what-is-head-in-git). pub fn get_current_head_name(&self, file: &Path) -> Option<Arc<ArcSwap<Box<str>>>> { self.providers .iter() @@ -81,40 +104,34 @@ impl Default for DiffProviderRegistry { fn default() -> Self { // currently only git is supported // TODO make this configurable when more providers are added - let providers = vec![ - #[cfg(feature = "git")] - DiffProvider::Git, - DiffProvider::None, - ]; + let providers = vec![Git.into()]; DiffProviderRegistry { providers } } } /// A union type that includes all types that implement [DiffProvider]. We need this type to allow /// cloning [DiffProviderRegistry] as `Clone` cannot be used in trait objects. -/// -/// `Copy` is simply to ensure the `clone()` call is the simplest it can be. -#[derive(Copy, Clone)] -enum DiffProvider { +#[derive(Clone)] +pub enum DiffProvider { + Dummy(Dummy), #[cfg(feature = "git")] - Git, - None, + Git(Git), } impl DiffProvider { fn get_diff_base(&self, file: &Path) -> Result<Vec<u8>> { match self { + Self::Dummy(inner) => inner.get_diff_base(file), #[cfg(feature = "git")] - Self::Git => git::get_diff_base(file), - Self::None => bail!("No diff support compiled in"), + Self::Git(inner) => inner.get_diff_base(file), } } fn get_current_head_name(&self, file: &Path) -> Result<Arc<ArcSwap<Box<str>>>> { match self { + Self::Dummy(inner) => inner.get_current_head_name(file), #[cfg(feature = "git")] - Self::Git => git::get_current_head_name(file), - Self::None => bail!("No diff support compiled in"), + Self::Git(inner) => inner.get_current_head_name(file), } } @@ -124,9 +141,9 @@ impl DiffProvider { f: impl Fn(Result<FileChange>) -> bool, ) -> Result<()> { match self { + Self::Dummy(inner) => inner.for_each_changed_file(cwd, f), #[cfg(feature = "git")] - Self::Git => git::for_each_changed_file(cwd, f), - Self::None => bail!("No diff support compiled in"), + Self::Git(inner) => inner.for_each_changed_file(cwd, f), } } } |