Added support for multiple authors and mailmap parsing for these authors

master
Wynd 2024-08-17 16:13:38 +03:00
parent 797ab6a9ac
commit 25d6b47e15
3 changed files with 91 additions and 11 deletions

View File

@ -8,8 +8,8 @@ use crate::heatmap::HeatmapColors;
#[derive(Clone, Debug, Parser, PartialEq, Eq)] #[derive(Clone, Debug, Parser, PartialEq, Eq)]
#[command(version, about, long_about = None)] #[command(version, about, long_about = None)]
pub struct CliArgs { pub struct CliArgs {
#[arg(short, long)] #[arg(short, long, num_args(0..))]
pub author: String, pub authors: Option<Vec<String>>,
#[arg(short, long, default_value = "")] #[arg(short, long, default_value = "")]
pub char: char, pub char: char,

61
src/mailmap.rs 100644
View File

@ -0,0 +1,61 @@
use std::path::Path;
use crate::Author;
pub struct Mailmap {
entries: Vec<MapEntry>,
}
#[derive(Debug)]
struct MapEntry {
new_name: Option<String>,
new_email: Option<String>,
old_name: Option<String>,
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<MapEntry> = 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
}
}

View File

@ -10,12 +10,14 @@ use clap::Parser;
use gix::{bstr::ByteSlice, traverse::commit::simple::Sorting, ObjectId}; use gix::{bstr::ByteSlice, traverse::commit::simple::Sorting, ObjectId};
use heatmap::HeatmapColors; use heatmap::HeatmapColors;
use itertools::Itertools; use itertools::Itertools;
use mailmap::Mailmap;
use rgb::Rgb; use rgb::Rgb;
use crate::{cli::CliArgs, heatmap::Heatmap}; use crate::{cli::CliArgs, heatmap::Heatmap};
mod cli; mod cli;
mod heatmap; mod heatmap;
mod mailmap;
mod rgb; mod rgb;
pub const ESCAPE: &str = "\x1B"; pub const ESCAPE: &str = "\x1B";
@ -40,14 +42,20 @@ const RED_COLOR_MAP: [Rgb; 5] = [
Rgb(255, 0, 0), Rgb(255, 0, 0),
]; ];
#[derive(PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
struct Commit { struct Commit {
id: ObjectId, id: ObjectId,
title: String, title: String,
author: String, author: Author,
time: DateTime<Local>, time: DateTime<Local>,
} }
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
struct Author {
name: String,
email: String,
}
fn main() -> Result<()> { fn main() -> Result<()> {
clear_screen(); clear_screen();
@ -140,8 +148,14 @@ fn get_commits(args: CliArgs, start_date: NaiveDate) -> Result<(usize, Vec<Commi
)); ));
} }
for (i, repo) in repos.iter().enumerate() { let current_time = Local::now().time();
let repo = gix::open(repo).unwrap(); let start_date = start_date.and_time(current_time);
let start_date = Local.from_local_datetime(&start_date).unwrap();
let authors = args.authors.unwrap_or_default();
for (i, repo_path) in repos.iter().enumerate() {
let repo = gix::open(repo_path).unwrap();
let branch_names = &*branches[i]; let branch_names = &*branches[i];
let mut branches = vec![]; let mut branches = vec![];
@ -153,9 +167,7 @@ fn get_commits(args: CliArgs, start_date: NaiveDate) -> Result<(usize, Vec<Commi
branches.extend(branch_names); branches.extend(branch_names);
} }
let current_time = Local::now().time(); let mailmap = Mailmap::new(repo_path);
let start_date = start_date.and_time(current_time);
let start_date = Local.from_local_datetime(&start_date).unwrap();
for branch in branches { for branch in branches {
let branch_commits = repo let branch_commits = repo
@ -181,8 +193,15 @@ fn get_commits(args: CliArgs, start_date: NaiveDate) -> Result<(usize, Vec<Commi
.ok()? .ok()?
.to_string(); .to_string();
let author = c.author().ok()?.name.to_string(); let author = c.author().ok()?;
if author != args.author {
let email = author.email.to_string();
let name = author.name.to_string();
let author = Author { name, email };
let author = mailmap.resolve(author);
if !authors.is_empty() && !authors.contains(&author.name) {
return None; return None;
} }