revset: fully consume Present(_) node by resolve_symbols()

Since resolve_symbols() now removes Present(_) node, it make sense to
handle symbol resolution error there. That's why I added a "pre" callback
to try_transform_expression().

Perhaps, "operation" scope (#1283) can be implemented in a similar way,
(but somehow need to resolve operation id and call repo.reload_at(op).)
This commit is contained in:
Yuya Nishihara 2023-04-02 13:41:55 +09:00
parent aeb93c7591
commit f1e2d19d57
2 changed files with 19 additions and 14 deletions

View file

@ -536,7 +536,8 @@ impl<'index, 'heads> EvaluationContext<'index, 'heads> {
| RevsetExpression::RemoteBranches { .. }
| RevsetExpression::Tags
| RevsetExpression::GitRefs
| RevsetExpression::GitHead => {
| RevsetExpression::GitHead
| RevsetExpression::Present(_) => {
panic!("Expression '{expression:?}' should have been resolved by caller");
}
RevsetExpression::None => Ok(Box::new(EagerRevset::empty())),
@ -644,7 +645,6 @@ impl<'index, 'heads> EvaluationContext<'index, 'heads> {
predicate: build_predicate_fn(self.store.clone(), self.index, predicate),
})),
RevsetExpression::AsFilter(candidates) => self.evaluate(candidates),
RevsetExpression::Present(candidates) => self.evaluate(candidates),
RevsetExpression::NotIn(complement) => {
let set1 = self.evaluate(&RevsetExpression::All)?;
let set2 = self.evaluate(complement)?;

View file

@ -1186,17 +1186,9 @@ fn try_transform_expression(
RevsetExpression::AsFilter(candidates) => {
transform_rec(candidates, pre, post)?.map(RevsetExpression::AsFilter)
}
RevsetExpression::Present(candidates) => match transform_rec(candidates, pre, post) {
Ok(None) => None,
Ok(Some(expression)) => Some(RevsetExpression::Present(expression)),
Err(RevsetResolutionError::NoSuchRevision(_)) => Some(RevsetExpression::None),
r @ Err(
RevsetResolutionError::AmbiguousIdPrefix(_)
| RevsetResolutionError::StoreError(_),
) => {
return r;
}
},
RevsetExpression::Present(candidates) => {
transform_rec(candidates, pre, post)?.map(RevsetExpression::Present)
}
RevsetExpression::NotIn(complement) => {
transform_rec(complement, pre, post)?.map(RevsetExpression::NotIn)
}
@ -1624,7 +1616,20 @@ pub fn resolve_symbols(
) -> Result<Rc<RevsetExpression>, RevsetResolutionError> {
Ok(try_transform_expression(
&expression,
|_| Ok(None),
|expression| match expression.as_ref() {
// 'present(x)' opens new symbol resolution scope to map error to 'none()'.
RevsetExpression::Present(candidates) => {
resolve_symbols(repo, candidates.clone(), workspace_ctx)
.or_else(|err| match err {
RevsetResolutionError::NoSuchRevision(_) => Ok(RevsetExpression::none()),
RevsetResolutionError::AmbiguousIdPrefix(_)
| RevsetResolutionError::StoreError(_) => Err(err),
})
.map(Some) // Always rewrite subtree
}
// Otherwise resolve symbols recursively.
_ => Ok(None),
},
|expression| {
Ok(match expression.as_ref() {
RevsetExpression::Symbol(symbol) => {