diff --git a/lib/src/revset.rs b/lib/src/revset.rs index 3ba1cb04c..67e70a218 100644 --- a/lib/src/revset.rs +++ b/lib/src/revset.rs @@ -202,6 +202,7 @@ pub enum RevsetExpression { RemoteBranches, Tags, GitRefs, + GitHead, ParentCount { candidates: Rc, parent_count_range: Range, @@ -260,6 +261,10 @@ impl RevsetExpression { Rc::new(RevsetExpression::GitRefs) } + pub fn git_head() -> Rc { + Rc::new(RevsetExpression::GitHead) + } + /// Commits in `self` that don't have descendants in `self`. // TODO: Perhaps this should be renamed to just `heads()` and the current // `heads()` should become `visible_heads()` or `current_heads()`. @@ -644,6 +649,16 @@ fn parse_function_expression( }) } } + "git_head" => { + if arg_count == 0 { + Ok(RevsetExpression::git_head()) + } else { + Err(RevsetParseError::InvalidFunctionArguments { + name, + message: "Expected 0 arguments".to_string(), + }) + } + } "merges" => { if arg_count > 1 { return Err(RevsetParseError::InvalidFunctionArguments { @@ -1156,6 +1171,10 @@ pub fn evaluate_expression<'repo>( } Ok(revset_for_commit_ids(repo, &commit_ids)) } + RevsetExpression::GitHead => { + let commit_ids = repo.view().git_head().into_iter().collect_vec(); + Ok(revset_for_commit_ids(repo, &commit_ids)) + } RevsetExpression::Description { needle, candidates } => { let candidates = candidates.evaluate(repo)?; let repo = repo; diff --git a/lib/tests/test_revset.rs b/lib/tests/test_revset.rs index 0d3ad381a..ba8a47811 100644 --- a/lib/tests/test_revset.rs +++ b/lib/tests/test_revset.rs @@ -980,6 +980,30 @@ fn test_evaluate_expression_git_refs(use_git: bool) { ); } +#[test_case(false ; "local backend")] +#[test_case(true ; "git backend")] +fn test_evaluate_expression_git_head(use_git: bool) { + let settings = testutils::user_settings(); + let test_workspace = testutils::init_repo(&settings, use_git); + let repo = &test_workspace.repo; + + let mut tx = repo.start_transaction("test"); + let mut_repo = tx.mut_repo(); + + let commit1 = testutils::create_random_commit(&settings, repo).write_to_repo(mut_repo); + + // Can get git head when it's not set + assert_eq!( + resolve_commit_ids(mut_repo.as_repo_ref(), "git_head()"), + vec![] + ); + mut_repo.set_git_head(commit1.id().clone()); + assert_eq!( + resolve_commit_ids(mut_repo.as_repo_ref(), "git_head()"), + vec![commit1.id().clone()] + ); +} + #[test_case(false ; "local backend")] #[test_case(true ; "git backend")] fn test_evaluate_expression_branches(use_git: bool) {