@@ -9,13 +9,28 @@ use git2::{
99 StatusShow ,
1010} ;
1111use regex:: Regex ;
12+ use std:: collections:: HashMap ;
1213use std:: path:: Path ;
1314
1415pub struct Repo < ' a > {
1516 repo : & ' a Repository ,
1617 logs : Vec < Commit < ' a > > ,
1718}
1819
20+ #[ derive( Hash , PartialEq , Eq ) ]
21+ pub struct Sig {
22+ name : String ,
23+ email : String ,
24+ }
25+
26+ impl From < Signature < ' _ > > for Sig {
27+ fn from ( sig : Signature ) -> Self {
28+ let name = String :: from_utf8_lossy ( sig. name_bytes ( ) ) . into_owned ( ) ;
29+ let email = String :: from_utf8_lossy ( sig. email_bytes ( ) ) . into_owned ( ) ;
30+ Self { name, email }
31+ }
32+ }
33+
1934impl < ' a > Repo < ' a > {
2035 pub fn new (
2136 repo : & ' a Repository ,
@@ -70,42 +85,46 @@ impl<'a> Repo<'a> {
7085
7186 pub fn get_authors (
7287 & self ,
73- n : usize ,
88+ number_of_author : usize ,
7489 show_email : bool ,
75- ) -> Vec < ( String , Option < String > , usize , usize ) > {
76- let mut authors = std:: collections:: HashMap :: new ( ) ;
77- let mut author_name_by_email = std:: collections:: HashMap :: new ( ) ;
90+ ) -> Result < Vec < ( String , Option < String > , usize , usize ) > > {
91+ let mut author_to_number_of_commits: HashMap < Sig , usize > = HashMap :: new ( ) ;
7892 let mut total_nbr_of_commits = 0 ;
93+ let mailmap = self . repo . mailmap ( ) ?;
7994 for commit in & self . logs {
80- let author = commit. author ( ) ;
81- let author_name = String :: from_utf8_lossy ( author . name_bytes ( ) ) . into_owned ( ) ;
82- let author_email = String :: from_utf8_lossy ( author . email_bytes ( ) ) . into_owned ( ) ;
83-
84- let author_nbr_of_commits = authors . entry ( author_email . to_string ( ) ) . or_insert ( 0 ) ;
85- author_name_by_email . entry ( author_email . to_string ( ) ) . or_insert ( author_name ) ;
95+ let author = match commit. author_with_mailmap ( & mailmap ) {
96+ Ok ( val ) => val ,
97+ Err ( _ ) => commit . author ( ) ,
98+ } ;
99+ let author_nbr_of_commits =
100+ author_to_number_of_commits . entry ( Sig :: from ( author ) ) . or_insert ( 0 ) ;
86101 * author_nbr_of_commits += 1 ;
87102 total_nbr_of_commits += 1 ;
88103 }
89104
90- let mut authors: Vec < ( String , usize ) > = authors. into_iter ( ) . collect ( ) ;
91- authors. sort_by ( |( _, a_count) , ( _, b_count) | b_count. cmp ( a_count) ) ;
92-
93- authors. truncate ( n) ;
94-
95- let authors: Vec < ( String , Option < String > , usize , usize ) > = authors
96- . into_iter ( )
97- . map ( |( author_email, author_nbr_of_commits) | {
98- (
99- author_name_by_email. get ( & author_email) . unwrap ( ) . trim_matches ( '\'' ) . to_string ( ) ,
100- show_email. then ( || author_email) ,
101- author_nbr_of_commits,
102- ( author_nbr_of_commits as f32 * 100. / total_nbr_of_commits as f32 ) . round ( )
103- as usize ,
104- )
105- } )
106- . collect ( ) ;
107-
108- authors
105+ let mut authors_sorted_by_number_of_commits: Vec < ( Sig , usize ) > =
106+ author_to_number_of_commits. into_iter ( ) . collect ( ) ;
107+
108+ authors_sorted_by_number_of_commits
109+ . sort_by ( |( _, a_count) , ( _, b_count) | b_count. cmp ( a_count) ) ;
110+
111+ authors_sorted_by_number_of_commits. truncate ( number_of_author) ;
112+
113+ let result: Vec < ( String , Option < String > , usize , usize ) > =
114+ authors_sorted_by_number_of_commits
115+ . into_iter ( )
116+ . map ( |( author, author_nbr_of_commits) | {
117+ (
118+ author. name . clone ( ) ,
119+ show_email. then ( || author. email ) ,
120+ author_nbr_of_commits,
121+ ( author_nbr_of_commits as f32 * 100. / total_nbr_of_commits as f32 ) . round ( )
122+ as usize ,
123+ )
124+ } )
125+ . collect ( ) ;
126+
127+ Ok ( result)
109128 }
110129
111130 pub fn get_date_of_last_commit ( & self , iso_time : bool ) -> String {
0 commit comments