From 25d6b47e15e16078fa48554237f1d09ddd92ad28 Mon Sep 17 00:00:00 2001 From: Wynd Date: Sat, 17 Aug 2024 16:13:38 +0300 Subject: [PATCH] Added support for multiple authors and mailmap parsing for these authors --- src/cli.rs | 4 ++-- src/mailmap.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 37 ++++++++++++++++++++++-------- 3 files changed, 91 insertions(+), 11 deletions(-) create mode 100644 src/mailmap.rs diff --git a/src/cli.rs b/src/cli.rs index 17b2204..d34f833 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -8,8 +8,8 @@ use crate::heatmap::HeatmapColors; #[derive(Clone, Debug, Parser, PartialEq, Eq)] #[command(version, about, long_about = None)] pub struct CliArgs { - #[arg(short, long)] - pub author: String, + #[arg(short, long, num_args(0..))] + pub authors: Option>, #[arg(short, long, default_value = "▩")] pub char: char, diff --git a/src/mailmap.rs b/src/mailmap.rs new file mode 100644 index 0000000..a0d654d --- /dev/null +++ b/src/mailmap.rs @@ -0,0 +1,61 @@ +use std::path::Path; + +use crate::Author; + +pub struct Mailmap { + entries: Vec, +} + +#[derive(Debug)] +struct MapEntry { + new_name: Option, + new_email: Option, + old_name: Option, + old_email: String, +} + +impl Mailmap { + pub fn new(repo_path: &Path) -> Self { + let mailmap_path = repo_path.join(".mailmap"); + let mailmap = std::fs::read_to_string(mailmap_path).unwrap_or_default(); + let mailmap = gix::mailmap::parse(mailmap.as_bytes()); + + let mut entries: Vec = vec![]; + for entry in mailmap { + let Ok(entry) = entry + else { + continue; + }; + + let entry = MapEntry { + new_name: entry.new_name().map(|v| v.to_string()), + new_email: entry.new_email().map(|v| v.to_string()), + old_name: entry.old_name().map(|v| v.to_string()), + old_email: entry.old_email().to_string(), + }; + + entries.push(entry); + } + + Self { entries } + } + + pub fn resolve(&self, author: Author) -> Author { + for entry in &self.entries { + if let Some(old_name) = &entry.old_name + && old_name == &author.name + { + return Author { + name: entry.new_name.as_ref().unwrap_or(&author.name).to_string(), + email: entry + .new_email + .as_ref() + .unwrap_or(&author.email) + .to_string(), + }; + } + } + + author + } +} diff --git a/src/main.rs b/src/main.rs index 30691d8..e84cf46 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,12 +10,14 @@ use clap::Parser; use gix::{bstr::ByteSlice, traverse::commit::simple::Sorting, ObjectId}; use heatmap::HeatmapColors; use itertools::Itertools; +use mailmap::Mailmap; use rgb::Rgb; use crate::{cli::CliArgs, heatmap::Heatmap}; mod cli; mod heatmap; +mod mailmap; mod rgb; pub const ESCAPE: &str = "\x1B"; @@ -40,14 +42,20 @@ const RED_COLOR_MAP: [Rgb; 5] = [ Rgb(255, 0, 0), ]; -#[derive(PartialEq, Eq, Hash)] +#[derive(Debug, PartialEq, Eq, Hash)] struct Commit { id: ObjectId, title: String, - author: String, + author: Author, time: DateTime, } +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +struct Author { + name: String, + email: String, +} + fn main() -> Result<()> { clear_screen(); @@ -140,8 +148,14 @@ fn get_commits(args: CliArgs, start_date: NaiveDate) -> Result<(usize, Vec Result<(usize, Vec Result<(usize, Vec