From aacdcf629b22863c71478d36d6b8ac4fb117835d Mon Sep 17 00:00:00 2001 From: Vamsi Avula Date: Fri, 10 Feb 2023 22:31:28 +0530 Subject: [PATCH] `author`/`committer` templates: add a `username` method I haven't used a proper email address parser as I'm not really sure if it's worth the extra dependency and effort -- thoughts? --- CHANGELOG.md | 3 ++ src/template_parser.rs | 18 ++++++++++++ tests/test_templater.rs | 62 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2795950c..461900c43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -142,6 +142,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * `jj new --insert-after` inserts the new commit between the target commit and its children. +* `author`/`committer` templates now support `.username()`, which leaves out the +domain information of `.email()`. + ### Fixed bugs * When sharing the working copy with a Git repo, we used to forget to export diff --git a/src/template_parser.rs b/src/template_parser.rs index 466f3fe05..cb0891fc4 100644 --- a/src/template_parser.rs +++ b/src/template_parser.rs @@ -360,6 +360,14 @@ fn expect_arguments( } } +fn split_email(email: &str) -> (&str, Option<&str>) { + if let Some((username, rest)) = email.split_once('@') { + (username, Some(rest)) + } else { + (email, None) + } +} + fn parse_method_chain<'a, I: 'a>( input_property: PropertyAndLabels<'a, I>, method_pairs: Pairs, @@ -556,6 +564,16 @@ fn parse_signature_method<'a, I: 'a>( TemplatePropertyFn(|signature: &Signature| signature.email.clone()), )) } + "username" => { + expect_no_arguments(args_pair)?; + Property::String(chain_properties( + self_property, + TemplatePropertyFn(|signature: &Signature| { + let (username, _) = split_email(&signature.email); + username.to_owned() + }), + )) + } "timestamp" => { expect_no_arguments(args_pair)?; Property::Timestamp(chain_properties( diff --git a/tests/test_templater.rs b/tests/test_templater.rs index b35f6d22c..8fffb353d 100644 --- a/tests/test_templater.rs +++ b/tests/test_templater.rs @@ -257,6 +257,68 @@ fn test_templater_string_method() { insta::assert_snapshot!(render(r#""foo\nbar".first_line()"#), @"foo"); } +#[test] +fn test_templater_signature() { + let test_env = TestEnvironment::default(); + test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]); + let repo_path = test_env.env_root().join("repo"); + let render = |template| get_template_output(&test_env, &repo_path, "@", template); + + test_env.jj_cmd_success(&repo_path, &["new"]); + + insta::assert_snapshot!(render(r#"author"#), @"Test User "); + insta::assert_snapshot!(render(r#"author.name()"#), @"Test User"); + insta::assert_snapshot!(render(r#"author.email()"#), @"test.user@example.com"); + insta::assert_snapshot!(render(r#"author.username()"#), @"test.user"); + + test_env.jj_cmd_success( + &repo_path, + &["--config-toml=user.name='Another Test User'", "new"], + ); + + insta::assert_snapshot!(render(r#"author"#), @"Another Test User "); + insta::assert_snapshot!(render(r#"author.name()"#), @"Another Test User"); + insta::assert_snapshot!(render(r#"author.email()"#), @"test.user@example.com"); + insta::assert_snapshot!(render(r#"author.username()"#), @"test.user"); + + test_env.jj_cmd_success( + &repo_path, + &[ + "--config-toml=user.email='test.user@invalid@example.com'", + "new", + ], + ); + + insta::assert_snapshot!(render(r#"author"#), @"Test User "); + insta::assert_snapshot!(render(r#"author.name()"#), @"Test User"); + insta::assert_snapshot!(render(r#"author.email()"#), @"test.user@invalid@example.com"); + insta::assert_snapshot!(render(r#"author.username()"#), @"test.user"); + + test_env.jj_cmd_success(&repo_path, &["--config-toml=user.email='test.user'", "new"]); + + insta::assert_snapshot!(render(r#"author"#), @"Test User "); + insta::assert_snapshot!(render(r#"author.email()"#), @"test.user"); + insta::assert_snapshot!(render(r#"author.username()"#), @"test.user"); + + test_env.jj_cmd_success( + &repo_path, + &[ + "--config-toml=user.email='test.user+tag@example.com'", + "new", + ], + ); + + insta::assert_snapshot!(render(r#"author"#), @"Test User "); + insta::assert_snapshot!(render(r#"author.email()"#), @"test.user+tag@example.com"); + insta::assert_snapshot!(render(r#"author.username()"#), @"test.user+tag"); + + test_env.jj_cmd_success(&repo_path, &["--config-toml=user.email='x@y'", "new"]); + + insta::assert_snapshot!(render(r#"author"#), @"Test User "); + insta::assert_snapshot!(render(r#"author.email()"#), @"x@y"); + insta::assert_snapshot!(render(r#"author.username()"#), @"x"); +} + #[test] fn test_templater_label_function() { let test_env = TestEnvironment::default();