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