mirror of
https://github.com/martinvonz/jj.git
synced 2024-12-24 12:48:55 +00:00
revset: add a connected()
function
This introduces a `connected(x)` function, which is simply the same as `x:x`. It's occasionally useful if `x` is a long expression. It's also useful as a building block for `root(x)` (coming soon).
This commit is contained in:
parent
fa6b14f166
commit
9ff21d8924
4 changed files with 110 additions and 2 deletions
|
@ -26,6 +26,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
`ui.editor` config. There is also a new `$JJ_EDITOR` environment variable,
|
||||
which has even higher priority than the config.
|
||||
|
||||
* The new revset function `connected(x)` is the same as `x:x`.
|
||||
|
||||
### Fixed bugs
|
||||
|
||||
* When rebasing a conflict where one side modified a file and the other side
|
||||
|
|
|
@ -85,6 +85,7 @@ revsets (expressions) as arguments.
|
|||
* `children(x)`: Same as `x+`.
|
||||
* `ancestors(x)`: Same as `:x`.
|
||||
* `descendants(x)`: Same as `x:`.
|
||||
* `connected(x)`: Same as `x:x`.
|
||||
* `all()`: All visible commits in the repo.
|
||||
* `none()`: No commits. This function is rarely useful; it is provided for
|
||||
completeness.
|
||||
|
|
|
@ -330,6 +330,12 @@ impl RevsetExpression {
|
|||
})
|
||||
}
|
||||
|
||||
/// Connects any ancestors and descendants in the set by adding the commits
|
||||
/// between them.
|
||||
pub fn connected(self: &Rc<RevsetExpression>) -> Rc<RevsetExpression> {
|
||||
self.dag_range_to(self)
|
||||
}
|
||||
|
||||
/// Commits reachable from `heads` but not from `self`.
|
||||
pub fn range(
|
||||
self: &Rc<RevsetExpression>,
|
||||
|
@ -600,6 +606,18 @@ fn parse_function_expression(
|
|||
})
|
||||
}
|
||||
}
|
||||
"connected" => {
|
||||
if arg_count == 1 {
|
||||
let candidates =
|
||||
parse_expression_rule(argument_pairs.next().unwrap().into_inner())?;
|
||||
Ok(candidates.connected())
|
||||
} else {
|
||||
Err(RevsetParseError::InvalidFunctionArguments {
|
||||
name,
|
||||
message: "Expected 1 argument".to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
"none" => {
|
||||
if arg_count == 0 {
|
||||
Ok(RevsetExpression::none())
|
||||
|
@ -1351,6 +1369,13 @@ mod tests {
|
|||
heads: checkout_symbol.clone(),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
foo_symbol.connected(),
|
||||
Rc::new(RevsetExpression::DagRange {
|
||||
roots: foo_symbol.clone(),
|
||||
heads: foo_symbol.clone(),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
foo_symbol.range(&checkout_symbol),
|
||||
Rc::new(RevsetExpression::Range {
|
||||
|
|
|
@ -765,7 +765,7 @@ fn test_evaluate_expression_dag_range(use_git: bool) {
|
|||
mut_repo.as_repo_ref(),
|
||||
&format!("{}:{}", root_commit_id.hex(), commit2.id().hex())
|
||||
),
|
||||
vec![commit2.id().clone(), commit1.id().clone(), root_commit_id,]
|
||||
vec![commit2.id().clone(), commit1.id().clone(), root_commit_id]
|
||||
);
|
||||
|
||||
// Empty range
|
||||
|
@ -792,7 +792,7 @@ fn test_evaluate_expression_dag_range(use_git: bool) {
|
|||
]
|
||||
);
|
||||
|
||||
// Including a merge, but only ancestors only from one side
|
||||
// Including a merge, but ancestors only from one side
|
||||
assert_eq!(
|
||||
resolve_commit_ids(
|
||||
mut_repo.as_repo_ref(),
|
||||
|
@ -806,6 +806,86 @@ fn test_evaluate_expression_dag_range(use_git: bool) {
|
|||
);
|
||||
}
|
||||
|
||||
#[test_case(false ; "local backend")]
|
||||
#[test_case(true ; "git backend")]
|
||||
fn test_evaluate_expression_connected(use_git: bool) {
|
||||
let settings = testutils::user_settings();
|
||||
let test_repo = testutils::init_repo(&settings, use_git);
|
||||
let repo = &test_repo.repo;
|
||||
|
||||
let root_commit_id = repo.store().root_commit_id().clone();
|
||||
let mut tx = repo.start_transaction("test");
|
||||
let mut_repo = tx.mut_repo();
|
||||
let mut graph_builder = CommitGraphBuilder::new(&settings, mut_repo);
|
||||
let commit1 = graph_builder.initial_commit();
|
||||
let commit2 = graph_builder.commit_with_parents(&[&commit1]);
|
||||
let commit3 = graph_builder.commit_with_parents(&[&commit2]);
|
||||
let commit4 = graph_builder.commit_with_parents(&[&commit1]);
|
||||
let commit5 = graph_builder.commit_with_parents(&[&commit3, &commit4]);
|
||||
|
||||
// Connecting an empty set yields an empty set
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo.as_repo_ref(), "connected(none())"),
|
||||
vec![]
|
||||
);
|
||||
|
||||
// Can connect just the root commit
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo.as_repo_ref(), "connected(root)"),
|
||||
vec![root_commit_id.clone()]
|
||||
);
|
||||
|
||||
// Can connect linearly
|
||||
assert_eq!(
|
||||
resolve_commit_ids(
|
||||
mut_repo.as_repo_ref(),
|
||||
&format!(
|
||||
"connected({} | {})",
|
||||
root_commit_id.hex(),
|
||||
commit2.id().hex()
|
||||
)
|
||||
),
|
||||
vec![commit2.id().clone(), commit1.id().clone(), root_commit_id]
|
||||
);
|
||||
|
||||
// Siblings don't get connected
|
||||
assert_eq!(
|
||||
resolve_commit_ids(
|
||||
mut_repo.as_repo_ref(),
|
||||
&format!("connected({} | {})", commit2.id().hex(), commit4.id().hex())
|
||||
),
|
||||
vec![commit4.id().clone(), commit2.id().clone()]
|
||||
);
|
||||
|
||||
// Including a merge
|
||||
assert_eq!(
|
||||
resolve_commit_ids(
|
||||
mut_repo.as_repo_ref(),
|
||||
&format!("connected({} | {})", commit1.id().hex(), commit5.id().hex())
|
||||
),
|
||||
vec![
|
||||
commit5.id().clone(),
|
||||
commit4.id().clone(),
|
||||
commit3.id().clone(),
|
||||
commit2.id().clone(),
|
||||
commit1.id().clone(),
|
||||
]
|
||||
);
|
||||
|
||||
// Including a merge, but ancestors only from one side
|
||||
assert_eq!(
|
||||
resolve_commit_ids(
|
||||
mut_repo.as_repo_ref(),
|
||||
&format!("connected({} | {})", commit2.id().hex(), commit5.id().hex())
|
||||
),
|
||||
vec![
|
||||
commit5.id().clone(),
|
||||
commit3.id().clone(),
|
||||
commit2.id().clone(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test_case(false ; "local backend")]
|
||||
#[test_case(true ; "git backend")]
|
||||
fn test_evaluate_expression_descendants(use_git: bool) {
|
||||
|
|
Loading…
Reference in a new issue