Added support for multiple authors and mailmap parsing for these authors
parent
797ab6a9ac
commit
25d6b47e15
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
37
src/main.rs
37
src/main.rs
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue