Skip to content

Commit cc6f332

Browse files
authoredApr 4, 2022
Merge pull request #635 from Byron/gitoxide-for-traversal
Gitoxide for performance improvements
2 parents a802f89 + b6cd415 commit cc6f332

File tree

11 files changed

+1272
-389
lines changed

11 files changed

+1272
-389
lines changed
 

Diff for: ‎.github/workflows/ci.yml

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ jobs:
4444
- name: Run clippy
4545
run: cargo clippy
4646

47+
- name: Run onefetch
48+
run: cargo run
49+
4750
rustfmt:
4851
name: Rustfmt
4952
runs-on: ubuntu-latest

Diff for: ‎Cargo.lock

+986-147
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: ‎Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,12 @@ section = "utility"
2828
[dependencies]
2929
anyhow = "1.0"
3030
askalono = "0.4.4"
31-
byte-unit = "4.0.14"
31+
byte-unit = "4.0" # to match git-repository's lower requirement, which it needs for MSRV
3232
bytecount = "0.6.2"
3333
clap = {version = "3.1.6", features = ["cargo", "wrap_help"]}
3434
color_quant = "1.1.0"
3535
git2 = {version = "0.14.2", default-features = false}
36+
git-repository = { version = "0.15.0", features = ["max-performance", "unstable", "serde1"] }
3637
image = "0.24.1"
3738
owo-colors = "3.3.0"
3839
regex = "1.5.5"

Diff for: ‎src/info/author.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use git_repository as git;
12
use serde::ser::SerializeStruct;
23
use serde::Serialize;
34

@@ -10,20 +11,24 @@ pub struct Author {
1011

1112
impl Author {
1213
pub fn new(
13-
name: String,
14-
email: Option<String>,
14+
name: git::bstr::BString,
15+
email: Option<git::bstr::BString>,
1516
nbr_of_commits: usize,
1617
total_nbr_of_commits: usize,
1718
) -> Self {
1819
let contribution =
1920
(nbr_of_commits as f32 * 100. / total_nbr_of_commits as f32).round() as usize;
2021
Self {
21-
name,
22-
email,
22+
name: name.to_string(),
23+
email: email.map(|e| e.to_string()),
2324
nbr_of_commits,
2425
contribution,
2526
}
2627
}
28+
29+
pub fn clear_email(&mut self) {
30+
self.email = None;
31+
}
2732
}
2833

2934
impl std::fmt::Display for Author {

Diff for: ‎src/info/deps/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use anyhow::Result;
22
use std::collections::HashMap;
3+
use std::path::Path;
34
use std::{ffi::OsStr, fs};
45

56
pub mod package_manager;
@@ -17,7 +18,7 @@ impl DependencyDetector {
1718
DependencyDetector { package_managers }
1819
}
1920

20-
pub fn get_dependencies(&self, dir: &str) -> Result<String> {
21+
pub fn get_dependencies(&self, dir: &Path) -> Result<String> {
2122
let deps = fs::read_dir(dir)?
2223
.filter_map(std::result::Result::ok)
2324
.map(|entry| entry.path())

Diff for: ‎src/info/head_refs.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,32 @@
1-
use git2::Oid;
21
use serde::ser::SerializeStruct;
32
use serde::Serialize;
43

54
pub struct HeadRefs {
6-
commit: Oid,
5+
short_commit_id: String,
76
refs: Vec<String>,
87
}
98

109
impl HeadRefs {
11-
pub fn new(commit: Oid, refs: Vec<String>) -> HeadRefs {
12-
HeadRefs { commit, refs }
10+
pub fn new(short_commit_id: String, refs: Vec<String>) -> HeadRefs {
11+
HeadRefs {
12+
short_commit_id,
13+
refs,
14+
}
1315
}
1416
}
1517

1618
impl std::fmt::Display for HeadRefs {
1719
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
18-
let short_commit = self.commit.to_string().chars().take(7).collect::<String>();
1920
if !self.refs.is_empty() {
2021
let refs_str = self
2122
.refs
2223
.iter()
2324
.map(|ref_name| ref_name.as_str())
2425
.collect::<Vec<&str>>()
2526
.join(", ");
26-
write!(f, "{} ({})", short_commit, refs_str)
27+
write!(f, "{} ({})", self.short_commit_id, refs_str)
2728
} else {
28-
write!(f, "{}", short_commit)
29+
write!(f, "{}", self.short_commit_id)
2930
}
3031
}
3132
}
@@ -37,10 +38,7 @@ impl Serialize for HeadRefs {
3738
{
3839
let mut state = serializer.serialize_struct("HeadRefs", 2)?;
3940
state.serialize_field("refs", &self.refs)?;
40-
state.serialize_field(
41-
"oid",
42-
&self.commit.to_string().chars().take(7).collect::<String>(),
43-
)?;
41+
state.serialize_field("oid", &self.short_commit_id)?;
4442
state.end()
4543
}
4644
}

Diff for: ‎src/info/langs/language.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ macro_rules! define_colors {
2424
( [ $($bc:ident),+ ] : [ $($c:ident($r:expr, $g:expr, $b:expr)),+ ] ) => { Colors { basic_colors: vec![$(clean_color!($bc)),+], true_colors: Some(vec![$(DynColors::$c($r, $g, $b)),+]) } };
2525
}
2626

27-
#[derive(PartialEq, EnumString, EnumIter, IntoStaticStr)]
27+
#[derive(Clone, PartialEq, EnumString, EnumIter, IntoStaticStr)]
2828
#[strum(serialize_all = "lowercase")]
2929
pub enum LanguageType {
3030
Programming,

Diff for: ‎src/info/langs/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use anyhow::{Context, Result};
22
use language::{Language, LanguageType};
33
use regex::Regex;
44
use std::collections::HashMap;
5+
use std::path::Path;
56
use strum::IntoEnumIterator;
67

78
pub mod language;
@@ -11,7 +12,7 @@ pub fn get_dominant_language(languages_stat_vec: &[(Language, f64)]) -> Language
1112
}
1213

1314
pub fn get_language_statistics(
14-
dir: &str,
15+
dir: &Path,
1516
ignored_directories: &[String],
1617
language_types: &[LanguageType],
1718
include_hidden: bool,
@@ -71,7 +72,7 @@ fn get_total_loc(languages: &tokei::Languages) -> usize {
7172
}
7273

7374
fn get_statistics(
74-
dir: &str,
75+
dir: &Path,
7576
ignored_directories: &[String],
7677
language_types: &[LanguageType],
7778
include_hidden: bool,

Diff for: ‎src/info/license.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use anyhow::{bail, Result};
22
use askalono::{Store, TextData};
3+
use std::path::Path;
34
use std::{ffi::OsStr, fs};
45

56
const LICENSE_FILES: [&str; 3] = ["LICENSE", "LICENCE", "COPYING"];
@@ -24,7 +25,7 @@ impl Detector {
2425
}
2526
}
2627

27-
pub fn get_license(&self, dir: &str) -> Result<String> {
28+
pub fn get_license(&self, dir: &Path) -> Result<String> {
2829
fn is_license_file<S: AsRef<str>>(file_name: S) -> bool {
2930
LICENSE_FILES
3031
.iter()

Diff for: ‎src/info/mod.rs

+55-22
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use crate::cli::{self, Config};
2+
use crate::repo::Commits;
23
use crate::ui::get_ascii_colors;
34
use crate::ui::text_colors::TextColors;
4-
use anyhow::Result;
5+
use anyhow::{Context, Result};
56
use author::Author;
67
use deps::DependencyDetector;
78
use git2::Repository;
@@ -159,29 +160,61 @@ impl Info {
159160
pub fn new(config: Config) -> Result<Self> {
160161
let git_version = cli::get_git_version();
161162
let repo = Repository::discover(&config.repo_path)?;
162-
let internal_repo = Repo::new(&repo, config.no_merges, &config.bot_regex_pattern)?;
163-
let (repo_name, repo_url) = internal_repo.get_name_and_url()?;
164-
let head_refs = internal_repo.get_head_refs()?;
165-
let pending_changes = internal_repo.get_pending_changes()?;
166-
let version = internal_repo.get_version()?;
167-
let git_username = internal_repo.get_git_username()?;
168-
let number_of_tags = internal_repo.get_number_of_tags()?;
169-
let number_of_branches = internal_repo.get_number_of_branches()?;
170-
let creation_date = internal_repo.get_creation_date(config.iso_time)?;
171-
let number_of_commits = internal_repo.get_number_of_commits();
172-
let (authors, contributors) =
173-
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);
175-
let (repo_size, file_count) = internal_repo.get_repo_size();
176-
let workdir = internal_repo.get_work_dir()?;
163+
let workdir = repo.workdir().expect("non-bare repo").to_owned();
164+
165+
let pending_changes = std::thread::spawn({
166+
let git_dir = repo.path().to_owned();
167+
move || {
168+
let repo = git2::Repository::open(git_dir)?;
169+
repo::get_pending_changes(&repo)
170+
}
171+
});
172+
let languages_handle = std::thread::spawn({
173+
let ignored_directories = config.ignored_directories.clone();
174+
let language_types = config.language_types.clone();
175+
let include_hidden = config.include_hidden;
176+
let workdir = workdir.clone();
177+
move || {
178+
langs::get_language_statistics(
179+
&workdir,
180+
&ignored_directories,
181+
&language_types,
182+
include_hidden,
183+
)
184+
}
185+
});
186+
187+
let repo = Repo::new(repo)?;
188+
let mut commits = Commits::new(
189+
repo.gitoxide(),
190+
config.no_merges,
191+
&config.bot_regex_pattern,
192+
config.number_of_authors,
193+
)?;
194+
let (repo_name, repo_url) = repo.get_name_and_url()?;
195+
let head_refs = repo.get_head_refs()?;
196+
let version = repo.get_version()?;
197+
let git_username = repo.get_git_username()?;
198+
let number_of_tags = repo.get_number_of_tags()?;
199+
let number_of_branches = repo.get_number_of_branches()?;
200+
let (repo_size, file_count) = repo.get_repo_size();
177201
let license = Detector::new()?.get_license(&workdir)?;
178202
let dependencies = DependencyDetector::new().get_dependencies(&workdir)?;
179-
let (languages, lines_of_code) = langs::get_language_statistics(
180-
&workdir,
181-
&config.ignored_directories,
182-
&config.language_types,
183-
config.include_hidden,
184-
)?;
203+
204+
let creation_date = commits.get_creation_date(config.iso_time);
205+
let number_of_commits = commits.count();
206+
let (authors, contributors) = commits.take_authors(config.show_email);
207+
let last_change = commits.get_date_of_last_commit(config.iso_time);
208+
209+
let pending_changes = pending_changes
210+
.join()
211+
.ok()
212+
.context("BUG: panic in pending-changes thread")??;
213+
214+
let (languages, lines_of_code) = languages_handle
215+
.join()
216+
.ok()
217+
.context("BUG: panic in language statistics thread")??;
185218
let dominant_language = langs::get_dominant_language(&languages);
186219
let ascii_colors = get_ascii_colors(
187220
&config.ascii_language,

Diff for: ‎src/info/repo.rs

+200-199
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.