From 5d7b5c8258b22fb71adf3f142e794949b703643c Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 29 Mar 2022 17:30:20 +0800 Subject: [PATCH 01/38] Add gitoxide as dependency It's using the latest version from github for now until it's clear what should be published later - gitoxide might change to provide the best possible experience. --- Cargo.lock | 582 +++++++++++++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 3 +- 2 files changed, 571 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 14f29cee9..972b25ff9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -38,6 +47,12 @@ version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" +[[package]] +name = "arc-swap" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5d78ce20460b82d3fa150275ed9d55e21064fc7951177baacf86a145c4a4b1f" + [[package]] name = "arrayvec" version = "0.4.12" @@ -83,6 +98,21 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "backtrace" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide 0.4.4", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.13.0" @@ -124,11 +154,22 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ + "lazy_static", "memchr", + "regex-automata", +] + +[[package]] +name = "btoi" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97c0869a9faa81f8bbf8102371105d6d0a7b79167a04c340b04ab16892246a11" +dependencies = [ + "num-traits", ] [[package]] @@ -145,9 +186,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "byte-unit" -version = "4.0.14" +version = "4.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ebf10dda65f19ff0f42ea15572a359ed60d7fc74fdc984d90310937be0014b" +checksum = "956ffc5b0ec7d7a6949e3f21fd63ba5af4cffdc2ba1e0b7bf62b481458c4ae7f" dependencies = [ "utf8-width", ] @@ -170,6 +211,12 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytesize" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70" + [[package]] name = "cc" version = "1.0.68" @@ -240,6 +287,12 @@ dependencies = [ "textwrap 0.15.0", ] +[[package]] +name = "clru" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "218d6bd3dde8e442a975fa1cd233c0e5fded7596bccfe39f58eca98d22421e0a" + [[package]] name = "color_quant" version = "1.1.0" @@ -310,6 +363,17 @@ dependencies = [ "serde", ] +[[package]] +name = "dashmap" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8858831f7781322e539ea39e72449c46b059638250c14344fec8d0aa6e539c" +dependencies = [ + "cfg-if", + "num_cpus", + "parking_lot 0.12.0", +] + [[package]] name = "deflate" version = "1.0.0" @@ -343,6 +407,15 @@ dependencies = [ "dirs-sys", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs-sys" version = "0.3.6" @@ -407,12 +480,43 @@ dependencies = [ "threadpool", ] +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + [[package]] name = "flate2" version = "1.0.20" @@ -498,6 +602,215 @@ dependencies = [ "weezl", ] +[[package]] +name = "gimli" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" + +[[package]] +name = "git-actor" +version = "0.8.1" +dependencies = [ + "bstr", + "btoi", + "itoa 1.0.1", + "nom", + "quick-error", +] + +[[package]] +name = "git-chunk" +version = "0.3.0" +dependencies = [ + "quick-error", +] + +[[package]] +name = "git-config" +version = "0.1.11" +dependencies = [ + "dirs 4.0.0", + "git-features", + "memchr", + "nom", + "pwd", + "quick-error", + "unicode-bom", +] + +[[package]] +name = "git-diff" +version = "0.13.0" +dependencies = [ + "git-hash", + "git-object", + "quick-error", +] + +[[package]] +name = "git-features" +version = "0.19.1" +dependencies = [ + "bstr", + "crc32fast", + "flate2", + "git-hash", + "libc", + "prodash", + "quick-error", + "sha1_smol", + "walkdir", +] + +[[package]] +name = "git-hash" +version = "0.9.2" +dependencies = [ + "hex", + "quick-error", +] + +[[package]] +name = "git-lock" +version = "2.0.0" +dependencies = [ + "fastrand", + "git-tempfile", + "quick-error", +] + +[[package]] +name = "git-object" +version = "0.17.1" +dependencies = [ + "bstr", + "btoi", + "git-actor", + "git-features", + "git-hash", + "git-validate", + "hex", + "itoa 1.0.1", + "nom", + "quick-error", + "smallvec", +] + +[[package]] +name = "git-odb" +version = "0.27.0" +dependencies = [ + "arc-swap", + "git-features", + "git-hash", + "git-object", + "git-pack", + "git-quote", + "parking_lot 0.12.0", + "tempfile", + "thiserror", +] + +[[package]] +name = "git-pack" +version = "0.17.0" +dependencies = [ + "bytesize", + "clru", + "dashmap 5.2.0", + "git-chunk", + "git-diff", + "git-features", + "git-hash", + "git-object", + "git-tempfile", + "git-traverse", + "hash_hasher", + "memmap2 0.5.3", + "parking_lot 0.12.0", + "smallvec", + "thiserror", +] + +[[package]] +name = "git-quote" +version = "0.1.0" +dependencies = [ + "bstr", + "btoi", + "quick-error", +] + +[[package]] +name = "git-ref" +version = "0.12.0" +dependencies = [ + "git-actor", + "git-features", + "git-hash", + "git-lock", + "git-object", + "git-tempfile", + "git-validate", + "memmap2 0.5.3", + "nom", + "quick-error", +] + +[[package]] +name = "git-repository" +version = "0.15.0" +dependencies = [ + "byte-unit", + "clru", + "git-actor", + "git-config", + "git-features", + "git-hash", + "git-lock", + "git-object", + "git-odb", + "git-pack", + "git-ref", + "git-tempfile", + "git-traverse", + "git-validate", + "log", + "signal-hook", + "thiserror", + "unicode-normalization", +] + +[[package]] +name = "git-tempfile" +version = "2.0.0" +dependencies = [ + "dashmap 5.2.0", + "libc", + "once_cell", + "signal-hook", + "signal-hook-registry", + "tempfile", +] + +[[package]] +name = "git-traverse" +version = "0.12.0" +dependencies = [ + "git-hash", + "git-object", + "quick-error", +] + +[[package]] +name = "git-validate" +version = "0.5.3" +dependencies = [ + "bstr", + "quick-error", +] + [[package]] name = "git2" version = "0.14.2" @@ -556,7 +869,7 @@ dependencies = [ "encoding_rs_io", "grep-matcher", "log", - "memmap2", + "memmap2 0.3.0", ] [[package]] @@ -565,6 +878,12 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +[[package]] +name = "hash_hasher" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74721d007512d0cb3338cd20f0654ac913920061a4c4d0d8708edb3f2a698c0c" + [[package]] name = "hashbrown" version = "0.11.2" @@ -586,6 +905,18 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "human_format" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86cce260d758a9aa3d7c4b99d55c815a540f8a37514ba6046ab6be402a157cb0" + [[package]] name = "humansize" version = "1.1.1" @@ -770,9 +1101,9 @@ checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "lock_api" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ "scopeguard", ] @@ -813,6 +1144,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.6.4" @@ -822,6 +1162,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.4.4" @@ -862,6 +1208,16 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num-format" version = "0.4.0" @@ -915,9 +1271,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", @@ -932,6 +1288,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c55827317fb4c08822499848a14237d2874d6f139828893017237e7ab93eb386" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.8.0" @@ -950,6 +1315,7 @@ dependencies = [ "bytecount", "clap 3.1.6", "color_quant", + "git-repository", "git2", "image", "libc", @@ -998,7 +1364,17 @@ checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" dependencies = [ "instant", "lock_api", - "parking_lot_core", + "parking_lot_core 0.8.3", +] + +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.1", ] [[package]] @@ -1015,6 +1391,19 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking_lot_core" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + [[package]] name = "parse-zoneinfo" version = "0.3.0" @@ -1132,6 +1521,32 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "prodash" +version = "19.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa75e7b3c1591d852ba49539ccac278cb2086e3f5cbbef0d9f5984b0fbcb4fcb" +dependencies = [ + "bytesize", + "human_format", +] + +[[package]] +name = "pwd" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9ca0304857594109dca88140120427c7a65027be6b77d86a5938588e79cb07b" +dependencies = [ + "failure", + "libc", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quote" version = "1.0.9" @@ -1236,12 +1651,27 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" + [[package]] name = "regex-syntax" version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "rmp" version = "0.8.10" @@ -1263,6 +1693,12 @@ dependencies = [ "serde", ] +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + [[package]] name = "rustversion" version = "1.0.5" @@ -1351,6 +1787,31 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "signal-hook" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + [[package]] name = "slug" version = "0.1.4" @@ -1420,6 +1881,32 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + [[package]] name = "tera" version = "1.12.0" @@ -1489,6 +1976,26 @@ dependencies = [ "terminal_size", ] +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.3" @@ -1572,8 +2079,8 @@ dependencies = [ "aho-corasick", "clap 2.34.0", "crossbeam-channel", - "dashmap", - "dirs", + "dashmap 4.0.2", + "dirs 3.0.2", "encoding_rs_io", "env_logger", "grep-searcher", @@ -1581,7 +2088,7 @@ dependencies = [ "log", "num-format", "once_cell", - "parking_lot", + "parking_lot 0.11.1", "rayon", "regex", "serde", @@ -1671,6 +2178,12 @@ dependencies = [ "matches", ] +[[package]] +name = "unicode-bom" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63ec69f541d875b783ca40184d655f2927c95f0bffd486faa83cd3ac3529ec32" + [[package]] name = "unicode-normalization" version = "0.1.19" @@ -1830,6 +2343,49 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_i686_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" + [[package]] name = "yaml-rust" version = "0.4.5" diff --git a/Cargo.toml b/Cargo.toml index f02d85243..0ebeec661 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,11 +28,12 @@ section = "utility" [dependencies] anyhow = "1.0" askalono = "0.4.4" -byte-unit = "4.0.14" +byte-unit = "=4.0.13" # to match git-repository's lower requirement, which it needs for MSRV bytecount = "0.6.2" clap = {version = "3.1.6", features = ["cargo", "wrap_help"]} color_quant = "1.1.0" git2 = {version = "0.14.2", default-features = false} +git-repository = { version = "0.15.0", optional = true, default-features = false, git = "https://github.com/Byron/gitoxide", branch = "main" } image = "0.24.1" owo-colors = "3.3.0" regex = "1.5.5" From 1bb11e649e2c09d0601409274094081ce3a26803 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 29 Mar 2022 20:13:30 +0800 Subject: [PATCH 02/38] get_logs() with gitoxide --- Cargo.toml | 2 +- src/info/repo.rs | 154 +++++++++++++++++++++++++++-------------------- 2 files changed, 90 insertions(+), 66 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0ebeec661..0062367fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ bytecount = "0.6.2" clap = {version = "3.1.6", features = ["cargo", "wrap_help"]} color_quant = "1.1.0" git2 = {version = "0.14.2", default-features = false} -git-repository = { version = "0.15.0", optional = true, default-features = false, git = "https://github.com/Byron/gitoxide", branch = "main" } +git-repository = { version = "0.15.0", default-features = false, git = "https://github.com/Byron/gitoxide", branch = "main" } image = "0.24.1" owo-colors = "3.3.0" regex = "1.5.5" diff --git a/src/info/repo.rs b/src/info/repo.rs index 1f949a715..c9322a3ce 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -4,9 +4,10 @@ use anyhow::{Context, Result}; use byte_unit::Byte; use git2::Time; use git2::{ - BranchType, Commit, Repository, RepositoryOpenFlags, Signature, Status, StatusOptions, - StatusShow, + BranchType, Repository, RepositoryOpenFlags, Signature, Status, StatusOptions, StatusShow, }; +use git_repository as git; +use git_repository::bstr::ByteSlice; use regex::Regex; use std::collections::HashMap; use std::path::Path; @@ -16,8 +17,9 @@ use time::OffsetDateTime; use time_humanize::HumanTime; pub struct Repo<'a> { - repo: &'a Repository, - logs: Vec>, + git2_repo: &'a Repository, + repo: git::Repository, + commits: Vec, } #[derive(Hash, PartialEq, Eq)] @@ -36,52 +38,68 @@ impl From> for Sig { impl<'a> Repo<'a> { pub fn new( - repo: &'a Repository, + git2_repo: &'a Repository, no_merges: bool, bot_regex_pattern: &Option, ) -> Result { - let logs = Self::get_logs(repo, no_merges, bot_regex_pattern)?; - Ok(Self { repo, logs }) + let mut repo = git::open(git2_repo.path())?; + let logs = Self::get_logs(&mut repo, no_merges, bot_regex_pattern)?; + Ok(Self { + git2_repo, + repo, + commits: logs, + }) } + // TODO: avoid allocating/copying buffers. Instead gather the desired information + // during traversal and keep only author names for processing. fn get_logs( - repo: &'a Repository, + repo: &mut git::Repository, no_merges: bool, bot_regex_pattern: &Option, - ) -> Result>> { - let mut revwalk = repo.revwalk()?; - revwalk.push_head()?; - let logs: Vec> = revwalk - .filter_map(|r| match r { - Err(_) => None, - Ok(r) => repo - .find_commit(r) - .ok() - .filter(|commit| !(no_merges && commit.parents().len() > 1)) - .filter(|commit| { - !(bot_regex_pattern.is_some() && is_bot(commit.author(), bot_regex_pattern)) - }), + ) -> Result> { + // assure that objects we just traversed are coming from cache + // when we read the commit right after. + repo.object_cache_size(128 * 1024); + let commits = repo + .head()? + .peel_to_commit_in_place()? + .ancestors() + .all() + .filter_map(|commit_id| { + let commit: git::Commit = commit_id + .ok()? + .object() + .expect("commit is still present/comes from cache") + .into_commit(); + if no_merges && commit.parent_ids().take(2).count() > 1 { + return None; + } + if is_bot(commit.iter().author(), bot_regex_pattern) { + return None; + } + commit.detach().into() }) .collect(); - - Ok(logs) + Ok(commits) } pub fn get_creation_date(&self, iso_time: bool) -> Result { - let first_commit = self.logs.last(); - let output = match first_commit { - Some(commit) => { - let time = commit.time(); - git_time_to_formatted_time(&time, iso_time) - } - None => "".into(), - }; - - Ok(output) + let first_commit = self.commits.last(); + todo!() + // let output = match first_commit { + // Some(commit) => { + // let time = commit.time(); + // git_time_to_formatted_time(&time, iso_time) + // } + // None => "".into(), + // }; + // + // Ok(output) } pub fn get_number_of_commits(&self) -> String { - let number_of_commits = self.logs.len(); + let number_of_commits = self.commits.len(); number_of_commits.to_string() } @@ -92,16 +110,16 @@ impl<'a> Repo<'a> { ) -> Result<(Vec, usize)> { let mut author_to_number_of_commits: HashMap = HashMap::new(); let mut total_nbr_of_commits = 0; - let mailmap = self.repo.mailmap()?; - for commit in &self.logs { - let author = match commit.author_with_mailmap(&mailmap) { - Ok(val) => val, - Err(_) => commit.author(), - }; - let author_nbr_of_commits = author_to_number_of_commits - .entry(Sig::from(author)) - .or_insert(0); - *author_nbr_of_commits += 1; + let mailmap = self.git2_repo.mailmap()?; + for commit in &self.commits { + // let author = match commit.author_with_mailmap(&mailmap) { + // Ok(val) => val, + // Err(_) => commit.author(), + // }; + // let author_nbr_of_commits = author_to_number_of_commits + // .entry(Sig::from(author)) + // .or_insert(0); + // *author_nbr_of_commits += 1; total_nbr_of_commits += 1; } @@ -132,17 +150,18 @@ impl<'a> Repo<'a> { } pub fn get_date_of_last_commit(&self, iso_time: bool) -> String { - let last_commit = self.logs.first(); + let last_commit = self.commits.first(); - match last_commit { - Some(commit) => git_time_to_formatted_time(&commit.time(), iso_time), - None => "".into(), - } + todo!() + // match last_commit { + // Some(commit) => git_time_to_formatted_time(&commit.time(), iso_time), + // None => "".into(), + // } } // This collects the repo size excluding .git pub fn get_repo_size(&self) -> (String, u64) { - let (repo_size, file_count) = match self.repo.index() { + let (repo_size, file_count) = match self.git2_repo.index() { Ok(index) => index.iter().fold( (0, 0), |(repo_size, file_count): (u128, u64), index_entry| -> (u128, u64) { @@ -164,11 +183,11 @@ impl<'a> Repo<'a> { } pub fn get_number_of_tags(&self) -> Result { - Ok(self.repo.tag_names(None)?.len()) + Ok(self.git2_repo.tag_names(None)?.len()) } pub fn get_number_of_branches(&self) -> Result { - let mut number_of_branches = self.repo.branches(Some(BranchType::Remote))?.count(); + let mut number_of_branches = self.git2_repo.branches(Some(BranchType::Remote))?.count(); if number_of_branches > 0 { //Exclude origin/HEAD -> origin/main number_of_branches -= 1; @@ -177,7 +196,7 @@ impl<'a> Repo<'a> { } pub fn get_git_username(&self) -> Result { - let config = self.repo.config()?; + let config = self.git2_repo.config()?; let username = match config.get_entry("user.name") { Ok(v) => v.value().unwrap_or("").into(), Err(_) => "".into(), @@ -190,14 +209,14 @@ impl<'a> Repo<'a> { let mut version_name = String::new(); let mut most_recent: i64 = 0; - self.repo.tag_foreach(|id, name| { + self.git2_repo.tag_foreach(|id, name| { if let Ok(name) = String::from_utf8(name[10..].into()) { let mut current_time: i64 = 0; - if let Ok(tag) = self.repo.find_tag(id) { - if let Ok(c) = self.repo.find_commit(tag.target_id()) { + if let Ok(tag) = self.git2_repo.find_tag(id) { + if let Ok(c) = self.git2_repo.find_commit(tag.target_id()) { current_time = c.time().seconds(); } - } else if let Ok(c) = self.repo.find_commit(id) { + } else if let Ok(c) = self.git2_repo.find_commit(id) { current_time = c.time().seconds(); } if current_time > most_recent { @@ -214,7 +233,7 @@ impl<'a> Repo<'a> { } pub fn get_pending_changes(&self) -> Result { - let statuses = self.repo.statuses(Some( + let statuses = self.git2_repo.statuses(Some( StatusOptions::default() .show(StatusShow::Workdir) .update_index(true) @@ -254,7 +273,7 @@ impl<'a> Repo<'a> { } pub fn get_name_and_url(&self) -> Result<(String, String)> { - let config = self.repo.config()?; + let config = self.git2_repo.config()?; let mut remote_origin_url: Option = None; let mut remote_url_fallback = String::new(); let mut repository_name = String::new(); @@ -304,9 +323,9 @@ impl<'a> Repo<'a> { } pub fn get_head_refs(&self) -> Result { - let head = self.repo.head()?; + let head = self.git2_repo.head()?; let head_oid = head.target().with_context(|| "Could not read HEAD")?; - let refs = self.repo.references()?; + let refs = self.git2_repo.references()?; let refs_info = refs .filter_map(|reference| match reference { Ok(reference) => match (reference.target(), reference.shorthand()) { @@ -322,15 +341,20 @@ impl<'a> Repo<'a> { } fn work_dir(&self) -> Result<&Path> { - self.repo + self.git2_repo .workdir() .with_context(|| "unable to query workdir") } } -fn is_bot(author: Signature, bot_regex_pattern: &Option) -> bool { - let author_name = String::from_utf8_lossy(author.name_bytes()).into_owned(); - bot_regex_pattern.as_ref().unwrap().is_match(&author_name) +fn is_bot(author: Option>, bot_regex_pattern: &Option) -> bool { + author + .and_then(|author| { + bot_regex_pattern + .as_ref() + .map(|regex| regex.is_match(author.name.to_str_lossy().as_ref())) + }) + .unwrap_or(false) } fn bytes_to_human_readable(bytes: u128) -> String { From e3b29b0aee7391baa39f613aa8798b0c137e386a Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 29 Mar 2022 21:12:41 +0800 Subject: [PATCH 03/38] Use gitoxide in all methods related to commits --- Cargo.lock | 504 ++++++++++++++++++++++++++++++++++------------- Cargo.toml | 2 +- src/info/mod.rs | 2 +- src/info/repo.rs | 88 +++++---- 4 files changed, 413 insertions(+), 183 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 972b25ff9..316005e60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ "gimli", ] @@ -62,6 +62,12 @@ dependencies = [ "nodrop", ] +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "askalono" version = "0.4.4" @@ -81,6 +87,15 @@ dependencies = [ "zstd", ] +[[package]] +name = "atoi" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" +dependencies = [ + "num-traits", +] + [[package]] name = "atty" version = "0.2.14" @@ -94,15 +109,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.61" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01" +checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" dependencies = [ "addr2line", "cc", @@ -127,9 +142,9 @@ checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" @@ -201,9 +216,9 @@ checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e" [[package]] name = "bytemuck" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9966d2ab714d0f785dbac0a0396251a35280aeb42413281617d0209ab4898435" +checksum = "0e851ca7c24871e7336801608a4797d7376545b6928a10d32d75685687141ead" [[package]] name = "byteorder" @@ -219,9 +234,9 @@ checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70" [[package]] name = "cc" -version = "1.0.68" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" dependencies = [ "jobserver", ] @@ -241,18 +256,29 @@ dependencies = [ "libc", "num-integer", "num-traits", - "time 0.1.43", "winapi", ] [[package]] name = "chrono-tz" -version = "0.5.3" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2554a3155fec064362507487171dcc4edc3df60cb10f3a1fb10ed8094822b120" +checksum = "58549f1842da3080ce63002102d5bc954c7bc843d4f47818e642abdc36253552" dependencies = [ "chrono", + "chrono-tz-build", + "phf", +] + +[[package]] +name = "chrono-tz-build" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db058d493fb2f65f41861bfed7e3fe6335264a9f0f92710cab5bdf01fef09069" +dependencies = [ "parse-zoneinfo", + "phf", + "phf_codegen", ] [[package]] @@ -293,6 +319,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "218d6bd3dde8e442a975fa1cd233c0e5fded7596bccfe39f58eca98d22421e0a" +[[package]] +name = "cmake" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" +dependencies = [ + "cc", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -301,18 +336,32 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "crc32fast" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845" +dependencies = [ + "cfg-if", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + [[package]] name = "crossbeam-channel" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" dependencies = [ "cfg-if", "crossbeam-utils", @@ -320,9 +369,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -331,10 +380,11 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.5" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" dependencies = [ + "autocfg", "cfg-if", "crossbeam-utils", "lazy_static", @@ -342,11 +392,21 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" dependencies = [ "cfg-if", "lazy_static", @@ -418,9 +478,9 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", @@ -435,9 +495,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "encoding_rs" -version = "0.8.28" +version = "0.8.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" +checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" dependencies = [ "cfg-if", ] @@ -517,23 +577,36 @@ dependencies = [ "instant", ] +[[package]] +name = "filetime" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi", +] + [[package]] name = "flate2" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" dependencies = [ "cfg-if", "crc32fast", "libc", + "libz-sys", "miniz_oxide 0.4.4", ] [[package]] name = "flume" -version = "0.10.11" +version = "0.10.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b279436a715a9de95dcd26b151db590a71961cc06e54918b24fe0dd5b7d3fc4" +checksum = "843c03199d0c0ca54bc1ea90ac0d507274c28abcc4f691ae8b4eaa375087c76a" dependencies = [ "futures-core", "futures-sink", @@ -581,9 +654,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if", "js-sys", @@ -594,9 +667,9 @@ dependencies = [ [[package]] name = "gif" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a668f699973d0f573d15749b7002a9ac9e1f9c6b220e7b165601334c173d8de" +checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b" dependencies = [ "color_quant", "weezl", @@ -604,9 +677,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.25.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" [[package]] name = "git-actor" @@ -614,11 +687,19 @@ version = "0.8.1" dependencies = [ "bstr", "btoi", + "git-features", "itoa 1.0.1", "nom", "quick-error", ] +[[package]] +name = "git-bitmap" +version = "0.0.1" +dependencies = [ + "quick-error", +] + [[package]] name = "git-chunk" version = "0.3.0" @@ -654,12 +735,18 @@ version = "0.19.1" dependencies = [ "bstr", "crc32fast", + "crossbeam-channel", + "crossbeam-utils", "flate2", "git-hash", + "jwalk", "libc", + "num_cpus", + "parking_lot 0.12.0", "prodash", "quick-error", "sha1_smol", + "time", "walkdir", ] @@ -671,6 +758,23 @@ dependencies = [ "quick-error", ] +[[package]] +name = "git-index" +version = "0.1.0" +dependencies = [ + "atoi", + "bitflags", + "bstr", + "filetime", + "git-bitmap", + "git-features", + "git-hash", + "git-object", + "memmap2 0.5.3", + "quick-error", + "smallvec", +] + [[package]] name = "git-lock" version = "2.0.0" @@ -680,6 +784,15 @@ dependencies = [ "quick-error", ] +[[package]] +name = "git-mailmap" +version = "0.0.0" +dependencies = [ + "bstr", + "git-actor", + "quick-error", +] + [[package]] name = "git-object" version = "0.17.1" @@ -731,6 +844,7 @@ dependencies = [ "parking_lot 0.12.0", "smallvec", "thiserror", + "uluru", ] [[package]] @@ -766,16 +880,21 @@ dependencies = [ "clru", "git-actor", "git-config", + "git-diff", "git-features", "git-hash", + "git-index", "git-lock", + "git-mailmap", "git-object", "git-odb", "git-pack", "git-ref", "git-tempfile", "git-traverse", + "git-url", "git-validate", + "git-worktree", "log", "signal-hook", "thiserror", @@ -803,6 +922,17 @@ dependencies = [ "quick-error", ] +[[package]] +name = "git-url" +version = "0.3.5" +dependencies = [ + "bstr", + "git-features", + "home", + "quick-error", + "url", +] + [[package]] name = "git-validate" version = "0.5.3" @@ -811,6 +941,19 @@ dependencies = [ "quick-error", ] +[[package]] +name = "git-worktree" +version = "0.0.0" +dependencies = [ + "bstr", + "git-features", + "git-hash", + "git-index", + "git-object", + "io-close", + "thiserror", +] + [[package]] name = "git2" version = "0.14.2" @@ -869,7 +1012,7 @@ dependencies = [ "encoding_rs_io", "grep-matcher", "log", - "memmap2 0.3.0", + "memmap2 0.3.1", ] [[package]] @@ -911,6 +1054,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "home" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654" +dependencies = [ + "winapi", +] + [[package]] name = "human_format" version = "1.0.3" @@ -969,7 +1121,7 @@ dependencies = [ "color_quant", "exr", "gif", - "jpeg-decoder 0.2.2", + "jpeg-decoder 0.2.3", "num-iter", "num-rational", "num-traits", @@ -980,9 +1132,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ "autocfg", "hashbrown", @@ -999,18 +1151,28 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.9" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", ] +[[package]] +name = "io-close" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cadcf447f06744f8ce713d2d6239bb5bde2c357a452397a9ed90c625da390bc" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "itoa" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" @@ -1020,9 +1182,9 @@ checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] name = "jobserver" -version = "0.1.22" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" dependencies = [ "libc", ] @@ -1035,9 +1197,9 @@ checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" [[package]] name = "jpeg-decoder" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "105fb082d64e2100074587f59a74231f771750c664af903f1f9f76c9dedfc6f1" +checksum = "a55ad40a2d27923f63b6fbde5934926176c69ac5e23da6ac05ebfaca984e163f" dependencies = [ "rayon", ] @@ -1051,6 +1213,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jwalk" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "172752e853a067cbce46427de8470ddf308af7fd8ceaf9b682ef31a5021b6bb9" +dependencies = [ + "crossbeam", + "rayon", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1083,11 +1255,12 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" +checksum = "6f35facd4a5673cb5a48822be2be1d4236c1c99cb4113cab7061ac720d5bf859" dependencies = [ "cc", + "cmake", "libc", "pkg-config", "vcpkg", @@ -1110,9 +1283,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.14" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" dependencies = [ "cfg-if", ] @@ -1125,21 +1298,21 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "matches" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "memchr" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memmap2" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20ff203f7bdc401350b1dbaa0355135777d25f41c0bbc601851bbd6cf61e8ff5" +checksum = "00b6c2ebff6180198788f5db08d7ce3bc1d0b617176678831a7510825973e357" dependencies = [ "libc", ] @@ -1155,9 +1328,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ "autocfg", ] @@ -1195,9 +1368,9 @@ checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" [[package]] name = "nanorand" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729eb334247daa1803e0a094d0a5c55711b85571179f5ec6e53eccfdf7008958" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" dependencies = [ "getrandom", ] @@ -1224,8 +1397,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" dependencies = [ - "arrayvec", - "itoa 0.4.7", + "arrayvec 0.4.12", + "itoa 0.4.8", ] [[package]] @@ -1281,27 +1454,27 @@ dependencies = [ [[package]] name = "num_threads" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ba99ba6393e2c3734791401b66902d981cb03bf190af674ca69949b6d5fb15" +checksum = "aba1801fb138d8e85e11d0fc70baf4fe1cdfffda7c6cd34a854905df588e5ed0" dependencies = [ "libc", ] [[package]] name = "object" -version = "0.26.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55827317fb4c08822499848a14237d2874d6f139828893017237e7ab93eb386" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" [[package]] name = "onefetch" @@ -1328,7 +1501,7 @@ dependencies = [ "serde_yaml", "strum", "term_size", - "time 0.3.7", + "time", "time-humanize", "tokei", "toml", @@ -1358,13 +1531,13 @@ checksum = "5e72e30578e0d0993c8ae20823dd9cff2bc5517d2f586a8aef462a581e8a03eb" [[package]] name = "parking_lot" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core 0.8.3", + "parking_lot_core 0.8.5", ] [[package]] @@ -1379,9 +1552,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ "cfg-if", "instant", @@ -1468,6 +1641,45 @@ dependencies = [ "sha-1", ] +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", + "uncased", +] + [[package]] name = "pin-project" version = "1.0.10" @@ -1490,9 +1702,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.19" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" [[package]] name = "png" @@ -1508,15 +1720,15 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.27" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] @@ -1549,23 +1761,22 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" -version = "1.0.9" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" dependencies = [ "proc-macro2", ] [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -1587,15 +1798,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - [[package]] name = "rayon" version = "1.5.1" @@ -1623,21 +1825,22 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" +checksum = "8ae183fc1b06c149f0c1793e1eb447c8b04bfe46d48e9e48bfb8d2d7ed64ecf0" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "7776223e2696f1aa4c6b0170e83212f47296a00424305117d013dfe86fb0fe55" dependencies = [ "getrandom", "redox_syscall", + "thiserror", ] [[package]] @@ -1701,15 +1904,15 @@ checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "rustversion" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "same-file" @@ -1812,6 +2015,12 @@ dependencies = [ "libc", ] +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + [[package]] name = "slug" version = "0.1.4" @@ -1872,9 +2081,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.73" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" +checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f" dependencies = [ "proc-macro2", "quote", @@ -1909,9 +2118,9 @@ dependencies = [ [[package]] name = "tera" -version = "1.12.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7571541dff0e57eaa2e931249f0d7489eb2b24b6b105546f8c2f1a47f15aaa3a" +checksum = "d3cac831b615c25bcef632d1cabf864fa05813baad3d526829db18eb70e8b58d" dependencies = [ "chrono", "chrono-tz", @@ -1941,9 +2150,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -1998,9 +2207,9 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ "once_cell", ] @@ -2027,19 +2236,9 @@ dependencies = [ [[package]] name = "time" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "time" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "004cbc98f30fa233c61a38bc77e96a9106e65c88f2d3bef182ae952027e5753d" +checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" dependencies = [ "itoa 1.0.1", "libc", @@ -2052,14 +2251,14 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e32d019b4f7c100bcd5494e40a27119d45b71fba2b07a4684153129279a4647" dependencies = [ - "time 0.3.7", + "time", ] [[package]] name = "tinyvec" -version = "1.2.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" dependencies = [ "tinyvec_macros", ] @@ -2088,7 +2287,7 @@ dependencies = [ "log", "num-format", "once_cell", - "parking_lot 0.11.1", + "parking_lot 0.11.2", "rayon", "regex", "serde", @@ -2109,9 +2308,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "ucd-trie" @@ -2119,6 +2318,24 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +[[package]] +name = "uluru" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794a32261a1f5eb6a4462c81b59cec87b5c27d5deea7dd1ac8fc781c41d226db" +dependencies = [ + "arrayvec 0.7.2", +] + +[[package]] +name = "uncased" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baeed7327e25054889b9bd4f975f32e5f4c5d434042d59ab6cd4142c0a76ed0" +dependencies = [ + "version_check", +] + [[package]] name = "unic-char-property" version = "0.9.0" @@ -2171,12 +2388,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" -dependencies = [ - "matches", -] +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" [[package]] name = "unicode-bom" @@ -2195,9 +2409,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" @@ -2219,9 +2433,9 @@ dependencies = [ [[package]] name = "utf8-width" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cf7d77f457ef8dfa11e4cd5933c5ddb5dc52a94664071951219a97710f0a32b" +checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" [[package]] name = "vcpkg" @@ -2235,6 +2449,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "walkdir" version = "2.3.2" diff --git a/Cargo.toml b/Cargo.toml index 0062367fa..f90785bd4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ bytecount = "0.6.2" clap = {version = "3.1.6", features = ["cargo", "wrap_help"]} color_quant = "1.1.0" git2 = {version = "0.14.2", default-features = false} -git-repository = { version = "0.15.0", default-features = false, git = "https://github.com/Byron/gitoxide", branch = "main" } +git-repository = { version = "0.15.0", git = "https://github.com/Byron/gitoxide", branch = "for-onefetch", features = ["max-performance", "unstable"] } image = "0.24.1" owo-colors = "3.3.0" regex = "1.5.5" diff --git a/src/info/mod.rs b/src/info/mod.rs index 45154e52c..426f39ca7 100644 --- a/src/info/mod.rs +++ b/src/info/mod.rs @@ -171,7 +171,7 @@ impl Info { let number_of_commits = internal_repo.get_number_of_commits(); let (authors, contributors) = internal_repo.get_authors(config.number_of_authors, config.show_email)?; - let last_change = internal_repo.get_date_of_last_commit(config.iso_time); + let last_change = internal_repo.get_date_of_last_commit(config.iso_time)?; let (repo_size, file_count) = internal_repo.get_repo_size(); let workdir = internal_repo.get_work_dir()?; let license = Detector::new()?.get_license(&workdir)?; diff --git a/src/info/repo.rs b/src/info/repo.rs index c9322a3ce..4c133a9ae 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -2,7 +2,6 @@ use crate::info::author::Author; use crate::info::head_refs::HeadRefs; use anyhow::{Context, Result}; use byte_unit::Byte; -use git2::Time; use git2::{ BranchType, Repository, RepositoryOpenFlags, Signature, Status, StatusOptions, StatusShow, }; @@ -28,6 +27,7 @@ pub struct Sig { email: String, } +// TODO: make Sig use BString, to avoid allocations/utf8 checks impl From> for Sig { fn from(sig: Signature) -> Self { let name = String::from_utf8_lossy(sig.name_bytes()).into_owned(); @@ -36,6 +36,14 @@ impl From> for Sig { } } +impl From for Sig { + fn from(sig: git::actor::Signature) -> Self { + let name = sig.name.to_string(); + let email = sig.email.to_string(); + Self { name, email } + } +} + impl<'a> Repo<'a> { pub fn new( git2_repo: &'a Repository, @@ -86,16 +94,16 @@ impl<'a> Repo<'a> { pub fn get_creation_date(&self, iso_time: bool) -> Result { let first_commit = self.commits.last(); - todo!() - // let output = match first_commit { - // Some(commit) => { - // let time = commit.time(); - // git_time_to_formatted_time(&time, iso_time) - // } - // None => "".into(), - // }; - // - // Ok(output) + let output = match first_commit { + Some(commit) => { + // TODO: no clone + let commit: git::Commit = commit.clone().attach(&self.repo).into_commit(); + gitoxide_time_to_formatted_time(commit.time()?, iso_time) + } + None => "".into(), + }; + + Ok(output) } pub fn get_number_of_commits(&self) -> String { @@ -110,16 +118,17 @@ impl<'a> Repo<'a> { ) -> Result<(Vec, usize)> { let mut author_to_number_of_commits: HashMap = HashMap::new(); let mut total_nbr_of_commits = 0; - let mailmap = self.git2_repo.mailmap()?; + let mailmap = self.repo.load_mailmap(); for commit in &self.commits { - // let author = match commit.author_with_mailmap(&mailmap) { - // Ok(val) => val, - // Err(_) => commit.author(), - // }; - // let author_nbr_of_commits = author_to_number_of_commits - // .entry(Sig::from(author)) - // .or_insert(0); - // *author_nbr_of_commits += 1; + let mut commit = git::objs::CommitRefIter::from_bytes(&commit.data); + let author = match commit.author() { + Some(author) => mailmap.resolve(&author), + None => continue, + }; + let author_nbr_of_commits = author_to_number_of_commits + .entry(Sig::from(author)) + .or_insert(0); + *author_nbr_of_commits += 1; total_nbr_of_commits += 1; } @@ -149,14 +158,17 @@ impl<'a> Repo<'a> { Ok((authors, number_of_authors)) } - pub fn get_date_of_last_commit(&self, iso_time: bool) -> String { + pub fn get_date_of_last_commit(&self, iso_time: bool) -> Result { let last_commit = self.commits.first(); - todo!() - // match last_commit { - // Some(commit) => git_time_to_formatted_time(&commit.time(), iso_time), - // None => "".into(), - // } + Ok(match last_commit { + Some(commit) => { + // TODO: no clone + let commit = commit.clone().attach(&self.repo).into_commit(); + gitoxide_time_to_formatted_time(commit.time()?, iso_time) + } + None => "".into(), + }) } // This collects the repo size excluding .git @@ -362,11 +374,11 @@ fn bytes_to_human_readable(bytes: u128) -> String { byte.get_appropriate_unit(true).to_string() } -fn git_time_to_formatted_time(time: &Time, iso_time: bool) -> String { +fn gitoxide_time_to_formatted_time(time: git::actor::Time, iso_time: bool) -> String { if iso_time { - to_rfc3339(HumanTime::from(time.seconds())) + to_rfc3339(HumanTime::from(time.seconds_since_unix_epoch as i64)) } else { - let ht = HumanTime::from_duration_since_timestamp(time.seconds().unsigned_abs()); + let ht = HumanTime::from_duration_since_timestamp(time.seconds_since_unix_epoch as u64); format!("{}", ht) } } @@ -385,9 +397,7 @@ pub fn is_valid(repo_path: &str) -> Result { #[cfg(test)] mod tests { - use super::*; - use git2::Time; use std::time::{Duration, SystemTime}; #[test] @@ -396,8 +406,8 @@ mod tests { .duration_since(SystemTime::UNIX_EPOCH) .unwrap(); - let time = Time::new(current_time.as_secs() as i64, 0); - let result = git_time_to_formatted_time(&time, false); + let time = git::actor::Time::new(current_time.as_secs() as u32, 0); + let result = gitoxide_time_to_formatted_time(time, false); assert_eq!(result, "now"); } @@ -409,8 +419,8 @@ mod tests { .unwrap(); // NOTE 366 so that it's a year ago even with leap years. let year_ago = current_time - (day * 366); - let time = Time::new(year_ago.as_secs() as i64, 0); - let result = git_time_to_formatted_time(&time, false); + let time = git::actor::Time::new(year_ago.as_secs() as u32, 0); + let result = gitoxide_time_to_formatted_time(time, false); assert_eq!(result, "a year ago"); } @@ -418,15 +428,15 @@ mod tests { fn display_time_as_iso_time_some_time() { // Set "current" time to 11/18/2021 11:02:22 let time_sample = 1637233282; - let time = Time::new(time_sample, 0); - let result = git_time_to_formatted_time(&time, true); + let time = git::actor::Time::new(time_sample, 0); + let result = gitoxide_time_to_formatted_time(time, true); assert_eq!(result, "2021-11-18T11:01:22Z"); } #[test] fn display_time_as_iso_time_current_epoch() { let time_sample = 0; - let time = Time::new(time_sample, 0); - let result = git_time_to_formatted_time(&time, true); + let time = git::actor::Time::new(time_sample, 0); + let result = gitoxide_time_to_formatted_time(time, true); assert_eq!(result, "1970-01-01T00:00:00Z"); } } From 8df0d1966642cfd77783b8222be8537f1fa31b7c Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 09:17:47 +0800 Subject: [PATCH 04/38] obtain all but author information on the fly --- src/info/mod.rs | 4 +- src/info/repo.rs | 100 ++++++++++++++++++++++++----------------------- 2 files changed, 54 insertions(+), 50 deletions(-) diff --git a/src/info/mod.rs b/src/info/mod.rs index 426f39ca7..0304b58cf 100644 --- a/src/info/mod.rs +++ b/src/info/mod.rs @@ -167,11 +167,11 @@ impl Info { let git_username = internal_repo.get_git_username()?; let number_of_tags = internal_repo.get_number_of_tags()?; let number_of_branches = internal_repo.get_number_of_branches()?; - let creation_date = internal_repo.get_creation_date(config.iso_time)?; + let creation_date = internal_repo.get_creation_date(config.iso_time); let number_of_commits = internal_repo.get_number_of_commits(); let (authors, contributors) = internal_repo.get_authors(config.number_of_authors, config.show_email)?; - let last_change = internal_repo.get_date_of_last_commit(config.iso_time)?; + let last_change = internal_repo.get_date_of_last_commit(config.iso_time); let (repo_size, file_count) = internal_repo.get_repo_size(); let workdir = internal_repo.get_work_dir()?; let license = Detector::new()?.get_license(&workdir)?; diff --git a/src/info/repo.rs b/src/info/repo.rs index 4c133a9ae..66a5acf95 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -19,6 +19,9 @@ pub struct Repo<'a> { git2_repo: &'a Repository, repo: git::Repository, commits: Vec, + num_commits: usize, + time_of_most_recent_commit: git::actor::Time, + time_of_first_commit: git::actor::Time, } #[derive(Hash, PartialEq, Eq)] @@ -51,64 +54,74 @@ impl<'a> Repo<'a> { bot_regex_pattern: &Option, ) -> Result { let mut repo = git::open(git2_repo.path())?; - let logs = Self::get_logs(&mut repo, no_merges, bot_regex_pattern)?; + let (logs, num_commits, time_of_first_commit, time_of_most_recent_commit) = + Self::extract_commit_infos(&mut repo, no_merges, bot_regex_pattern)?; Ok(Self { git2_repo, repo, commits: logs, + num_commits, + time_of_first_commit, + time_of_most_recent_commit, }) } // TODO: avoid allocating/copying buffers. Instead gather the desired information // during traversal and keep only author names for processing. - fn get_logs( + fn extract_commit_infos( repo: &mut git::Repository, no_merges: bool, bot_regex_pattern: &Option, - ) -> Result> { + ) -> Result<( + Vec, + usize, + git::actor::Time, + git::actor::Time, + )> { // assure that objects we just traversed are coming from cache // when we read the commit right after. repo.object_cache_size(128 * 1024); - let commits = repo - .head()? - .peel_to_commit_in_place()? - .ancestors() - .all() - .filter_map(|commit_id| { - let commit: git::Commit = commit_id - .ok()? - .object() - .expect("commit is still present/comes from cache") - .into_commit(); - if no_merges && commit.parent_ids().take(2).count() > 1 { - return None; - } - if is_bot(commit.iter().author(), bot_regex_pattern) { - return None; - } - commit.detach().into() - }) - .collect(); - Ok(commits) - } + let mut commits = Vec::new(); + + let mut most_recent_commit_time = None; + let mut first_commit_time = None; + let mut ancestors = repo.head()?.peel_to_commit_in_place()?.ancestors(); + let mut commit_iter = ancestors.all().peekable(); + + while let Some(commit_id) = commit_iter.next() { + let commit: git::Commit = commit_id? + .object() + .expect("commit is still present/comes from cache") + .into_commit(); + if no_merges && commit.parent_ids().take(2).count() > 1 { + continue; + } + if is_bot(commit.iter().author(), bot_regex_pattern) { + continue; + } - pub fn get_creation_date(&self, iso_time: bool) -> Result { - let first_commit = self.commits.last(); - let output = match first_commit { - Some(commit) => { - // TODO: no clone - let commit: git::Commit = commit.clone().attach(&self.repo).into_commit(); - gitoxide_time_to_formatted_time(commit.time()?, iso_time) + most_recent_commit_time.get_or_insert_with(|| commit.time()); + if commit_iter.peek().is_none() { + first_commit_time = commit.time()?.into(); } - None => "".into(), - }; + commits.push(commit.detach().into()); + } + + let num_commits = commits.len(); + Ok(( + commits, + num_commits, + first_commit_time.expect("at least one commit"), + most_recent_commit_time.expect("at least one commit")?, + )) + } - Ok(output) + pub fn get_creation_date(&self, iso_time: bool) -> String { + gitoxide_time_to_formatted_time(self.time_of_first_commit, iso_time) } pub fn get_number_of_commits(&self) -> String { - let number_of_commits = self.commits.len(); - number_of_commits.to_string() + self.num_commits.to_string() } pub fn get_authors( @@ -158,17 +171,8 @@ impl<'a> Repo<'a> { Ok((authors, number_of_authors)) } - pub fn get_date_of_last_commit(&self, iso_time: bool) -> Result { - let last_commit = self.commits.first(); - - Ok(match last_commit { - Some(commit) => { - // TODO: no clone - let commit = commit.clone().attach(&self.repo).into_commit(); - gitoxide_time_to_formatted_time(commit.time()?, iso_time) - } - None => "".into(), - }) + pub fn get_date_of_last_commit(&self, iso_time: bool) -> String { + gitoxide_time_to_formatted_time(self.time_of_most_recent_commit, iso_time) } // This collects the repo size excluding .git From 954de842f1f91dff19898158ba593a1a39f3e3a5 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 09:25:22 +0800 Subject: [PATCH 05/38] no cloning for `Sig` and `Author` by using BString directly --- Cargo.lock | 62 ++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 +- src/info/author.rs | 9 ++++--- src/info/repo.rs | 26 ++++++------------- 4 files changed, 75 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 316005e60..e4ee75db4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -176,6 +176,7 @@ dependencies = [ "lazy_static", "memchr", "regex-automata", + "serde", ] [[package]] @@ -691,6 +692,7 @@ dependencies = [ "itoa 1.0.1", "nom", "quick-error", + "serde", ] [[package]] @@ -756,6 +758,7 @@ version = "0.9.2" dependencies = [ "hex", "quick-error", + "serde", ] [[package]] @@ -772,6 +775,7 @@ dependencies = [ "git-object", "memmap2 0.5.3", "quick-error", + "serde", "smallvec", ] @@ -791,6 +795,7 @@ dependencies = [ "bstr", "git-actor", "quick-error", + "serde", ] [[package]] @@ -807,6 +812,7 @@ dependencies = [ "itoa 1.0.1", "nom", "quick-error", + "serde", "smallvec", ] @@ -821,6 +827,7 @@ dependencies = [ "git-pack", "git-quote", "parking_lot 0.12.0", + "serde", "tempfile", "thiserror", ] @@ -842,11 +849,36 @@ dependencies = [ "hash_hasher", "memmap2 0.5.3", "parking_lot 0.12.0", + "serde", "smallvec", "thiserror", "uluru", ] +[[package]] +name = "git-packetline" +version = "0.12.3" +dependencies = [ + "bstr", + "hex", + "quick-error", +] + +[[package]] +name = "git-protocol" +version = "0.14.0" +dependencies = [ + "bstr", + "btoi", + "git-features", + "git-hash", + "git-transport", + "maybe-async", + "nom", + "quick-error", + "serde", +] + [[package]] name = "git-quote" version = "0.1.0" @@ -870,6 +902,7 @@ dependencies = [ "memmap2 0.5.3", "nom", "quick-error", + "serde", ] [[package]] @@ -889,8 +922,10 @@ dependencies = [ "git-object", "git-odb", "git-pack", + "git-protocol", "git-ref", "git-tempfile", + "git-transport", "git-traverse", "git-url", "git-validate", @@ -913,6 +948,19 @@ dependencies = [ "tempfile", ] +[[package]] +name = "git-transport" +version = "0.15.0" +dependencies = [ + "bstr", + "git-features", + "git-packetline", + "git-url", + "quick-error", + "serde", + "thiserror", +] + [[package]] name = "git-traverse" version = "0.12.0" @@ -1302,6 +1350,17 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +[[package]] +name = "maybe-async" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6007f9dad048e0a224f27ca599d669fca8cfa0dac804725aab542b2eb032bce6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "memchr" version = "2.4.1" @@ -2035,6 +2094,9 @@ name = "smallvec" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +dependencies = [ + "serde", +] [[package]] name = "spin" diff --git a/Cargo.toml b/Cargo.toml index f90785bd4..530a9d88d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ bytecount = "0.6.2" clap = {version = "3.1.6", features = ["cargo", "wrap_help"]} color_quant = "1.1.0" git2 = {version = "0.14.2", default-features = false} -git-repository = { version = "0.15.0", git = "https://github.com/Byron/gitoxide", branch = "for-onefetch", features = ["max-performance", "unstable"] } +git-repository = { version = "0.15.0", git = "https://github.com/Byron/gitoxide", branch = "for-onefetch", features = ["max-performance", "unstable", "serde1"] } image = "0.24.1" owo-colors = "3.3.0" regex = "1.5.5" diff --git a/src/info/author.rs b/src/info/author.rs index 50d12f1f7..3cfa7b5f6 100644 --- a/src/info/author.rs +++ b/src/info/author.rs @@ -1,17 +1,18 @@ +use git_repository as git; use serde::ser::SerializeStruct; use serde::Serialize; pub struct Author { - name: String, - email: Option, + name: git::bstr::BString, + email: Option, nbr_of_commits: usize, contribution: usize, } impl Author { pub fn new( - name: String, - email: Option, + name: git::bstr::BString, + email: Option, nbr_of_commits: usize, total_nbr_of_commits: usize, ) -> Self { diff --git a/src/info/repo.rs b/src/info/repo.rs index 66a5acf95..652549ee1 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -2,9 +2,7 @@ use crate::info::author::Author; use crate::info::head_refs::HeadRefs; use anyhow::{Context, Result}; use byte_unit::Byte; -use git2::{ - BranchType, Repository, RepositoryOpenFlags, Signature, Status, StatusOptions, StatusShow, -}; +use git2::{BranchType, Repository, RepositoryOpenFlags, Status, StatusOptions, StatusShow}; use git_repository as git; use git_repository::bstr::ByteSlice; use regex::Regex; @@ -26,23 +24,12 @@ pub struct Repo<'a> { #[derive(Hash, PartialEq, Eq)] pub struct Sig { - name: String, - email: String, -} - -// TODO: make Sig use BString, to avoid allocations/utf8 checks -impl From> for Sig { - fn from(sig: Signature) -> Self { - let name = String::from_utf8_lossy(sig.name_bytes()).into_owned(); - let email = String::from_utf8_lossy(sig.email_bytes()).into_owned(); - Self { name, email } - } + name: git::bstr::BString, + email: git::bstr::BString, } impl From for Sig { - fn from(sig: git::actor::Signature) -> Self { - let name = sig.name.to_string(); - let email = sig.email.to_string(); + fn from(git::actor::Signature { name, email, .. }: git::actor::Signature) -> Self { Self { name, email } } } @@ -159,9 +146,10 @@ impl<'a> Repo<'a> { let authors: Vec = authors_by_number_of_commits .into_iter() .map(|(author, author_nbr_of_commits)| { + let email = author.email; Author::new( - author.name.clone(), - show_email.then(|| author.email), + author.name, + show_email.then(|| email), author_nbr_of_commits, total_nbr_of_commits, ) From 0652bbeb488c51243aa3a2283dc0bc6994a4f37b Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 10:49:07 +0800 Subject: [PATCH 06/38] Calculate authors on the fly as much as possible; don't store commits --- src/info/author.rs | 4 ++ src/info/mod.rs | 4 +- src/info/repo.rs | 142 +++++++++++++++++++++++---------------------- 3 files changed, 80 insertions(+), 70 deletions(-) diff --git a/src/info/author.rs b/src/info/author.rs index 3cfa7b5f6..1debabe7b 100644 --- a/src/info/author.rs +++ b/src/info/author.rs @@ -25,6 +25,10 @@ impl Author { contribution, } } + + pub fn clear_email(&mut self) { + self.email = None; + } } impl std::fmt::Display for Author { diff --git a/src/info/mod.rs b/src/info/mod.rs index 0304b58cf..0544d16d2 100644 --- a/src/info/mod.rs +++ b/src/info/mod.rs @@ -159,7 +159,7 @@ impl Info { pub fn new(config: Config) -> Result { let git_version = cli::get_git_version(); let repo = Repository::discover(&config.repo_path)?; - let internal_repo = Repo::new(&repo, config.no_merges, &config.bot_regex_pattern)?; + let mut internal_repo = Repo::new(&repo, config.no_merges, &config.bot_regex_pattern)?; let (repo_name, repo_url) = internal_repo.get_name_and_url()?; let head_refs = internal_repo.get_head_refs()?; let pending_changes = internal_repo.get_pending_changes()?; @@ -170,7 +170,7 @@ impl Info { let creation_date = internal_repo.get_creation_date(config.iso_time); let number_of_commits = internal_repo.get_number_of_commits(); let (authors, contributors) = - internal_repo.get_authors(config.number_of_authors, config.show_email)?; + internal_repo.take_authors(config.number_of_authors, config.show_email); let last_change = internal_repo.get_date_of_last_commit(config.iso_time); let (repo_size, file_count) = internal_repo.get_repo_size(); let workdir = internal_repo.get_work_dir()?; diff --git a/src/info/repo.rs b/src/info/repo.rs index 652549ee1..a81040863 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -15,8 +15,8 @@ use time_humanize::HumanTime; pub struct Repo<'a> { git2_repo: &'a Repository, - repo: git::Repository, - commits: Vec, + authors: Vec, + total_num_authors: usize, num_commits: usize, time_of_most_recent_commit: git::actor::Time, time_of_first_commit: git::actor::Time, @@ -41,12 +41,17 @@ impl<'a> Repo<'a> { bot_regex_pattern: &Option, ) -> Result { let mut repo = git::open(git2_repo.path())?; - let (logs, num_commits, time_of_first_commit, time_of_most_recent_commit) = - Self::extract_commit_infos(&mut repo, no_merges, bot_regex_pattern)?; + let ( + authors, + total_num_authors, + num_commits, + time_of_first_commit, + time_of_most_recent_commit, + ) = Self::extract_commit_infos(&mut repo, no_merges, bot_regex_pattern)?; Ok(Self { git2_repo, - repo, - commits: logs, + authors, + total_num_authors, num_commits, time_of_first_commit, time_of_most_recent_commit, @@ -60,7 +65,8 @@ impl<'a> Repo<'a> { no_merges: bool, bot_regex_pattern: &Option, ) -> Result<( - Vec, + Vec, + usize, usize, git::actor::Time, git::actor::Time, @@ -68,68 +74,44 @@ impl<'a> Repo<'a> { // assure that objects we just traversed are coming from cache // when we read the commit right after. repo.object_cache_size(128 * 1024); - let mut commits = Vec::new(); let mut most_recent_commit_time = None; let mut first_commit_time = None; let mut ancestors = repo.head()?.peel_to_commit_in_place()?.ancestors(); let mut commit_iter = ancestors.all().peekable(); + let mailmap = repo.load_mailmap(); + let mut author_to_number_of_commits: HashMap = HashMap::new(); + let mut total_nbr_of_commits = 0; + + let mut num_commits = 0; while let Some(commit_id) = commit_iter.next() { let commit: git::Commit = commit_id? .object() .expect("commit is still present/comes from cache") .into_commit(); - if no_merges && commit.parent_ids().take(2).count() > 1 { - continue; - } - if is_bot(commit.iter().author(), bot_regex_pattern) { - continue; - } - - most_recent_commit_time.get_or_insert_with(|| commit.time()); - if commit_iter.peek().is_none() { - first_commit_time = commit.time()?.into(); - } - commits.push(commit.detach().into()); - } - - let num_commits = commits.len(); - Ok(( - commits, - num_commits, - first_commit_time.expect("at least one commit"), - most_recent_commit_time.expect("at least one commit")?, - )) - } + num_commits += 1; + { + let commit = commit.decode()?; + if no_merges && commit.parents().take(2).count() > 1 { + continue; + } - pub fn get_creation_date(&self, iso_time: bool) -> String { - gitoxide_time_to_formatted_time(self.time_of_first_commit, iso_time) - } + if is_bot(commit.author, bot_regex_pattern) { + continue; + } - pub fn get_number_of_commits(&self) -> String { - self.num_commits.to_string() - } + let author_nbr_of_commits = author_to_number_of_commits + .entry(Sig::from(mailmap.resolve(commit.author))) + .or_insert(0); + *author_nbr_of_commits += 1; + total_nbr_of_commits += 1; - pub fn get_authors( - &self, - number_of_authors_to_display: usize, - show_email: bool, - ) -> Result<(Vec, usize)> { - let mut author_to_number_of_commits: HashMap = HashMap::new(); - let mut total_nbr_of_commits = 0; - let mailmap = self.repo.load_mailmap(); - for commit in &self.commits { - let mut commit = git::objs::CommitRefIter::from_bytes(&commit.data); - let author = match commit.author() { - Some(author) => mailmap.resolve(&author), - None => continue, - }; - let author_nbr_of_commits = author_to_number_of_commits - .entry(Sig::from(author)) - .or_insert(0); - *author_nbr_of_commits += 1; - total_nbr_of_commits += 1; + most_recent_commit_time.get_or_insert_with(|| commit.committer.time); + if commit_iter.peek().is_none() { + first_commit_time = commit.committer.time.into(); + } + } } let mut authors_by_number_of_commits: Vec<(Sig, usize)> = @@ -139,24 +121,51 @@ impl<'a> Repo<'a> { authors_by_number_of_commits.sort_by(|(_, a_count), (_, b_count)| b_count.cmp(a_count)); - if number_of_authors > number_of_authors_to_display { - authors_by_number_of_commits.truncate(number_of_authors_to_display); - } - let authors: Vec = authors_by_number_of_commits .into_iter() .map(|(author, author_nbr_of_commits)| { let email = author.email; Author::new( author.name, - show_email.then(|| email), + email.into(), author_nbr_of_commits, total_nbr_of_commits, ) }) .collect(); - Ok((authors, number_of_authors)) + Ok(( + authors, + number_of_authors, + num_commits, + first_commit_time.expect("at least one commit"), + most_recent_commit_time.expect("at least one commit"), + )) + } + + pub fn get_creation_date(&self, iso_time: bool) -> String { + gitoxide_time_to_formatted_time(self.time_of_first_commit, iso_time) + } + + pub fn get_number_of_commits(&self) -> String { + self.num_commits.to_string() + } + + pub fn take_authors( + &mut self, + number_of_authors_to_display: usize, + show_email: bool, + ) -> (Vec, usize) { + if self.total_num_authors > number_of_authors_to_display { + self.authors.truncate(number_of_authors_to_display); + } + + if !show_email { + for author in &mut self.authors { + author.clear_email(); + } + } + (std::mem::take(&mut self.authors), self.total_num_authors) } pub fn get_date_of_last_commit(&self, iso_time: bool) -> String { @@ -351,13 +360,10 @@ impl<'a> Repo<'a> { } } -fn is_bot(author: Option>, bot_regex_pattern: &Option) -> bool { - author - .and_then(|author| { - bot_regex_pattern - .as_ref() - .map(|regex| regex.is_match(author.name.to_str_lossy().as_ref())) - }) +fn is_bot(author: git::actor::SignatureRef<'_>, bot_regex_pattern: &Option) -> bool { + bot_regex_pattern + .as_ref() + .map(|regex| regex.is_match(author.name.to_str_lossy().as_ref())) .unwrap_or(false) } From 65da5be0af20c38fdc3994cae88d3218d2ae6f49 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 11:05:39 +0800 Subject: [PATCH 07/38] fix commit count --- src/info/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index a81040863..f6d18f7e8 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -90,7 +90,6 @@ impl<'a> Repo<'a> { .object() .expect("commit is still present/comes from cache") .into_commit(); - num_commits += 1; { let commit = commit.decode()?; if no_merges && commit.parents().take(2).count() > 1 { @@ -100,6 +99,7 @@ impl<'a> Repo<'a> { if is_bot(commit.author, bot_regex_pattern) { continue; } + num_commits += 1; let author_nbr_of_commits = author_to_number_of_commits .entry(Sig::from(mailmap.resolve(commit.author))) From 28deadfe3422c238e7838f13bbcba718bb54f712 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 11:10:07 +0800 Subject: [PATCH 08/38] refactor --- src/info/repo.rs | 51 +++++++++++------------------------------------- 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index f6d18f7e8..596f1a31e 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -41,42 +41,13 @@ impl<'a> Repo<'a> { bot_regex_pattern: &Option, ) -> Result { let mut repo = git::open(git2_repo.path())?; - let ( - authors, - total_num_authors, - num_commits, - time_of_first_commit, - time_of_most_recent_commit, - ) = Self::extract_commit_infos(&mut repo, no_merges, bot_regex_pattern)?; - Ok(Self { - git2_repo, - authors, - total_num_authors, - num_commits, - time_of_first_commit, - time_of_most_recent_commit, - }) - } - // TODO: avoid allocating/copying buffers. Instead gather the desired information - // during traversal and keep only author names for processing. - fn extract_commit_infos( - repo: &mut git::Repository, - no_merges: bool, - bot_regex_pattern: &Option, - ) -> Result<( - Vec, - usize, - usize, - git::actor::Time, - git::actor::Time, - )> { // assure that objects we just traversed are coming from cache // when we read the commit right after. repo.object_cache_size(128 * 1024); - let mut most_recent_commit_time = None; - let mut first_commit_time = None; + let mut time_of_most_recent_commit = None; + let mut time_of_first_commit = None; let mut ancestors = repo.head()?.peel_to_commit_in_place()?.ancestors(); let mut commit_iter = ancestors.all().peekable(); @@ -107,9 +78,9 @@ impl<'a> Repo<'a> { *author_nbr_of_commits += 1; total_nbr_of_commits += 1; - most_recent_commit_time.get_or_insert_with(|| commit.committer.time); + time_of_most_recent_commit.get_or_insert_with(|| commit.committer.time); if commit_iter.peek().is_none() { - first_commit_time = commit.committer.time.into(); + time_of_first_commit = commit.committer.time.into(); } } } @@ -117,8 +88,7 @@ impl<'a> Repo<'a> { let mut authors_by_number_of_commits: Vec<(Sig, usize)> = author_to_number_of_commits.into_iter().collect(); - let number_of_authors = authors_by_number_of_commits.len(); - + let total_num_authors = authors_by_number_of_commits.len(); authors_by_number_of_commits.sort_by(|(_, a_count), (_, b_count)| b_count.cmp(a_count)); let authors: Vec = authors_by_number_of_commits @@ -134,13 +104,14 @@ impl<'a> Repo<'a> { }) .collect(); - Ok(( + Ok(Self { + git2_repo, authors, - number_of_authors, + total_num_authors, num_commits, - first_commit_time.expect("at least one commit"), - most_recent_commit_time.expect("at least one commit"), - )) + time_of_first_commit: time_of_first_commit.expect("at least one commit"), + time_of_most_recent_commit: time_of_most_recent_commit.expect("at least one commit"), + }) } pub fn get_creation_date(&self, iso_time: bool) -> String { From 2a67bb4c8b19fd829ac0d1e96f439b4c882ead03 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 11:42:07 +0800 Subject: [PATCH 09/38] Use `gitoxide` for calculating repo size --- src/info/repo.rs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index 596f1a31e..2c302204f 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -15,6 +15,7 @@ use time_humanize::HumanTime; pub struct Repo<'a> { git2_repo: &'a Repository, + repo: git::Repository, authors: Vec, total_num_authors: usize, num_commits: usize, @@ -104,7 +105,9 @@ impl<'a> Repo<'a> { }) .collect(); + drop(commit_iter); Ok(Self { + repo, git2_repo, authors, total_num_authors, @@ -145,15 +148,17 @@ impl<'a> Repo<'a> { // This collects the repo size excluding .git pub fn get_repo_size(&self) -> (String, u64) { - let (repo_size, file_count) = match self.git2_repo.index() { - Ok(index) => index.iter().fold( - (0, 0), - |(repo_size, file_count): (u128, u64), index_entry| -> (u128, u64) { - (repo_size + index_entry.file_size as u128, file_count + 1) - }, - ), - Err(_) => (0, 0), - }; + let (repo_size, file_count) = self + .repo + .load_index() + .transpose() + .ok() + .flatten() + .map(|index| { + let repo_size = index.entries().iter().map(|e| e.stat.size as u128).sum(); + (repo_size, index.entries().len() as u64) + }) + .unwrap_or_default(); (bytes_to_human_readable(repo_size), file_count) } From 9b2774cf046523240af85787e8d0f2afcc874426 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 11:44:10 +0800 Subject: [PATCH 10/38] refactor --- src/info/repo.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index 2c302204f..2f9738811 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -148,17 +148,13 @@ impl<'a> Repo<'a> { // This collects the repo size excluding .git pub fn get_repo_size(&self) -> (String, u64) { - let (repo_size, file_count) = self - .repo - .load_index() - .transpose() - .ok() - .flatten() - .map(|index| { + let (repo_size, file_count) = match self.repo.load_index() { + Some(Ok(index)) => { let repo_size = index.entries().iter().map(|e| e.stat.size as u128).sum(); (repo_size, index.entries().len() as u64) - }) - .unwrap_or_default(); + } + _ => (0, 0), + }; (bytes_to_human_readable(repo_size), file_count) } From c42a1ef809bb122caf064741554fa9e7ca5482f3 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 11:57:27 +0800 Subject: [PATCH 11/38] gitoxide for tags; Fix author name and email printing; avoid doing unnecessary work Now we only create as many authors as we need to avoid allocating more strings then needed when converting BString to its display representation. --- src/info/author.rs | 8 ++++---- src/info/mod.rs | 10 +++++++--- src/info/repo.rs | 14 ++++---------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/info/author.rs b/src/info/author.rs index 1debabe7b..01746602e 100644 --- a/src/info/author.rs +++ b/src/info/author.rs @@ -3,8 +3,8 @@ use serde::ser::SerializeStruct; use serde::Serialize; pub struct Author { - name: git::bstr::BString, - email: Option, + name: String, + email: Option, nbr_of_commits: usize, contribution: usize, } @@ -19,8 +19,8 @@ impl Author { let contribution = (nbr_of_commits as f32 * 100. / total_nbr_of_commits as f32).round() as usize; Self { - name, - email, + name: name.to_string(), + email: email.map(|e| e.to_string()), nbr_of_commits, contribution, } diff --git a/src/info/mod.rs b/src/info/mod.rs index 0544d16d2..526e231b8 100644 --- a/src/info/mod.rs +++ b/src/info/mod.rs @@ -159,7 +159,12 @@ impl Info { pub fn new(config: Config) -> Result { let git_version = cli::get_git_version(); let repo = Repository::discover(&config.repo_path)?; - let mut internal_repo = Repo::new(&repo, config.no_merges, &config.bot_regex_pattern)?; + let mut internal_repo = Repo::new( + &repo, + config.no_merges, + &config.bot_regex_pattern, + config.number_of_authors, + )?; let (repo_name, repo_url) = internal_repo.get_name_and_url()?; let head_refs = internal_repo.get_head_refs()?; let pending_changes = internal_repo.get_pending_changes()?; @@ -169,8 +174,7 @@ impl Info { let number_of_branches = internal_repo.get_number_of_branches()?; let creation_date = internal_repo.get_creation_date(config.iso_time); let number_of_commits = internal_repo.get_number_of_commits(); - let (authors, contributors) = - internal_repo.take_authors(config.number_of_authors, config.show_email); + let (authors, contributors) = internal_repo.take_authors(config.show_email); let last_change = internal_repo.get_date_of_last_commit(config.iso_time); let (repo_size, file_count) = internal_repo.get_repo_size(); let workdir = internal_repo.get_work_dir()?; diff --git a/src/info/repo.rs b/src/info/repo.rs index 2f9738811..d9e64c66f 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -40,6 +40,7 @@ impl<'a> Repo<'a> { git2_repo: &'a Repository, no_merges: bool, bot_regex_pattern: &Option, + number_of_authors_to_display: usize, ) -> Result { let mut repo = git::open(git2_repo.path())?; @@ -103,6 +104,7 @@ impl<'a> Repo<'a> { total_nbr_of_commits, ) }) + .take(number_of_authors_to_display) .collect(); drop(commit_iter); @@ -125,15 +127,7 @@ impl<'a> Repo<'a> { self.num_commits.to_string() } - pub fn take_authors( - &mut self, - number_of_authors_to_display: usize, - show_email: bool, - ) -> (Vec, usize) { - if self.total_num_authors > number_of_authors_to_display { - self.authors.truncate(number_of_authors_to_display); - } - + pub fn take_authors(&mut self, show_email: bool) -> (Vec, usize) { if !show_email { for author in &mut self.authors { author.clear_email(); @@ -168,7 +162,7 @@ impl<'a> Repo<'a> { } pub fn get_number_of_tags(&self) -> Result { - Ok(self.git2_repo.tag_names(None)?.len()) + Ok(self.repo.references()?.tags()?.count()) } pub fn get_number_of_branches(&self) -> Result { From 615e0712ab0fba29ff309b3a01dfc9433cf1d988 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 13:24:06 +0800 Subject: [PATCH 12/38] Retrieve all branches with `gitoxide` --- src/info/repo.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index d9e64c66f..8342d3f52 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -2,7 +2,7 @@ use crate::info::author::Author; use crate::info::head_refs::HeadRefs; use anyhow::{Context, Result}; use byte_unit::Byte; -use git2::{BranchType, Repository, RepositoryOpenFlags, Status, StatusOptions, StatusShow}; +use git2::{Repository, RepositoryOpenFlags, Status, StatusOptions, StatusShow}; use git_repository as git; use git_repository::bstr::ByteSlice; use regex::Regex; @@ -50,8 +50,12 @@ impl<'a> Repo<'a> { let mut time_of_most_recent_commit = None; let mut time_of_first_commit = None; - let mut ancestors = repo.head()?.peel_to_commit_in_place()?.ancestors(); - let mut commit_iter = ancestors.all().peekable(); + let mut commit_iter = repo + .head()? + .peel_to_commit_in_place()? + .ancestors() + .all() + .peekable(); let mailmap = repo.load_mailmap(); let mut author_to_number_of_commits: HashMap = HashMap::new(); @@ -166,7 +170,7 @@ impl<'a> Repo<'a> { } pub fn get_number_of_branches(&self) -> Result { - let mut number_of_branches = self.git2_repo.branches(Some(BranchType::Remote))?.count(); + let mut number_of_branches = self.repo.references()?.remote_branches()?.count(); if number_of_branches > 0 { //Exclude origin/HEAD -> origin/main number_of_branches -= 1; @@ -320,8 +324,8 @@ impl<'a> Repo<'a> { } fn work_dir(&self) -> Result<&Path> { - self.git2_repo - .workdir() + self.repo + .work_dir() .with_context(|| "unable to query workdir") } } From 2c6016eba41caccddea3ac02a18ea5079b92298f Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 14:22:25 +0800 Subject: [PATCH 13/38] get most recent version with gitoxide --- src/info/repo.rs | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index 8342d3f52..7539d54cd 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -190,28 +190,23 @@ impl<'a> Repo<'a> { pub fn get_version(&self) -> Result { let mut version_name = String::new(); - let mut most_recent: i64 = 0; - - self.git2_repo.tag_foreach(|id, name| { - if let Ok(name) = String::from_utf8(name[10..].into()) { - let mut current_time: i64 = 0; - if let Ok(tag) = self.git2_repo.find_tag(id) { - if let Ok(c) = self.git2_repo.find_commit(tag.target_id()) { - current_time = c.time().seconds(); - } - } else if let Ok(c) = self.git2_repo.find_commit(id) { - current_time = c.time().seconds(); - } + let mut most_recent = 0; + + for tag in self + .repo + .references()? + .tags()? + .peeled() + .filter_map(Result::ok) + { + if let Ok(commit) = tag.id().object()?.try_into_commit() { + let current_time = commit.time()?.seconds(); if current_time > most_recent { most_recent = current_time; - version_name = name; + version_name = tag.name().strip_prefix().to_string(); } - - return true; } - false - })?; - + } Ok(version_name) } From f61761d990f76ecaba82557da3259c9cb6731af7 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 17:08:14 +0800 Subject: [PATCH 14/38] Collect branches at current head-commit with gitoxide --- src/info/head_refs.rs | 6 +++--- src/info/repo.rs | 32 ++++++++++++++++++-------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/info/head_refs.rs b/src/info/head_refs.rs index fdf7319cc..b259955c6 100644 --- a/src/info/head_refs.rs +++ b/src/info/head_refs.rs @@ -1,14 +1,14 @@ -use git2::Oid; +use git_repository as git; use serde::ser::SerializeStruct; use serde::Serialize; pub struct HeadRefs { - commit: Oid, + commit: git::hash::ObjectId, refs: Vec, } impl HeadRefs { - pub fn new(commit: Oid, refs: Vec) -> HeadRefs { + pub fn new(commit: git::hash::ObjectId, refs: Vec) -> HeadRefs { HeadRefs { commit, refs } } } diff --git a/src/info/repo.rs b/src/info/repo.rs index 7539d54cd..93c6cf6dd 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -203,7 +203,7 @@ impl<'a> Repo<'a> { let current_time = commit.time()?.seconds(); if current_time > most_recent { most_recent = current_time; - version_name = tag.name().strip_prefix().to_string(); + version_name = tag.name().shorten().to_string(); } } } @@ -301,20 +301,24 @@ impl<'a> Repo<'a> { } pub fn get_head_refs(&self) -> Result { - let head = self.git2_repo.head()?; - let head_oid = head.target().with_context(|| "Could not read HEAD")?; - let refs = self.git2_repo.references()?; - let refs_info = refs - .filter_map(|reference| match reference { - Ok(reference) => match (reference.target(), reference.shorthand()) { - (Some(oid), Some(shorthand)) if oid == head_oid && !reference.is_tag() => { - Some(String::from(shorthand)) - } - _ => None, - }, - Err(_) => None, + let head_oid = self + .repo + .head() + .with_context(|| "Could not read HEAD")? + .peel_to_commit_in_place()? + .id; + let refs_info = self + .repo + .references()? + .all()? + .peeled() + .filter_map(Result::ok) + .filter_map(|reference: git::Reference<'_>| { + (reference.id() == head_oid + && reference.name().category() != Some(git::reference::Category::Tag)) + .then(|| reference.name().shorten().to_string()) }) - .collect::>(); + .collect(); Ok(HeadRefs::new(head_oid, refs_info)) } From 1942087b15d6aa4ef192724f71936cd085ac1340 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 17:16:58 +0800 Subject: [PATCH 15/38] Assure short ids are not ambiguous It's actually quite involved to get proper short-ids, and git even applies some heuristics to calculate good starting values for the abbreviation length, right before validating uniqueness. --- src/info/head_refs.rs | 20 +++++++++----------- src/info/repo.rs | 8 ++++---- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/info/head_refs.rs b/src/info/head_refs.rs index b259955c6..e23869b73 100644 --- a/src/info/head_refs.rs +++ b/src/info/head_refs.rs @@ -1,21 +1,22 @@ -use git_repository as git; use serde::ser::SerializeStruct; use serde::Serialize; pub struct HeadRefs { - commit: git::hash::ObjectId, + short_commit_id: String, refs: Vec, } impl HeadRefs { - pub fn new(commit: git::hash::ObjectId, refs: Vec) -> HeadRefs { - HeadRefs { commit, refs } + pub fn new(short_commit_id: String, refs: Vec) -> HeadRefs { + HeadRefs { + short_commit_id, + refs, + } } } impl std::fmt::Display for HeadRefs { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let short_commit = self.commit.to_string().chars().take(7).collect::(); if !self.refs.is_empty() { let refs_str = self .refs @@ -23,9 +24,9 @@ impl std::fmt::Display for HeadRefs { .map(|ref_name| ref_name.as_str()) .collect::>() .join(", "); - write!(f, "{} ({})", short_commit, refs_str) + write!(f, "{} ({})", self.short_commit_id, refs_str) } else { - write!(f, "{}", short_commit) + write!(f, "{}", self.short_commit_id) } } } @@ -37,10 +38,7 @@ impl Serialize for HeadRefs { { let mut state = serializer.serialize_struct("HeadRefs", 2)?; state.serialize_field("refs", &self.refs)?; - state.serialize_field( - "oid", - &self.commit.to_string().chars().take(7).collect::(), - )?; + state.serialize_field("oid", &self.short_commit_id)?; state.end() } } diff --git a/src/info/repo.rs b/src/info/repo.rs index 93c6cf6dd..1e70960f6 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -304,9 +304,9 @@ impl<'a> Repo<'a> { let head_oid = self .repo .head() - .with_context(|| "Could not read HEAD")? - .peel_to_commit_in_place()? - .id; + .context("Could not read HEAD")? + .peel_to_id_in_place() + .context("The repository isn't initialized")??; let refs_info = self .repo .references()? @@ -319,7 +319,7 @@ impl<'a> Repo<'a> { .then(|| reference.name().shorten().to_string()) }) .collect(); - Ok(HeadRefs::new(head_oid, refs_info)) + Ok(HeadRefs::new(head_oid.shorten()?.to_string(), refs_info)) } fn work_dir(&self) -> Result<&Path> { From 4fc333417165e969b93147224803e6a110165294 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 17:46:31 +0800 Subject: [PATCH 16/38] refactor --- src/info/repo.rs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index 1e70960f6..ea7d43eeb 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -50,12 +50,7 @@ impl<'a> Repo<'a> { let mut time_of_most_recent_commit = None; let mut time_of_first_commit = None; - let mut commit_iter = repo - .head()? - .peel_to_commit_in_place()? - .ancestors() - .all() - .peekable(); + let mut commit_iter = repo.head_commit()?.ancestors().all().peekable(); let mailmap = repo.load_mailmap(); let mut author_to_number_of_commits: HashMap = HashMap::new(); @@ -301,12 +296,7 @@ impl<'a> Repo<'a> { } pub fn get_head_refs(&self) -> Result { - let head_oid = self - .repo - .head() - .context("Could not read HEAD")? - .peel_to_id_in_place() - .context("The repository isn't initialized")??; + let head_oid = self.repo.head_id().context("Could not read HEAD")?; let refs_info = self .repo .references()? From 4085053f6a10658b98592008d66f4b44987bfdea Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 17:58:29 +0800 Subject: [PATCH 17/38] refactor --- src/info/repo.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index ea7d43eeb..64d69c654 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -79,9 +79,9 @@ impl<'a> Repo<'a> { *author_nbr_of_commits += 1; total_nbr_of_commits += 1; - time_of_most_recent_commit.get_or_insert_with(|| commit.committer.time); + time_of_most_recent_commit.get_or_insert_with(|| commit.time()); if commit_iter.peek().is_none() { - time_of_first_commit = commit.committer.time.into(); + time_of_first_commit = commit.time().into(); } } } From 5394f3c0bc21bb7bb3249f8723986d2542634ba6 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 18:07:40 +0800 Subject: [PATCH 18/38] get worktree status in parallel This can take a long time on massive repos. --- src/info/mod.rs | 16 ++++++++-- src/info/repo.rs | 80 ++++++++++++++++++++++++------------------------ 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/info/mod.rs b/src/info/mod.rs index 526e231b8..c4ca5c407 100644 --- a/src/info/mod.rs +++ b/src/info/mod.rs @@ -1,7 +1,7 @@ use crate::cli::{self, Config}; use crate::ui::get_ascii_colors; use crate::ui::text_colors::TextColors; -use anyhow::Result; +use anyhow::{Context, Result}; use author::Author; use deps::DependencyDetector; use git2::Repository; @@ -166,8 +166,15 @@ impl Info { config.number_of_authors, )?; let (repo_name, repo_url) = internal_repo.get_name_and_url()?; + let pending_changes = std::thread::spawn({ + let git_dir = repo.path().to_owned(); + move || { + let repo = git2::Repository::open(git_dir)?; + repo::get_pending_changes(&repo) + } + }); + let head_refs = internal_repo.get_head_refs()?; - let pending_changes = internal_repo.get_pending_changes()?; let version = internal_repo.get_version()?; let git_username = internal_repo.get_git_username()?; let number_of_tags = internal_repo.get_number_of_tags()?; @@ -202,7 +209,10 @@ impl Info { number_of_tags, number_of_branches, head_refs, - pending_changes, + pending_changes: pending_changes + .join() + .ok() + .context("BUG: panic in pending-changes thread")??, version, creation_date, languages, diff --git a/src/info/repo.rs b/src/info/repo.rs index 64d69c654..74d01b85e 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -205,46 +205,6 @@ impl<'a> Repo<'a> { Ok(version_name) } - pub fn get_pending_changes(&self) -> Result { - let statuses = self.git2_repo.statuses(Some( - StatusOptions::default() - .show(StatusShow::Workdir) - .update_index(true) - .include_untracked(true) - .renames_head_to_index(true) - .recurse_untracked_dirs(true), - ))?; - - let (added, deleted, modified) = - statuses - .iter() - .fold((0, 0, 0), |(added, deleted, modified), e| { - let s: Status = e.status(); - if s.is_index_new() || s.is_wt_new() { - (added + 1, deleted, modified) - } else if s.is_index_deleted() || s.is_wt_deleted() { - (added, deleted + 1, modified) - } else { - (added, deleted, modified + 1) - } - }); - - let mut result = String::new(); - if modified > 0 { - result = format!("{}+-", modified) - } - - if added > 0 { - result = format!("{} {}+", result, added); - } - - if deleted > 0 { - result = format!("{} {}-", result, deleted); - } - - Ok(result.trim().into()) - } - pub fn get_name_and_url(&self) -> Result<(String, String)> { let config = self.git2_repo.config()?; let mut remote_origin_url: Option = None; @@ -397,3 +357,43 @@ mod tests { assert_eq!(result, "1970-01-01T00:00:00Z"); } } + +pub fn get_pending_changes(repo: &git2::Repository) -> Result { + let statuses = repo.statuses(Some( + StatusOptions::default() + .show(StatusShow::Workdir) + .update_index(true) + .include_untracked(true) + .renames_head_to_index(true) + .recurse_untracked_dirs(true), + ))?; + + let (added, deleted, modified) = + statuses + .iter() + .fold((0, 0, 0), |(added, deleted, modified), e| { + let s: Status = e.status(); + if s.is_index_new() || s.is_wt_new() { + (added + 1, deleted, modified) + } else if s.is_index_deleted() || s.is_wt_deleted() { + (added, deleted + 1, modified) + } else { + (added, deleted, modified + 1) + } + }); + + let mut result = String::new(); + if modified > 0 { + result = format!("{}+-", modified) + } + + if added > 0 { + result = format!("{} {}+", result, added); + } + + if deleted > 0 { + result = format!("{} {}-", result, deleted); + } + + Ok(result.trim().into()) +} From d178a5c721cf2d7154548ab92f90beaabe2bcda3 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 18:16:54 +0800 Subject: [PATCH 19/38] gather language statistics in parallel to everything else --- src/info/langs/language.rs | 2 +- src/info/mod.rs | 40 ++++++++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/info/langs/language.rs b/src/info/langs/language.rs index 75230a40f..06dc5c3d2 100644 --- a/src/info/langs/language.rs +++ b/src/info/langs/language.rs @@ -24,7 +24,7 @@ macro_rules! define_colors { ( [ $($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)),+]) } }; } -#[derive(PartialEq, EnumString, EnumIter, IntoStaticStr)] +#[derive(Clone, PartialEq, EnumString, EnumIter, IntoStaticStr)] #[strum(serialize_all = "lowercase")] pub enum LanguageType { Programming, diff --git a/src/info/mod.rs b/src/info/mod.rs index c4ca5c407..d35012a51 100644 --- a/src/info/mod.rs +++ b/src/info/mod.rs @@ -165,7 +165,8 @@ impl Info { &config.bot_regex_pattern, config.number_of_authors, )?; - let (repo_name, repo_url) = internal_repo.get_name_and_url()?; + let workdir = internal_repo.get_work_dir()?; + let pending_changes = std::thread::spawn({ let git_dir = repo.path().to_owned(); move || { @@ -173,7 +174,22 @@ impl Info { repo::get_pending_changes(&repo) } }); + let languages_handle = std::thread::spawn({ + let ignored_directories = config.ignored_directories.clone(); + let language_types = config.language_types.clone(); + let include_hidden = config.include_hidden; + let workdir = workdir.clone(); + move || { + langs::get_language_statistics( + &workdir, + &ignored_directories, + &language_types, + include_hidden, + ) + } + }); + let (repo_name, repo_url) = internal_repo.get_name_and_url()?; let head_refs = internal_repo.get_head_refs()?; let version = internal_repo.get_version()?; let git_username = internal_repo.get_git_username()?; @@ -184,15 +200,18 @@ impl Info { let (authors, contributors) = internal_repo.take_authors(config.show_email); let last_change = internal_repo.get_date_of_last_commit(config.iso_time); let (repo_size, file_count) = internal_repo.get_repo_size(); - let workdir = internal_repo.get_work_dir()?; let license = Detector::new()?.get_license(&workdir)?; let dependencies = DependencyDetector::new().get_dependencies(&workdir)?; - let (languages, lines_of_code) = langs::get_language_statistics( - &workdir, - &config.ignored_directories, - &config.language_types, - config.include_hidden, - )?; + + let pending_changes = pending_changes + .join() + .ok() + .context("BUG: panic in pending-changes thread")??; + + let (languages, lines_of_code) = languages_handle + .join() + .ok() + .context("BUG: panic in language statistics thread")??; let dominant_language = langs::get_dominant_language(&languages); let ascii_colors = get_ascii_colors( &config.ascii_language, @@ -209,10 +228,7 @@ impl Info { number_of_tags, number_of_branches, head_refs, - pending_changes: pending_changes - .join() - .ok() - .context("BUG: panic in pending-changes thread")??, + pending_changes, version, creation_date, languages, From 633f0ce6cad0a664e764627b3f193aa59eb212a6 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 30 Mar 2022 18:23:57 +0800 Subject: [PATCH 20/38] Do three things in parallel, don't wait for `Repo::new()` --- src/info/deps/mod.rs | 3 ++- src/info/langs/mod.rs | 5 +++-- src/info/license.rs | 3 ++- src/info/mod.rs | 14 +++++++------- src/info/repo.rs | 14 -------------- 5 files changed, 14 insertions(+), 25 deletions(-) diff --git a/src/info/deps/mod.rs b/src/info/deps/mod.rs index 9adc2dc4b..fff6ad1db 100644 --- a/src/info/deps/mod.rs +++ b/src/info/deps/mod.rs @@ -1,5 +1,6 @@ use anyhow::Result; use std::collections::HashMap; +use std::path::Path; use std::{ffi::OsStr, fs}; pub mod package_manager; @@ -17,7 +18,7 @@ impl DependencyDetector { DependencyDetector { package_managers } } - pub fn get_dependencies(&self, dir: &str) -> Result { + pub fn get_dependencies(&self, dir: &Path) -> Result { let deps = fs::read_dir(dir)? .filter_map(std::result::Result::ok) .map(|entry| entry.path()) diff --git a/src/info/langs/mod.rs b/src/info/langs/mod.rs index 04aa67e8b..f77f5f810 100644 --- a/src/info/langs/mod.rs +++ b/src/info/langs/mod.rs @@ -2,6 +2,7 @@ use anyhow::{Context, Result}; use language::{Language, LanguageType}; use regex::Regex; use std::collections::HashMap; +use std::path::Path; use strum::IntoEnumIterator; pub mod language; @@ -11,7 +12,7 @@ pub fn get_dominant_language(languages_stat_vec: &[(Language, f64)]) -> Language } pub fn get_language_statistics( - dir: &str, + dir: &Path, ignored_directories: &[String], language_types: &[LanguageType], include_hidden: bool, @@ -71,7 +72,7 @@ fn get_total_loc(languages: &tokei::Languages) -> usize { } fn get_statistics( - dir: &str, + dir: &Path, ignored_directories: &[String], language_types: &[LanguageType], include_hidden: bool, diff --git a/src/info/license.rs b/src/info/license.rs index ba93aa34e..7e1b90c03 100644 --- a/src/info/license.rs +++ b/src/info/license.rs @@ -1,5 +1,6 @@ use anyhow::{bail, Result}; use askalono::{Store, TextData}; +use std::path::Path; use std::{ffi::OsStr, fs}; const LICENSE_FILES: [&str; 3] = ["LICENSE", "LICENCE", "COPYING"]; @@ -24,7 +25,7 @@ impl Detector { } } - pub fn get_license(&self, dir: &str) -> Result { + pub fn get_license(&self, dir: &Path) -> Result { fn is_license_file>(file_name: S) -> bool { LICENSE_FILES .iter() diff --git a/src/info/mod.rs b/src/info/mod.rs index d35012a51..4412dfd5d 100644 --- a/src/info/mod.rs +++ b/src/info/mod.rs @@ -159,13 +159,7 @@ impl Info { pub fn new(config: Config) -> Result { let git_version = cli::get_git_version(); let repo = Repository::discover(&config.repo_path)?; - let mut internal_repo = Repo::new( - &repo, - config.no_merges, - &config.bot_regex_pattern, - config.number_of_authors, - )?; - let workdir = internal_repo.get_work_dir()?; + let workdir = repo.workdir().expect("non-bare repo").to_owned(); let pending_changes = std::thread::spawn({ let git_dir = repo.path().to_owned(); @@ -189,6 +183,12 @@ impl Info { } }); + let mut internal_repo = Repo::new( + &repo, + config.no_merges, + &config.bot_regex_pattern, + config.number_of_authors, + )?; let (repo_name, repo_url) = internal_repo.get_name_and_url()?; let head_refs = internal_repo.get_head_refs()?; let version = internal_repo.get_version()?; diff --git a/src/info/repo.rs b/src/info/repo.rs index 74d01b85e..a5c76bd64 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -152,14 +152,6 @@ impl<'a> Repo<'a> { (bytes_to_human_readable(repo_size), file_count) } - pub fn get_work_dir(&self) -> Result { - let workdir = self - .work_dir()? - .to_str() - .with_context(|| "invalid workdir")?; - Ok(workdir.to_string()) - } - pub fn get_number_of_tags(&self) -> Result { Ok(self.repo.references()?.tags()?.count()) } @@ -271,12 +263,6 @@ impl<'a> Repo<'a> { .collect(); Ok(HeadRefs::new(head_oid.shorten()?.to_string(), refs_info)) } - - fn work_dir(&self) -> Result<&Path> { - self.repo - .work_dir() - .with_context(|| "unable to query workdir") - } } fn is_bot(author: git::actor::SignatureRef<'_>, bot_regex_pattern: &Option) -> bool { From 6817e48be827d95efa1c3ad87cdc0bfaf3421cd4 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 31 Mar 2022 07:56:25 +0800 Subject: [PATCH 21/38] Don't take risks when making assumptions about what branches point at Addresses https://github.com/o2sh/onefetch/pull/635#discussion_r838496169 --- src/info/repo.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index a5c76bd64..51cedefaa 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -106,6 +106,11 @@ impl<'a> Repo<'a> { .take(number_of_authors_to_display) .collect(); + // This could happen if a branch pointed to non-commit object, so no traversal actually happens. + let (time_of_first_commit, time_of_most_recent_commit) = time_of_first_commit + .and_then(|a| time_of_most_recent_commit.map(|b| (a, b))) + .unwrap_or_default(); + drop(commit_iter); Ok(Self { repo, @@ -113,8 +118,8 @@ impl<'a> Repo<'a> { authors, total_num_authors, num_commits, - time_of_first_commit: time_of_first_commit.expect("at least one commit"), - time_of_most_recent_commit: time_of_most_recent_commit.expect("at least one commit"), + time_of_first_commit, + time_of_most_recent_commit, }) } From a5ab965a24b97cb0fe33e7b68a8e9fdf8af40701 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 31 Mar 2022 09:10:15 +0800 Subject: [PATCH 22/38] =?UTF-8?q?Tune=20the=20object=20cache=20based=20on?= =?UTF-8?q?=20science=E2=84=A2=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/info/repo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index 51cedefaa..86580f3ad 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -46,7 +46,7 @@ impl<'a> Repo<'a> { // assure that objects we just traversed are coming from cache // when we read the commit right after. - repo.object_cache_size(128 * 1024); + repo.object_cache_size(32 * 1024); let mut time_of_most_recent_commit = None; let mut time_of_first_commit = None; From 04ff54742b8a58b61a6dd3a5c558187ea248bcb5 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 31 Mar 2022 11:57:20 +0800 Subject: [PATCH 23/38] Improve unification of contributors by taking the lower-case email as identity Additionally we sort contributors by name in case they have the same amount of commits to assure stable results, which may help in some cases where similar commits counts would be displayed as they are in the top 3. --- src/info/repo.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index 86580f3ad..280386a9f 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -23,14 +23,22 @@ pub struct Repo<'a> { time_of_first_commit: git::actor::Time, } -#[derive(Hash, PartialEq, Eq)] +#[derive(Hash, PartialEq, Eq, Ord, PartialOrd)] pub struct Sig { name: git::bstr::BString, email: git::bstr::BString, } impl From for Sig { - fn from(git::actor::Signature { name, email, .. }: git::actor::Signature) -> Self { + fn from( + git::actor::Signature { + name, mut email, .. + }: git::actor::Signature, + ) -> Self { + // authors who aren't mail-mapped would otherwise seem dissimilar if the email case is different. + // Explicitly lower-casing it normalizes for that. + // This comes at the cost of displaying only lower-case emails as well, which seems beneficial. + email.make_ascii_lowercase(); Self { name, email } } } @@ -90,7 +98,8 @@ impl<'a> Repo<'a> { author_to_number_of_commits.into_iter().collect(); let total_num_authors = authors_by_number_of_commits.len(); - authors_by_number_of_commits.sort_by(|(_, a_count), (_, b_count)| b_count.cmp(a_count)); + authors_by_number_of_commits + .sort_by(|(sa, a_count), (sb, b_count)| b_count.cmp(a_count).then_with(|| sa.cmp(&sb))); let authors: Vec = authors_by_number_of_commits .into_iter() From 397b4aec6e125b6a85dbb0fd85f9b7ed978aebdb Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 31 Mar 2022 12:12:17 +0800 Subject: [PATCH 24/38] Compute contributor identity using emails, lowercase, only We cache the lower-case value only if it is different from what's there to speed up comparisons while using memory/allocations only when needed. --- src/info/repo.rs | 58 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index 280386a9f..138107a98 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -6,6 +6,7 @@ use git2::{Repository, RepositoryOpenFlags, Status, StatusOptions, StatusShow}; use git_repository as git; use git_repository::bstr::ByteSlice; use regex::Regex; +use std::cmp::Ordering; use std::collections::HashMap; use std::path::Path; use time::format_description::well_known::Rfc3339; @@ -23,23 +24,53 @@ pub struct Repo<'a> { time_of_first_commit: git::actor::Time, } -#[derive(Hash, PartialEq, Eq, Ord, PartialOrd)] +#[derive(Hash)] pub struct Sig { name: git::bstr::BString, email: git::bstr::BString, + email_lowercase: Option, } impl From for Sig { - fn from( - git::actor::Signature { - name, mut email, .. - }: git::actor::Signature, - ) -> Self { - // authors who aren't mail-mapped would otherwise seem dissimilar if the email case is different. - // Explicitly lower-casing it normalizes for that. - // This comes at the cost of displaying only lower-case emails as well, which seems beneficial. - email.make_ascii_lowercase(); - Self { name, email } + fn from(git::actor::Signature { name, email, .. }: git::actor::Signature) -> Self { + let needs_lowercase = email.chars().any(|c| c.to_ascii_lowercase() != c); + let email_lowercase = needs_lowercase.then(|| email.chars().collect::()); + Self { + name, + email, + email_lowercase, + } + } +} + +impl Eq for Sig {} + +impl PartialEq for Sig { + fn eq(&self, other: &Self) -> bool { + self.cmp(other) == Ordering::Equal + } +} + +impl PartialOrd for Sig { + fn partial_cmp(&self, other: &Self) -> Option { + self.cmp(other).into() + } +} + +impl Ord for Sig { + fn cmp(&self, other: &Self) -> Ordering { + self.email_lowercase + .as_ref() + .and_then(|a_email_lc| { + other + .email_lowercase + .as_ref() + .map(|b_email_lc| (a_email_lc, b_email_lc)) + }) + .map_or_else( + || self.email.cmp(&other.email), + |(a_email_lc, b_email_lc)| a_email_lc.cmp(b_email_lc), + ) } } @@ -98,8 +129,9 @@ impl<'a> Repo<'a> { author_to_number_of_commits.into_iter().collect(); let total_num_authors = authors_by_number_of_commits.len(); - authors_by_number_of_commits - .sort_by(|(sa, a_count), (sb, b_count)| b_count.cmp(a_count).then_with(|| sa.cmp(&sb))); + authors_by_number_of_commits.sort_by(|(sa, a_count), (sb, b_count)| { + b_count.cmp(a_count).then_with(|| sa.name.cmp(&sb.name)) + }); let authors: Vec = authors_by_number_of_commits .into_iter() From 3f94c5138809a67e7d77fd36795d506f896dfd8d Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 31 Mar 2022 13:41:38 +0800 Subject: [PATCH 25/38] thanks clippy --- src/info/repo.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index 138107a98..ec5885686 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -24,7 +24,6 @@ pub struct Repo<'a> { time_of_first_commit: git::actor::Time, } -#[derive(Hash)] pub struct Sig { name: git::bstr::BString, email: git::bstr::BString, @@ -43,6 +42,15 @@ impl From for Sig { } } +impl std::hash::Hash for Sig { + fn hash(&self, state: &mut H) { + self.email_lowercase + .as_ref() + .map(|email_lc| email_lc.hash(state)) + .unwrap_or_else(|| self.email.hash(state)) + } +} + impl Eq for Sig {} impl PartialEq for Sig { From 82fbbb25acd558ee85fe8fa56ab1291d3b7a68b1 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 31 Mar 2022 21:10:54 +0800 Subject: [PATCH 26/38] See if running onefetch on itself can reproduce the crashing on windows --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ae4a8a78..242fbe36c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,6 +44,11 @@ jobs: - name: Run clippy run: cargo clippy + - name: Debug + run: "cat .git/HEAD; git cat-file -p a802f89fc823c6c8cf2467c2b7908e1d78e8b755" + - name: Run onefetch + run: cargo run + rustfmt: name: Rustfmt runs-on: ubuntu-latest From 1a494a933856f4494749ecf66a58161c2a167535 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 31 Mar 2022 21:33:14 +0800 Subject: [PATCH 27/38] support for shallow clones --- .github/workflows/ci.yml | 2 -- src/info/repo.rs | 13 +++++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 242fbe36c..325a82738 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,8 +44,6 @@ jobs: - name: Run clippy run: cargo clippy - - name: Debug - run: "cat .git/HEAD; git cat-file -p a802f89fc823c6c8cf2467c2b7908e1d78e8b755" - name: Run onefetch run: cargo run diff --git a/src/info/repo.rs b/src/info/repo.rs index ec5885686..8d7de35cb 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -105,10 +105,15 @@ impl<'a> Repo<'a> { let mut num_commits = 0; while let Some(commit_id) = commit_iter.next() { - let commit: git::Commit = commit_id? - .object() - .expect("commit is still present/comes from cache") - .into_commit(); + let commit = match commit_id { + Ok(commit_id) => commit_id + .object() + .expect("commit is still present/comes from cache") + .into_commit(), + Err(git::traverse::commit::ancestors::Error::FindExisting { .. }) => break, // assume a shallow clone + Err(err) => return Err(err.into()), + }; + { let commit = commit.decode()?; if no_merges && commit.parents().take(2).count() > 1 { From d3d20eda4dd76720110f70b4992bb9c6483b1f12 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Fri, 1 Apr 2022 07:18:12 +0800 Subject: [PATCH 28/38] Use email and name to identify contributors, similar to what git does `git shortlog -sne | wc -l` is the reference. --- src/info/repo.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index 8d7de35cb..e090a6c85 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -47,7 +47,8 @@ impl std::hash::Hash for Sig { self.email_lowercase .as_ref() .map(|email_lc| email_lc.hash(state)) - .unwrap_or_else(|| self.email.hash(state)) + .unwrap_or_else(|| self.email.hash(state)); + self.name.hash(state); } } @@ -79,6 +80,7 @@ impl Ord for Sig { || self.email.cmp(&other.email), |(a_email_lc, b_email_lc)| a_email_lc.cmp(b_email_lc), ) + .then_with(|| self.name.cmp(&other.name)) } } From eb753f9ca38adcc3e4ad21196bfdd0d1a52c8aa6 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Fri, 1 Apr 2022 07:49:54 +0800 Subject: [PATCH 29/38] =?UTF-8?q?Don't=20peel=20references=20-=20this=20wo?= =?UTF-8?q?uld=20resolve=20remotes/origin/HEAD=20to=20=E2=80=A6main?= =?UTF-8?q?=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …leading to it being displayed twice. --- src/info/repo.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index e090a6c85..373a1903c 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -314,10 +314,9 @@ impl<'a> Repo<'a> { .repo .references()? .all()? - .peeled() .filter_map(Result::ok) .filter_map(|reference: git::Reference<'_>| { - (reference.id() == head_oid + (reference.target().try_id() == Some(&head_oid) && reference.name().category() != Some(git::reference::Category::Tag)) .then(|| reference.name().shorten().to_string()) }) From 927815a5d46f9cc22261ba3796bdee515e139bb1 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Fri, 1 Apr 2022 11:14:50 +0800 Subject: [PATCH 30/38] Make clear that the commit count might be truncated due to shallow cloning --- src/info/repo.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index 373a1903c..da5248b31 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -20,6 +20,8 @@ pub struct Repo<'a> { authors: Vec, total_num_authors: usize, num_commits: usize, + /// false if we have found the first commit that started it all, true if the repository is shallow. + is_shallow: bool, time_of_most_recent_commit: git::actor::Time, time_of_first_commit: git::actor::Time, } @@ -100,6 +102,7 @@ impl<'a> Repo<'a> { let mut time_of_most_recent_commit = None; let mut time_of_first_commit = None; let mut commit_iter = repo.head_commit()?.ancestors().all().peekable(); + let mut is_shallow = false; let mailmap = repo.load_mailmap(); let mut author_to_number_of_commits: HashMap = HashMap::new(); @@ -112,7 +115,10 @@ impl<'a> Repo<'a> { .object() .expect("commit is still present/comes from cache") .into_commit(), - Err(git::traverse::commit::ancestors::Error::FindExisting { .. }) => break, // assume a shallow clone + Err(git::traverse::commit::ancestors::Error::FindExisting { .. }) => { + is_shallow = true; + break; + } Err(err) => return Err(err.into()), }; @@ -174,6 +180,7 @@ impl<'a> Repo<'a> { authors, total_num_authors, num_commits, + is_shallow, time_of_first_commit, time_of_most_recent_commit, }) @@ -184,7 +191,11 @@ impl<'a> Repo<'a> { } pub fn get_number_of_commits(&self) -> String { - self.num_commits.to_string() + format!( + "{}{}", + self.num_commits, + self.is_shallow.then(|| " (shallow)").unwrap_or_default() + ) } pub fn take_authors(&mut self, show_email: bool) -> (Vec, usize) { From b9b65c7eea79b30582be58541554ad35948c909f Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Fri, 1 Apr 2022 12:26:35 +0800 Subject: [PATCH 31/38] Update to use gitoxide's built-in shallow clone detection That way apps using it won't be surprised by default, but instead can upgrade to deal even better with shallow clones by using the data provided in the iterator. --- src/info/repo.rs | 55 ++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index da5248b31..e6f182ce4 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -101,48 +101,36 @@ impl<'a> Repo<'a> { let mut time_of_most_recent_commit = None; let mut time_of_first_commit = None; - let mut commit_iter = repo.head_commit()?.ancestors().all().peekable(); - let mut is_shallow = false; + let mut commit_iter = repo.head_commit()?.ancestors().all(); + let mut commit_iter_peekable = commit_iter.by_ref().peekable(); let mailmap = repo.load_mailmap(); let mut author_to_number_of_commits: HashMap = HashMap::new(); let mut total_nbr_of_commits = 0; let mut num_commits = 0; - while let Some(commit_id) = commit_iter.next() { - let commit = match commit_id { - Ok(commit_id) => commit_id - .object() - .expect("commit is still present/comes from cache") - .into_commit(), - Err(git::traverse::commit::ancestors::Error::FindExisting { .. }) => { - is_shallow = true; - break; - } - Err(err) => return Err(err.into()), - }; + while let Some(commit_id) = commit_iter_peekable.next() { + let commit = commit_id?.object()?.into_commit(); + let commit = commit.decode()?; - { - let commit = commit.decode()?; - if no_merges && commit.parents().take(2).count() > 1 { - continue; - } + if no_merges && commit.parents().take(2).count() > 1 { + continue; + } - if is_bot(commit.author, bot_regex_pattern) { - continue; - } - num_commits += 1; + if is_bot(commit.author, bot_regex_pattern) { + continue; + } + num_commits += 1; - let author_nbr_of_commits = author_to_number_of_commits - .entry(Sig::from(mailmap.resolve(commit.author))) - .or_insert(0); - *author_nbr_of_commits += 1; - total_nbr_of_commits += 1; + let author_nbr_of_commits = author_to_number_of_commits + .entry(Sig::from(mailmap.resolve(commit.author))) + .or_insert(0); + *author_nbr_of_commits += 1; + total_nbr_of_commits += 1; - time_of_most_recent_commit.get_or_insert_with(|| commit.time()); - if commit_iter.peek().is_none() { - time_of_first_commit = commit.time().into(); - } + time_of_most_recent_commit.get_or_insert_with(|| commit.time()); + if commit_iter_peekable.peek().is_none() { + time_of_first_commit = commit.time().into(); } } @@ -173,6 +161,9 @@ impl<'a> Repo<'a> { .and_then(|a| time_of_most_recent_commit.map(|b| (a, b))) .unwrap_or_default(); + let is_shallow = commit_iter + .is_shallow + .expect("BUG: we must deplete the iterator"); drop(commit_iter); Ok(Self { repo, From fb4d449134eff556aac1d14fb95ee9243b0e747e Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sat, 2 Apr 2022 09:35:19 +0800 Subject: [PATCH 32/38] Remove additional deduplication of contributors by email --- src/info/repo.rs | 53 ++---------------------------------------------- 1 file changed, 2 insertions(+), 51 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index e6f182ce4..d7edbb9ee 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -6,7 +6,6 @@ use git2::{Repository, RepositoryOpenFlags, Status, StatusOptions, StatusShow}; use git_repository as git; use git_repository::bstr::ByteSlice; use regex::Regex; -use std::cmp::Ordering; use std::collections::HashMap; use std::path::Path; use time::format_description::well_known::Rfc3339; @@ -26,63 +25,15 @@ pub struct Repo<'a> { time_of_first_commit: git::actor::Time, } +#[derive(Hash, PartialOrd, Ord, Eq, PartialEq)] pub struct Sig { name: git::bstr::BString, email: git::bstr::BString, - email_lowercase: Option, } impl From for Sig { fn from(git::actor::Signature { name, email, .. }: git::actor::Signature) -> Self { - let needs_lowercase = email.chars().any(|c| c.to_ascii_lowercase() != c); - let email_lowercase = needs_lowercase.then(|| email.chars().collect::()); - Self { - name, - email, - email_lowercase, - } - } -} - -impl std::hash::Hash for Sig { - fn hash(&self, state: &mut H) { - self.email_lowercase - .as_ref() - .map(|email_lc| email_lc.hash(state)) - .unwrap_or_else(|| self.email.hash(state)); - self.name.hash(state); - } -} - -impl Eq for Sig {} - -impl PartialEq for Sig { - fn eq(&self, other: &Self) -> bool { - self.cmp(other) == Ordering::Equal - } -} - -impl PartialOrd for Sig { - fn partial_cmp(&self, other: &Self) -> Option { - self.cmp(other).into() - } -} - -impl Ord for Sig { - fn cmp(&self, other: &Self) -> Ordering { - self.email_lowercase - .as_ref() - .and_then(|a_email_lc| { - other - .email_lowercase - .as_ref() - .map(|b_email_lc| (a_email_lc, b_email_lc)) - }) - .map_or_else( - || self.email.cmp(&other.email), - |(a_email_lc, b_email_lc)| a_email_lc.cmp(b_email_lc), - ) - .then_with(|| self.name.cmp(&other.name)) + Self { name, email } } } From 80f4710104ef90a82c07de073964f1691d819fe5 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sun, 3 Apr 2022 11:02:11 +0800 Subject: [PATCH 33/38] switch gitoxide crates from git to crates.io --- Cargo.lock | 82 +++++++++++++++++++++++++++++++++++++++++++----------- Cargo.toml | 2 +- 2 files changed, 66 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4ee75db4..55536cd34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -684,7 +684,9 @@ checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" [[package]] name = "git-actor" -version = "0.8.1" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9da34835e5f98530fa2c13d3b1538589b2d3d37e903c4cfc652dd30a2968bdc5" dependencies = [ "bstr", "btoi", @@ -697,7 +699,9 @@ dependencies = [ [[package]] name = "git-bitmap" -version = "0.0.1" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7715cc94cd761fe92bb5626a332e4886292c7af88984abfdafad82dd56002475" dependencies = [ "quick-error", ] @@ -705,13 +709,17 @@ dependencies = [ [[package]] name = "git-chunk" version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c915097c009d7870a27ee62dcadbf1410f07cdc6c510efcfb8c1011917bd4f22" dependencies = [ "quick-error", ] [[package]] name = "git-config" -version = "0.1.11" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b21a3fec9a7437ebee54c52f1fcb6795bf8e97a5f058d4bde015fc37ff8193a3" dependencies = [ "dirs 4.0.0", "git-features", @@ -724,7 +732,9 @@ dependencies = [ [[package]] name = "git-diff" -version = "0.13.0" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "998568f4940544cbb37dfef9da39b1d3a818df625fd9f417e637df38440dfdd9" dependencies = [ "git-hash", "git-object", @@ -733,7 +743,9 @@ dependencies = [ [[package]] name = "git-features" -version = "0.19.1" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebc06d6b83be53d9c7a00937a6baed4566aad7dba12af11ac830ea72c080af0" dependencies = [ "bstr", "crc32fast", @@ -754,7 +766,9 @@ dependencies = [ [[package]] name = "git-hash" -version = "0.9.2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "106e7c3a08b97285bf0bca7f109e67d286e7fbf34b222faf742443b021de2bb4" dependencies = [ "hex", "quick-error", @@ -763,7 +777,9 @@ dependencies = [ [[package]] name = "git-index" -version = "0.1.0" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c5f876a2eee84018c41c515e982ddf451d1da8b058ba2298f9458b9b55ff8c8" dependencies = [ "atoi", "bitflags", @@ -782,6 +798,8 @@ dependencies = [ [[package]] name = "git-lock" version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade7bf16268f52cf544dd5109c6ee6cad4d524635215b3479ba06bad2eef6e9a" dependencies = [ "fastrand", "git-tempfile", @@ -790,7 +808,9 @@ dependencies = [ [[package]] name = "git-mailmap" -version = "0.0.0" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd3e458fb3f0cda4510169f1f1afb7f4769641151999da0133d2a082b3638f6" dependencies = [ "bstr", "git-actor", @@ -800,7 +820,9 @@ dependencies = [ [[package]] name = "git-object" -version = "0.17.1" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed579fcef038a366a6146acfe61ea74945d137d56366ff50dfe90b1227f6a370" dependencies = [ "bstr", "btoi", @@ -819,6 +841,8 @@ dependencies = [ [[package]] name = "git-odb" version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2f1759675e6a7d886a603d4bc1dab2dd8cf80554b30583fa0ff4ad0a282df1" dependencies = [ "arc-swap", "git-features", @@ -835,6 +859,8 @@ dependencies = [ [[package]] name = "git-pack" version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61defa05833ee427f1e2ce7b184d1203db7b68485da1b0c3fbc6f0d7d86641c1" dependencies = [ "bytesize", "clru", @@ -857,7 +883,9 @@ dependencies = [ [[package]] name = "git-packetline" -version = "0.12.3" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dd72d1851a70ec9dbffb5e70bf59848ae0a5d86bfc3f1d764c65bbf958a881d" dependencies = [ "bstr", "hex", @@ -866,7 +894,9 @@ dependencies = [ [[package]] name = "git-protocol" -version = "0.14.0" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc884ae8963cc6624199c68730da42457cb6cb98e27e6bfae69110bc67cd774e" dependencies = [ "bstr", "btoi", @@ -881,7 +911,9 @@ dependencies = [ [[package]] name = "git-quote" -version = "0.1.0" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec1960fa4f68a1637ce03d8c151ae2f8565d1de119a3eee8b5b9a364a08aacb" dependencies = [ "bstr", "btoi", @@ -891,6 +923,8 @@ dependencies = [ [[package]] name = "git-ref" version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98bd1c0a2dae60c96740eb541a52d813039f6e7e9bc2a92d1626c0906047905d" dependencies = [ "git-actor", "git-features", @@ -908,6 +942,8 @@ dependencies = [ [[package]] name = "git-repository" version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17a9816ad58d09ed8e821b068217a060622bef5a02f3a5c24df36cc244bd09dc" dependencies = [ "byte-unit", "clru", @@ -938,7 +974,9 @@ dependencies = [ [[package]] name = "git-tempfile" -version = "2.0.0" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeeaa7c09e5503b0a8835872c2801807f636f6a9ef6333c28e28f0b00a660535" dependencies = [ "dashmap 5.2.0", "libc", @@ -950,7 +988,9 @@ dependencies = [ [[package]] name = "git-transport" -version = "0.15.0" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "785add28a93f13f8bf1637744bcf40f0d9129f80344e3dd15fca44d1fe42c265" dependencies = [ "bstr", "git-features", @@ -963,7 +1003,9 @@ dependencies = [ [[package]] name = "git-traverse" -version = "0.12.0" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f3e9d3ba80f78964c4b9bbf69fe68c95d1d1ba3a3185e173e31c3bec97aeb1b" dependencies = [ "git-hash", "git-object", @@ -972,7 +1014,9 @@ dependencies = [ [[package]] name = "git-url" -version = "0.3.5" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9766368c3a6c58f5c64e1cb514708a355c92cb654dff20127b76b69a475b15d6" dependencies = [ "bstr", "git-features", @@ -984,6 +1028,8 @@ dependencies = [ [[package]] name = "git-validate" version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58bafc6cd6f455a95997c47823182dd62cdb47f03564c44c6b6d910221801dc" dependencies = [ "bstr", "quick-error", @@ -991,7 +1037,9 @@ dependencies = [ [[package]] name = "git-worktree" -version = "0.0.0" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057b77dc725bd6e55c6c844bacc0f68e7839917a7c7808caab3fcbf010f47d20" dependencies = [ "bstr", "git-features", diff --git a/Cargo.toml b/Cargo.toml index 530a9d88d..723677099 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ bytecount = "0.6.2" clap = {version = "3.1.6", features = ["cargo", "wrap_help"]} color_quant = "1.1.0" git2 = {version = "0.14.2", default-features = false} -git-repository = { version = "0.15.0", git = "https://github.com/Byron/gitoxide", branch = "for-onefetch", features = ["max-performance", "unstable", "serde1"] } +git-repository = { version = "0.15.0", features = ["max-performance", "unstable", "serde1"] } image = "0.24.1" owo-colors = "3.3.0" regex = "1.5.5" From 41594424e79178db1bc2b26ecba4c284aacc11df Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 4 Apr 2022 10:43:18 +0800 Subject: [PATCH 34/38] Improve Cargo.toml dependency declaration --- Cargo.lock | 115 ++++++++++++++++------------------------------------- Cargo.toml | 2 +- 2 files changed, 35 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 55536cd34..519bebbb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,9 +217,9 @@ checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e" [[package]] name = "bytemuck" -version = "1.8.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e851ca7c24871e7336801608a4797d7376545b6928a10d32d75685687141ead" +checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" [[package]] name = "byteorder" @@ -299,9 +299,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.6" +version = "3.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123" +checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c" dependencies = [ "atty", "bitflags", @@ -685,8 +685,6 @@ checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" [[package]] name = "git-actor" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9da34835e5f98530fa2c13d3b1538589b2d3d37e903c4cfc652dd30a2968bdc5" dependencies = [ "bstr", "btoi", @@ -700,8 +698,6 @@ dependencies = [ [[package]] name = "git-bitmap" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7715cc94cd761fe92bb5626a332e4886292c7af88984abfdafad82dd56002475" dependencies = [ "quick-error", ] @@ -709,8 +705,6 @@ dependencies = [ [[package]] name = "git-chunk" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c915097c009d7870a27ee62dcadbf1410f07cdc6c510efcfb8c1011917bd4f22" dependencies = [ "quick-error", ] @@ -718,8 +712,6 @@ dependencies = [ [[package]] name = "git-config" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b21a3fec9a7437ebee54c52f1fcb6795bf8e97a5f058d4bde015fc37ff8193a3" dependencies = [ "dirs 4.0.0", "git-features", @@ -733,8 +725,6 @@ dependencies = [ [[package]] name = "git-diff" version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "998568f4940544cbb37dfef9da39b1d3a818df625fd9f417e637df38440dfdd9" dependencies = [ "git-hash", "git-object", @@ -744,8 +734,6 @@ dependencies = [ [[package]] name = "git-features" version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebc06d6b83be53d9c7a00937a6baed4566aad7dba12af11ac830ea72c080af0" dependencies = [ "bstr", "crc32fast", @@ -767,8 +755,6 @@ dependencies = [ [[package]] name = "git-hash" version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "106e7c3a08b97285bf0bca7f109e67d286e7fbf34b222faf742443b021de2bb4" dependencies = [ "hex", "quick-error", @@ -778,8 +764,6 @@ dependencies = [ [[package]] name = "git-index" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c5f876a2eee84018c41c515e982ddf451d1da8b058ba2298f9458b9b55ff8c8" dependencies = [ "atoi", "bitflags", @@ -798,8 +782,6 @@ dependencies = [ [[package]] name = "git-lock" version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade7bf16268f52cf544dd5109c6ee6cad4d524635215b3479ba06bad2eef6e9a" dependencies = [ "fastrand", "git-tempfile", @@ -809,8 +791,6 @@ dependencies = [ [[package]] name = "git-mailmap" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd3e458fb3f0cda4510169f1f1afb7f4769641151999da0133d2a082b3638f6" dependencies = [ "bstr", "git-actor", @@ -821,8 +801,6 @@ dependencies = [ [[package]] name = "git-object" version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed579fcef038a366a6146acfe61ea74945d137d56366ff50dfe90b1227f6a370" dependencies = [ "bstr", "btoi", @@ -841,8 +819,6 @@ dependencies = [ [[package]] name = "git-odb" version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2f1759675e6a7d886a603d4bc1dab2dd8cf80554b30583fa0ff4ad0a282df1" dependencies = [ "arc-swap", "git-features", @@ -859,8 +835,6 @@ dependencies = [ [[package]] name = "git-pack" version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61defa05833ee427f1e2ce7b184d1203db7b68485da1b0c3fbc6f0d7d86641c1" dependencies = [ "bytesize", "clru", @@ -884,8 +858,6 @@ dependencies = [ [[package]] name = "git-packetline" version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd72d1851a70ec9dbffb5e70bf59848ae0a5d86bfc3f1d764c65bbf958a881d" dependencies = [ "bstr", "hex", @@ -895,8 +867,6 @@ dependencies = [ [[package]] name = "git-protocol" version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc884ae8963cc6624199c68730da42457cb6cb98e27e6bfae69110bc67cd774e" dependencies = [ "bstr", "btoi", @@ -912,8 +882,6 @@ dependencies = [ [[package]] name = "git-quote" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ec1960fa4f68a1637ce03d8c151ae2f8565d1de119a3eee8b5b9a364a08aacb" dependencies = [ "bstr", "btoi", @@ -923,8 +891,6 @@ dependencies = [ [[package]] name = "git-ref" version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98bd1c0a2dae60c96740eb541a52d813039f6e7e9bc2a92d1626c0906047905d" dependencies = [ "git-actor", "git-features", @@ -942,8 +908,6 @@ dependencies = [ [[package]] name = "git-repository" version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17a9816ad58d09ed8e821b068217a060622bef5a02f3a5c24df36cc244bd09dc" dependencies = [ "byte-unit", "clru", @@ -975,8 +939,6 @@ dependencies = [ [[package]] name = "git-tempfile" version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeeaa7c09e5503b0a8835872c2801807f636f6a9ef6333c28e28f0b00a660535" dependencies = [ "dashmap 5.2.0", "libc", @@ -989,8 +951,6 @@ dependencies = [ [[package]] name = "git-transport" version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "785add28a93f13f8bf1637744bcf40f0d9129f80344e3dd15fca44d1fe42c265" dependencies = [ "bstr", "git-features", @@ -1004,8 +964,6 @@ dependencies = [ [[package]] name = "git-traverse" version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f3e9d3ba80f78964c4b9bbf69fe68c95d1d1ba3a3185e173e31c3bec97aeb1b" dependencies = [ "git-hash", "git-object", @@ -1015,8 +973,6 @@ dependencies = [ [[package]] name = "git-url" version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9766368c3a6c58f5c64e1cb514708a355c92cb654dff20127b76b69a475b15d6" dependencies = [ "bstr", "git-features", @@ -1028,8 +984,6 @@ dependencies = [ [[package]] name = "git-validate" version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58bafc6cd6f455a95997c47823182dd62cdb47f03564c44c6b6d910221801dc" dependencies = [ "bstr", "quick-error", @@ -1038,8 +992,6 @@ dependencies = [ [[package]] name = "git-worktree" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057b77dc725bd6e55c6c844bacc0f68e7839917a7c7808caab3fcbf010f47d20" dependencies = [ "bstr", "git-features", @@ -1217,7 +1169,7 @@ dependencies = [ "color_quant", "exr", "gif", - "jpeg-decoder 0.2.3", + "jpeg-decoder 0.2.4", "num-iter", "num-rational", "num-traits", @@ -1228,9 +1180,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" dependencies = [ "autocfg", "hashbrown", @@ -1293,9 +1245,9 @@ checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" [[package]] name = "jpeg-decoder" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55ad40a2d27923f63b6fbde5934926176c69ac5e23da6ac05ebfaca984e163f" +checksum = "744c24117572563a98a7e9168a5ac1ee4a1ca7f702211258797bbe0ed0346c3c" dependencies = [ "rayon", ] @@ -1370,10 +1322,11 @@ checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "lock_api" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" dependencies = [ + "autocfg", "scopeguard", ] @@ -1593,7 +1546,7 @@ dependencies = [ "base64", "byte-unit", "bytecount", - "clap 3.1.6", + "clap 3.1.8", "color_quant", "git-repository", "git2", @@ -1654,7 +1607,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" dependencies = [ "lock_api", - "parking_lot_core 0.9.1", + "parking_lot_core 0.9.2", ] [[package]] @@ -1673,9 +1626,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37" dependencies = [ "cfg-if", "libc", @@ -1809,9 +1762,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "png" @@ -1932,18 +1885,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae183fc1b06c149f0c1793e1eb447c8b04bfe46d48e9e48bfb8d2d7ed64ecf0" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7776223e2696f1aa4c6b0170e83212f47296a00424305117d013dfe86fb0fe55" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", "redox_syscall", @@ -2675,9 +2628,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.32.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825" dependencies = [ "windows_aarch64_msvc", "windows_i686_gnu", @@ -2688,33 +2641,33 @@ dependencies = [ [[package]] name = "windows_aarch64_msvc" -version = "0.32.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" +checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" [[package]] name = "windows_i686_gnu" -version = "0.32.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" +checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" [[package]] name = "windows_i686_msvc" -version = "0.32.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" +checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" [[package]] name = "windows_x86_64_gnu" -version = "0.32.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" +checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" [[package]] name = "windows_x86_64_msvc" -version = "0.32.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" +checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" [[package]] name = "yaml-rust" diff --git a/Cargo.toml b/Cargo.toml index 723677099..049e019f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ section = "utility" [dependencies] anyhow = "1.0" askalono = "0.4.4" -byte-unit = "=4.0.13" # to match git-repository's lower requirement, which it needs for MSRV +byte-unit = "4.0" # to match git-repository's lower requirement, which it needs for MSRV bytecount = "0.6.2" clap = {version = "3.1.6", features = ["cargo", "wrap_help"]} color_quant = "1.1.0" From c6d7cbae0835a3ee21aa88c353f17d885e8164ee Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 4 Apr 2022 10:48:27 +0800 Subject: [PATCH 35/38] Make expect("msg") more informative to help users file an issue Ideally we add more test coverage so users have no chance from ever seeing it. --- src/info/repo.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index d7edbb9ee..e72e4a574 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -112,9 +112,9 @@ impl<'a> Repo<'a> { .and_then(|a| time_of_most_recent_commit.map(|b| (a, b))) .unwrap_or_default(); - let is_shallow = commit_iter - .is_shallow - .expect("BUG: we must deplete the iterator"); + let is_shallow = commit_iter.is_shallow.expect( + "BUG: we must deplete the iterator. If you are seeing this, please let us know at https://github.com/o2sh/onefetch/issues/new", + ); drop(commit_iter); Ok(Self { repo, From d00ab45d3cab26e6c8394c2952d7704dd58b8245 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 4 Apr 2022 11:08:31 +0800 Subject: [PATCH 36/38] refactor: put all commit-traversal related initialization into own struct --- src/info/repo.rs | 59 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/src/info/repo.rs b/src/info/repo.rs index e72e4a574..28ecf2b78 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -13,9 +13,7 @@ use time::OffsetDateTime; use time_humanize::HumanTime; -pub struct Repo<'a> { - git2_repo: &'a Repository, - repo: git::Repository, +pub struct Commits { authors: Vec, total_num_authors: usize, num_commits: usize, @@ -25,6 +23,12 @@ pub struct Repo<'a> { time_of_first_commit: git::actor::Time, } +pub struct Repo<'a> { + git2_repo: &'a Repository, + repo: git::Repository, + commits: Commits, +} + #[derive(Hash, PartialOrd, Ord, Eq, PartialEq)] pub struct Sig { name: git::bstr::BString, @@ -37,15 +41,13 @@ impl From for Sig { } } -impl<'a> Repo<'a> { +impl Commits { pub fn new( - git2_repo: &'a Repository, + mut repo: git::Repository, no_merges: bool, bot_regex_pattern: &Option, number_of_authors_to_display: usize, ) -> Result { - let mut repo = git::open(git2_repo.path())?; - // assure that objects we just traversed are coming from cache // when we read the commit right after. repo.object_cache_size(32 * 1024); @@ -117,8 +119,6 @@ impl<'a> Repo<'a> { ); drop(commit_iter); Ok(Self { - repo, - git2_repo, authors, total_num_authors, num_commits, @@ -127,30 +127,59 @@ impl<'a> Repo<'a> { time_of_most_recent_commit, }) } +} + +impl<'a> Repo<'a> { + pub fn new( + git2_repo: &'a Repository, + no_merges: bool, + bot_regex_pattern: &Option, + number_of_authors_to_display: usize, + ) -> Result { + let repo = git::open(git2_repo.path())?; + let commits = Commits::new( + repo.clone(), + no_merges, + bot_regex_pattern, + number_of_authors_to_display, + )?; + + Ok(Self { + repo, + git2_repo, + commits, + }) + } pub fn get_creation_date(&self, iso_time: bool) -> String { - gitoxide_time_to_formatted_time(self.time_of_first_commit, iso_time) + gitoxide_time_to_formatted_time(self.commits.time_of_first_commit, iso_time) } pub fn get_number_of_commits(&self) -> String { format!( "{}{}", - self.num_commits, - self.is_shallow.then(|| " (shallow)").unwrap_or_default() + self.commits.num_commits, + self.commits + .is_shallow + .then(|| " (shallow)") + .unwrap_or_default() ) } pub fn take_authors(&mut self, show_email: bool) -> (Vec, usize) { if !show_email { - for author in &mut self.authors { + for author in &mut self.commits.authors { author.clear_email(); } } - (std::mem::take(&mut self.authors), self.total_num_authors) + ( + std::mem::take(&mut self.commits.authors), + self.commits.total_num_authors, + ) } pub fn get_date_of_last_commit(&self, iso_time: bool) -> String { - gitoxide_time_to_formatted_time(self.time_of_most_recent_commit, iso_time) + gitoxide_time_to_formatted_time(self.commits.time_of_most_recent_commit, iso_time) } // This collects the repo size excluding .git From 7b34b0aef20b1bc1dfd5de56596d3dca53e28d3e Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 4 Apr 2022 11:16:48 +0800 Subject: [PATCH 37/38] refactor: completely separate `Commits` and `Repo` structure --- src/info/mod.rs | 28 +++++++++++++----------- src/info/repo.rs | 56 ++++++++++++++++-------------------------------- 2 files changed, 34 insertions(+), 50 deletions(-) diff --git a/src/info/mod.rs b/src/info/mod.rs index 4412dfd5d..437498111 100644 --- a/src/info/mod.rs +++ b/src/info/mod.rs @@ -1,4 +1,5 @@ use crate::cli::{self, Config}; +use crate::repo::Commits; use crate::ui::get_ascii_colors; use crate::ui::text_colors::TextColors; use anyhow::{Context, Result}; @@ -183,23 +184,24 @@ impl Info { } }); - let mut internal_repo = Repo::new( - &repo, + let repo = Repo::new(&repo)?; + let mut commits = Commits::new( + repo.gitoxide(), config.no_merges, &config.bot_regex_pattern, config.number_of_authors, )?; - let (repo_name, repo_url) = internal_repo.get_name_and_url()?; - let head_refs = internal_repo.get_head_refs()?; - let version = internal_repo.get_version()?; - let git_username = internal_repo.get_git_username()?; - let number_of_tags = internal_repo.get_number_of_tags()?; - let number_of_branches = internal_repo.get_number_of_branches()?; - let creation_date = internal_repo.get_creation_date(config.iso_time); - let number_of_commits = internal_repo.get_number_of_commits(); - let (authors, contributors) = internal_repo.take_authors(config.show_email); - let last_change = internal_repo.get_date_of_last_commit(config.iso_time); - let (repo_size, file_count) = internal_repo.get_repo_size(); + let (repo_name, repo_url) = repo.get_name_and_url()?; + let head_refs = repo.get_head_refs()?; + let version = repo.get_version()?; + let git_username = repo.get_git_username()?; + let number_of_tags = repo.get_number_of_tags()?; + let number_of_branches = repo.get_number_of_branches()?; + let creation_date = commits.get_creation_date(config.iso_time); + let number_of_commits = commits.count(); + let (authors, contributors) = commits.take_authors(config.show_email); + let last_change = commits.get_date_of_last_commit(config.iso_time); + let (repo_size, file_count) = repo.get_repo_size(); let license = Detector::new()?.get_license(&workdir)?; let dependencies = DependencyDetector::new().get_dependencies(&workdir)?; diff --git a/src/info/repo.rs b/src/info/repo.rs index 28ecf2b78..648ea38ba 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -26,7 +26,6 @@ pub struct Commits { pub struct Repo<'a> { git2_repo: &'a Repository, repo: git::Repository, - commits: Commits, } #[derive(Hash, PartialOrd, Ord, Eq, PartialEq)] @@ -127,59 +126,42 @@ impl Commits { time_of_most_recent_commit, }) } -} - -impl<'a> Repo<'a> { - pub fn new( - git2_repo: &'a Repository, - no_merges: bool, - bot_regex_pattern: &Option, - number_of_authors_to_display: usize, - ) -> Result { - let repo = git::open(git2_repo.path())?; - let commits = Commits::new( - repo.clone(), - no_merges, - bot_regex_pattern, - number_of_authors_to_display, - )?; - - Ok(Self { - repo, - git2_repo, - commits, - }) - } pub fn get_creation_date(&self, iso_time: bool) -> String { - gitoxide_time_to_formatted_time(self.commits.time_of_first_commit, iso_time) + gitoxide_time_to_formatted_time(self.time_of_first_commit, iso_time) } - pub fn get_number_of_commits(&self) -> String { + pub fn count(&self) -> String { format!( "{}{}", - self.commits.num_commits, - self.commits - .is_shallow - .then(|| " (shallow)") - .unwrap_or_default() + self.num_commits, + self.is_shallow.then(|| " (shallow)").unwrap_or_default() ) } pub fn take_authors(&mut self, show_email: bool) -> (Vec, usize) { if !show_email { - for author in &mut self.commits.authors { + for author in &mut self.authors { author.clear_email(); } } - ( - std::mem::take(&mut self.commits.authors), - self.commits.total_num_authors, - ) + (std::mem::take(&mut self.authors), self.total_num_authors) } pub fn get_date_of_last_commit(&self, iso_time: bool) -> String { - gitoxide_time_to_formatted_time(self.commits.time_of_most_recent_commit, iso_time) + gitoxide_time_to_formatted_time(self.time_of_most_recent_commit, iso_time) + } +} + +impl<'a> Repo<'a> { + pub fn new(git2_repo: &'a Repository) -> Result { + let repo = git::open(git2_repo.path())?; + + Ok(Self { repo, git2_repo }) + } + + pub fn gitoxide(&self) -> git::Repository { + self.repo.clone() } // This collects the repo size excluding .git From b6cd415d049b24348150e0e2088f2fdb5822e1cb Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 4 Apr 2022 11:18:10 +0800 Subject: [PATCH 38/38] refactor: git2 repository can now be owned by the `Repo` type Previously this wasn't possible as commits would be kept in `Repo` which would cause self-referential borrow check issues unless the git2 repository was kept outside. --- src/info/mod.rs | 9 +++++---- src/info/repo.rs | 8 ++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/info/mod.rs b/src/info/mod.rs index 437498111..62eaeca6d 100644 --- a/src/info/mod.rs +++ b/src/info/mod.rs @@ -184,7 +184,7 @@ impl Info { } }); - let repo = Repo::new(&repo)?; + let repo = Repo::new(repo)?; let mut commits = Commits::new( repo.gitoxide(), config.no_merges, @@ -197,13 +197,14 @@ impl Info { let git_username = repo.get_git_username()?; let number_of_tags = repo.get_number_of_tags()?; let number_of_branches = repo.get_number_of_branches()?; + let (repo_size, file_count) = repo.get_repo_size(); + let license = Detector::new()?.get_license(&workdir)?; + let dependencies = DependencyDetector::new().get_dependencies(&workdir)?; + let creation_date = commits.get_creation_date(config.iso_time); let number_of_commits = commits.count(); let (authors, contributors) = commits.take_authors(config.show_email); let last_change = commits.get_date_of_last_commit(config.iso_time); - let (repo_size, file_count) = repo.get_repo_size(); - let license = Detector::new()?.get_license(&workdir)?; - let dependencies = DependencyDetector::new().get_dependencies(&workdir)?; let pending_changes = pending_changes .join() diff --git a/src/info/repo.rs b/src/info/repo.rs index 648ea38ba..3a0764936 100644 --- a/src/info/repo.rs +++ b/src/info/repo.rs @@ -23,8 +23,8 @@ pub struct Commits { time_of_first_commit: git::actor::Time, } -pub struct Repo<'a> { - git2_repo: &'a Repository, +pub struct Repo { + git2_repo: Repository, repo: git::Repository, } @@ -153,8 +153,8 @@ impl Commits { } } -impl<'a> Repo<'a> { - pub fn new(git2_repo: &'a Repository) -> Result { +impl Repo { + pub fn new(git2_repo: Repository) -> Result { let repo = git::open(git2_repo.path())?; Ok(Self { repo, git2_repo })