From 0757fe03b4b3618507c3449373d1781de685760b Mon Sep 17 00:00:00 2001 From: Austin Seipp Date: Mon, 18 Nov 2024 11:58:59 -0600 Subject: [PATCH] revset: allow `tags()` to take a pattern for an argument This makes it more consistent with `bookmarks()`, as noted by `@ldrndll` on Discord. Signed-off-by: Austin Seipp --- lib/src/revset.rs | 31 +++++++++++++++++++------------ lib/src/view.rs | 11 +++++++++++ 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/lib/src/revset.rs b/lib/src/revset.rs index 22a235e3a6..9804a3f6be 100644 --- a/lib/src/revset.rs +++ b/lib/src/revset.rs @@ -137,7 +137,7 @@ pub enum RevsetCommitRef { remote_pattern: StringPattern, remote_ref_state: Option, }, - Tags, + Tags(StringPattern), GitRefs, GitHead, } @@ -348,8 +348,8 @@ impl> RevsetExpression { })) } - pub fn tags() -> Rc { - Rc::new(Self::CommitRef(RevsetCommitRef::Tags)) + pub fn tags(pattern: StringPattern) -> Rc { + Rc::new(Self::CommitRef(RevsetCommitRef::Tags(pattern))) } pub fn git_refs() -> Rc { @@ -785,9 +785,14 @@ static BUILTIN_FUNCTION_MAP: Lazy> = Lazy: map["untracked_remote_bookmarks"], ); - map.insert("tags", |_diagnostics, function, _context| { - function.expect_no_arguments()?; - Ok(RevsetExpression::tags()) + map.insert("tags", |diagnostics, function, _context| { + let ([], [opt_arg]) = function.expect_arguments()?; + let pattern = if let Some(arg) = opt_arg { + expect_string_pattern(diagnostics, arg)? + } else { + StringPattern::everything() + }; + Ok(RevsetExpression::tags(pattern)) }); map.insert("git_refs", |_diagnostics, function, _context| { function.expect_no_arguments()?; @@ -2172,11 +2177,13 @@ fn resolve_commit_ref( .collect(); Ok(commit_ids) } - RevsetCommitRef::Tags => { - let mut commit_ids = vec![]; - for ref_target in repo.view().tags().values() { - commit_ids.extend(ref_target.added_ids().cloned()); - } + RevsetCommitRef::Tags(pattern) => { + let commit_ids = repo + .view() + .local_tags_matching(pattern) + .flat_map(|(_, target)| target.added_ids()) + .cloned() + .collect(); Ok(commit_ids) } RevsetCommitRef::GitRefs => { @@ -3565,7 +3572,7 @@ mod tests { )); assert_matches!( unwrap_union(&optimized).1.as_ref(), - RevsetExpression::CommitRef(RevsetCommitRef::Tags) + RevsetExpression::CommitRef(RevsetCommitRef::Tags(_)) ); } diff --git a/lib/src/view.rs b/lib/src/view.rs index 64b677bcdb..307fb5371b 100644 --- a/lib/src/view.rs +++ b/lib/src/view.rs @@ -309,6 +309,17 @@ impl View { self.data.tags.get(name).flatten() } + /// Iterates local tag `(name, target)`s matching the given pattern. Entries + /// are sorted by `name`. + pub fn local_tags_matching<'a: 'b, 'b>( + &'a self, + pattern: &'b StringPattern, + ) -> impl Iterator + 'b { + pattern + .filter_btree_map(&self.data.tags) + .map(|(name, target)| (name.as_ref(), target)) + } + /// Sets tag to point to the given target. If the target is absent, the tag /// will be removed. pub fn set_tag_target(&mut self, name: &str, target: RefTarget) {