ok/jj
1
0
Fork 0
forked from mirrors/jj

revset: extract function that builds predicate function from spec

This commit is contained in:
Yuya Nishihara 2022-11-17 16:13:59 +09:00
parent ce84d17060
commit ec6f2cf393

View file

@ -1718,69 +1718,10 @@ pub fn evaluate_expression<'repo>(
RevsetExpression::Filter { RevsetExpression::Filter {
candidates, candidates,
predicate, predicate,
} => { } => Ok(Box::new(FilterRevset {
let candidates = candidates.evaluate(repo, workspace_ctx)?; candidates: candidates.evaluate(repo, workspace_ctx)?,
match predicate { predicate: build_predicate_fn(repo, predicate),
RevsetFilterPredicate::ParentCount(parent_count_range) => { })),
let parent_count_range = parent_count_range.clone();
Ok(Box::new(FilterRevset {
candidates,
predicate: Box::new(move |entry| {
parent_count_range.contains(&entry.num_parents())
}),
}))
}
RevsetFilterPredicate::Description(needle) => {
let needle = needle.clone();
Ok(Box::new(FilterRevset {
candidates,
predicate: Box::new(move |entry| {
repo.store()
.get_commit(&entry.commit_id())
.unwrap()
.description()
.contains(needle.as_str())
}),
}))
}
RevsetFilterPredicate::Author(needle) => {
let needle = needle.clone();
// TODO: Make these functions that take a needle to search for accept some
// syntax for specifying whether it's a regex and whether it's
// case-sensitive.
Ok(Box::new(FilterRevset {
candidates,
predicate: Box::new(move |entry| {
let commit = repo.store().get_commit(&entry.commit_id()).unwrap();
commit.author().name.contains(needle.as_str())
|| commit.author().email.contains(needle.as_str())
}),
}))
}
RevsetFilterPredicate::Committer(needle) => {
let needle = needle.clone();
Ok(Box::new(FilterRevset {
candidates,
predicate: Box::new(move |entry| {
let commit = repo.store().get_commit(&entry.commit_id()).unwrap();
commit.committer().name.contains(needle.as_str())
|| commit.committer().email.contains(needle.as_str())
}),
}))
}
RevsetFilterPredicate::Empty => Ok(Box::new(FilterRevset {
candidates,
predicate: Box::new(move |entry| {
!has_diff_from_parent(repo, entry, &EverythingMatcher)
}),
})),
RevsetFilterPredicate::File(paths) => {
// TODO: Add support for globs and other formats
let matcher: Box<dyn Matcher> = Box::new(PrefixMatcher::new(paths));
Ok(filter_by_diff(repo, matcher, candidates))
}
}
}
RevsetExpression::Present(candidates) => match candidates.evaluate(repo, workspace_ctx) { RevsetExpression::Present(candidates) => match candidates.evaluate(repo, workspace_ctx) {
Ok(set) => Ok(set), Ok(set) => Ok(set),
Err(RevsetError::NoSuchRevision(_)) => Ok(Box::new(EagerRevset::empty())), Err(RevsetError::NoSuchRevision(_)) => Ok(Box::new(EagerRevset::empty())),
@ -1836,6 +1777,55 @@ pub fn revset_for_commits<'revset, 'repo: 'revset>(
Box::new(EagerRevset { index_entries }) Box::new(EagerRevset { index_entries })
} }
fn build_predicate_fn<'repo>(
repo: RepoRef<'repo>,
predicate: &RevsetFilterPredicate,
) -> Box<dyn Fn(&IndexEntry<'repo>) -> bool + 'repo> {
match predicate {
RevsetFilterPredicate::ParentCount(parent_count_range) => {
let parent_count_range = parent_count_range.clone();
Box::new(move |entry| parent_count_range.contains(&entry.num_parents()))
}
RevsetFilterPredicate::Description(needle) => {
let needle = needle.clone();
Box::new(move |entry| {
repo.store()
.get_commit(&entry.commit_id())
.unwrap()
.description()
.contains(needle.as_str())
})
}
RevsetFilterPredicate::Author(needle) => {
let needle = needle.clone();
// TODO: Make these functions that take a needle to search for accept some
// syntax for specifying whether it's a regex and whether it's
// case-sensitive.
Box::new(move |entry| {
let commit = repo.store().get_commit(&entry.commit_id()).unwrap();
commit.author().name.contains(needle.as_str())
|| commit.author().email.contains(needle.as_str())
})
}
RevsetFilterPredicate::Committer(needle) => {
let needle = needle.clone();
Box::new(move |entry| {
let commit = repo.store().get_commit(&entry.commit_id()).unwrap();
commit.committer().name.contains(needle.as_str())
|| commit.committer().email.contains(needle.as_str())
})
}
RevsetFilterPredicate::Empty => {
Box::new(move |entry| !has_diff_from_parent(repo, entry, &EverythingMatcher))
}
RevsetFilterPredicate::File(paths) => {
// TODO: Add support for globs and other formats
let matcher: Box<dyn Matcher> = Box::new(PrefixMatcher::new(paths));
Box::new(move |entry| has_diff_from_parent(repo, entry, matcher.as_ref()))
}
}
}
pub fn filter_by_diff<'revset, 'repo: 'revset>( pub fn filter_by_diff<'revset, 'repo: 'revset>(
repo: RepoRef<'repo>, repo: RepoRef<'repo>,
matcher: impl Borrow<dyn Matcher + 'repo> + 'repo, matcher: impl Borrow<dyn Matcher + 'repo> + 'repo,