Skip to content

Commit f9d14d8

Browse files
committed
feat: Add PathspecDetached as pathspec that can more easily be used across threads.
1 parent e22893c commit f9d14d8

File tree

3 files changed

+65
-3
lines changed

3 files changed

+65
-3
lines changed

gix/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ pub use types::{
161161
Commit, Head, Id, Object, ObjectDetached, Reference, Remote, Repository, Tag, ThreadSafeRepository, Tree, Worktree,
162162
};
163163
#[cfg(feature = "attributes")]
164-
pub use types::{Pathspec, Submodule};
164+
pub use types::{Pathspec, PathspecDetached, Submodule};
165165

166166
///
167167
pub mod clone;

gix/src/pathspec.rs

+52-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use gix_macros::momo;
33
use gix_odb::FindExt;
44
pub use gix_pathspec::*;
55

6-
use crate::{bstr::BStr, AttributeStack, Pathspec, Repository};
6+
use crate::{bstr::BStr, AttributeStack, Pathspec, PathspecDetached, Repository};
77

88
///
99
pub mod init {
@@ -75,6 +75,15 @@ impl<'repo> Pathspec<'repo> {
7575
self.stack.map(|stack| AttributeStack::new(stack, self.repo)),
7676
)
7777
}
78+
79+
/// Turn ourselves into an implementation that works without a repository instance and that is rather minimal.
80+
pub fn detach(self) -> std::io::Result<PathspecDetached> {
81+
Ok(PathspecDetached {
82+
search: self.search,
83+
stack: self.stack,
84+
odb: self.repo.objects.clone().into_arc()?,
85+
})
86+
}
7887
}
7988

8089
/// Access
@@ -145,8 +154,49 @@ impl<'repo> Pathspec<'repo> {
145154
}
146155
}
147156

157+
/// Access
158+
impl PathspecDetached {
159+
/// Return the first [`Match`](search::Match) of `relative_path`, or `None`.
160+
/// Note that the match might [be excluded](search::Match::is_excluded()).
161+
/// `is_dir` is true if `relative_path` is a directory.
162+
#[doc(
163+
alias = "match_diff",
164+
alias = "match_tree",
165+
alias = "match_index",
166+
alias = "match_workdir",
167+
alias = "matches_path",
168+
alias = "git2"
169+
)]
170+
#[momo]
171+
pub fn pattern_matching_relative_path<'a>(
172+
&mut self,
173+
relative_path: impl Into<&'a BStr>,
174+
is_dir: Option<bool>,
175+
) -> Option<gix_pathspec::search::Match<'_>> {
176+
self.search.pattern_matching_relative_path(
177+
relative_path.into(),
178+
is_dir,
179+
&mut |relative_path, case, is_dir, out| {
180+
let stack = self.stack.as_mut().expect("initialized in advance");
181+
stack
182+
.set_case(case)
183+
.at_entry(relative_path, Some(is_dir), |id, buf| self.odb.find_blob(id, buf))
184+
.map_or(false, |platform| platform.matching_attributes(out))
185+
},
186+
)
187+
}
188+
189+
/// The simplified version of [`pattern_matching_relative_path()`](Self::pattern_matching_relative_path()) which returns
190+
/// `true` if `relative_path` is included in the set of positive pathspecs, while not being excluded.
191+
#[momo]
192+
pub fn is_included<'a>(&mut self, relative_path: impl Into<&'a BStr>, is_dir: Option<bool>) -> bool {
193+
self.pattern_matching_relative_path(relative_path, is_dir)
194+
.map_or(false, |m| !m.is_excluded())
195+
}
196+
}
197+
148198
#[cfg(feature = "status")]
149-
impl gix_status::Pathspec for Pathspec<'_> {
199+
impl gix_status::Pathspec for PathspecDetached {
150200
fn common_prefix(&self) -> &BStr {
151201
self.search.common_prefix()
152202
}

gix/src/types.rs

+12
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,18 @@ pub struct Pathspec<'repo> {
218218
pub(crate) search: gix_pathspec::Search,
219219
}
220220

221+
/// Like [`Pathspec`], but without a Repository reference and with minimal API.
222+
#[derive(Clone)]
223+
#[cfg(feature = "attributes")]
224+
pub struct PathspecDetached {
225+
/// The cache to power attribute access. It's only initialized if we have a pattern with attributes.
226+
pub stack: Option<gix_worktree::Stack>,
227+
/// The prepared search to use for checking matches.
228+
pub search: gix_pathspec::Search,
229+
/// A thread-safe version of an ODB.
230+
pub odb: gix_odb::HandleArc,
231+
}
232+
221233
/// A stand-in for the submodule of a particular name.
222234
#[derive(Clone)]
223235
#[cfg(feature = "attributes")]

0 commit comments

Comments
 (0)