Skip to content

Commit 8df0d19

Browse files
committed
obtain all but author information on the fly
1 parent e3b29b0 commit 8df0d19

File tree

2 files changed

+54
-50
lines changed

2 files changed

+54
-50
lines changed

src/info/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,11 @@ impl Info {
167167
let git_username = internal_repo.get_git_username()?;
168168
let number_of_tags = internal_repo.get_number_of_tags()?;
169169
let number_of_branches = internal_repo.get_number_of_branches()?;
170-
let creation_date = internal_repo.get_creation_date(config.iso_time)?;
170+
let creation_date = internal_repo.get_creation_date(config.iso_time);
171171
let number_of_commits = internal_repo.get_number_of_commits();
172172
let (authors, contributors) =
173173
internal_repo.get_authors(config.number_of_authors, config.show_email)?;
174-
let last_change = internal_repo.get_date_of_last_commit(config.iso_time)?;
174+
let last_change = internal_repo.get_date_of_last_commit(config.iso_time);
175175
let (repo_size, file_count) = internal_repo.get_repo_size();
176176
let workdir = internal_repo.get_work_dir()?;
177177
let license = Detector::new()?.get_license(&workdir)?;

src/info/repo.rs

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ pub struct Repo<'a> {
1919
git2_repo: &'a Repository,
2020
repo: git::Repository,
2121
commits: Vec<git::DetachedObject>,
22+
num_commits: usize,
23+
time_of_most_recent_commit: git::actor::Time,
24+
time_of_first_commit: git::actor::Time,
2225
}
2326

2427
#[derive(Hash, PartialEq, Eq)]
@@ -51,64 +54,74 @@ impl<'a> Repo<'a> {
5154
bot_regex_pattern: &Option<Regex>,
5255
) -> Result<Self> {
5356
let mut repo = git::open(git2_repo.path())?;
54-
let logs = Self::get_logs(&mut repo, no_merges, bot_regex_pattern)?;
57+
let (logs, num_commits, time_of_first_commit, time_of_most_recent_commit) =
58+
Self::extract_commit_infos(&mut repo, no_merges, bot_regex_pattern)?;
5559
Ok(Self {
5660
git2_repo,
5761
repo,
5862
commits: logs,
63+
num_commits,
64+
time_of_first_commit,
65+
time_of_most_recent_commit,
5966
})
6067
}
6168

6269
// TODO: avoid allocating/copying buffers. Instead gather the desired information
6370
// during traversal and keep only author names for processing.
64-
fn get_logs(
71+
fn extract_commit_infos(
6572
repo: &mut git::Repository,
6673
no_merges: bool,
6774
bot_regex_pattern: &Option<Regex>,
68-
) -> Result<Vec<git::DetachedObject>> {
75+
) -> Result<(
76+
Vec<git::DetachedObject>,
77+
usize,
78+
git::actor::Time,
79+
git::actor::Time,
80+
)> {
6981
// assure that objects we just traversed are coming from cache
7082
// when we read the commit right after.
7183
repo.object_cache_size(128 * 1024);
72-
let commits = repo
73-
.head()?
74-
.peel_to_commit_in_place()?
75-
.ancestors()
76-
.all()
77-
.filter_map(|commit_id| {
78-
let commit: git::Commit = commit_id
79-
.ok()?
80-
.object()
81-
.expect("commit is still present/comes from cache")
82-
.into_commit();
83-
if no_merges && commit.parent_ids().take(2).count() > 1 {
84-
return None;
85-
}
86-
if is_bot(commit.iter().author(), bot_regex_pattern) {
87-
return None;
88-
}
89-
commit.detach().into()
90-
})
91-
.collect();
92-
Ok(commits)
93-
}
84+
let mut commits = Vec::new();
85+
86+
let mut most_recent_commit_time = None;
87+
let mut first_commit_time = None;
88+
let mut ancestors = repo.head()?.peel_to_commit_in_place()?.ancestors();
89+
let mut commit_iter = ancestors.all().peekable();
90+
91+
while let Some(commit_id) = commit_iter.next() {
92+
let commit: git::Commit = commit_id?
93+
.object()
94+
.expect("commit is still present/comes from cache")
95+
.into_commit();
96+
if no_merges && commit.parent_ids().take(2).count() > 1 {
97+
continue;
98+
}
99+
if is_bot(commit.iter().author(), bot_regex_pattern) {
100+
continue;
101+
}
94102

95-
pub fn get_creation_date(&self, iso_time: bool) -> Result<String> {
96-
let first_commit = self.commits.last();
97-
let output = match first_commit {
98-
Some(commit) => {
99-
// TODO: no clone
100-
let commit: git::Commit = commit.clone().attach(&self.repo).into_commit();
101-
gitoxide_time_to_formatted_time(commit.time()?, iso_time)
103+
most_recent_commit_time.get_or_insert_with(|| commit.time());
104+
if commit_iter.peek().is_none() {
105+
first_commit_time = commit.time()?.into();
102106
}
103-
None => "".into(),
104-
};
107+
commits.push(commit.detach().into());
108+
}
109+
110+
let num_commits = commits.len();
111+
Ok((
112+
commits,
113+
num_commits,
114+
first_commit_time.expect("at least one commit"),
115+
most_recent_commit_time.expect("at least one commit")?,
116+
))
117+
}
105118

106-
Ok(output)
119+
pub fn get_creation_date(&self, iso_time: bool) -> String {
120+
gitoxide_time_to_formatted_time(self.time_of_first_commit, iso_time)
107121
}
108122

109123
pub fn get_number_of_commits(&self) -> String {
110-
let number_of_commits = self.commits.len();
111-
number_of_commits.to_string()
124+
self.num_commits.to_string()
112125
}
113126

114127
pub fn get_authors(
@@ -158,17 +171,8 @@ impl<'a> Repo<'a> {
158171
Ok((authors, number_of_authors))
159172
}
160173

161-
pub fn get_date_of_last_commit(&self, iso_time: bool) -> Result<String> {
162-
let last_commit = self.commits.first();
163-
164-
Ok(match last_commit {
165-
Some(commit) => {
166-
// TODO: no clone
167-
let commit = commit.clone().attach(&self.repo).into_commit();
168-
gitoxide_time_to_formatted_time(commit.time()?, iso_time)
169-
}
170-
None => "".into(),
171-
})
174+
pub fn get_date_of_last_commit(&self, iso_time: bool) -> String {
175+
gitoxide_time_to_formatted_time(self.time_of_most_recent_commit, iso_time)
172176
}
173177

174178
// This collects the repo size excluding .git

0 commit comments

Comments
 (0)