Skip to content

Commit 2a56387

Browse files
committed
feat: add mailmap check similar to git check-mailmap.
That way it becomes a little easier to maybe try out other special cases in the wild.
1 parent ca05471 commit 2a56387

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

gitoxide-core/src/repository/mailmap.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use anyhow::bail;
2+
use gix::bstr::{BString, ByteSlice};
13
use std::io;
24

35
#[cfg(feature = "serde")]
@@ -50,3 +52,59 @@ pub fn entries(
5052

5153
Ok(())
5254
}
55+
56+
pub fn check(
57+
repo: gix::Repository,
58+
format: OutputFormat,
59+
contacts: Vec<BString>,
60+
mut out: impl io::Write,
61+
mut err: impl io::Write,
62+
) -> anyhow::Result<()> {
63+
if format != OutputFormat::Human {
64+
bail!("Only human output is supported right now");
65+
}
66+
if contacts.is_empty() {
67+
bail!("specify at least one contact to run through the mailmap")
68+
}
69+
70+
let mut mailmap = gix::mailmap::Snapshot::default();
71+
if let Err(err) = repo.open_mailmap_into(&mut mailmap) {
72+
bail!(err);
73+
}
74+
75+
let mut buf = Vec::new();
76+
for contact in contacts {
77+
let actor = match gix::actor::IdentityRef::from_bytes::<()>(&contact) {
78+
Ok(a) => a,
79+
Err(_) => {
80+
let Some(email) = contact
81+
.trim_start()
82+
.strip_prefix(b"<")
83+
.and_then(|rest| rest.trim_end().strip_suffix(b">"))
84+
else {
85+
writeln!(err, "Failed to parse contact '{contact}' - skipping")?;
86+
continue;
87+
};
88+
gix::actor::IdentityRef {
89+
name: "".into(),
90+
email: email.into(),
91+
}
92+
}
93+
};
94+
let resolved = mailmap.resolve_cow(gix::actor::SignatureRef {
95+
name: actor.name,
96+
email: actor.email,
97+
time: Default::default(),
98+
});
99+
let resolved = gix::actor::IdentityRef {
100+
name: resolved.name.as_ref(),
101+
email: resolved.email.as_ref(),
102+
};
103+
buf.clear();
104+
resolved.write_to(&mut buf)?;
105+
106+
out.write_all(&buf)?;
107+
out.write_all(b"\n")?;
108+
}
109+
Ok(())
110+
}

src/plumbing/main.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,17 @@ pub fn main() -> Result<()> {
12161216
core::repository::mailmap::entries(repository(Mode::Lenient)?, format, out, err)
12171217
},
12181218
),
1219+
mailmap::Subcommands::Check { contacts } => prepare_and_run(
1220+
"mailmap-check",
1221+
trace,
1222+
verbose,
1223+
progress,
1224+
progress_keep_open,
1225+
None,
1226+
move |_progress, out, err| {
1227+
core::repository::mailmap::check(repository(Mode::Lenient)?, format, contacts, out, err)
1228+
},
1229+
),
12191230
},
12201231
Subcommands::Attributes(cmd) => match cmd {
12211232
attributes::Subcommands::Query { statistics, pathspec } => prepare_and_run(

src/plumbing/options/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,10 +512,17 @@ pub mod remote {
512512
}
513513

514514
pub mod mailmap {
515+
use gix::bstr::BString;
516+
515517
#[derive(Debug, clap::Subcommand)]
516518
pub enum Subcommands {
517519
/// Print all entries in configured mailmaps, inform about errors as well.
518520
Entries,
521+
/// Print all entries in configured mailmaps, inform about errors as well.
522+
Check {
523+
/// One or more `Name <email>` or `<email>` to pass through the mailmap.
524+
contacts: Vec<BString>,
525+
},
519526
}
520527
}
521528

0 commit comments

Comments
 (0)