diff --git a/gitoxide-core/src/lib.rs b/gitoxide-core/src/lib.rs index ed27b601f77..30af836bfce 100644 --- a/gitoxide-core/src/lib.rs +++ b/gitoxide-core/src/lib.rs @@ -46,6 +46,7 @@ pub mod commitgraph; #[cfg(feature = "estimate-hours")] pub mod hours; pub mod index; +pub mod mailmap; #[cfg(feature = "organize")] pub mod organize; pub mod pack; diff --git a/gitoxide-core/src/mailmap.rs b/gitoxide-core/src/mailmap.rs index e69de29bb2d..04d985853c8 100644 --- a/gitoxide-core/src/mailmap.rs +++ b/gitoxide-core/src/mailmap.rs @@ -0,0 +1,26 @@ +use crate::OutputFormat; +use anyhow::{bail, Context}; +use git_repository as git; +use std::io::Write; +use std::path::Path; + +pub const PROGRESS_RANGE: std::ops::RangeInclusive = 1..=2; + +pub fn verify(path: impl AsRef, format: OutputFormat, mut out: impl Write) -> anyhow::Result<()> { + if format != OutputFormat::Human { + bail!("Only 'human' format is currently supported"); + } + let path = path.as_ref(); + let buf = std::fs::read(path).with_context(|| format!("Failed to read mailmap file at '{}'", path.display()))?; + let mut err_count = 0; + for err in git::mailmap::parse(&buf).filter_map(Result::err) { + err_count += 1; + writeln!(out, "{}", err)?; + } + if err_count == 0 { + writeln!(out, "{} lines OK", git::mailmap::parse(&buf).count())?; + Ok(()) + } else { + bail!("{} lines in '{}' could not be parsed", err_count, path.display()); + } +} diff --git a/src/plumbing/main.rs b/src/plumbing/main.rs index dd72bd6f48c..11b47ccf4e0 100644 --- a/src/plumbing/main.rs +++ b/src/plumbing/main.rs @@ -12,6 +12,7 @@ use clap::Parser; use gitoxide_core as core; use gitoxide_core::pack::verify; +use crate::plumbing::options::mailmap; use crate::plumbing::options::pack::multi_index; #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))] use crate::plumbing::options::remote; @@ -74,6 +75,16 @@ pub fn main() -> Result<()> { })?; match cmd { + Subcommands::Mailmap(mailmap::Platform { path, cmd }) => match cmd { + mailmap::Subcommands::Verify => prepare_and_run( + "mailmap-verify", + verbose, + progress, + progress_keep_open, + core::mailmap::PROGRESS_RANGE, + move |_progress, out, _err| core::mailmap::verify(path, format, out), + ), + }, Subcommands::Index(index::Platform { object_hash, index_path, diff --git a/src/plumbing/options.rs b/src/plumbing/options.rs index 4a75745dcf6..37290700461 100644 --- a/src/plumbing/options.rs +++ b/src/plumbing/options.rs @@ -60,6 +60,8 @@ pub enum Subcommands { Index(index::Platform), /// Subcommands for interacting with entire git repositories Repository(repo::Platform), + /// Subcommands for interacting with mailmaps + Mailmap(mailmap::Platform), } /// @@ -448,6 +450,28 @@ pub mod index { } } +/// +pub mod mailmap { + use std::path::PathBuf; + + #[derive(Debug, clap::Parser)] + pub struct Platform { + /// The path to the mailmap file. + #[clap(short = 'p', long, default_value = ".mailmap")] + pub path: PathBuf, + + /// Subcommands + #[clap(subcommand)] + pub cmd: Subcommands, + } + + #[derive(Debug, clap::Subcommand)] + pub enum Subcommands { + /// Parse all entries in the mailmap and report malformed lines. + Verify, + } +} + /// pub mod commitgraph { use std::path::PathBuf;