Skip to content

Commit

Permalink
revset: Add optional argument n to ancestors() in revset language
Browse files Browse the repository at this point in the history
  • Loading branch information
sullyj3 committed Sep 7, 2023
1 parent 1810576 commit 6cda4cf
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### New features

* The `ancestors()` revset function now takes an optional `depth` argument
to specify how many ancestors to return. For example, use `jj log -r 'ancestors(@, 5)`
to view the last 5 commits.

### Fixed bugs

## [0.9.0] - 2023-09-06
Expand Down
3 changes: 2 additions & 1 deletion docs/revsets.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ revsets (expressions) as arguments.

* `parents(x)`: Same as `x-`.
* `children(x)`: Same as `x+`.
* `ancestors(x)`: Same as `:x`.
* `ancestors(x[, depth])`: Last `depth` ancestors of `x` (including `x`
itself). `ancestors(x)` is the same as `:x`, returning all ancestors.
* `descendants(x)`: Same as `x::`.
* `connected(x)`: Same as `x::x`. Useful when `x` includes several commits.
* `all()`: All visible commits in the repo.
Expand Down
12 changes: 9 additions & 3 deletions lib/src/revset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1168,9 +1168,15 @@ static BUILTIN_FUNCTION_MAP: Lazy<HashMap<&'static str, RevsetFunction>> = Lazy:
Ok(expression.children())
});
map.insert("ancestors", |name, arguments_pair, state| {
let arg = expect_one_argument(name, arguments_pair)?;
let expression = parse_expression_rule(arg.into_inner(), state)?;
Ok(expression.ancestors())
let ([descendents_arg], [depth_opt_arg]) = expect_arguments(name, arguments_pair)?;
let descendents = parse_expression_rule(descendents_arg.into_inner(), state)?;
let generation = if let Some(depth_arg) = depth_opt_arg {
let depth = parse_function_argument_as_literal("integer", name, depth_arg, state)?;
0..depth
} else {
GENERATION_RANGE_FULL
};
Ok(descendents.ancestors_range(generation))
});
map.insert("descendants", |name, arguments_pair, state| {
let arg = expect_one_argument(name, arguments_pair)?;
Expand Down
27 changes: 27 additions & 0 deletions lib/tests/test_revset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,33 @@ fn test_evaluate_expression_ancestors(use_git: bool) {
root_commit.id().clone(),
]
);

// Can find last n ancestors of a commit
assert_eq!(
resolve_commit_ids(
mut_repo,
&format!("ancestors({}, 0)", commit2.id().hex())
),
vec![]
);
assert_eq!(
resolve_commit_ids(
mut_repo,
&format!("ancestors({}, 1)", commit3.id().hex())
),
vec![commit3.id().clone()]
);
assert_eq!(
resolve_commit_ids(
mut_repo,
&format!("ancestors({}, 3)", commit3.id().hex())
),
vec![
commit3.id().clone(),
commit2.id().clone(),
commit1.id().clone(),
]
);
}

#[test_case(false ; "local backend")]
Expand Down

0 comments on commit 6cda4cf

Please sign in to comment.