Skip to content

Commit

Permalink
Make names & emails ASCII-case-insensitive
Browse files Browse the repository at this point in the history
  • Loading branch information
GrigorenkoPV committed Aug 14, 2024
1 parent 5b2c975 commit a1e9e01
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 30 deletions.
1 change: 1 addition & 0 deletions mailmap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ categories = ["parsing"]
license = "MIT OR Apache-2.0"

[dependencies]
uncased = "0.9.10"
56 changes: 37 additions & 19 deletions mailmap/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::fmt;
use std::pin::Pin;
use std::ptr::NonNull;

use uncased::{Uncased, UncasedStr};

#[cfg(test)]
mod test;

Expand Down Expand Up @@ -36,10 +38,10 @@ impl fmt::Debug for Mailmap {

#[derive(Copy, Clone)]
struct RawMapEntry {
canonical_name: Option<NonNull<str>>,
canonical_email: Option<NonNull<str>>,
current_name: Option<NonNull<str>>,
current_email: Option<NonNull<str>>,
canonical_name: Option<NonNull<UncasedStr>>,
canonical_email: Option<NonNull<UncasedStr>>,
current_name: Option<NonNull<UncasedStr>>,
current_email: Option<NonNull<UncasedStr>>,
}

impl RawMapEntry {
Expand All @@ -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> {
Expand All @@ -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 {
Expand Down Expand Up @@ -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(),
};
}
}
Expand All @@ -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;
}
Expand All @@ -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())
}
}

Expand Down
31 changes: 20 additions & 11 deletions mailmap/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fn comment_2() {
fn email_1() {
assert_eq!(
test_parser!(read_email, "<[email protected]>", ""),
Some("[email protected]")
Some("[email protected]".into())
);
}

Expand All @@ -35,7 +35,7 @@ fn email_2() {
"<[email protected]> <[email protected]>",
" <[email protected]>"
),
Some("[email protected]")
Some("[email protected]".into())
);
}

Expand All @@ -59,7 +59,7 @@ fn name_1() {
"Canonical Name <[email protected]>",
"<[email protected]>"
),
Some("Canonical Name"),
Some("Canonical Name".into()),
);
}

Expand All @@ -68,10 +68,10 @@ fn line_1() {
assert_eq!(
parse_line("Joe Bob <email1> <email2>", 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()),
})
);
}
Expand All @@ -81,18 +81,18 @@ fn line_2() {
assert_eq!(
parse_line("Joe Bob <email1>", 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(),
}
}

Expand Down Expand Up @@ -123,3 +123,12 @@ fn map_4() {
let mm = map("<PE> <CE>");
assert_eq!(mm.canonicalize(&a("any", "CE")), a("any", "PE"));
}

#[test]
fn case_insensitive() {
let mm = map("Proper Name <[email protected]> CoMmIt NaMe <[email protected]>");
assert_eq!(
mm.canonicalize(&a("Commit Name", "[email protected]")),
a("Proper Name", "[email protected]")
);
}

0 comments on commit a1e9e01

Please sign in to comment.