Skip to content

Commit

Permalink
feat: Add PathspecDetached as pathspec that can more easily be used…
Browse files Browse the repository at this point in the history
… across threads.
  • Loading branch information
Byron committed Sep 23, 2023
1 parent e22893c commit f9d14d8
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 3 deletions.
2 changes: 1 addition & 1 deletion gix/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ pub use types::{
Commit, Head, Id, Object, ObjectDetached, Reference, Remote, Repository, Tag, ThreadSafeRepository, Tree, Worktree,
};
#[cfg(feature = "attributes")]
pub use types::{Pathspec, Submodule};
pub use types::{Pathspec, PathspecDetached, Submodule};

///
pub mod clone;
Expand Down
54 changes: 52 additions & 2 deletions gix/src/pathspec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use gix_macros::momo;
use gix_odb::FindExt;
pub use gix_pathspec::*;

use crate::{bstr::BStr, AttributeStack, Pathspec, Repository};
use crate::{bstr::BStr, AttributeStack, Pathspec, PathspecDetached, Repository};

///
pub mod init {
Expand Down Expand Up @@ -75,6 +75,15 @@ impl<'repo> Pathspec<'repo> {
self.stack.map(|stack| AttributeStack::new(stack, self.repo)),
)
}

/// Turn ourselves into an implementation that works without a repository instance and that is rather minimal.
pub fn detach(self) -> std::io::Result<PathspecDetached> {
Ok(PathspecDetached {
search: self.search,
stack: self.stack,
odb: self.repo.objects.clone().into_arc()?,
})
}
}

/// Access
Expand Down Expand Up @@ -145,8 +154,49 @@ impl<'repo> Pathspec<'repo> {
}
}

/// Access
impl PathspecDetached {
/// Return the first [`Match`](search::Match) of `relative_path`, or `None`.
/// Note that the match might [be excluded](search::Match::is_excluded()).
/// `is_dir` is true if `relative_path` is a directory.
#[doc(
alias = "match_diff",
alias = "match_tree",
alias = "match_index",
alias = "match_workdir",
alias = "matches_path",
alias = "git2"
)]
#[momo]
pub fn pattern_matching_relative_path<'a>(
&mut self,
relative_path: impl Into<&'a BStr>,
is_dir: Option<bool>,
) -> Option<gix_pathspec::search::Match<'_>> {
self.search.pattern_matching_relative_path(
relative_path.into(),
is_dir,
&mut |relative_path, case, is_dir, out| {
let stack = self.stack.as_mut().expect("initialized in advance");
stack
.set_case(case)
.at_entry(relative_path, Some(is_dir), |id, buf| self.odb.find_blob(id, buf))
.map_or(false, |platform| platform.matching_attributes(out))
},
)
}

/// The simplified version of [`pattern_matching_relative_path()`](Self::pattern_matching_relative_path()) which returns
/// `true` if `relative_path` is included in the set of positive pathspecs, while not being excluded.
#[momo]
pub fn is_included<'a>(&mut self, relative_path: impl Into<&'a BStr>, is_dir: Option<bool>) -> bool {
self.pattern_matching_relative_path(relative_path, is_dir)
.map_or(false, |m| !m.is_excluded())
}
}

#[cfg(feature = "status")]
impl gix_status::Pathspec for Pathspec<'_> {
impl gix_status::Pathspec for PathspecDetached {
fn common_prefix(&self) -> &BStr {
self.search.common_prefix()
}
Expand Down
12 changes: 12 additions & 0 deletions gix/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,18 @@ pub struct Pathspec<'repo> {
pub(crate) search: gix_pathspec::Search,
}

/// Like [`Pathspec`], but without a Repository reference and with minimal API.
#[derive(Clone)]
#[cfg(feature = "attributes")]
pub struct PathspecDetached {
/// The cache to power attribute access. It's only initialized if we have a pattern with attributes.
pub stack: Option<gix_worktree::Stack>,
/// The prepared search to use for checking matches.
pub search: gix_pathspec::Search,
/// A thread-safe version of an ODB.
pub odb: gix_odb::HandleArc,
}

/// A stand-in for the submodule of a particular name.
#[derive(Clone)]
#[cfg(feature = "attributes")]
Expand Down

0 comments on commit f9d14d8

Please sign in to comment.