git_mailmap/snapshot/
mod.rs1use bstr::ByteSlice;
2use git_actor::SignatureRef;
3
4use crate::Snapshot;
5
6mod signature;
7pub use signature::{ResolvedSignature, Signature};
8
9mod util;
10use util::EncodedStringRef;
11
12mod entry;
13pub(crate) use entry::EmailEntry;
14
15impl Snapshot {
16 pub fn from_bytes(buf: &[u8]) -> Self {
20 Self::new(crate::parse_ignore_errors(buf))
21 }
22
23 pub fn new<'a>(entries: impl IntoIterator<Item = crate::Entry<'a>>) -> Self {
27 let mut snapshot = Self::default();
28 snapshot.merge(entries);
29 snapshot
30 }
31
32 pub fn merge<'a>(&mut self, entries: impl IntoIterator<Item = crate::Entry<'a>>) -> &mut Self {
35 for entry in entries {
36 let old_email: EncodedStringRef<'_> = entry.old_email.into();
37 assert!(
38 entry.new_name.is_some() || entry.new_email.is_some(),
39 "BUG: encountered entry without any mapped/new name or email."
40 );
41 match self
42 .entries_by_old_email
43 .binary_search_by(|e| e.old_email.cmp_ref(old_email))
44 {
45 Ok(pos) => self.entries_by_old_email[pos].merge(entry),
46 Err(insert_pos) => {
47 self.entries_by_old_email.insert(insert_pos, entry.into());
48 }
49 };
50 }
51 self
52 }
53
54 pub fn entries(&self) -> Vec<crate::Entry<'_>> {
59 let mut out = Vec::with_capacity(self.entries_by_old_email.len());
60 for entry in &self.entries_by_old_email {
61 if entry.new_email.is_some() || entry.new_name.is_some() {
62 out.push(crate::Entry {
63 new_name: entry.new_name.as_ref().map(|b| b.as_bstr()),
64 new_email: entry.new_email.as_ref().map(|b| b.as_bstr()),
65 old_name: None,
66 old_email: entry.old_email.as_bstr(),
67 });
68 }
69
70 for name_entry in &entry.entries_by_old_name {
71 out.push(crate::Entry {
72 new_name: name_entry.new_name.as_ref().map(|b| b.as_bstr()),
73 new_email: name_entry.new_email.as_ref().map(|b| b.as_bstr()),
74 old_name: name_entry.old_name.as_bstr().into(),
75 old_email: entry.old_email.as_bstr(),
76 });
77 }
78 }
79 out
80 }
81
82 pub fn try_resolve_ref(&self, signature: git_actor::SignatureRef<'_>) -> Option<ResolvedSignature<'_>> {
91 let email: EncodedStringRef<'_> = signature.email.into();
92 let pos = self
93 .entries_by_old_email
94 .binary_search_by(|e| e.old_email.cmp_ref(email))
95 .ok()?;
96 let entry = &self.entries_by_old_email[pos];
97
98 let name: EncodedStringRef<'_> = signature.name.into();
99
100 match entry.entries_by_old_name.binary_search_by(|e| e.old_name.cmp_ref(name)) {
101 Ok(pos) => {
102 let name_entry = &entry.entries_by_old_name[pos];
103 ResolvedSignature::try_new(
104 name_entry.new_email.as_ref(),
105 entry.old_email.as_bstr(),
106 signature.email,
107 name_entry.new_name.as_ref(),
108 )
109 }
110 Err(_) => ResolvedSignature::try_new(
111 entry.new_email.as_ref(),
112 entry.old_email.as_bstr(),
113 signature.email,
114 entry.new_name.as_ref(),
115 ),
116 }
117 }
118
119 pub fn try_resolve(&self, signature: git_actor::SignatureRef<'_>) -> Option<git_actor::Signature> {
124 self.try_resolve_ref(signature)
125 .map(|new| enriched_signature(signature, new).into())
126 }
127
128 pub fn resolve(&self, signature: git_actor::SignatureRef<'_>) -> git_actor::Signature {
133 self.try_resolve(signature).unwrap_or_else(|| signature.to_owned())
134 }
135
136 pub fn resolve_cow<'a>(&self, signature: git_actor::SignatureRef<'a>) -> Signature<'a> {
139 self.try_resolve_ref(signature)
140 .map(|new| enriched_signature(signature, new))
141 .unwrap_or_else(|| signature.into())
142 }
143}
144
145fn enriched_signature<'a>(
146 SignatureRef { name, email, time }: SignatureRef<'a>,
147 new: ResolvedSignature<'_>,
148) -> Signature<'a> {
149 match (new.email, new.name) {
150 (Some(new_email), Some(new_name)) => Signature {
151 email: new_email.to_owned().into(),
152 name: new_name.to_owned().into(),
153 time,
154 },
155 (Some(new_email), None) => Signature {
156 email: new_email.to_owned().into(),
157 name: name.into(),
158 time,
159 },
160 (None, Some(new_name)) => Signature {
161 email: email.into(),
162 name: new_name.to_owned().into(),
163 time,
164 },
165 (None, None) => unreachable!("BUG: ResolvedSignatures don't exist here when nothing is set"),
166 }
167}