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

revset: add present(set) predicate that suppresses NoSuchRevision error

This is copied from Mercurial. Typical use case I have in mind is
"present(master) | present(main)" in stock revset.
This commit is contained in:
Yuya Nishihara 2022-11-07 16:29:35 +09:00
parent ed14292aa2
commit fa3ad16bf2
3 changed files with 38 additions and 0 deletions

View file

@ -109,6 +109,8 @@ revsets (expressions) as arguments.
* `committer(needle)`: Commits with the given string in the committer's
name or email.
* `file(pattern..)`: Commits modifying the paths specified by the `pattern..`.
* `present(x)`: Same as `x`, but evaluated to `none()` if any of the commits
in `x` doesn't exist (e.g. is an unknown branch name.)
## Examples

View file

@ -311,6 +311,7 @@ pub enum RevsetExpression {
candidates: Rc<RevsetExpression>,
predicate: RevsetFilterPredicate,
},
Present(Rc<RevsetExpression>),
Union(Rc<RevsetExpression>, Rc<RevsetExpression>),
Intersection(Rc<RevsetExpression>, Rc<RevsetExpression>),
Difference(Rc<RevsetExpression>, Rc<RevsetExpression>),
@ -782,6 +783,11 @@ fn parse_function_expression(
))
}
}
"present" => {
let arg = expect_one_argument(name, arguments_pair)?;
let expression = parse_expression_rule(arg.into_inner(), workspace_ctx)?;
Ok(Rc::new(RevsetExpression::Present(expression)))
}
_ => Err(RevsetParseError::with_span(
RevsetParseErrorKind::NoSuchFunction(name.to_owned()),
name_pair.as_span(),
@ -934,6 +940,9 @@ fn transform_expression_bottom_up(
candidates,
predicate: predicate.clone(),
}),
RevsetExpression::Present(candidates) => {
transform_rec(candidates, f).map(RevsetExpression::Present)
}
RevsetExpression::Union(expression1, expression2) => {
transform_rec_pair((expression1, expression2), f).map(
|(expression1, expression2)| RevsetExpression::Union(expression1, expression2),
@ -1608,6 +1617,15 @@ pub fn evaluate_expression<'repo>(
}
}
}
RevsetExpression::Present(candidates) => match candidates.evaluate(repo, workspace_ctx) {
Ok(set) => Ok(set),
Err(RevsetError::NoSuchRevision(_)) => Ok(Box::new(EagerRevset::empty())),
r @ Err(
RevsetError::AmbiguousCommitIdPrefix(_)
| RevsetError::AmbiguousChangeIdPrefix(_)
| RevsetError::StoreError(_),
) => r,
},
RevsetExpression::Union(expression1, expression2) => {
let set1 = expression1.evaluate(repo, workspace_ctx)?;
let set2 = expression2.evaluate(repo, workspace_ctx)?;
@ -1995,6 +2013,11 @@ mod tests {
RevsetExpression::branches().roots()
);
assert_eq!(
optimize(parse("present(branches() & all())").unwrap()),
Rc::new(RevsetExpression::Present(RevsetExpression::branches()))
);
assert_eq!(
optimize(parse("(branches() & all()) | (all() & tags())").unwrap()),
RevsetExpression::branches().union(&RevsetExpression::tags())

View file

@ -125,6 +125,19 @@ fn test_resolve_symbol_commit_id() {
resolve_symbol(repo_ref, "foo", None),
Err(RevsetError::NoSuchRevision("foo".to_string()))
);
// Test present() suppresses only NoSuchRevision error
assert_eq!(resolve_commit_ids(repo_ref, "present(foo)"), []);
assert_eq!(
optimize(parse("present(04)", None).unwrap())
.evaluate(repo_ref, None)
.map(|_| ()),
Err(RevsetError::AmbiguousCommitIdPrefix("04".to_string()))
);
assert_eq!(
resolve_commit_ids(repo_ref, "present(046)"),
vec![commits[2].id().clone()]
);
}
#[test]