mirror of
https://github.com/martinvonz/jj.git
synced 2024-12-26 14:00:51 +00:00
revsets: add a all_heads() revset function
This adds a `all_heads()` revset function, which contains all heads in the view, i.e. including non-public heads and obsolete heads.
This commit is contained in:
parent
88904e2b63
commit
30aa459d2a
3 changed files with 45 additions and 1 deletions
|
@ -18,7 +18,7 @@ literal_string = { "\"" ~ (!"\"" ~ ANY)+ ~ "\"" }
|
|||
parents = { ":" }
|
||||
ancestors = { "*:" }
|
||||
|
||||
function_name = @{ ASCII_ALPHANUMERIC+ }
|
||||
function_name = @{ (ASCII_ALPHANUMERIC | "_")+ }
|
||||
// The grammar accepts a string literal or an expression for function
|
||||
// arguments. We then decide when walking the parse tree if we
|
||||
// should interpret the string value of the literal string or the expression
|
||||
|
|
|
@ -99,6 +99,7 @@ pub enum RevsetExpression {
|
|||
Symbol(String),
|
||||
Parents(Box<RevsetExpression>),
|
||||
Ancestors(Box<RevsetExpression>),
|
||||
AllHeads,
|
||||
}
|
||||
|
||||
fn parse_expression_rule(mut pairs: Pairs<Rule>) -> Result<RevsetExpression, RevsetParseError> {
|
||||
|
@ -164,6 +165,16 @@ fn parse_function_expression(
|
|||
})
|
||||
}
|
||||
}
|
||||
"all_heads" => {
|
||||
if arg_count == 0 {
|
||||
Ok(RevsetExpression::AllHeads)
|
||||
} else {
|
||||
Err(RevsetParseError::InvalidFunctionArguments {
|
||||
name,
|
||||
message: "Expected 0 arguments".to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => Err(RevsetParseError::NoSuchFunction(name)),
|
||||
}
|
||||
}
|
||||
|
@ -269,5 +280,15 @@ pub fn evaluate_expression<'repo>(
|
|||
let walk = repo.index().walk_revs(&base_ids, &[]);
|
||||
Ok(Box::new(RevWalkRevset { walk }))
|
||||
}
|
||||
RevsetExpression::AllHeads => {
|
||||
let index = repo.index();
|
||||
let heads = repo.view().heads();
|
||||
let mut index_entries: Vec<_> = heads
|
||||
.iter()
|
||||
.map(|id| index.entry_by_id(id).unwrap())
|
||||
.collect();
|
||||
index_entries.sort_by_key(|b| Reverse(b.position()));
|
||||
Ok(Box::new(EagerRevset { index_entries }))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -399,3 +399,26 @@ fn test_evaluate_expression_ancestors(use_git: bool) {
|
|||
|
||||
tx.discard();
|
||||
}
|
||||
|
||||
#[test_case(false ; "local store")]
|
||||
#[test_case(true ; "git store")]
|
||||
fn test_evaluate_expression_all_heads(use_git: bool) {
|
||||
let settings = testutils::user_settings();
|
||||
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
||||
|
||||
let mut tx = repo.start_transaction("test");
|
||||
let mut_repo = tx.mut_repo();
|
||||
|
||||
let wc_commit = repo.working_copy_locked().current_commit();
|
||||
let commit1 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo);
|
||||
let commit2 = testutils::create_random_commit(&settings, &repo)
|
||||
.set_parents(vec![commit1.id().clone()])
|
||||
.write_to_repo(mut_repo);
|
||||
|
||||
assert_eq!(
|
||||
resolve_commit_ids(mut_repo.as_repo_ref(), "all_heads()"),
|
||||
vec![commit2.id().clone(), wc_commit.id().clone()]
|
||||
);
|
||||
|
||||
tx.discard();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue