From b6794ca04aea588d9ab560b7b8131144bad433a3 Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Sat, 19 Aug 2023 09:59:40 +0900 Subject: [PATCH] revset: rename literal:"" prefix to exact:"" Per discussion in #2107, I believe "exact" is preferred. We can also change the default to exact match, but it doesn't always make sense. Exact match would be useful for branches(), but not for description(). We could define default per predicate function, but I'm pretty sure I cannot remember which one is which. --- CHANGELOG.md | 6 +++--- docs/revsets.md | 2 +- lib/src/revset.rs | 36 ++++++++++++++++++------------------ lib/tests/test_revset.rs | 23 +++++++---------------- 4 files changed, 29 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0d81ffec..cb2b6d3a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,11 +82,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 description was empty on the input commit. * `branches()`/`remote_branches()`/`author()`/`committer()`/`description()` - revsets now support literal matching. For example, `branch(literal:main)` - selects the branch named "main", but not "maint". `description(literal:"")` + revsets now support exact matching. For example, `branch(exact:main)` + selects the branch named "main", but not "maint". `description(exact:"")` selects commits whose description is empty. -* Revsets gained a new function `mine()` that aliases `author([literal:"your_email"])`. +* Revsets gained a new function `mine()` that aliases `author(exact:"your_email")`. ### Fixed bugs diff --git a/docs/revsets.md b/docs/revsets.md index cbba30ed3..353a05ae5 100644 --- a/docs/revsets.md +++ b/docs/revsets.md @@ -142,7 +142,7 @@ revsets (expressions) as arguments. Functions that perform string matching support the following pattern syntax. * `"string"`, `substring:"string"`: Matches strings that contain `string`. -* `literal:"string"`: Matches strings exactly equal to `string`. +* `exact:"string"`: Matches strings exactly equal to `string`. ## Aliases diff --git a/lib/src/revset.rs b/lib/src/revset.rs index efc3e95a3..c48ed68d6 100644 --- a/lib/src/revset.rs +++ b/lib/src/revset.rs @@ -212,7 +212,7 @@ pub const GENERATION_RANGE_EMPTY: Range = 0..0; #[derive(Clone, Debug, Eq, PartialEq)] pub enum StringPattern { /// Matches strings exactly equal to `string`. - Literal(String), + Exact(String), /// Matches strings that contain `substring`. Substring(String), } @@ -226,17 +226,17 @@ impl StringPattern { /// Returns true if this pattern matches the `haystack`. pub fn matches(&self, haystack: &str) -> bool { match self { - StringPattern::Literal(literal) => haystack == literal, + StringPattern::Exact(literal) => haystack == literal, StringPattern::Substring(needle) => haystack.contains(needle), } } - /// Returns a literal string if this pattern is of that kind. + /// Returns a literal pattern if this should match input strings exactly. /// /// This can be used to optimize map lookup by exact key. - pub fn as_literal(&self) -> Option<&str> { + pub fn as_exact(&self) -> Option<&str> { match self { - StringPattern::Literal(literal) => Some(literal), + StringPattern::Exact(literal) => Some(literal), StringPattern::Substring(_) => None, } } @@ -1093,7 +1093,7 @@ static BUILTIN_FUNCTION_MAP: Lazy> = Lazy: map.insert("mine", |name, arguments_pair, state| { expect_no_arguments(name, arguments_pair)?; Ok(RevsetExpression::filter(RevsetFilterPredicate::Author( - StringPattern::Literal(state.user_email.to_owned()), + StringPattern::Exact(state.user_email.to_owned()), ))) }); map.insert("committer", |name, arguments_pair, state| { @@ -1323,7 +1323,7 @@ fn parse_function_argument_to_string_pattern( return Err(make_type_error()); }; match kind.as_ref() { - "literal" => StringPattern::Literal(needle.clone()), + "exact" => StringPattern::Exact(needle.clone()), "substring" => StringPattern::Substring(needle.clone()), _ => { // TODO: error span can be narrowed to the lhs node @@ -1796,7 +1796,7 @@ fn filter_map_values_by_key_pattern<'a: 'b, 'b, V>( map: &'a BTreeMap, pattern: &'b StringPattern, ) -> impl Iterator + 'b { - if let Some(key) = pattern.as_literal() { + if let Some(key) = pattern.as_exact() { Either::Left(map.get(key).into_iter()) } else { Either::Right( @@ -2694,8 +2694,8 @@ mod tests { ))) ); assert_eq!( - parse(r#"branches(literal:"foo")"#), - Ok(RevsetExpression::branches(StringPattern::Literal( + parse(r#"branches(exact:"foo")"#), + Ok(RevsetExpression::branches(StringPattern::Exact( "foo".to_owned() ))) ); @@ -2706,9 +2706,9 @@ mod tests { ))) ); assert_eq!( - parse(r#"branches("literal:foo")"#), + parse(r#"branches("exact:foo")"#), Ok(RevsetExpression::branches(StringPattern::Substring( - "literal:foo".to_owned() + "exact:foo".to_owned() ))) ); assert_eq!( @@ -2719,7 +2719,7 @@ mod tests { }) ); assert_eq!( - parse(r#"branches(literal::"foo")"#), + parse(r#"branches(exact::"foo")"#), Err(RevsetParseErrorKind::InvalidFunctionArguments { name: "branches".to_owned(), message: "Expected function argument of string pattern".to_owned() @@ -2868,7 +2868,7 @@ mod tests { assert_eq!( parse("mine()"), Ok(RevsetExpression::filter(RevsetFilterPredicate::Author( - StringPattern::Literal("test.user@example.com".to_string()) + StringPattern::Exact("test.user@example.com".to_string()) ))) ); assert_eq!( @@ -2974,12 +2974,12 @@ mod tests { parse("author(a)").unwrap() ); assert_eq!( - parse_with_aliases("author(A)", [("A", "literal:a")]).unwrap(), - parse("author(literal:a)").unwrap() + parse_with_aliases("author(A)", [("A", "exact:a")]).unwrap(), + parse("author(exact:a)").unwrap() ); assert_eq!( - parse_with_aliases("author(literal:A)", [("A", "a")]).unwrap(), - parse("author(literal:a)").unwrap() + parse_with_aliases("author(exact:A)", [("A", "a")]).unwrap(), + parse("author(exact:a)").unwrap() ); // Multi-level substitution. diff --git a/lib/tests/test_revset.rs b/lib/tests/test_revset.rs index 6590108de..a02b0a87a 100644 --- a/lib/tests/test_revset.rs +++ b/lib/tests/test_revset.rs @@ -1717,13 +1717,13 @@ fn test_evaluate_expression_branches(use_git: bool) { vec![commit2.id().clone(), commit1.id().clone()] ); assert_eq!( - resolve_commit_ids(mut_repo, "branches(literal:branch1)"), + resolve_commit_ids(mut_repo, "branches(exact:branch1)"), vec![commit1.id().clone()] ); // Can silently resolve to an empty set if there's no matches assert_eq!(resolve_commit_ids(mut_repo, "branches(branch3)"), vec![]); assert_eq!( - resolve_commit_ids(mut_repo, "branches(literal:ranch1)"), + resolve_commit_ids(mut_repo, "branches(exact:ranch1)"), vec![] ); // Two branches pointing to the same commit does not result in a duplicate in @@ -1797,7 +1797,7 @@ fn test_evaluate_expression_remote_branches(use_git: bool) { vec![commit2.id().clone(), commit1.id().clone()] ); assert_eq!( - resolve_commit_ids(mut_repo, "remote_branches(literal:branch1)"), + resolve_commit_ids(mut_repo, "remote_branches(exact:branch1)"), vec![commit1.id().clone()] ); // Can get branches from matching remotes @@ -1810,7 +1810,7 @@ fn test_evaluate_expression_remote_branches(use_git: bool) { vec![commit2.id().clone(), commit1.id().clone()] ); assert_eq!( - resolve_commit_ids(mut_repo, r#"remote_branches("", literal:origin)"#), + resolve_commit_ids(mut_repo, r#"remote_branches("", exact:origin)"#), vec![commit1.id().clone()] ); // Can get branches with matching names from matching remotes @@ -1823,10 +1823,7 @@ fn test_evaluate_expression_remote_branches(use_git: bool) { vec![commit2.id().clone()] ); assert_eq!( - resolve_commit_ids( - mut_repo, - r#"remote_branches(literal:branch1, literal:origin)"# - ), + resolve_commit_ids(mut_repo, r#"remote_branches(exact:branch1, exact:origin)"#), vec![commit1.id().clone()] ); // Can silently resolve to an empty set if there's no matches @@ -1843,17 +1840,11 @@ fn test_evaluate_expression_remote_branches(use_git: bool) { vec![] ); assert_eq!( - resolve_commit_ids( - mut_repo, - r#"remote_branches(literal:ranch1, literal:origin)"# - ), + resolve_commit_ids(mut_repo, r#"remote_branches(exact:ranch1, exact:origin)"#), vec![] ); assert_eq!( - resolve_commit_ids( - mut_repo, - r#"remote_branches(literal:branch1, literal:orig)"# - ), + resolve_commit_ids(mut_repo, r#"remote_branches(exact:branch1, exact:orig)"#), vec![] ); // Two branches pointing to the same commit does not result in a duplicate in