@@ -15,8 +15,8 @@ use time_humanize::HumanTime;
1515
1616pub struct Repo < ' a > {
1717 git2_repo : & ' a Repository ,
18- repo : git :: Repository ,
19- commits : Vec < git :: DetachedObject > ,
18+ authors : Vec < Author > ,
19+ total_num_authors : usize ,
2020 num_commits : usize ,
2121 time_of_most_recent_commit : git:: actor:: Time ,
2222 time_of_first_commit : git:: actor:: Time ,
@@ -41,12 +41,17 @@ impl<'a> Repo<'a> {
4141 bot_regex_pattern : & Option < Regex > ,
4242 ) -> Result < Self > {
4343 let mut repo = git:: open ( git2_repo. path ( ) ) ?;
44- let ( logs, num_commits, time_of_first_commit, time_of_most_recent_commit) =
45- Self :: extract_commit_infos ( & mut repo, no_merges, bot_regex_pattern) ?;
44+ let (
45+ authors,
46+ total_num_authors,
47+ num_commits,
48+ time_of_first_commit,
49+ time_of_most_recent_commit,
50+ ) = Self :: extract_commit_infos ( & mut repo, no_merges, bot_regex_pattern) ?;
4651 Ok ( Self {
4752 git2_repo,
48- repo ,
49- commits : logs ,
53+ authors ,
54+ total_num_authors ,
5055 num_commits,
5156 time_of_first_commit,
5257 time_of_most_recent_commit,
@@ -60,76 +65,53 @@ impl<'a> Repo<'a> {
6065 no_merges : bool ,
6166 bot_regex_pattern : & Option < Regex > ,
6267 ) -> Result < (
63- Vec < git:: DetachedObject > ,
68+ Vec < Author > ,
69+ usize ,
6470 usize ,
6571 git:: actor:: Time ,
6672 git:: actor:: Time ,
6773 ) > {
6874 // assure that objects we just traversed are coming from cache
6975 // when we read the commit right after.
7076 repo. object_cache_size ( 128 * 1024 ) ;
71- let mut commits = Vec :: new ( ) ;
7277
7378 let mut most_recent_commit_time = None ;
7479 let mut first_commit_time = None ;
7580 let mut ancestors = repo. head ( ) ?. peel_to_commit_in_place ( ) ?. ancestors ( ) ;
7681 let mut commit_iter = ancestors. all ( ) . peekable ( ) ;
7782
83+ let mailmap = repo. load_mailmap ( ) ;
84+ let mut author_to_number_of_commits: HashMap < Sig , usize > = HashMap :: new ( ) ;
85+ let mut total_nbr_of_commits = 0 ;
86+
87+ let mut num_commits = 0 ;
7888 while let Some ( commit_id) = commit_iter. next ( ) {
7989 let commit: git:: Commit = commit_id?
8090 . object ( )
8191 . expect ( "commit is still present/comes from cache" )
8292 . into_commit ( ) ;
83- if no_merges && commit. parent_ids ( ) . take ( 2 ) . count ( ) > 1 {
84- continue ;
85- }
86- if is_bot ( commit. iter ( ) . author ( ) , bot_regex_pattern) {
87- continue ;
88- }
89-
90- most_recent_commit_time. get_or_insert_with ( || commit. time ( ) ) ;
91- if commit_iter. peek ( ) . is_none ( ) {
92- first_commit_time = commit. time ( ) ?. into ( ) ;
93- }
94- commits. push ( commit. detach ( ) . into ( ) ) ;
95- }
96-
97- let num_commits = commits. len ( ) ;
98- Ok ( (
99- commits,
100- num_commits,
101- first_commit_time. expect ( "at least one commit" ) ,
102- most_recent_commit_time. expect ( "at least one commit" ) ?,
103- ) )
104- }
93+ num_commits += 1 ;
94+ {
95+ let commit = commit. decode ( ) ?;
96+ if no_merges && commit. parents ( ) . take ( 2 ) . count ( ) > 1 {
97+ continue ;
98+ }
10599
106- pub fn get_creation_date ( & self , iso_time : bool ) -> String {
107- gitoxide_time_to_formatted_time ( self . time_of_first_commit , iso_time )
108- }
100+ if is_bot ( commit . author , bot_regex_pattern ) {
101+ continue ;
102+ }
109103
110- pub fn get_number_of_commits ( & self ) -> String {
111- self . num_commits . to_string ( )
112- }
104+ let author_nbr_of_commits = author_to_number_of_commits
105+ . entry ( Sig :: from ( mailmap. resolve ( commit. author ) ) )
106+ . or_insert ( 0 ) ;
107+ * author_nbr_of_commits += 1 ;
108+ total_nbr_of_commits += 1 ;
113109
114- pub fn get_authors (
115- & self ,
116- number_of_authors_to_display : usize ,
117- show_email : bool ,
118- ) -> Result < ( Vec < Author > , usize ) > {
119- let mut author_to_number_of_commits: HashMap < Sig , usize > = HashMap :: new ( ) ;
120- let mut total_nbr_of_commits = 0 ;
121- let mailmap = self . repo . load_mailmap ( ) ;
122- for commit in & self . commits {
123- let mut commit = git:: objs:: CommitRefIter :: from_bytes ( & commit. data ) ;
124- let author = match commit. author ( ) {
125- Some ( author) => mailmap. resolve ( & author) ,
126- None => continue ,
127- } ;
128- let author_nbr_of_commits = author_to_number_of_commits
129- . entry ( Sig :: from ( author) )
130- . or_insert ( 0 ) ;
131- * author_nbr_of_commits += 1 ;
132- total_nbr_of_commits += 1 ;
110+ most_recent_commit_time. get_or_insert_with ( || commit. committer . time ) ;
111+ if commit_iter. peek ( ) . is_none ( ) {
112+ first_commit_time = commit. committer . time . into ( ) ;
113+ }
114+ }
133115 }
134116
135117 let mut authors_by_number_of_commits: Vec < ( Sig , usize ) > =
@@ -139,24 +121,51 @@ impl<'a> Repo<'a> {
139121
140122 authors_by_number_of_commits. sort_by ( |( _, a_count) , ( _, b_count) | b_count. cmp ( a_count) ) ;
141123
142- if number_of_authors > number_of_authors_to_display {
143- authors_by_number_of_commits. truncate ( number_of_authors_to_display) ;
144- }
145-
146124 let authors: Vec < Author > = authors_by_number_of_commits
147125 . into_iter ( )
148126 . map ( |( author, author_nbr_of_commits) | {
149127 let email = author. email ;
150128 Author :: new (
151129 author. name ,
152- show_email . then ( || email ) ,
130+ email . into ( ) ,
153131 author_nbr_of_commits,
154132 total_nbr_of_commits,
155133 )
156134 } )
157135 . collect ( ) ;
158136
159- Ok ( ( authors, number_of_authors) )
137+ Ok ( (
138+ authors,
139+ number_of_authors,
140+ num_commits,
141+ first_commit_time. expect ( "at least one commit" ) ,
142+ most_recent_commit_time. expect ( "at least one commit" ) ,
143+ ) )
144+ }
145+
146+ pub fn get_creation_date ( & self , iso_time : bool ) -> String {
147+ gitoxide_time_to_formatted_time ( self . time_of_first_commit , iso_time)
148+ }
149+
150+ pub fn get_number_of_commits ( & self ) -> String {
151+ self . num_commits . to_string ( )
152+ }
153+
154+ pub fn take_authors (
155+ & mut self ,
156+ number_of_authors_to_display : usize ,
157+ show_email : bool ,
158+ ) -> ( Vec < Author > , usize ) {
159+ if self . total_num_authors > number_of_authors_to_display {
160+ self . authors . truncate ( number_of_authors_to_display) ;
161+ }
162+
163+ if !show_email {
164+ for author in & mut self . authors {
165+ author. clear_email ( ) ;
166+ }
167+ }
168+ ( std:: mem:: take ( & mut self . authors ) , self . total_num_authors )
160169 }
161170
162171 pub fn get_date_of_last_commit ( & self , iso_time : bool ) -> String {
@@ -351,13 +360,10 @@ impl<'a> Repo<'a> {
351360 }
352361}
353362
354- fn is_bot ( author : Option < git:: actor:: SignatureRef < ' _ > > , bot_regex_pattern : & Option < Regex > ) -> bool {
355- author
356- . and_then ( |author| {
357- bot_regex_pattern
358- . as_ref ( )
359- . map ( |regex| regex. is_match ( author. name . to_str_lossy ( ) . as_ref ( ) ) )
360- } )
363+ fn is_bot ( author : git:: actor:: SignatureRef < ' _ > , bot_regex_pattern : & Option < Regex > ) -> bool {
364+ bot_regex_pattern
365+ . as_ref ( )
366+ . map ( |regex| regex. is_match ( author. name . to_str_lossy ( ) . as_ref ( ) ) )
361367 . unwrap_or ( false )
362368}
363369
0 commit comments