@@ -15,8 +15,8 @@ use time_humanize::HumanTime;
15
15
16
16
pub struct Repo < ' a > {
17
17
git2_repo : & ' a Repository ,
18
- repo : git :: Repository ,
19
- commits : Vec < git :: DetachedObject > ,
18
+ authors : Vec < Author > ,
19
+ total_num_authors : usize ,
20
20
num_commits : usize ,
21
21
time_of_most_recent_commit : git:: actor:: Time ,
22
22
time_of_first_commit : git:: actor:: Time ,
@@ -41,12 +41,17 @@ impl<'a> Repo<'a> {
41
41
bot_regex_pattern : & Option < Regex > ,
42
42
) -> Result < Self > {
43
43
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) ?;
46
51
Ok ( Self {
47
52
git2_repo,
48
- repo ,
49
- commits : logs ,
53
+ authors ,
54
+ total_num_authors ,
50
55
num_commits,
51
56
time_of_first_commit,
52
57
time_of_most_recent_commit,
@@ -60,76 +65,53 @@ impl<'a> Repo<'a> {
60
65
no_merges : bool ,
61
66
bot_regex_pattern : & Option < Regex > ,
62
67
) -> Result < (
63
- Vec < git:: DetachedObject > ,
68
+ Vec < Author > ,
69
+ usize ,
64
70
usize ,
65
71
git:: actor:: Time ,
66
72
git:: actor:: Time ,
67
73
) > {
68
74
// assure that objects we just traversed are coming from cache
69
75
// when we read the commit right after.
70
76
repo. object_cache_size ( 128 * 1024 ) ;
71
- let mut commits = Vec :: new ( ) ;
72
77
73
78
let mut most_recent_commit_time = None ;
74
79
let mut first_commit_time = None ;
75
80
let mut ancestors = repo. head ( ) ?. peel_to_commit_in_place ( ) ?. ancestors ( ) ;
76
81
let mut commit_iter = ancestors. all ( ) . peekable ( ) ;
77
82
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 ;
78
88
while let Some ( commit_id) = commit_iter. next ( ) {
79
89
let commit: git:: Commit = commit_id?
80
90
. object ( )
81
91
. expect ( "commit is still present/comes from cache" )
82
92
. 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
+ }
105
99
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
+ }
109
103
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 ;
113
109
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
+ }
133
115
}
134
116
135
117
let mut authors_by_number_of_commits: Vec < ( Sig , usize ) > =
@@ -139,24 +121,51 @@ impl<'a> Repo<'a> {
139
121
140
122
authors_by_number_of_commits. sort_by ( |( _, a_count) , ( _, b_count) | b_count. cmp ( a_count) ) ;
141
123
142
- if number_of_authors > number_of_authors_to_display {
143
- authors_by_number_of_commits. truncate ( number_of_authors_to_display) ;
144
- }
145
-
146
124
let authors: Vec < Author > = authors_by_number_of_commits
147
125
. into_iter ( )
148
126
. map ( |( author, author_nbr_of_commits) | {
149
127
let email = author. email ;
150
128
Author :: new (
151
129
author. name ,
152
- show_email . then ( || email ) ,
130
+ email . into ( ) ,
153
131
author_nbr_of_commits,
154
132
total_nbr_of_commits,
155
133
)
156
134
} )
157
135
. collect ( ) ;
158
136
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 )
160
169
}
161
170
162
171
pub fn get_date_of_last_commit ( & self , iso_time : bool ) -> String {
@@ -351,13 +360,10 @@ impl<'a> Repo<'a> {
351
360
}
352
361
}
353
362
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 ( ) ) )
361
367
. unwrap_or ( false )
362
368
}
363
369
0 commit comments