mirror of
https://github.com/martinvonz/jj.git
synced 2025-02-03 10:24:28 +00:00
revset: create wrapper for current revset implementation
We don't want the public `Revset` interface to know about `ToPredicateFn`. In order to hide it, I'm wrapping the internal type in another type, so only the internal type can keep implementing `ToPredicateFn`.
This commit is contained in:
parent
6c9cefb8a0
commit
9e6c139fa0
1 changed files with 67 additions and 38 deletions
|
@ -540,7 +540,8 @@ impl RevsetExpression {
|
||||||
repo: &'index dyn Repo,
|
repo: &'index dyn Repo,
|
||||||
workspace_ctx: Option<&RevsetWorkspaceContext>,
|
workspace_ctx: Option<&RevsetWorkspaceContext>,
|
||||||
) -> Result<Box<dyn Revset<'index> + 'index>, RevsetError> {
|
) -> Result<Box<dyn Revset<'index> + 'index>, RevsetError> {
|
||||||
evaluate(repo, self, workspace_ctx)
|
let revset = evaluate(repo, self, workspace_ctx)?;
|
||||||
|
Ok(Box::new(revset))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1620,6 +1621,28 @@ impl<'index> Iterator for ReverseRevsetIterator<'index> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct RevsetImpl<'index> {
|
||||||
|
inner: Box<dyn Revset<'index> + 'index>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'index> RevsetImpl<'index> {
|
||||||
|
fn new(revset: Box<dyn Revset<'index> + 'index>) -> Self {
|
||||||
|
Self { inner: revset }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'index> ToPredicateFn<'index> for RevsetImpl<'index> {
|
||||||
|
fn to_predicate_fn(&self) -> Box<dyn FnMut(&IndexEntry<'index>) -> bool + '_> {
|
||||||
|
predicate_fn_from_iter(self.iter())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'index> Revset<'index> for RevsetImpl<'index> {
|
||||||
|
fn iter(&self) -> Box<dyn Iterator<Item = IndexEntry<'index>> + '_> {
|
||||||
|
self.inner.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct EagerRevset<'index> {
|
struct EagerRevset<'index> {
|
||||||
index_entries: Vec<IndexEntry<'index>>,
|
index_entries: Vec<IndexEntry<'index>>,
|
||||||
}
|
}
|
||||||
|
@ -1673,9 +1696,9 @@ where
|
||||||
|
|
||||||
struct ChildrenRevset<'index> {
|
struct ChildrenRevset<'index> {
|
||||||
// The revisions we want to find children for
|
// The revisions we want to find children for
|
||||||
root_set: Box<dyn Revset<'index> + 'index>,
|
root_set: RevsetImpl<'index>,
|
||||||
// Consider only candidates from this set
|
// Consider only candidates from this set
|
||||||
candidate_set: Box<dyn Revset<'index> + 'index>,
|
candidate_set: RevsetImpl<'index>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'index> Revset<'index> for ChildrenRevset<'index> {
|
impl<'index> Revset<'index> for ChildrenRevset<'index> {
|
||||||
|
@ -1703,7 +1726,7 @@ impl<'index> ToPredicateFn<'index> for ChildrenRevset<'index> {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FilterRevset<'index, P> {
|
struct FilterRevset<'index, P> {
|
||||||
candidates: Box<dyn Revset<'index> + 'index>,
|
candidates: RevsetImpl<'index>,
|
||||||
predicate: P,
|
predicate: P,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1730,8 +1753,8 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UnionRevset<'index> {
|
struct UnionRevset<'index> {
|
||||||
set1: Box<dyn Revset<'index> + 'index>,
|
set1: RevsetImpl<'index>,
|
||||||
set2: Box<dyn Revset<'index> + 'index>,
|
set2: RevsetImpl<'index>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'index> Revset<'index> for UnionRevset<'index> {
|
impl<'index> Revset<'index> for UnionRevset<'index> {
|
||||||
|
@ -1782,8 +1805,8 @@ impl<'index, I1: Iterator<Item = IndexEntry<'index>>, I2: Iterator<Item = IndexE
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IntersectionRevset<'index> {
|
struct IntersectionRevset<'index> {
|
||||||
set1: Box<dyn Revset<'index> + 'index>,
|
set1: RevsetImpl<'index>,
|
||||||
set2: Box<dyn Revset<'index> + 'index>,
|
set2: RevsetImpl<'index>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'index> Revset<'index> for IntersectionRevset<'index> {
|
impl<'index> Revset<'index> for IntersectionRevset<'index> {
|
||||||
|
@ -1845,9 +1868,9 @@ impl<'index, I1: Iterator<Item = IndexEntry<'index>>, I2: Iterator<Item = IndexE
|
||||||
|
|
||||||
struct DifferenceRevset<'index> {
|
struct DifferenceRevset<'index> {
|
||||||
// The minuend (what to subtract from)
|
// The minuend (what to subtract from)
|
||||||
set1: Box<dyn Revset<'index> + 'index>,
|
set1: RevsetImpl<'index>,
|
||||||
// The subtrahend (what to subtract)
|
// The subtrahend (what to subtract)
|
||||||
set2: Box<dyn Revset<'index> + 'index>,
|
set2: RevsetImpl<'index>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'index> Revset<'index> for DifferenceRevset<'index> {
|
impl<'index> Revset<'index> for DifferenceRevset<'index> {
|
||||||
|
@ -1920,9 +1943,9 @@ fn evaluate<'index>(
|
||||||
repo: &'index dyn Repo,
|
repo: &'index dyn Repo,
|
||||||
expression: &RevsetExpression,
|
expression: &RevsetExpression,
|
||||||
workspace_ctx: Option<&RevsetWorkspaceContext>,
|
workspace_ctx: Option<&RevsetWorkspaceContext>,
|
||||||
) -> Result<Box<dyn Revset<'index> + 'index>, RevsetError> {
|
) -> Result<RevsetImpl<'index>, RevsetError> {
|
||||||
match expression {
|
match expression {
|
||||||
RevsetExpression::None => Ok(Box::new(EagerRevset::empty())),
|
RevsetExpression::None => Ok(RevsetImpl::new(Box::new(EagerRevset::empty()))),
|
||||||
RevsetExpression::All => {
|
RevsetExpression::All => {
|
||||||
// Since `all()` does not include hidden commits, some of the logical
|
// Since `all()` does not include hidden commits, some of the logical
|
||||||
// transformation rules may subtly change the evaluated set. For example,
|
// transformation rules may subtly change the evaluated set. For example,
|
||||||
|
@ -1946,10 +1969,10 @@ fn evaluate<'index>(
|
||||||
let root_set = evaluate(repo, roots, workspace_ctx)?;
|
let root_set = evaluate(repo, roots, workspace_ctx)?;
|
||||||
let candidates_expression = roots.descendants();
|
let candidates_expression = roots.descendants();
|
||||||
let candidate_set = evaluate(repo, &candidates_expression, workspace_ctx)?;
|
let candidate_set = evaluate(repo, &candidates_expression, workspace_ctx)?;
|
||||||
Ok(Box::new(ChildrenRevset {
|
Ok(RevsetImpl::new(Box::new(ChildrenRevset {
|
||||||
root_set,
|
root_set,
|
||||||
candidate_set,
|
candidate_set,
|
||||||
}))
|
})))
|
||||||
}
|
}
|
||||||
RevsetExpression::Ancestors { heads, generation } => {
|
RevsetExpression::Ancestors { heads, generation } => {
|
||||||
let range_expression = RevsetExpression::Range {
|
let range_expression = RevsetExpression::Range {
|
||||||
|
@ -1970,10 +1993,10 @@ fn evaluate<'index>(
|
||||||
let head_ids = head_set.iter().commit_ids().collect_vec();
|
let head_ids = head_set.iter().commit_ids().collect_vec();
|
||||||
let walk = repo.index().walk_revs(&head_ids, &root_ids);
|
let walk = repo.index().walk_revs(&head_ids, &root_ids);
|
||||||
if generation == &GENERATION_RANGE_FULL {
|
if generation == &GENERATION_RANGE_FULL {
|
||||||
Ok(Box::new(RevWalkRevset { walk }))
|
Ok(RevsetImpl::new(Box::new(RevWalkRevset { walk })))
|
||||||
} else {
|
} else {
|
||||||
let walk = walk.filter_by_generation(generation.clone());
|
let walk = walk.filter_by_generation(generation.clone());
|
||||||
Ok(Box::new(RevWalkRevset { walk }))
|
Ok(RevsetImpl::new(Box::new(RevWalkRevset { walk })))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RevsetExpression::DagRange { roots, heads } => {
|
RevsetExpression::DagRange { roots, heads } => {
|
||||||
|
@ -1994,9 +2017,9 @@ fn evaluate<'index>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.reverse();
|
result.reverse();
|
||||||
Ok(Box::new(EagerRevset {
|
Ok(RevsetImpl::new(Box::new(EagerRevset {
|
||||||
index_entries: result,
|
index_entries: result,
|
||||||
}))
|
})))
|
||||||
}
|
}
|
||||||
RevsetExpression::VisibleHeads => Ok(revset_for_commit_ids(
|
RevsetExpression::VisibleHeads => Ok(revset_for_commit_ids(
|
||||||
repo,
|
repo,
|
||||||
|
@ -2024,7 +2047,7 @@ fn evaluate<'index>(
|
||||||
index_entries.push(candidate);
|
index_entries.push(candidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Box::new(EagerRevset { index_entries }))
|
Ok(RevsetImpl::new(Box::new(EagerRevset { index_entries })))
|
||||||
}
|
}
|
||||||
RevsetExpression::PublicHeads => Ok(revset_for_commit_ids(
|
RevsetExpression::PublicHeads => Ok(revset_for_commit_ids(
|
||||||
repo,
|
repo,
|
||||||
|
@ -2080,49 +2103,55 @@ fn evaluate<'index>(
|
||||||
}
|
}
|
||||||
Ok(revset_for_commit_ids(repo, &commit_ids))
|
Ok(revset_for_commit_ids(repo, &commit_ids))
|
||||||
}
|
}
|
||||||
RevsetExpression::Filter(predicate) => Ok(Box::new(FilterRevset {
|
RevsetExpression::Filter(predicate) => Ok(RevsetImpl::new(Box::new(FilterRevset {
|
||||||
candidates: evaluate(repo, &RevsetExpression::All, workspace_ctx)?,
|
candidates: evaluate(repo, &RevsetExpression::All, workspace_ctx)?,
|
||||||
predicate: build_predicate_fn(repo, predicate),
|
predicate: build_predicate_fn(repo, predicate),
|
||||||
})),
|
}))),
|
||||||
RevsetExpression::AsFilter(candidates) => evaluate(repo, candidates, workspace_ctx),
|
RevsetExpression::AsFilter(candidates) => evaluate(repo, candidates, workspace_ctx),
|
||||||
RevsetExpression::Present(candidates) => match evaluate(repo, candidates, workspace_ctx) {
|
RevsetExpression::Present(candidates) => match evaluate(repo, candidates, workspace_ctx) {
|
||||||
Ok(set) => Ok(set),
|
Ok(set) => Ok(set),
|
||||||
Err(RevsetError::NoSuchRevision(_)) => Ok(Box::new(EagerRevset::empty())),
|
Err(RevsetError::NoSuchRevision(_)) => {
|
||||||
|
Ok(RevsetImpl::new(Box::new(EagerRevset::empty())))
|
||||||
|
}
|
||||||
r @ Err(RevsetError::AmbiguousIdPrefix(_) | RevsetError::StoreError(_)) => r,
|
r @ Err(RevsetError::AmbiguousIdPrefix(_) | RevsetError::StoreError(_)) => r,
|
||||||
},
|
},
|
||||||
RevsetExpression::NotIn(complement) => {
|
RevsetExpression::NotIn(complement) => {
|
||||||
let set1 = evaluate(repo, &RevsetExpression::All, workspace_ctx)?;
|
let set1 = evaluate(repo, &RevsetExpression::All, workspace_ctx)?;
|
||||||
let set2 = evaluate(repo, complement, workspace_ctx)?;
|
let set2 = evaluate(repo, complement, workspace_ctx)?;
|
||||||
Ok(Box::new(DifferenceRevset { set1, set2 }))
|
Ok(RevsetImpl::new(Box::new(DifferenceRevset { set1, set2 })))
|
||||||
}
|
}
|
||||||
RevsetExpression::Union(expression1, expression2) => {
|
RevsetExpression::Union(expression1, expression2) => {
|
||||||
let set1 = evaluate(repo, expression1, workspace_ctx)?;
|
let set1 = evaluate(repo, expression1, workspace_ctx)?;
|
||||||
let set2 = evaluate(repo, expression2, workspace_ctx)?;
|
let set2 = evaluate(repo, expression2, workspace_ctx)?;
|
||||||
Ok(Box::new(UnionRevset { set1, set2 }))
|
Ok(RevsetImpl::new(Box::new(UnionRevset { set1, set2 })))
|
||||||
}
|
}
|
||||||
RevsetExpression::Intersection(expression1, expression2) => {
|
RevsetExpression::Intersection(expression1, expression2) => {
|
||||||
match expression2.as_ref() {
|
match expression2.as_ref() {
|
||||||
RevsetExpression::Filter(predicate) => Ok(Box::new(FilterRevset {
|
RevsetExpression::Filter(predicate) => {
|
||||||
candidates: evaluate(repo, expression1, workspace_ctx)?,
|
Ok(RevsetImpl::new(Box::new(FilterRevset {
|
||||||
predicate: build_predicate_fn(repo, predicate),
|
candidates: evaluate(repo, expression1, workspace_ctx)?,
|
||||||
})),
|
predicate: build_predicate_fn(repo, predicate),
|
||||||
RevsetExpression::AsFilter(expression2) => Ok(Box::new(FilterRevset {
|
})))
|
||||||
candidates: evaluate(repo, expression1, workspace_ctx)?,
|
}
|
||||||
predicate: evaluate(repo, expression2, workspace_ctx)?,
|
RevsetExpression::AsFilter(expression2) => {
|
||||||
})),
|
Ok(RevsetImpl::new(Box::new(FilterRevset {
|
||||||
|
candidates: evaluate(repo, expression1, workspace_ctx)?,
|
||||||
|
predicate: evaluate(repo, expression2, workspace_ctx)?,
|
||||||
|
})))
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// TODO: 'set2' can be turned into a predicate, and use FilterRevset
|
// TODO: 'set2' can be turned into a predicate, and use FilterRevset
|
||||||
// if a predicate function can terminate the 'set1' iterator early.
|
// if a predicate function can terminate the 'set1' iterator early.
|
||||||
let set1 = evaluate(repo, expression1, workspace_ctx)?;
|
let set1 = evaluate(repo, expression1, workspace_ctx)?;
|
||||||
let set2 = evaluate(repo, expression2, workspace_ctx)?;
|
let set2 = evaluate(repo, expression2, workspace_ctx)?;
|
||||||
Ok(Box::new(IntersectionRevset { set1, set2 }))
|
Ok(RevsetImpl::new(Box::new(IntersectionRevset { set1, set2 })))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RevsetExpression::Difference(expression1, expression2) => {
|
RevsetExpression::Difference(expression1, expression2) => {
|
||||||
let set1 = evaluate(repo, expression1, workspace_ctx)?;
|
let set1 = evaluate(repo, expression1, workspace_ctx)?;
|
||||||
let set2 = evaluate(repo, expression2, workspace_ctx)?;
|
let set2 = evaluate(repo, expression2, workspace_ctx)?;
|
||||||
Ok(Box::new(DifferenceRevset { set1, set2 }))
|
Ok(RevsetImpl::new(Box::new(DifferenceRevset { set1, set2 })))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2130,7 +2159,7 @@ fn evaluate<'index>(
|
||||||
fn revset_for_commit_ids<'index>(
|
fn revset_for_commit_ids<'index>(
|
||||||
repo: &'index dyn Repo,
|
repo: &'index dyn Repo,
|
||||||
commit_ids: &[CommitId],
|
commit_ids: &[CommitId],
|
||||||
) -> Box<dyn Revset<'index> + 'index> {
|
) -> RevsetImpl<'index> {
|
||||||
let index = repo.index();
|
let index = repo.index();
|
||||||
let mut index_entries = vec![];
|
let mut index_entries = vec![];
|
||||||
for id in commit_ids {
|
for id in commit_ids {
|
||||||
|
@ -2138,7 +2167,7 @@ fn revset_for_commit_ids<'index>(
|
||||||
}
|
}
|
||||||
index_entries.sort_by_key(|b| Reverse(b.position()));
|
index_entries.sort_by_key(|b| Reverse(b.position()));
|
||||||
index_entries.dedup();
|
index_entries.dedup();
|
||||||
Box::new(EagerRevset { index_entries })
|
RevsetImpl::new(Box::new(EagerRevset { index_entries }))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn revset_for_commits<'index>(
|
pub fn revset_for_commits<'index>(
|
||||||
|
@ -3795,9 +3824,9 @@ mod tests {
|
||||||
|
|
||||||
let get_entry = |id: &CommitId| index.entry_by_id(id).unwrap();
|
let get_entry = |id: &CommitId| index.entry_by_id(id).unwrap();
|
||||||
let make_entries = |ids: &[&CommitId]| ids.iter().map(|id| get_entry(id)).collect_vec();
|
let make_entries = |ids: &[&CommitId]| ids.iter().map(|id| get_entry(id)).collect_vec();
|
||||||
let make_set = |ids: &[&CommitId]| -> Box<dyn Revset<'_> + '_> {
|
let make_set = |ids: &[&CommitId]| -> RevsetImpl {
|
||||||
let index_entries = make_entries(ids);
|
let index_entries = make_entries(ids);
|
||||||
Box::new(EagerRevset { index_entries })
|
RevsetImpl::new(Box::new(EagerRevset { index_entries }))
|
||||||
};
|
};
|
||||||
|
|
||||||
let set = make_set(&[&id_4, &id_3, &id_2, &id_0]);
|
let set = make_set(&[&id_4, &id_3, &id_2, &id_0]);
|
||||||
|
|
Loading…
Reference in a new issue