diff --git a/Cargo.lock b/Cargo.lock index 4ab7db8f05..3351098f8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1860,6 +1860,7 @@ dependencies = [ "git-url", "itertools", "jwalk", + "mime_guess", "num_cpus", "serde", "serde_json", @@ -2199,6 +2200,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "minimal-lexical" version = "0.2.1" diff --git a/gitoxide-core/Cargo.toml b/gitoxide-core/Cargo.toml index 046f72a76b..44f9c90ba8 100644 --- a/gitoxide-core/Cargo.toml +++ b/gitoxide-core/Cargo.toml @@ -18,7 +18,7 @@ default = [] ## Discover all git repositories within a directory. Particularly useful with [skim](https://github.com/lotabout/skim). organize = ["git-url", "jwalk"] ## Derive the amount of time invested into a git repository akin to [git-hours](https://github.com/kimmobrunfeldt/git-hours). -estimate-hours = ["itertools", "fs-err", "num_cpus", "crossbeam-channel"] +estimate-hours = ["itertools", "fs-err", "num_cpus", "crossbeam-channel", "mime_guess"] #! ### Mutually Exclusive Networking #! If both are set, _blocking-client_ will take precedence, allowing `--all-features` to be used. @@ -64,6 +64,7 @@ itertools = { version = "0.10.1", optional = true } fs-err = { version = "2.6.0", optional = true } num_cpus = { version = "1.13.1", optional = true } crossbeam-channel = { version = "0.5.6", optional = true } +mime_guess = { version = "2.0.4", optional = true } document-features = { version = "0.2.0", optional = true } diff --git a/gitoxide-core/src/hours.rs b/gitoxide-core/src/hours.rs index c678f548a2..c11b621768 100644 --- a/gitoxide-core/src/hours.rs +++ b/gitoxide-core/src/hours.rs @@ -171,7 +171,7 @@ where Some(c) => c, None => continue, }; - from.changes().for_each_to_obtain_tree(&to, |change| { + from.changes().track_filename().for_each_to_obtain_tree(&to, |change| { use git::object::tree::diff::change::Event::*; if let Some(c) = change_counter.as_ref() { c.fetch_add(1, Ordering::SeqCst); @@ -205,29 +205,37 @@ where if entry_mode.is_no_tree() { files.modified += 1; } - if let Some(Ok(diff)) = - line_stats.then(|| change.event.diff()).flatten() - { - use git::diff::lines::similar::ChangeTag::*; - let mut nl = 0; - for change in diff - .text(git::diff::lines::Algorithm::Myers) - .iter_all_changes() + if line_stats { + let is_text_file = mime_guess::from_path( + git::path::from_bstr(change.location).as_ref(), + ) + .first_or_text_plain() + .type_() + == mime_guess::mime::TEXT; + if let Some(Ok(diff)) = + is_text_file.then(|| change.event.diff()).flatten() { - match change.tag() { - Delete => { - lines.removed += 1; - nl += 1; + use git::diff::lines::similar::ChangeTag::*; + let mut nl = 0; + for change in diff + .text(git::diff::lines::Algorithm::Myers) + .iter_all_changes() + { + match change.tag() { + Delete => { + lines.removed += 1; + nl += 1; + } + Insert => { + lines.added += 1; + nl += 1 + } + Equal => {} } - Insert => { - lines.added += 1; - nl += 1 - } - Equal => {} } - } - if let Some(c) = lines_counter.as_ref() { - c.fetch_add(nl, Ordering::SeqCst); + if let Some(c) = lines_counter.as_ref() { + c.fetch_add(nl, Ordering::SeqCst); + } } } }