Skip to content

Commit 0574a0f

Browse files
committed
Make names & emails ASCII-case-insensitive
1 parent 5b2c975 commit 0574a0f

File tree

7 files changed

+84
-38
lines changed

7 files changed

+84
-38
lines changed

Cargo.lock

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mailmap/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ categories = ["parsing"]
1111
license = "MIT OR Apache-2.0"
1212

1313
[dependencies]
14+
uncased = "0.9.10"

mailmap/src/lib.rs

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::fmt;
22
use std::pin::Pin;
33
use std::ptr::NonNull;
44

5+
use uncased::{Uncased, UncasedStr};
6+
57
#[cfg(test)]
68
mod test;
79

@@ -36,10 +38,10 @@ impl fmt::Debug for Mailmap {
3638

3739
#[derive(Copy, Clone)]
3840
struct RawMapEntry {
39-
canonical_name: Option<NonNull<str>>,
40-
canonical_email: Option<NonNull<str>>,
41-
current_name: Option<NonNull<str>>,
42-
current_email: Option<NonNull<str>>,
41+
canonical_name: Option<NonNull<UncasedStr>>,
42+
canonical_email: Option<NonNull<UncasedStr>>,
43+
current_name: Option<NonNull<UncasedStr>>,
44+
current_email: Option<NonNull<UncasedStr>>,
4345
}
4446

4547
impl RawMapEntry {
@@ -55,10 +57,10 @@ impl RawMapEntry {
5557

5658
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
5759
struct MapEntry<'a> {
58-
canonical_name: Option<&'a str>,
59-
canonical_email: Option<&'a str>,
60-
current_name: Option<&'a str>,
61-
current_email: Option<&'a str>,
60+
canonical_name: Option<&'a UncasedStr>,
61+
canonical_email: Option<&'a UncasedStr>,
62+
current_name: Option<&'a UncasedStr>,
63+
current_email: Option<&'a UncasedStr>,
6264
}
6365

6466
impl<'a> MapEntry<'a> {
@@ -74,8 +76,8 @@ impl<'a> MapEntry<'a> {
7476

7577
#[derive(Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
7678
pub struct Author {
77-
pub name: String,
78-
pub email: String,
79+
pub name: Uncased<'static>,
80+
pub email: Uncased<'static>,
7981
}
8082

8183
impl fmt::Debug for Author {
@@ -107,15 +109,31 @@ impl Mailmap {
107109
if let Some(name) = entry.current_name {
108110
if author.name == name && author.email == email {
109111
return Author {
110-
name: entry.canonical_name.unwrap_or(&author.name).to_owned(),
111-
email: entry.canonical_email.expect("canonical email").to_owned(),
112+
name: entry
113+
.canonical_name
114+
.unwrap_or(&author.name)
115+
.to_string()
116+
.into(),
117+
email: entry
118+
.canonical_email
119+
.expect("canonical email")
120+
.to_string()
121+
.into(),
112122
};
113123
}
114124
} else {
115125
if author.email == email {
116126
return Author {
117-
name: entry.canonical_name.unwrap_or(&author.name).to_owned(),
118-
email: entry.canonical_email.expect("canonical email").to_owned(),
127+
name: entry
128+
.canonical_name
129+
.unwrap_or(&author.name)
130+
.to_string()
131+
.into(),
132+
email: entry
133+
.canonical_email
134+
.expect("canonical email")
135+
.to_string()
136+
.into(),
119137
};
120138
}
121139
}
@@ -126,7 +144,7 @@ impl Mailmap {
126144
}
127145
}
128146

129-
fn read_email<'a>(line: &mut &'a str) -> Option<&'a str> {
147+
fn read_email<'a>(line: &mut &'a str) -> Option<&'a UncasedStr> {
130148
if !line.starts_with('<') {
131149
return None;
132150
}
@@ -136,21 +154,21 @@ fn read_email<'a>(line: &mut &'a str) -> Option<&'a str> {
136154
.unwrap_or_else(|| panic!("could not find email end in {:?}", line));
137155
let ret = &line[1..end];
138156
*line = &line[end + 1..];
139-
Some(ret)
157+
Some(ret.into())
140158
}
141159

142-
fn read_name<'a>(line: &mut &'a str) -> Option<&'a str> {
160+
fn read_name<'a>(line: &mut &'a str) -> Option<&'a UncasedStr> {
143161
let end = if let Some(end) = line.find('<') {
144162
end
145163
} else {
146164
return None;
147165
};
148-
let ret = &line[..end].trim();
166+
let ret = line[..end].trim();
149167
*line = &line[end..];
150168
if ret.is_empty() {
151169
None
152170
} else {
153-
Some(ret)
171+
Some(ret.into())
154172
}
155173
}
156174

mailmap/src/test.rs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fn comment_2() {
2323
fn email_1() {
2424
assert_eq!(
2525
test_parser!(read_email, "<foo@example.com>", ""),
26-
Some("foo@example.com")
26+
Some("foo@example.com".into())
2727
);
2828
}
2929

@@ -35,7 +35,7 @@ fn email_2() {
3535
"<foo@example.com> <foo2@example.com>",
3636
" <foo2@example.com>"
3737
),
38-
Some("foo@example.com")
38+
Some("foo@example.com".into())
3939
);
4040
}
4141

@@ -59,7 +59,7 @@ fn name_1() {
5959
"Canonical Name <foo@example.com>",
6060
"<foo@example.com>"
6161
),
62-
Some("Canonical Name"),
62+
Some("Canonical Name".into()),
6363
);
6464
}
6565

@@ -68,10 +68,10 @@ fn line_1() {
6868
assert_eq!(
6969
parse_line("Joe Bob <email1> <email2>", 0),
7070
Some(MapEntry {
71-
canonical_name: Some("Joe Bob"),
72-
canonical_email: Some("email1"),
71+
canonical_name: Some("Joe Bob".into()),
72+
canonical_email: Some("email1".into()),
7373
current_name: None,
74-
current_email: Some("email2"),
74+
current_email: Some("email2".into()),
7575
})
7676
);
7777
}
@@ -81,18 +81,18 @@ fn line_2() {
8181
assert_eq!(
8282
parse_line("Joe Bob <email1>", 0),
8383
Some(MapEntry {
84-
canonical_name: Some("Joe Bob"),
85-
canonical_email: Some("email1"),
84+
canonical_name: Some("Joe Bob".into()),
85+
canonical_email: Some("email1".into()),
8686
current_name: None,
87-
current_email: Some("email1"),
87+
current_email: Some("email1".into()),
8888
})
8989
);
9090
}
9191

9292
fn a(name: &str, email: &str) -> Author {
9393
Author {
94-
name: name.into(),
95-
email: email.into(),
94+
name: name.to_owned().into(),
95+
email: email.to_owned().into(),
9696
}
9797
}
9898

@@ -123,3 +123,12 @@ fn map_4() {
123123
let mm = map("<PE> <CE>");
124124
assert_eq!(mm.canonicalize(&a("any", "CE")), a("any", "PE"));
125125
}
126+
127+
#[test]
128+
fn case_insensitive() {
129+
let mm = map("Proper Name <proper@email.xx> CoMmIt NaMe <CoMmIt@EmAiL.xX>");
130+
assert_eq!(
131+
mm.canonicalize(&a("Commit Name", "commit@email.xx")),
132+
a("Proper Name", "proper@email.xx")
133+
);
134+
}

src/main.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ impl ToAuthor for Author {
3131
.unwrap_or_else(|| panic!("no email for {}", sig));
3232

3333
Author {
34-
name: name.to_string(),
35-
email: email.to_string(),
34+
name: name.to_string().into(),
35+
email: email.to_string().into(),
3636
}
3737
}
3838
}
@@ -259,8 +259,8 @@ fn commit_coauthors(commit: &Commit) -> Vec<Author> {
259259
if line.starts_with("Co-authored-by") {
260260
if let Some(caps) = RE.captures(line) {
261261
coauthors.push(Author {
262-
name: caps["name"].to_string(),
263-
email: caps["email"].to_string(),
262+
name: caps["name"].to_string().into(),
263+
email: caps["email"].to_string().into(),
264264
});
265265
}
266266
}
@@ -589,7 +589,7 @@ fn main() {
589589
eprintln!("\tcaused by: {}", cause);
590590
cur = cause;
591591
}
592-
std::mem::drop(cur);
592+
let _ = cur;
593593
std::process::exit(1);
594594
}
595595
}

src/reviewers.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ impl Reviewers {
1515

1616
fn a(name: &str, email: &str) -> Author {
1717
Author {
18-
name: name.into(),
19-
email: email.into(),
18+
name: name.to_string().into(),
19+
email: email.to_string().into(),
2020
}
2121
}
2222

src/site.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ fn author_map_to_scores(map: &AuthorMap) -> Vec<Entry> {
146146
.iter()
147147
.map(|(author, commits)| Entry {
148148
rank: 0,
149-
author: author.name.clone(),
149+
author: author.name.to_string(),
150150
commits: commits,
151151
})
152152
.collect::<Vec<_>>();

0 commit comments

Comments
 (0)