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:
parent
ed14292aa2
commit
fa3ad16bf2
3 changed files with 38 additions and 0 deletions
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Reference in a new issue