diff --git a/mailmap/Cargo.toml b/mailmap/Cargo.toml index 8d2a1a40..dd3a0d39 100644 --- a/mailmap/Cargo.toml +++ b/mailmap/Cargo.toml @@ -11,3 +11,4 @@ categories = ["parsing"] license = "MIT OR Apache-2.0" [dependencies] +uncased = "0.9.10" diff --git a/mailmap/src/lib.rs b/mailmap/src/lib.rs index c3984464..92d96548 100644 --- a/mailmap/src/lib.rs +++ b/mailmap/src/lib.rs @@ -2,6 +2,8 @@ use std::fmt; use std::pin::Pin; use std::ptr::NonNull; +use uncased::{Uncased, UncasedStr}; + #[cfg(test)] mod test; @@ -36,10 +38,10 @@ impl fmt::Debug for Mailmap { #[derive(Copy, Clone)] struct RawMapEntry { - canonical_name: Option>, - canonical_email: Option>, - current_name: Option>, - current_email: Option>, + canonical_name: Option>, + canonical_email: Option>, + current_name: Option>, + current_email: Option>, } impl RawMapEntry { @@ -55,10 +57,10 @@ impl RawMapEntry { #[derive(Copy, Clone, Debug, PartialEq, Eq)] struct MapEntry<'a> { - canonical_name: Option<&'a str>, - canonical_email: Option<&'a str>, - current_name: Option<&'a str>, - current_email: Option<&'a str>, + canonical_name: Option<&'a UncasedStr>, + canonical_email: Option<&'a UncasedStr>, + current_name: Option<&'a UncasedStr>, + current_email: Option<&'a UncasedStr>, } impl<'a> MapEntry<'a> { @@ -74,8 +76,8 @@ impl<'a> MapEntry<'a> { #[derive(Clone, PartialEq, PartialOrd, Ord, Eq, Hash)] pub struct Author { - pub name: String, - pub email: String, + pub name: Uncased<'static>, + pub email: Uncased<'static>, } impl fmt::Debug for Author { @@ -107,15 +109,31 @@ impl Mailmap { if let Some(name) = entry.current_name { if author.name == name && author.email == email { return Author { - name: entry.canonical_name.unwrap_or(&author.name).to_owned(), - email: entry.canonical_email.expect("canonical email").to_owned(), + name: entry + .canonical_name + .unwrap_or(&author.name) + .to_string() + .into(), + email: entry + .canonical_email + .expect("canonical email") + .to_string() + .into(), }; } } else { if author.email == email { return Author { - name: entry.canonical_name.unwrap_or(&author.name).to_owned(), - email: entry.canonical_email.expect("canonical email").to_owned(), + name: entry + .canonical_name + .unwrap_or(&author.name) + .to_string() + .into(), + email: entry + .canonical_email + .expect("canonical email") + .to_string() + .into(), }; } } @@ -126,7 +144,7 @@ impl Mailmap { } } -fn read_email<'a>(line: &mut &'a str) -> Option<&'a str> { +fn read_email<'a>(line: &mut &'a str) -> Option<&'a UncasedStr> { if !line.starts_with('<') { return None; } @@ -136,21 +154,21 @@ fn read_email<'a>(line: &mut &'a str) -> Option<&'a str> { .unwrap_or_else(|| panic!("could not find email end in {:?}", line)); let ret = &line[1..end]; *line = &line[end + 1..]; - Some(ret) + Some(ret.into()) } -fn read_name<'a>(line: &mut &'a str) -> Option<&'a str> { +fn read_name<'a>(line: &mut &'a str) -> Option<&'a UncasedStr> { let end = if let Some(end) = line.find('<') { end } else { return None; }; - let ret = &line[..end].trim(); + let ret = line[..end].trim(); *line = &line[end..]; if ret.is_empty() { None } else { - Some(ret) + Some(ret.into()) } } diff --git a/mailmap/src/test.rs b/mailmap/src/test.rs index a6407545..c58b9c2a 100644 --- a/mailmap/src/test.rs +++ b/mailmap/src/test.rs @@ -23,7 +23,7 @@ fn comment_2() { fn email_1() { assert_eq!( test_parser!(read_email, "", ""), - Some("foo@example.com") + Some("foo@example.com".into()) ); } @@ -35,7 +35,7 @@ fn email_2() { " ", " " ), - Some("foo@example.com") + Some("foo@example.com".into()) ); } @@ -59,7 +59,7 @@ fn name_1() { "Canonical Name ", "" ), - Some("Canonical Name"), + Some("Canonical Name".into()), ); } @@ -68,10 +68,10 @@ fn line_1() { assert_eq!( parse_line("Joe Bob ", 0), Some(MapEntry { - canonical_name: Some("Joe Bob"), - canonical_email: Some("email1"), + canonical_name: Some("Joe Bob".into()), + canonical_email: Some("email1".into()), current_name: None, - current_email: Some("email2"), + current_email: Some("email2".into()), }) ); } @@ -81,18 +81,18 @@ fn line_2() { assert_eq!( parse_line("Joe Bob ", 0), Some(MapEntry { - canonical_name: Some("Joe Bob"), - canonical_email: Some("email1"), + canonical_name: Some("Joe Bob".into()), + canonical_email: Some("email1".into()), current_name: None, - current_email: Some("email1"), + current_email: Some("email1".into()), }) ); } fn a(name: &str, email: &str) -> Author { Author { - name: name.into(), - email: email.into(), + name: name.to_owned().into(), + email: email.to_owned().into(), } } @@ -123,3 +123,12 @@ fn map_4() { let mm = map(" "); assert_eq!(mm.canonicalize(&a("any", "CE")), a("any", "PE")); } + +#[test] +fn case_insensitive() { + let mm = map("Proper Name CoMmIt NaMe "); + assert_eq!( + mm.canonicalize(&a("Commit Name", "commit@email.xx")), + a("Proper Name", "proper@email.xx") + ); +}