Skip to content

Commit d71d067

Browse files
committed
sketch of mailmap snapshot for lookups (#366)
1 parent b67b0f9 commit d71d067

File tree

3 files changed

+108
-16
lines changed

3 files changed

+108
-16
lines changed

git-mailmap/src/entry.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ use bstr::BStr;
44
impl<'a> Entry<'a> {
55
pub fn change_name_by_email(proper_name: impl Into<&'a BStr>, commit_email: impl Into<&'a BStr>) -> Self {
66
Entry {
7-
canonical_name: Some(proper_name.into()),
8-
commit_email: Some(commit_email.into()),
7+
new_name: Some(proper_name.into()),
8+
old_email: Some(commit_email.into()),
99
..Default::default()
1010
}
1111
}
1212
pub fn change_email_by_email(proper_email: impl Into<&'a BStr>, commit_email: impl Into<&'a BStr>) -> Self {
1313
Entry {
14-
canonical_email: Some(proper_email.into()),
15-
commit_email: Some(commit_email.into()),
14+
new_email: Some(proper_email.into()),
15+
old_email: Some(commit_email.into()),
1616
..Default::default()
1717
}
1818
}
@@ -22,9 +22,9 @@ impl<'a> Entry<'a> {
2222
commit_email: impl Into<&'a BStr>,
2323
) -> Self {
2424
Entry {
25-
canonical_name: Some(proper_name.into()),
26-
canonical_email: Some(proper_email.into()),
27-
commit_email: Some(commit_email.into()),
25+
new_name: Some(proper_name.into()),
26+
new_email: Some(proper_email.into()),
27+
old_email: Some(commit_email.into()),
2828
..Default::default()
2929
}
3030
}
@@ -36,10 +36,10 @@ impl<'a> Entry<'a> {
3636
commit_email: impl Into<&'a BStr>,
3737
) -> Self {
3838
Entry {
39-
canonical_name: Some(proper_name.into()),
40-
canonical_email: Some(proper_email.into()),
41-
commit_name: Some(commit_name.into()),
42-
commit_email: Some(commit_email.into()),
39+
new_name: Some(proper_name.into()),
40+
new_email: Some(proper_email.into()),
41+
old_name: Some(commit_name.into()),
42+
old_email: Some(commit_email.into()),
4343
}
4444
}
4545
}

git-mailmap/src/lib.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,24 @@ pub fn parse(buf: &[u8]) -> parse::Lines<'_> {
1010

1111
mod entry;
1212

13-
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Default)]
13+
mod snapshot;
14+
15+
#[derive(Default, Clone)]
16+
pub struct Snapshot {
17+
/// Sorted by `old_email`
18+
entries_by_old_email: Vec<snapshot::EmailEntry>,
19+
}
20+
21+
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy, Default)]
1422
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
1523
pub struct Entry<'a> {
1624
#[cfg_attr(feature = "serde1", serde(borrow))]
1725
/// The name to map to.
18-
canonical_name: Option<&'a BStr>,
26+
new_name: Option<&'a BStr>,
1927
/// The email map to.
20-
canonical_email: Option<&'a BStr>,
28+
new_email: Option<&'a BStr>,
2129
/// The name to look for and replace.
22-
commit_name: Option<&'a BStr>,
30+
old_name: Option<&'a BStr>,
2331
/// The email to look for and replace.
24-
commit_email: Option<&'a BStr>,
32+
old_email: Option<&'a BStr>,
2533
}

git-mailmap/src/snapshot.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use bstr::{BString, ByteSlice};
2+
use std::cmp::Ordering;
3+
use std::ops::Deref;
4+
5+
#[cfg_attr(test, derive(Debug))]
6+
#[derive(Clone)]
7+
enum EncodedString {
8+
Utf8(String),
9+
Unknown(BString),
10+
}
11+
12+
impl Eq for EncodedString {}
13+
14+
impl PartialEq<Self> for EncodedString {
15+
fn eq(&self, other: &Self) -> bool {
16+
self.cmp(other) == Ordering::Equal
17+
}
18+
}
19+
20+
impl PartialOrd<Self> for EncodedString {
21+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
22+
self.cmp(other).into()
23+
}
24+
}
25+
26+
impl Ord for EncodedString {
27+
fn cmp(&self, other: &Self) -> Ordering {
28+
use EncodedString::*;
29+
match (self, other) {
30+
(Utf8(a), Utf8(b)) => {
31+
let a = a.chars().map(|c| c.to_ascii_lowercase());
32+
let b = b.chars().map(|c| c.to_ascii_lowercase());
33+
a.cmp(b)
34+
}
35+
(Unknown(a), Unknown(b)) => a.cmp(b),
36+
(Utf8(a), Unknown(b)) => a.as_bytes().cmp(b.as_ref()),
37+
(Unknown(a), Utf8(b)) => a.deref().as_bytes().cmp(b.as_bytes()),
38+
}
39+
}
40+
}
41+
42+
#[derive(Clone)]
43+
pub(crate) struct NameEntry {
44+
new_name: Option<BString>,
45+
new_email: Option<BString>,
46+
old_name: EncodedString,
47+
}
48+
49+
#[derive(Clone)]
50+
pub(crate) struct EmailEntry {
51+
new_name: Option<BString>,
52+
new_email: Option<BString>,
53+
old_email: EncodedString,
54+
55+
entries_by_old_name: Vec<NameEntry>,
56+
}
57+
58+
#[cfg(test)]
59+
mod encoded_string {
60+
use crate::snapshot::EncodedString;
61+
62+
#[test]
63+
fn basic_ascii_case_folding() {
64+
assert_eq!(
65+
EncodedString::Utf8("FooBar".into()),
66+
EncodedString::Utf8("foobar".into())
67+
)
68+
}
69+
70+
#[test]
71+
fn no_advanced_unicode_folding() {
72+
assert_ne!(EncodedString::Utf8("Masse".into()), EncodedString::Utf8("Maße".into()))
73+
}
74+
75+
#[test]
76+
fn unknown_encoding_pairs_do_not_try_to_ignore_cases() {
77+
assert_ne!(EncodedString::Utf8("Foo".into()), EncodedString::Unknown("foo".into()));
78+
assert_ne!(EncodedString::Unknown("Foo".into()), EncodedString::Utf8("foo".into()));
79+
assert_ne!(
80+
EncodedString::Unknown("Foo".into()),
81+
EncodedString::Unknown("foo".into())
82+
);
83+
}
84+
}

0 commit comments

Comments
 (0)