revset: evaluate "..y" expression to "root()..y"

This seems useful since the root commit is often uninteresting. It's also
consistent with "x::y" in a way that the left operand defaults to "root()".
This commit is contained in:
Yuya Nishihara 2023-09-05 08:38:28 +09:00
parent f2c1697362
commit 6b2ad23f8f
4 changed files with 23 additions and 4 deletions

View File

@ -52,6 +52,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* The `root` revset symbol has been converted to function `root()`.
* The `..x` revset is now evaluated to `root()..x`, which means the root commit
is no longer included.
* `jj git push` will now push all branches in the range `remote_branches()..@`
instead of only branches pointing to `@` or `@-`.

View File

@ -62,8 +62,8 @@ only symbols.
released in jj 0.9.0. We plan to delete the latter in jj 0.15+.
* `x..y`: Ancestors of `y` that are not also ancestors of `x`. Equivalent to
`:y ~ :x`. This is what `git log` calls `x..y` (i.e. the same as we call it).
* `..x`: Ancestors of `x`, including the commits in `x` itself. Equivalent to
`:x` and provided for consistency.
* `..x`: Ancestors of `x`, including the commits in `x` itself, but excluding
the root commit. Equivalent to `:x ~ root()`.
* `x..`: Revisions that are not ancestors of `x`.
You can use parentheses to control evaluation order, such as `(x & y) | z` or

View File

@ -853,8 +853,9 @@ fn parse_expression_rule(
.map_primary(|primary| parse_primary_rule(primary, state))
.map_prefix(|op, rhs| match op.as_rule() {
Rule::negate_op => Ok(rhs?.negated()),
Rule::dag_range_pre_op | Rule::range_pre_op => Ok(rhs?.ancestors()),
Rule::dag_range_pre_op => Ok(rhs?.ancestors()),
Rule::legacy_dag_range_pre_op => Ok(rhs?.legacy_ancestors()),
Rule::range_pre_op => Ok(RevsetExpression::root().range(&rhs?)),
r => panic!("unexpected prefix operator rule {r:?}"),
})
.map_postfix(|lhs, op| match op.as_rule() {
@ -2767,7 +2768,10 @@ mod tests {
// Parse the "dag range" operator
assert_eq!(parse("foo::bar"), Ok(foo_symbol.dag_range_to(&bar_symbol)));
// Parse the "range" prefix operator
assert_eq!(parse("..foo"), Ok(foo_symbol.ancestors()));
assert_eq!(
parse("..foo"),
Ok(RevsetExpression::root().range(&foo_symbol))
);
assert_eq!(
parse("foo.."),
Ok(foo_symbol.range(&RevsetExpression::visible_heads()))

View File

@ -1238,6 +1238,18 @@ fn test_evaluate_expression_range(use_git: bool) {
),
vec![commit3.id().clone()]
);
// Left operand defaults to root()
assert_eq!(
resolve_commit_ids(mut_repo, &format!("..{}", commit2.id().hex())),
vec![commit2.id().clone(), commit1.id().clone()]
);
// Right operand defaults to visible_heads()
assert_eq!(
resolve_commit_ids(mut_repo, &format!("{}..", commit2.id().hex())),
vec![commit4.id().clone(), commit3.id().clone()]
);
}
#[test_case(false ; "local backend")]