From 6b2ad23f8f5554480a8b2467c57c2c65ed70353e Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Tue, 5 Sep 2023 08:38:28 +0900 Subject: [PATCH] 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()". --- CHANGELOG.md | 3 +++ docs/revsets.md | 4 ++-- lib/src/revset.rs | 8 ++++++-- lib/tests/test_revset.rs | 12 ++++++++++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57c68df33..1b9763634 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 `@-`. diff --git a/docs/revsets.md b/docs/revsets.md index 5b66709f9..224c996bd 100644 --- a/docs/revsets.md +++ b/docs/revsets.md @@ -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 diff --git a/lib/src/revset.rs b/lib/src/revset.rs index d151dacda..f48973be2 100644 --- a/lib/src/revset.rs +++ b/lib/src/revset.rs @@ -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())) diff --git a/lib/tests/test_revset.rs b/lib/tests/test_revset.rs index ba40ee2ff..6b647480f 100644 --- a/lib/tests/test_revset.rs +++ b/lib/tests/test_revset.rs @@ -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")]