@@ -4,13 +4,28 @@ use git2::{
4
4
StatusShow ,
5
5
} ;
6
6
use regex:: Regex ;
7
+ use std:: collections:: HashMap ;
7
8
use std:: path:: Path ;
8
9
9
10
pub struct Repo < ' a > {
10
11
repo : & ' a Repository ,
11
12
logs : Vec < Commit < ' a > > ,
12
13
}
13
14
15
+ #[ derive( Hash , PartialEq , Eq ) ]
16
+ pub struct Sig {
17
+ name : String ,
18
+ email : String ,
19
+ }
20
+
21
+ impl From < Signature < ' _ > > for Sig {
22
+ fn from ( sig : Signature ) -> Self {
23
+ let name = String :: from_utf8_lossy ( sig. name_bytes ( ) ) . into_owned ( ) ;
24
+ let email = String :: from_utf8_lossy ( sig. email_bytes ( ) ) . into_owned ( ) ;
25
+ Self { name, email }
26
+ }
27
+ }
28
+
14
29
impl < ' a > Repo < ' a > {
15
30
pub fn new (
16
31
repo : & ' a Repository ,
@@ -65,43 +80,43 @@ impl<'a> Repo<'a> {
65
80
66
81
pub fn get_authors (
67
82
& self ,
68
- n : usize ,
83
+ number_of_author : usize ,
69
84
show_email : bool ,
70
85
) -> Result < Vec < ( String , Option < String > , usize , usize ) > > {
71
- let mut authors = std:: collections:: HashMap :: new ( ) ;
72
- let mut author_name_by_email = std:: collections:: HashMap :: new ( ) ;
86
+ let mut author_to_number_of_commits: HashMap < Sig , usize > = HashMap :: new ( ) ;
73
87
let mut total_nbr_of_commits = 0 ;
74
88
let mailmap = self . repo . mailmap ( ) ?;
75
89
for commit in & self . logs {
76
90
let author = commit. author_with_mailmap ( & mailmap) ?;
77
- let author_name = String :: from_utf8_lossy ( author. name_bytes ( ) ) . into_owned ( ) ;
78
- let author_email = String :: from_utf8_lossy ( author. email_bytes ( ) ) . into_owned ( ) ;
79
-
80
- let author_nbr_of_commits = authors. entry ( author_email. to_string ( ) ) . or_insert ( 0 ) ;
81
- author_name_by_email. entry ( author_email. to_string ( ) ) . or_insert ( author_name) ;
91
+ let author_nbr_of_commits =
92
+ author_to_number_of_commits. entry ( Sig :: from ( author) ) . or_insert ( 0 ) ;
82
93
* author_nbr_of_commits += 1 ;
83
94
total_nbr_of_commits += 1 ;
84
95
}
85
96
86
- let mut authors: Vec < ( String , usize ) > = authors. into_iter ( ) . collect ( ) ;
87
- authors. sort_by ( |( _, a_count) , ( _, b_count) | b_count. cmp ( a_count) ) ;
88
-
89
- authors. truncate ( n) ;
90
-
91
- let authors: Vec < ( String , Option < String > , usize , usize ) > = authors
92
- . into_iter ( )
93
- . map ( |( author_email, author_nbr_of_commits) | {
94
- (
95
- author_name_by_email. get ( & author_email) . unwrap ( ) . trim_matches ( '\'' ) . to_string ( ) ,
96
- show_email. then ( || author_email) ,
97
- author_nbr_of_commits,
98
- ( author_nbr_of_commits as f32 * 100. / total_nbr_of_commits as f32 ) . round ( )
99
- as usize ,
100
- )
101
- } )
102
- . collect ( ) ;
103
-
104
- Ok ( authors)
97
+ let mut authors_sorted_by_number_of_commits: Vec < ( Sig , usize ) > =
98
+ author_to_number_of_commits. into_iter ( ) . collect ( ) ;
99
+
100
+ authors_sorted_by_number_of_commits
101
+ . sort_by ( |( _, a_count) , ( _, b_count) | b_count. cmp ( a_count) ) ;
102
+
103
+ authors_sorted_by_number_of_commits. truncate ( number_of_author) ;
104
+
105
+ let result: Vec < ( String , Option < String > , usize , usize ) > =
106
+ authors_sorted_by_number_of_commits
107
+ . into_iter ( )
108
+ . map ( |( author, author_nbr_of_commits) | {
109
+ (
110
+ author. name . clone ( ) ,
111
+ show_email. then ( || author. email ) ,
112
+ author_nbr_of_commits,
113
+ ( author_nbr_of_commits as f32 * 100. / total_nbr_of_commits as f32 ) . round ( )
114
+ as usize ,
115
+ )
116
+ } )
117
+ . collect ( ) ;
118
+
119
+ Ok ( result)
105
120
}
106
121
107
122
pub fn get_date_of_last_commit ( & self , iso_time : bool ) -> String {
0 commit comments