From acd0a0a161d2a29adbd685ae91d81af44c698ad9 Mon Sep 17 00:00:00 2001 From: Noah Mayr Date: Wed, 1 May 2024 21:49:26 +0200 Subject: [PATCH] lib: add support for filtering by topics to revsets --- lib/src/revset.rs | 48 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/lib/src/revset.rs b/lib/src/revset.rs index 027e2014ac..4732fe9388 100644 --- a/lib/src/revset.rs +++ b/lib/src/revset.rs @@ -318,6 +318,7 @@ pub enum RevsetCommitRef { remote_pattern: StringPattern, }, Tags, + Topics(StringPattern), GitRefs, GitHead, } @@ -452,6 +453,12 @@ impl RevsetExpression { Rc::new(RevsetExpression::CommitRef(RevsetCommitRef::Tags)) } + pub fn topics(pattern: StringPattern) -> Rc { + Rc::new(RevsetExpression::CommitRef(RevsetCommitRef::Topics( + pattern, + ))) + } + pub fn git_refs() -> Rc { Rc::new(RevsetExpression::CommitRef(RevsetCommitRef::GitRefs)) } @@ -1271,6 +1278,15 @@ static BUILTIN_FUNCTION_MAP: Lazy> = Lazy: expect_no_arguments(name, arguments_pair)?; Ok(RevsetExpression::tags()) }); + map.insert("topics", |name, arguments_pair, state| { + let ([], [opt_arg]) = expect_arguments(name, arguments_pair)?; + let pattern = if let Some(arg) = opt_arg { + parse_function_argument_to_string_pattern(name, arg, state)? + } else { + StringPattern::everything() + }; + Ok(RevsetExpression::topics(pattern)) + }); map.insert("git_refs", |name, arguments_pair, _state| { expect_no_arguments(name, arguments_pair)?; Ok(RevsetExpression::git_refs()) @@ -2111,6 +2127,21 @@ impl PartialSymbolResolver for TagResolver { } } +struct TopicResolver; + +impl PartialSymbolResolver for TopicResolver { + fn resolve_symbol( + &self, + repo: &dyn Repo, + symbol: &str, + ) -> Result>, RevsetResolutionError> { + Ok(repo + .view() + .get_topic_commits(symbol) + .map(|set| set.iter().cloned().collect_vec())) + } +} + struct BranchResolver; impl PartialSymbolResolver for BranchResolver { @@ -2146,8 +2177,12 @@ impl PartialSymbolResolver for GitRefResolver { } } -const DEFAULT_RESOLVERS: &[&'static dyn PartialSymbolResolver] = - &[&TagResolver, &BranchResolver, &GitRefResolver]; +const DEFAULT_RESOLVERS: &[&'static dyn PartialSymbolResolver] = &[ + &TagResolver, + &BranchResolver, + &TopicResolver, + &GitRefResolver, +]; #[derive(Default)] struct CommitPrefixResolver<'a> { @@ -2331,6 +2366,15 @@ fn resolve_commit_ref( } Ok(commit_ids) } + RevsetCommitRef::Topics(pattern) => { + let commit_ids = repo + .view() + .topics_matching(pattern) + .flat_map(|(_, ids)| ids) + .cloned() + .collect(); + Ok(commit_ids) + } RevsetCommitRef::GitRefs => { let mut commit_ids = vec![]; for ref_target in repo.view().git_refs().values() {