Skip to content

Commit f1905dc

Browse files
authored
Refactoring git metrics module (#1217)
* refacot * add break line
1 parent 621da73 commit f1905dc

File tree

11 files changed

+284
-248
lines changed

11 files changed

+284
-248
lines changed

src/info/authors.rs

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use super::git::metrics::GitMetrics;
1+
use super::git::sig::Sig;
22
use crate::{
33
cli::NumberSeparator,
44
info::utils::{format_number, info_field::InfoField},
55
};
66
use serde::Serialize;
7-
use std::fmt::Write;
7+
use std::{collections::HashMap, fmt::Write};
88

99
#[derive(Serialize, Clone, Debug, PartialEq)]
1010
#[serde(rename_all = "camelCase")]
@@ -66,8 +66,20 @@ pub struct AuthorsInfo {
6666
}
6767

6868
impl AuthorsInfo {
69-
pub fn new(git_metrics: &GitMetrics) -> Self {
70-
let authors = git_metrics.authors_to_display.clone();
69+
pub fn new(
70+
number_of_commits_by_signature: &HashMap<Sig, usize>,
71+
total_number_of_commits: usize,
72+
number_of_authors_to_display: usize,
73+
show_email: bool,
74+
number_separator: NumberSeparator,
75+
) -> Self {
76+
let authors = compute_authors(
77+
number_of_commits_by_signature,
78+
total_number_of_commits,
79+
number_of_authors_to_display,
80+
show_email,
81+
number_separator,
82+
);
7183
Self { authors }
7284
}
7385

@@ -79,6 +91,40 @@ impl AuthorsInfo {
7991
}
8092
}
8193

94+
fn compute_authors(
95+
number_of_commits_by_signature: &HashMap<Sig, usize>,
96+
total_number_of_commits: usize,
97+
number_of_authors_to_display: usize,
98+
show_email: bool,
99+
number_separator: NumberSeparator,
100+
) -> Vec<Author> {
101+
let mut signature_with_number_of_commits_sorted: Vec<(&Sig, &usize)> =
102+
Vec::from_iter(number_of_commits_by_signature);
103+
104+
signature_with_number_of_commits_sorted.sort_by(|(sa, a_count), (sb, b_count)| {
105+
b_count.cmp(a_count).then_with(|| sa.name.cmp(&sb.name))
106+
});
107+
108+
let authors: Vec<Author> = signature_with_number_of_commits_sorted
109+
.into_iter()
110+
.map(|(author, author_nbr_of_commits)| {
111+
Author::new(
112+
author.name.to_string(),
113+
if show_email {
114+
Some(author.email.to_string())
115+
} else {
116+
None
117+
},
118+
*author_nbr_of_commits,
119+
total_number_of_commits,
120+
number_separator,
121+
)
122+
})
123+
.take(number_of_authors_to_display)
124+
.collect();
125+
authors
126+
}
127+
82128
fn digit_difference(num1: usize, num2: usize) -> usize {
83129
let count_digits = |num: usize| (num.checked_ilog10().unwrap_or(0) + 1) as usize;
84130
count_digits(num1).abs_diff(count_digits(num2))
@@ -285,4 +331,48 @@ mod test {
285331
let result = digit_difference(num1, num2);
286332
assert_eq!(result, expected);
287333
}
334+
335+
#[test]
336+
fn test_compute_authors() {
337+
let mut number_of_commits_by_signature: HashMap<Sig, usize> = HashMap::new();
338+
number_of_commits_by_signature.insert(
339+
Sig {
340+
name: "John Doe".into(),
341+
email: "[email protected]".into(),
342+
},
343+
30,
344+
);
345+
number_of_commits_by_signature.insert(
346+
Sig {
347+
name: "Jane Doe".into(),
348+
email: "[email protected]".into(),
349+
},
350+
20,
351+
);
352+
number_of_commits_by_signature.insert(
353+
Sig {
354+
name: "Ellen Smith".into(),
355+
email: "[email protected]".into(),
356+
},
357+
50,
358+
);
359+
let total_number_of_commits = 100;
360+
let number_of_authors_to_display = 2;
361+
let show_email = false;
362+
let number_separator = NumberSeparator::Comma;
363+
364+
let actual = compute_authors(
365+
&number_of_commits_by_signature,
366+
total_number_of_commits,
367+
number_of_authors_to_display,
368+
show_email,
369+
number_separator,
370+
);
371+
372+
let expected = vec![
373+
Author::new(String::from("Ellen Smith"), None, 50, 100, number_separator),
374+
Author::new(String::from("John Doe"), None, 30, 100, number_separator),
375+
];
376+
assert_eq!(actual, expected);
377+
}
288378
}

src/info/churn.rs

Lines changed: 88 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
use super::{git::metrics::GitMetrics, utils::info_field::InfoField};
1+
use super::utils::info_field::InfoField;
22
use crate::{cli::NumberSeparator, info::utils::format_number};
3+
use anyhow::Result;
4+
use gix::bstr::BString;
5+
use globset::{Glob, GlobSetBuilder};
36
use serde::Serialize;
4-
use std::fmt::Write;
7+
use std::{collections::HashMap, fmt::Write};
58

69
#[derive(Serialize, Clone, Debug, PartialEq)]
710
#[serde(rename_all = "camelCase")]
@@ -42,15 +45,62 @@ pub struct ChurnInfo {
4245
pub file_churns: Vec<FileChurn>,
4346
pub churn_pool_size: usize,
4447
}
48+
4549
impl ChurnInfo {
46-
pub fn new(git_metrics: &GitMetrics) -> Self {
47-
let file_churns = git_metrics.file_churns_to_display.clone();
48-
Self {
50+
pub fn new(
51+
number_of_commits_by_file_path: &HashMap<BString, usize>,
52+
churn_pool_size: usize,
53+
number_of_file_churns_to_display: usize,
54+
globs_to_exclude: &[String],
55+
number_separator: NumberSeparator,
56+
) -> Result<Self> {
57+
let file_churns = compute_file_churns(
58+
number_of_commits_by_file_path,
59+
number_of_file_churns_to_display,
60+
globs_to_exclude,
61+
number_separator,
62+
)?;
63+
64+
Ok(Self {
4965
file_churns,
50-
churn_pool_size: git_metrics.churn_pool_size,
51-
}
66+
churn_pool_size,
67+
})
68+
}
69+
}
70+
71+
fn compute_file_churns(
72+
number_of_commits_by_file_path: &HashMap<BString, usize>,
73+
number_of_file_churns_to_display: usize,
74+
globs_to_exclude: &[String],
75+
number_separator: NumberSeparator,
76+
) -> Result<Vec<FileChurn>> {
77+
let mut builder = GlobSetBuilder::new();
78+
for glob in globs_to_exclude {
79+
builder.add(Glob::new(glob)?);
5280
}
81+
let glob_set = builder.build()?;
82+
let mut number_of_commits_by_file_path_sorted = Vec::from_iter(number_of_commits_by_file_path);
83+
84+
number_of_commits_by_file_path_sorted
85+
.sort_by(|(_, a_count), (_, b_count)| b_count.cmp(a_count));
86+
87+
Ok(number_of_commits_by_file_path_sorted
88+
.into_iter()
89+
.filter_map(|(file_path, nbr_of_commits)| {
90+
if !glob_set.is_match(file_path.to_string()) {
91+
Some(FileChurn::new(
92+
file_path.to_string(),
93+
*nbr_of_commits,
94+
number_separator,
95+
))
96+
} else {
97+
None
98+
}
99+
})
100+
.take(number_of_file_churns_to_display)
101+
.collect())
53102
}
103+
54104
impl std::fmt::Display for ChurnInfo {
55105
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
56106
let mut churn_info = String::new();
@@ -139,4 +189,35 @@ mod tests {
139189
);
140190
assert_eq!(shorten_file_path("file.txt", 0), "file.txt");
141191
}
192+
193+
#[test]
194+
fn test_compute_file_churns() -> Result<()> {
195+
let mut number_of_commits_by_file_path = HashMap::new();
196+
number_of_commits_by_file_path.insert("path/to/file1.txt".into(), 2);
197+
number_of_commits_by_file_path.insert("path/to/file2.txt".into(), 5);
198+
number_of_commits_by_file_path.insert("path/to/file3.txt".into(), 3);
199+
number_of_commits_by_file_path.insert("path/to/file4.txt".into(), 7);
200+
number_of_commits_by_file_path.insert("foo/x/y/file.txt".into(), 70);
201+
number_of_commits_by_file_path.insert("foo/x/file.txt".into(), 10);
202+
203+
let number_of_file_churns_to_display = 3;
204+
let number_separator = NumberSeparator::Comma;
205+
let globs_to_exclude = vec![
206+
"foo/**/file.txt".to_string(),
207+
"path/to/file2.txt".to_string(),
208+
];
209+
let actual = compute_file_churns(
210+
&number_of_commits_by_file_path,
211+
number_of_file_churns_to_display,
212+
&globs_to_exclude,
213+
number_separator,
214+
)?;
215+
let expected = vec![
216+
FileChurn::new(String::from("path/to/file4.txt"), 7, number_separator),
217+
FileChurn::new(String::from("path/to/file3.txt"), 3, number_separator),
218+
FileChurn::new(String::from("path/to/file1.txt"), 2, number_separator),
219+
];
220+
assert_eq!(actual, expected);
221+
Ok(())
222+
}
142223
}

src/info/contributors.rs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{git::metrics::GitMetrics, utils::format_number};
1+
use super::utils::format_number;
22
use crate::{cli::NumberSeparator, info::utils::info_field::InfoField};
33
use serde::Serialize;
44

@@ -14,12 +14,12 @@ pub struct ContributorsInfo {
1414

1515
impl ContributorsInfo {
1616
pub fn new(
17-
git_metrics: &GitMetrics,
17+
total_number_of_authors: usize,
1818
number_of_authors_to_display: usize,
1919
number_separator: NumberSeparator,
2020
) -> Self {
2121
Self {
22-
total_number_of_authors: git_metrics.total_number_of_authors,
22+
total_number_of_authors,
2323
number_of_authors_to_display,
2424
number_separator,
2525
}
@@ -44,22 +44,10 @@ impl InfoField for ContributorsInfo {
4444
#[cfg(test)]
4545
mod test {
4646
use super::*;
47-
use gix::date::Time;
4847

4948
#[test]
5049
fn test_display_contributors_info() {
51-
let timestamp = Time::now_utc();
52-
let git_metrics = GitMetrics {
53-
authors_to_display: vec![],
54-
file_churns_to_display: vec![],
55-
total_number_of_authors: 12,
56-
total_number_of_commits: 2,
57-
churn_pool_size: 0,
58-
time_of_most_recent_commit: timestamp,
59-
time_of_first_commit: timestamp,
60-
};
61-
62-
let contributors_info = ContributorsInfo::new(&git_metrics, 2, NumberSeparator::Plain);
50+
let contributors_info = ContributorsInfo::new(12, 2, NumberSeparator::Plain);
6351
assert_eq!(contributors_info.value(), "12".to_string());
6452
assert_eq!(contributors_info.title(), "Contributors".to_string());
6553
}

0 commit comments

Comments
 (0)