diff options
Diffstat (limited to 'vendor/gix-features')
30 files changed, 4176 insertions, 0 deletions
diff --git a/vendor/gix-features/.cargo-checksum.json b/vendor/gix-features/.cargo-checksum.json new file mode 100644 index 000000000..14b6a61d4 --- /dev/null +++ b/vendor/gix-features/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"9c722584b07c154a9b92e2fb2db53aaaa0e2604a43703c6c0230cf07253e1d55","Cargo.toml":"29a3ce857f725c72c163aee07f776269d50be36b5c3f08cc3389cc3b8e2c08ea","src/cache.rs":"0ae91d58914d8e6ac2d2d6fa52522364db6ea8e81421614a36b4009a184a4705","src/decode.rs":"bf614320c6b69556da40d8412c73fb6a8648c80b7d75b9b2525eb62ac6c8d802","src/fs.rs":"0f7d98d943c642bc0fcbdf51990ee8d557397515f85be9e858f290468d0812b4","src/hash.rs":"95c5fe92beb1807b269bb86764c7ebb49363167a3d97931e06a20643b4c68f5e","src/interrupt.rs":"e9e91b50eadae55e4b2ca33482093697960a9dd4c3b7eaf7d1efb0dce495aa1e","src/io.rs":"6e4b80ce21d914e670629e9dbda13a8ebf0f523beb9036558236a94d00e88311","src/lib.rs":"e7ffd154849245bacb1f9c00e709b0b1c8d338755d7624507fbf3fd0adeffc0a","src/parallel/eager_iter.rs":"3bfb3e44478243afb7bfc68089c4c715131c2ce6d494450ce408001a28bf4dc9","src/parallel/in_order.rs":"a1c8c2f6ee4a91d6103f3fc6f27525e309cccc49ffc661d1403dbcdc57d120ad","src/parallel/in_parallel.rs":"d7182854eccf0f5d0af589f5efec02d0c14bbe9906920311e5d7516ddcc4fc31","src/parallel/mod.rs":"d74cf6da2ec807fbb34e75370470f34e5cbd9ae3440e5bac0d7def1167978521","src/parallel/reduce.rs":"3ed124c86af1860dbb07f01ad0249714955327c687bda7ee024cf3a3baf94186","src/parallel/serial.rs":"3cabe5acced4c0bbd79c71042c4fe71fb42bc8503416147bf7e94f14d1c66ebc","src/progress.rs":"714f17c069e8da215cb6359a1934d555121d302d3d4179d793e914f9bc488cf7","src/threading.rs":"241bec714a4ff6d94cf74804ac7e3ac172bda5394be799df4958740cf48e4bbb","src/zlib/mod.rs":"fd27b104abe2d93b71123e4f16640bc32703d6d09ba8e800c430dcfd72a07b06","src/zlib/stream/deflate/mod.rs":"8a69ea48012633f322e6bccc14dccaa29e8960bad7135f4abe924a38afc73c59","src/zlib/stream/deflate/tests.rs":"1a42b2c4fdbe8383d75ebdaae825c9ab0ac03a461e2177026e6be57c1101b37e","src/zlib/stream/inflate.rs":"d5bb3b858e42aecb263f2b24f110fffe22e94b507e963f156831868119dc3f20","src/zlib/stream/mod.rs":"0af2967eb75a07308c789a4187490cc7c36693b7f7d8a4f7705f3b4b90568f6f","tests/hash.rs":"d03f99e2ed1f00066e14212e7e65ee3ae076df42935d38c47d5a563b69367e8c","tests/parallel/in_order_iter.rs":"acd746c25929406748de5080b7ae5dcb2516269f037944d7aa84802520b885b4","tests/parallel/mod.rs":"c6b6d1b1db1a59f07fac93ed7ce10558a46eba38cfa3fc50659d3262ce58e313","tests/parallel_shared.rs":"5d8dabaa42fce087e2ec57843cfe69f2be1ca2fa3518030b5a31aeaa706675e0","tests/parallel_shared_threaded.rs":"5d8dabaa42fce087e2ec57843cfe69f2be1ca2fa3518030b5a31aeaa706675e0","tests/parallel_threaded.rs":"02cfb39c7e81bca7e92a851c731e993cad13eff87ec1f8a228d74761ec964f7a","tests/pipe.rs":"54c070bb8dc5f6b495131ff4342a715b0e6491a68d2477143eeb76b7d05f4019"},"package":"5e6a9dfa7b3c1a99315203e8b97f8f99f3bd95731590607abeaa5ca31bc41fe3"}
\ No newline at end of file diff --git a/vendor/gix-features/CHANGELOG.md b/vendor/gix-features/CHANGELOG.md new file mode 100644 index 000000000..7f34fbe23 --- /dev/null +++ b/vendor/gix-features/CHANGELOG.md @@ -0,0 +1,1174 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 0.28.0 (2023-03-04) + +### New Features (BREAKING) + + - <csr-id-571ec0d7c3e1eb167d55daa6551bd2b27d3c5b25/> use `std::thread::scope()` instead of `crossbeam-utils::thread::scope()`. + This cuts a direct dependency. + We can't removed `crossbeam-channel` yet due to the need for single-produce-multiple-consumer + channels. + +### Commit Statistics + +<csr-read-only-do-not-edit/> + + - 3 commits contributed to the release over the course of 1 calendar day. + - 3 days passed between releases. + - 1 commit was understood as [conventional](https://www.conventionalcommits.org). + - 0 issues like '(#ID)' were seen in commit messages + +### Commit Details + +<csr-read-only-do-not-edit/> + +<details><summary>view details</summary> + + * **Uncategorized** + - Prepare changelogs prior to release of `gix-pack` ([`6db30ef`](https://github.com/Byron/gitoxide/commit/6db30ef6b5e931bbf12135507a3d922051de4d4b)) + - Merge branch 'adjustments-for-cargo' ([`04ab852`](https://github.com/Byron/gitoxide/commit/04ab852f3be76bdf151affa25cf4b999b127bdfe)) + - Use `std::thread::scope()` instead of `crossbeam-utils::thread::scope()`. ([`571ec0d`](https://github.com/Byron/gitoxide/commit/571ec0d7c3e1eb167d55daa6551bd2b27d3c5b25)) +</details> + +## 0.27.0 (2023-03-01) + +<csr-id-cce96ee1382d3d56d77820a2aba6e2d17b52f91c/> + +### Chore + + - <csr-id-cce96ee1382d3d56d77820a2aba6e2d17b52f91c/> replace `quick-error` with `thiserror` + This increases the compile time of the crate alone if there is no proc-macro + in the dependency tree, but will ever so slightly improve compile times for `gix` + as a whole. + +### New Features + + - <csr-id-7a442313c57f58fec5217484f268516711c3d52b/> make `bytesize` available in `progress`. + Note that it is stubbed out unless the `progress-unit-bytes` feature is set. + - <csr-id-7f6a807ea506358b6dc4fd0c7a648770f1dc91e9/> add `progress::count_with_decimals()` and `progress-unit-*` feature toggles. + The new feature toggles allow controlling the inclusion of the `bytesize` and `human_format` + crates, which can be toggled with the `progress-unit-bytes` and `progress-unit-human-numbers` respectively. + + Without these features, the respective functions exist but don't provide special formatting, making bytes and + larger numbers harder to read. + +### Bug Fixes + + - <csr-id-264f78a508d3030cb346623f57ac75add7682169/> remove `num_cpus` in favor of `std::thread::available_parallelism()`. + `num_cpus` was needed back in the days when `std` didn't support such + functionality yet. + +### Changed (BREAKING) + + - <csr-id-0cc548041a861be21001462cbe0ef29b1d61d1c4/> use new `dep:` syntax to hide optional features from feature-set. + That way, the set of features is clearly defined and controlled. + This migth break applications who relied on direect access to features named + after optional dependencies. + +### Commit Statistics + +<csr-read-only-do-not-edit/> + + - 11 commits contributed to the release over the course of 3 calendar days. + - 8 days passed between releases. + - 5 commits were understood as [conventional](https://www.conventionalcommits.org). + - 0 issues like '(#ID)' were seen in commit messages + +### Commit Details + +<csr-read-only-do-not-edit/> + +<details><summary>view details</summary> + + * **Uncategorized** + - Release gix-features v0.27.0, gix-actor v0.18.0, gix-quote v0.4.3, gix-attributes v0.9.0, gix-object v0.27.0, gix-ref v0.25.0, gix-config v0.17.0, gix-url v0.14.0, gix-credentials v0.10.0, gix-diff v0.27.0, gix-discover v0.14.0, gix-hashtable v0.1.2, gix-bitmap v0.2.2, gix-traverse v0.23.0, gix-index v0.13.0, gix-mailmap v0.10.0, gix-pack v0.31.0, gix-odb v0.41.0, gix-transport v0.26.0, gix-protocol v0.27.0, gix-revision v0.11.0, gix-refspec v0.8.0, gix-worktree v0.13.0, gix v0.38.0 ([`e6cc618`](https://github.com/Byron/gitoxide/commit/e6cc6184a7a49dbc2503c1c1bdd3688ca5cec5fe)) + - Adjust manifests prior to release ([`addd789`](https://github.com/Byron/gitoxide/commit/addd78958fdd1e54eb702854e96079539d01965a)) + - Prepare changelogs prior to release ([`94c99c7`](https://github.com/Byron/gitoxide/commit/94c99c71520f33269cc8dbc26f82a74747cc7e16)) + - Merge branch 'adjustments-for-cargo' ([`d686d94`](https://github.com/Byron/gitoxide/commit/d686d94e1030a8591ba074757d56927a346c8351)) + - Depend on latest version of `prodash` for performance improvements. ([`5d00324`](https://github.com/Byron/gitoxide/commit/5d003242abe82b1604e2188d49dec9690ebb2a6a)) + - Make `bytesize` available in `progress`. ([`7a44231`](https://github.com/Byron/gitoxide/commit/7a442313c57f58fec5217484f268516711c3d52b)) + - Add `progress::count_with_decimals()` and `progress-unit-*` feature toggles. ([`7f6a807`](https://github.com/Byron/gitoxide/commit/7f6a807ea506358b6dc4fd0c7a648770f1dc91e9)) + - Use new `dep:` syntax to hide optional features from feature-set. ([`0cc5480`](https://github.com/Byron/gitoxide/commit/0cc548041a861be21001462cbe0ef29b1d61d1c4)) + - Remove `num_cpus` in favor of `std::thread::available_parallelism()`. ([`264f78a`](https://github.com/Byron/gitoxide/commit/264f78a508d3030cb346623f57ac75add7682169)) + - Replace `quick-error` with `thiserror` ([`cce96ee`](https://github.com/Byron/gitoxide/commit/cce96ee1382d3d56d77820a2aba6e2d17b52f91c)) + - Make fmt ([`8ef1cb2`](https://github.com/Byron/gitoxide/commit/8ef1cb293434c7b9e1fda4a6963368e0435920a9)) +</details> + +## 0.26.5 (2023-02-20) + +### Bug Fixes + + - <csr-id-e14dc7d475373d2c266e84ff8f1826c68a34ab92/> note that crates have been renamed from `git-*` to `gix-*`. + This also means that the `git-*` prefixed crates of the `gitoxide` project + are effectively unmaintained. + Use the crates with the `gix-*` prefix instead. + + If you were using `git-repository`, then `gix` is its substitute. + - <csr-id-135d317065aae87af302beb6c26bb6ca8e30b6aa/> compatibility with `bstr` v1.3, use `*.as_bytes()` instead of `.as_ref()`. + `as_ref()` relies on a known target type which isn't always present. However, once + there is only one implementation, that's no problem, but when that changes compilation + fails due to ambiguity. + +### Commit Statistics + +<csr-read-only-do-not-edit/> + + - 2 commits contributed to the release. + - 3 days passed between releases. + - 1 commit was understood as [conventional](https://www.conventionalcommits.org). + - 0 issues like '(#ID)' were seen in commit messages + +### Commit Details + +<csr-read-only-do-not-edit/> + +<details><summary>view details</summary> + + * **Uncategorized** + - Release gix-date v0.4.3, gix-hash v0.10.3, gix-features v0.26.5, gix-actor v0.17.2, gix-glob v0.5.5, gix-path v0.7.2, gix-quote v0.4.2, gix-attributes v0.8.3, gix-validate v0.7.3, gix-object v0.26.2, gix-ref v0.24.1, gix-config v0.16.2, gix-command v0.2.4, gix-url v0.13.3, gix-credentials v0.9.2, gix-discover v0.13.1, gix-index v0.12.4, gix-mailmap v0.9.3, gix-pack v0.30.3, gix-packetline v0.14.3, gix-transport v0.25.6, gix-protocol v0.26.4, gix-revision v0.10.4, gix-refspec v0.7.3, gix-worktree v0.12.3, gix v0.36.1 ([`9604783`](https://github.com/Byron/gitoxide/commit/96047839a20a657a559376b0b14c65aeab96acbd)) + - Compatibility with `bstr` v1.3, use `*.as_bytes()` instead of `.as_ref()`. ([`135d317`](https://github.com/Byron/gitoxide/commit/135d317065aae87af302beb6c26bb6ca8e30b6aa)) +</details> + +## 0.26.4 (2023-02-17) + +<csr-id-5bf0034fb3918e57562b7089ceba83d63a1854bf/> +<csr-id-ab6f98b905f13ed2a7c0c483f34fab63141fbc5b/> +<csr-id-f7f136dbe4f86e7dee1d54835c420ec07c96cd78/> +<csr-id-361892ca15aa648802f6701ab6a5a30aedde3449/> + +### New Features (BREAKING) + + - <csr-id-0f27c67c92fc0bc23a6712b5c4c730ad6a0156bf/> add support for explicit non-parallel iteration. + That way we can allow the implementation to choose whether they + need greatest speed at some cost or not. + + This also allows us to create a new thread-pool on each iteration + as those who expect high cost or many files will likely chose to do + that instead of single-threaded iteration, which nicely contains the + threads needed and avoids keeping them alive as part of some global pool. + - <csr-id-3b29fc18672c0176684c797a0f16f85d09369bf8/> make jwalk fully optional + - <csr-id-d078d6ee76a80d1dfaf71608c12d8a402bd670d4/> mild refactor of paths module to waste less on unix + Previously it might have performed find-and-replace on unix paths even + though they wouldn't have changed afterwards, yet costing an allocation. + + There is also the realization that it should go into its own crate to have + neater import paths and more convenience. + - <csr-id-8945d95f7fa88562d37ff67ac6e38bead73dd2df/> `interrupt::Iter`, rename `interrupt::Iter` -> `interrupt::IterWithError` + +### Chore (BREAKING) + + - <csr-id-5bf0034fb3918e57562b7089ceba83d63a1854bf/> upgrade to prodash v23 + +### Changed (BREAKING) + + - <csr-id-38446dc8824afef30ef121598de3451d13b9262c/> remove `fs-jwalk-single-threaded` in favor of `fs-walkdir-parallel`. + This way, `jwalk` and the dependencies (and troubles) it brings have to + be opted in, but also allow other users to actually opt out while + allowing the `parallel` feature to be in effect. + + In other words, previously the `parallel` feature conflated `jwalk` + dependencies into the tree, which isn't the case anymore. + - <csr-id-89a41bf2b37db29b9983b4e5492cfd67ed490b23/> remove local-time-support feature toggle. + We treat local time as default feature without a lot of fuzz, and + will eventually document that definitive support needs a compile + time switch in the compiler (`--cfg unsound_local_offset` or something). + + One day it will perish. Failure is possible anyway and we will write + code to deal with it while minimizing the amount of system time + fetches when asking for the current local time. + - <csr-id-90611ce1527618bcc738440bfc1ccc7a45319974/> remove `path` module in favor of `git-path` crate + - <csr-id-61e5cfece4d8f405e35fc1957b00ce1da7526c26/> renamed `progress::Read::reader` -> `progress::Read::inner` + - <csr-id-e7526b2a7b51cbac4018e1ab3b623a85987fadc2/> parallel utilities now use `Send + Clone` insted of `Send + Sync` + This helps to assure that thread-local computations always work with the + kind of types we provide. The ones that are carrying out actions are + notably not `Sync` anymore. + + We cater to that by defining our bounds accordingly, but for those + who want to use other utilities that need Sync, using types like + `Repository` and `thread_local!()` is the only way to make this + work. + +### Other + + - <csr-id-ab6f98b905f13ed2a7c0c483f34fab63141fbc5b/> try-join with static typing works, but… + …seems like a lot of effort. Probably not worth continuing here + +### Bug Fixes + + - <csr-id-234cd10ca55482ce1a840ce3244308d249895bcc/> Assure std::io::copy() doesn't hang when we cause an interrupt + The user can ask for interruptions which previously used the + error kind Interrupted. This however has special meaning and + usually means to retry. + +### Documentation + + - <csr-id-39ed9eda62b7718d5109135e5ad406fb1fe2978c/> fix typos + +### Chore + + - <csr-id-f7f136dbe4f86e7dee1d54835c420ec07c96cd78/> uniformize deny attributes + - <csr-id-361892ca15aa648802f6701ab6a5a30aedde3449/> update sha-1 dependency to 0.10 + +### New Features + + - <csr-id-a3bd14a7753716e7ad67cd56d24eee1fa099a6fd/> re-export `prodash::progress::(Task|Value)` directly under `progress` + This is in addition to the `progress` re-export which allows everything + but yields less optimal import paths. + - <csr-id-426057247a80821b3da22b4ae5d67bda89ce0631/> re-export `prodash` in `progress` module. + That way one can access all types even if they are not re-exported. + - <csr-id-c4a7634b0b29c74625e183953e59c65987e9d66c/> export `prodash::progress::Id` in the `progress` module for convenience. + - <csr-id-25ad372bf500b851105f53b10369b5a689ba167e/> zlib::inflate::Error can now represent zlib status codes that represent failure. + - <csr-id-6d530a1dc77f0f4ac00622a2fd47c7bdb731a77a/> name spawned threads + That way it's a bit more obvious what's happening when the CPU goes + up in flames. + - <csr-id-c8835c6edae784c9ffcb69a674c0a6545dbb2af3/> upgrade to `prodash 21.1` and add `Ids` to all progress instances. + That way callers can identify progress they are interested in, say, for + selective visualizations. + - <csr-id-9076ce33ec167e425a0163d3e40a81a3fd0db6cd/> `fs::Snapshot` can `Clone` if `T` can `Clone`. + - <csr-id-a7c11d2cb5f88a4ff322d9a9848459062790d8b3/> perfect granularity for threads processing with `in_parallel_with_slice()` + - <csr-id-ff1db66f2dad3afc8bc77610006bca9fea5947d2/> add `progress::Step|StepShared` as types of `prodash` + This may help to use the `Progress::counter()` method as part of method + signatures, being an `Option<progress::StepShared>`. + - <csr-id-cfe46b502afc3ecb312849ddbd7748007d432cd1/> add zlib-ng feature to allow linking against system libz-ng + Allow to use zlib-ng (zlib-ng-sys) with native API (no compat mode) + that can co-exist with system libz (loaded by e.g. libcurl). + This is used in gitoxide package on Alpine Linux. + - <csr-id-b1c40b0364ef092cd52d03b34f491b254816b18d/> use docsrs feature in code to show what is feature-gated automatically on docs.rs + - <csr-id-517677147f1c17304c62cf97a1dd09f232ebf5db/> pass --cfg docsrs when compiling for https://docs.rs + - <csr-id-f498d35baba52e40ecd47381e87c1ce49cf13285/> add `fs-jwalk-single-threaded` feature to specifically decouple `jwalk` from rayon + It has been an issue in https://github.com/starship/starship/issues/4251 + apparently and rayon interactions can be difficult. + - <csr-id-7f199f0e5246809efde9880110093fbd11a4f8fe/> `fs::Snapshot` to on-demand reload shared resources. + - <csr-id-c76fde7de278b49ded13b655d5345e4eb8c1b134/> initialize `Time` from `now_utc` and `now_local` + Localtime support depends on some other factors now, but that + will only get better over time. + + We might have to document `unsound_local_time` at some point. + - <csr-id-e4d6685064ad2b433f8acd3a74b320bf0169a994/> Add `git_config::values::Path` for a typesafe git path + Add a `Path` type to the `git_config::values` which + can be interpolated according to gits own path interpolation + rules. + - <csr-id-3c8581fc294c65c9eb42698969fe3263135a864e/> add new 'path' module for all path-related conversions + It's meant to unify all path and byte related handling to help assuring + encoding is handled correctly or at least similarly everywhere. + - <csr-id-15ff212b17087de93f259e366f4e4b821cfbc28e/> in-manifest and in-lib documentation of feature toggles + - <csr-id-cb7e4e784d615f9fa3d6fb9c36240f0592403358/> Add InOrderIter to 'parallel' module + This iterator makes possible identifies results using a sequence id + and returns only consecutive items. + + Use it to collect unordered results produced by threads. + It's advantage to collecting yourself and sorting is the potential + for a smaller memory footprint of in-flight results, one doesn't + have to collect them all for ordering, necessarily. + - <csr-id-ca095ed881db2a8f06a6b067dbaac17e923b0945/> Make a scope-like abstraction available + This allows more delicate threading control like is required for the + index. + - <csr-id-b8400ed80543d67a5895c975ba9b1fc28427411c/> decoding of variable int numbers. + It's here only so that we can share the code across crates, for now + without any feature toggles. + - <csr-id-0a749a22057b5513a8cefa0e26b0a9a268c769d3/> Add `progress::Write` to automatically pass bytes written to a progress instance + - <csr-id-7e95d8ab29051ffc892f2dcbaf5369e8c7e7b294/> add threading primitives with feature toggle + If the `threading` feature is set, the `threading` module will contain thread-safe primitives + for shared ownership and mutation, otherwise these will be their single threaded counterparts. + + This way, single-threaded applications don't have to pay for threaded primitives. + +### Commit Statistics + +<csr-read-only-do-not-edit/> + + - 509 commits contributed to the release over the course of 962 calendar days. + - 38 commits were understood as [conventional](https://www.conventionalcommits.org). + - 21 unique issues were worked on: [#198](https://github.com/Byron/gitoxide/issues/198), [#222](https://github.com/Byron/gitoxide/issues/222), [#259](https://github.com/Byron/gitoxide/issues/259), [#263](https://github.com/Byron/gitoxide/issues/263), [#266](https://github.com/Byron/gitoxide/issues/266), [#279](https://github.com/Byron/gitoxide/issues/279), [#287](https://github.com/Byron/gitoxide/issues/287), [#293](https://github.com/Byron/gitoxide/issues/293), [#298](https://github.com/Byron/gitoxide/issues/298), [#301](https://github.com/Byron/gitoxide/issues/301), [#329](https://github.com/Byron/gitoxide/issues/329), [#331](https://github.com/Byron/gitoxide/issues/331), [#333](https://github.com/Byron/gitoxide/issues/333), [#366](https://github.com/Byron/gitoxide/issues/366), [#427](https://github.com/Byron/gitoxide/issues/427), [#450](https://github.com/Byron/gitoxide/issues/450), [#470](https://github.com/Byron/gitoxide/issues/470), [#503](https://github.com/Byron/gitoxide/issues/503), [#524](https://github.com/Byron/gitoxide/issues/524), [#63](https://github.com/Byron/gitoxide/issues/63), [#691](https://github.com/Byron/gitoxide/issues/691) + +### Commit Details + +<csr-read-only-do-not-edit/> + +<details><summary>view details</summary> + + * **[#198](https://github.com/Byron/gitoxide/issues/198)** + - Handle changelogs with upcoming version section if they were left for editing ([`0f5f47d`](https://github.com/Byron/gitoxide/commit/0f5f47da4662b596cbbbd9c0d83e135e2cc52c11)) + - Deduplicate conventional message ids ([`e695eda`](https://github.com/Byron/gitoxide/commit/e695eda8cd183f703d9a3e59b7c3c7fa496ea1d2)) + - Regenerate all changelogs to get links ([`0c81769`](https://github.com/Byron/gitoxide/commit/0c817690bd444f52bed2936b2b451cafd87dde92)) + - Mention actual issues that where worked on ([`a517e39`](https://github.com/Byron/gitoxide/commit/a517e39a81145b331f6c7a6cc2fc22e25daf42e2)) + - Allow 'refactor' and 'other' in conventional messages if they have breaking changes ([`4eebaac`](https://github.com/Byron/gitoxide/commit/4eebaac669e590beed112b622752997c64772ef1)) + - New changelogs for actor and features crates ([`e0d437c`](https://github.com/Byron/gitoxide/commit/e0d437c4cfa06e0792609f41ed5876c390634921)) + * **[#222](https://github.com/Byron/gitoxide/issues/222)** + - Update changelogs prior to release ([`9a493d0`](https://github.com/Byron/gitoxide/commit/9a493d0651b0b6d71cf230dc510a658be7f8cb19)) + - Stabilize changelogs ([`920e832`](https://github.com/Byron/gitoxide/commit/920e83219911df1c440d3fe42fd5ec3a295b0bb8)) + - Update changelogs prior to release ([`b3e2252`](https://github.com/Byron/gitoxide/commit/b3e2252f7461a003d9a4612da60ba931dd8c0bef)) + * **[#259](https://github.com/Byron/gitoxide/issues/259)** + - Unify trait bounds for parallel code: prefer Clone over Sync ([`c805d0b`](https://github.com/Byron/gitoxide/commit/c805d0b231cf4d2f51dae7705bfbbc6562f86c32)) + - Remove trait bounds to allow single-threaded applications to exist ([`3c790e0`](https://github.com/Byron/gitoxide/commit/3c790e01de0dbd3ffa2683d5cf060723d11d64a5)) + * **[#263](https://github.com/Byron/gitoxide/issues/263)** + - Make it possible to return read guards with packed buffers ([`f5c3c8f`](https://github.com/Byron/gitoxide/commit/f5c3c8f7309bf53b9e53f786e75931d701a8585c)) + - Parallel utilities now use `Send + Clone` insted of `Send + Sync` ([`e7526b2`](https://github.com/Byron/gitoxide/commit/e7526b2a7b51cbac4018e1ab3b623a85987fadc2)) + - A mad attempt to use thread-local everywhere and avoid Sync… ([`0af5077`](https://github.com/Byron/gitoxide/commit/0af5077e1f028c1c69bbdc098bb567e486282c37)) + - Add threading primitives with feature toggle ([`7e95d8a`](https://github.com/Byron/gitoxide/commit/7e95d8ab29051ffc892f2dcbaf5369e8c7e7b294)) + * **[#266](https://github.com/Byron/gitoxide/issues/266)** + - Update sha-1 dependency to 0.10 ([`361892c`](https://github.com/Byron/gitoxide/commit/361892ca15aa648802f6701ab6a5a30aedde3449)) + - Remove slow/unnecessary threading utilities ([`269b7ef`](https://github.com/Byron/gitoxide/commit/269b7efc47bb1d6380b2059f63bd0c53fcd285de)) + * **[#279](https://github.com/Byron/gitoxide/issues/279)** + - Add `progress::Write` to automatically pass bytes written to a progress instance ([`0a749a2`](https://github.com/Byron/gitoxide/commit/0a749a22057b5513a8cefa0e26b0a9a268c769d3)) + - Renamed `progress::Read::reader` -> `progress::Read::inner` ([`61e5cfe`](https://github.com/Byron/gitoxide/commit/61e5cfece4d8f405e35fc1957b00ce1da7526c26)) + - Adjust to changes in git-hash and git-pack ([`0cae25b`](https://github.com/Byron/gitoxide/commit/0cae25b1bb3c902ec323f17a1d9743e42fe213d0)) + * **[#287](https://github.com/Byron/gitoxide/issues/287)** + - Upgrade to prodash 17 ([`47860b7`](https://github.com/Byron/gitoxide/commit/47860b7e2769260cfb8522ae455c491605093423)) + * **[#293](https://github.com/Byron/gitoxide/issues/293)** + - Prepare changelogs for git-index and dependencies ([`f54bf4b`](https://github.com/Byron/gitoxide/commit/f54bf4bde92b892b6d425987a6a37e10319c4635)) + - Fix docs ([`3f89b63`](https://github.com/Byron/gitoxide/commit/3f89b6336e79bc12bc31d40b74221e79a72d2b36)) + - Fix build ([`e3977fe`](https://github.com/Byron/gitoxide/commit/e3977fe033550bfd3297cdd674934e40476aa38b)) + - Use InOrderIter from git-features ([`7721b5f`](https://github.com/Byron/gitoxide/commit/7721b5fc7cba86d785e0936fdfab2ea41163219f)) + - Add InOrderIter to 'parallel' module ([`cb7e4e7`](https://github.com/Byron/gitoxide/commit/cb7e4e784d615f9fa3d6fb9c36240f0592403358)) + - Make a scope-like abstraction available ([`ca095ed`](https://github.com/Byron/gitoxide/commit/ca095ed881db2a8f06a6b067dbaac17e923b0945)) + - Single and multi-threaded index tests ([`a22cb0f`](https://github.com/Byron/gitoxide/commit/a22cb0f1ead9a2f32e43eb2fb378281e592a4ed3)) + - Decoding of variable int numbers. ([`b8400ed`](https://github.com/Byron/gitoxide/commit/b8400ed80543d67a5895c975ba9b1fc28427411c)) + * **[#298](https://github.com/Byron/gitoxide/issues/298)** + - Enforce path conversion on windows gnu, it doesn't seem to like slashes ([`4d55a8f`](https://github.com/Byron/gitoxide/commit/4d55a8f99f2a0b7c0c4ed70a615b7e58b5bee04b)) + - Use hash_hasher based hash state for better keys/less collisions ([`814de07`](https://github.com/Byron/gitoxide/commit/814de079f4226f42efa49ad334a348bce67184e4)) + - Upgrade parking_lot and cargo_toml ([`f95c1a0`](https://github.com/Byron/gitoxide/commit/f95c1a0d9c19bcc6feb9b8739a09d86f9970a0e0)) + * **[#301](https://github.com/Byron/gitoxide/issues/301)** + - Update changelogs prior to release ([`84cb256`](https://github.com/Byron/gitoxide/commit/84cb25614a5fcddff297c1713eba4efbb6ff1596)) + - Remove `path` module in favor of `git-path` crate ([`90611ce`](https://github.com/Byron/gitoxide/commit/90611ce1527618bcc738440bfc1ccc7a45319974)) + - Mild refactor of paths module to waste less on unix ([`d078d6e`](https://github.com/Byron/gitoxide/commit/d078d6ee76a80d1dfaf71608c12d8a402bd670d4)) + - Refactor ([`8345b7c`](https://github.com/Byron/gitoxide/commit/8345b7caa0cc1cd8489e41822eea89da4c539e6d)) + - More stable testing of perviously racy test for new parallelization mechanism ([`0b4b90f`](https://github.com/Byron/gitoxide/commit/0b4b90fa498d9e07a55b72af2f799da4cd2da81f)) + - Salvage an alternative parallelization approach which might be good for index-creation ([`7e76796`](https://github.com/Byron/gitoxide/commit/7e76796d5c2956961bd998286bec05fca1ba8fc4)) + - Refactor ([`f86eacc`](https://github.com/Byron/gitoxide/commit/f86eacc5cfaf6d88ead4f8dbd65989d32674c213)) + - Use hopefully faster crossbeam channel to receive parallelized results ([`3b324b8`](https://github.com/Byron/gitoxide/commit/3b324b868d9d172038797f911eeebfcba8107865)) + - Switch index checkout to chunk-based operation ([`e5f6943`](https://github.com/Byron/gitoxide/commit/e5f69433e4a6cc7866b666e0baccfa32efb92a7f)) + - Add thread-count and chunk-size computation; interrupt capability ([`8cbe85d`](https://github.com/Byron/gitoxide/commit/8cbe85d135898826a91939726465a9e295c1e24b)) + - `interrupt::Iter`, rename `interrupt::Iter` -> `interrupt::IterWithError` ([`8945d95`](https://github.com/Byron/gitoxide/commit/8945d95f7fa88562d37ff67ac6e38bead73dd2df)) + - Fix `interrupt::Iter` ([`0f0d390`](https://github.com/Byron/gitoxide/commit/0f0d390c475044a75e5db4dcd831d755e74aa3e9)) + * **[#329](https://github.com/Byron/gitoxide/issues/329)** + - In-manifest and in-lib documentation of feature toggles ([`15ff212`](https://github.com/Byron/gitoxide/commit/15ff212b17087de93f259e366f4e4b821cfbc28e)) + * **[#331](https://github.com/Byron/gitoxide/issues/331)** + - Remove local-time-support feature toggle. ([`89a41bf`](https://github.com/Byron/gitoxide/commit/89a41bf2b37db29b9983b4e5492cfd67ed490b23)) + - Initialize `Time` from `now_utc` and `now_local` ([`c76fde7`](https://github.com/Byron/gitoxide/commit/c76fde7de278b49ded13b655d5345e4eb8c1b134)) + - A first sketch on how identity management could look like. ([`780f14f`](https://github.com/Byron/gitoxide/commit/780f14f5c270802e51cf039639c2fbdb5ac5a85e)) + - Update changelog prior to release ([`1d07934`](https://github.com/Byron/gitoxide/commit/1d079346e789b0acc9a4bdf7577b21c1c37b6106)) + - Remove Option return values in favor of Result ([`493dbae`](https://github.com/Byron/gitoxide/commit/493dbae434e8e4a939e90d03ec3f500744c0725a)) + - Add `git_config::values::Path` for a typesafe git path ([`e4d6685`](https://github.com/Byron/gitoxide/commit/e4d6685064ad2b433f8acd3a74b320bf0169a994)) + * **[#333](https://github.com/Byron/gitoxide/issues/333)** + - Use git_features::path everywhere where there is a path conversion ([`2e1437c`](https://github.com/Byron/gitoxide/commit/2e1437cb0b5dc77f2317881767f71eaf9b009ebf)) + - Make real clear panics are only possible on windows ([`6b283dc`](https://github.com/Byron/gitoxide/commit/6b283dc7b9339fd65ea35f56eb29f121f571caf7)) + - One usage of os_str_bytes down, along with some custom conversion code ([`1cc95ce`](https://github.com/Byron/gitoxide/commit/1cc95cefbd132a4277ec52c2147f7c81fea92d48)) + - Gitoxide-core without os-str-bytes ([`909aa14`](https://github.com/Byron/gitoxide/commit/909aa1402c82c3128052023613a297b213716e3d)) + - Remove os_str_bytes from git-pack ([`86f6e50`](https://github.com/Byron/gitoxide/commit/86f6e5054ea11b7aeb9c85321913de090f71e3a1)) + - Don't use os_str_ext in git-features; adapt git-ref ([`9258b7b`](https://github.com/Byron/gitoxide/commit/9258b7baf0895593c13a152ff9e6f52e036cebe1)) + - Add new 'path' module for all path-related conversions ([`3c8581f`](https://github.com/Byron/gitoxide/commit/3c8581fc294c65c9eb42698969fe3263135a864e)) + * **[#366](https://github.com/Byron/gitoxide/issues/366)** + - The first possibly working version of loading a mailmap with multiple sources ([`98d745e`](https://github.com/Byron/gitoxide/commit/98d745e8080975a91cff1ce75e187258c851d3f4)) + - Cleanup bstr usage to not accidentally pull in unicode ([`8ff53af`](https://github.com/Byron/gitoxide/commit/8ff53af9876a5e35bcfd076124ad776e1b6ff331)) + * **[#427](https://github.com/Byron/gitoxide/issues/427)** + - Make fmt ([`4b320e7`](https://github.com/Byron/gitoxide/commit/4b320e773368ac5e8c38dd8a779ef3d6d2d024ec)) + - Optimize some portions of the Snapshot code for speed. ([`711fd5c`](https://github.com/Byron/gitoxide/commit/711fd5c6c221440917fa68248e45d5278c780a9e)) + - More convenient API for fs::Snapshots ([`561d2e7`](https://github.com/Byron/gitoxide/commit/561d2e746b1b82ac20f6f14b9c4e3910240075b4)) + - `fs::Snapshot` to on-demand reload shared resources. ([`7f199f0`](https://github.com/Byron/gitoxide/commit/7f199f0e5246809efde9880110093fbd11a4f8fe)) + - Use generalized reload-on-demand in `git-ref` ([`8d0cce7`](https://github.com/Byron/gitoxide/commit/8d0cce7d1521374d5199552fc69a417a957519bc)) + - Now it's possible to update packed refs using the shared code ([`78222c2`](https://github.com/Byron/gitoxide/commit/78222c2e39aa24c84852e999448c042f2fd37db4)) + - The first step towards using the generalized `ReloadIfChanged` in git-ref ([`e8de0ef`](https://github.com/Byron/gitoxide/commit/e8de0ef38db2f2d83cb277ed101464f23c0e98e4)) + - Generalized port of packed-refs update logic for use in index ([`e3aff0c`](https://github.com/Byron/gitoxide/commit/e3aff0c2b83720e5745f3d7a8d0f571421a26d99)) + - Turn on performance mode for sha-1 computation ([`44371a1`](https://github.com/Byron/gitoxide/commit/44371a10f464f32db346aa6b8309e983cfa20933)) + * **[#450](https://github.com/Byron/gitoxide/issues/450)** + - Upgrade to `prodash` v21 ([`a0655dc`](https://github.com/Byron/gitoxide/commit/a0655dc7bc5dff388bc69a648e7f16b44fd1abd9)) + - `fs::Snapshot` can `Clone` if `T` can `Clone`. ([`9076ce3`](https://github.com/Byron/gitoxide/commit/9076ce33ec167e425a0163d3e40a81a3fd0db6cd)) + * **[#470](https://github.com/Byron/gitoxide/issues/470)** + - Update changelogs prior to release ([`caa7a1b`](https://github.com/Byron/gitoxide/commit/caa7a1bdef74d7d3166a7e38127a59f5ab3cfbdd)) + - Working progress printing ([`67ec2c7`](https://github.com/Byron/gitoxide/commit/67ec2c7f9a4a6cefdf7148f5c7e48a79f201c4d2)) + - First attempt to get progress information from stat worker. ([`0947c70`](https://github.com/Byron/gitoxide/commit/0947c703f9cecc31ceba101565e6ecafb00adb08)) + - Upgrade to prodash 20.1 for `Progress::counter()` feature ([`0ac4a2c`](https://github.com/Byron/gitoxide/commit/0ac4a2c514aeb94d8e90ce28ae7a0e0350c21ab2)) + * **[#503](https://github.com/Byron/gitoxide/issues/503)** + - Prepare changelog ([`3c99e7f`](https://github.com/Byron/gitoxide/commit/3c99e7f02ada72a171856ffc5b870da83fffc703)) + * **[#524](https://github.com/Byron/gitoxide/issues/524)** + - Prepare changelogs prior to release ([`6446b39`](https://github.com/Byron/gitoxide/commit/6446b395d5926565ef899b0c923f35468ccf1921)) + * **[#63](https://github.com/Byron/gitoxide/issues/63)** + - Git-protocol uses `oid` type ([`3930a6f`](https://github.com/Byron/gitoxide/commit/3930a6ff508f5bb2249fb2c2f21e00b74fecda22)) + - Make ObjectId/oid happen! ([`ca78d15`](https://github.com/Byron/gitoxide/commit/ca78d15373ec988d909be8f240baefe75555e077)) + - Move git-hash::owned::Id into git-hash::Id ([`fdbe704`](https://github.com/Byron/gitoxide/commit/fdbe704b6c9ace2b8f629f681a0580b24749a238)) + - Rename `git_hash::*::Digest` to `Id` ([`188d90a`](https://github.com/Byron/gitoxide/commit/188d90ad463d342d715af701b03f0ed392c977fc)) + * **[#691](https://github.com/Byron/gitoxide/issues/691)** + - Set `rust-version` to 1.64 ([`55066ce`](https://github.com/Byron/gitoxide/commit/55066ce5fd71209abb5d84da2998b903504584bb)) + * **Uncategorized** + - Release gix-features v0.26.4, gix-actor v0.17.1, gix-glob v0.5.3, gix-path v0.7.1, gix-quote v0.4.1, gix-attributes v0.8.2, gix-config-value v0.10.1, gix-tempfile v3.0.2, gix-lock v3.0.2, gix-validate v0.7.2, gix-object v0.26.1, gix-ref v0.24.0, gix-sec v0.6.2, gix-config v0.16.1, gix-command v0.2.3, gix-prompt v0.3.2, gix-url v0.13.2, gix-credentials v0.9.1, gix-diff v0.26.1, gix-discover v0.13.0, gix-hashtable v0.1.1, gix-bitmap v0.2.1, gix-traverse v0.22.1, gix-index v0.12.3, gix-mailmap v0.9.2, gix-chunk v0.4.1, gix-pack v0.30.2, gix-odb v0.40.2, gix-packetline v0.14.2, gix-transport v0.25.4, gix-protocol v0.26.3, gix-revision v0.10.3, gix-refspec v0.7.2, gix-worktree v0.12.2, gix v0.36.0 ([`6efd0d3`](https://github.com/Byron/gitoxide/commit/6efd0d31fbeca31ab7319aa2ac97bb31dc4ce055)) + - Release gix-date v0.4.2, gix-hash v0.10.2, gix-features v0.26.4, gix-actor v0.17.1, gix-glob v0.5.3, gix-path v0.7.1, gix-quote v0.4.1, gix-attributes v0.8.2, gix-config-value v0.10.1, gix-tempfile v3.0.2, gix-lock v3.0.2, gix-validate v0.7.2, gix-object v0.26.1, gix-ref v0.24.0, gix-sec v0.6.2, gix-config v0.16.1, gix-command v0.2.3, gix-prompt v0.3.2, gix-url v0.13.2, gix-credentials v0.9.1, gix-diff v0.26.1, gix-discover v0.13.0, gix-hashtable v0.1.1, gix-bitmap v0.2.1, gix-traverse v0.22.1, gix-index v0.12.3, gix-mailmap v0.9.2, gix-chunk v0.4.1, gix-pack v0.30.2, gix-odb v0.40.2, gix-packetline v0.14.2, gix-transport v0.25.4, gix-protocol v0.26.3, gix-revision v0.10.3, gix-refspec v0.7.2, gix-worktree v0.12.2, gix v0.36.0 ([`6ccc88a`](https://github.com/Byron/gitoxide/commit/6ccc88a8e4a56973b1a358cf72dc012ee3c75d56)) + - Merge branch 'rename-crates' into inform-about-gix-rename ([`c9275b9`](https://github.com/Byron/gitoxide/commit/c9275b99ea43949306d93775d9d78c98fb86cfb1)) + - Rename `git-testtools` to `gix-testtools` ([`b65c33d`](https://github.com/Byron/gitoxide/commit/b65c33d256cfed65d11adeff41132e3e58754089)) + - Adjust to renaming of `git-pack` to `gix-pack` ([`1ee81ad`](https://github.com/Byron/gitoxide/commit/1ee81ad310285ee4aa118118a2be3810dbace574)) + - Adjust to renaming of `git-odb` to `gix-odb` ([`476e2ad`](https://github.com/Byron/gitoxide/commit/476e2ad1a64e9e3f0d7c8651d5bcbee36cd78241)) + - Adjust to renaming of `git-index` to `gix-index` ([`86db5e0`](https://github.com/Byron/gitoxide/commit/86db5e09fc58ce66b252dc13b8d7e2c48e4d5062)) + - Adjust to renaming of `git-diff` to `gix-diff` ([`49a163e`](https://github.com/Byron/gitoxide/commit/49a163ec8b18f0e5fcd05a315de16d5d8be7650e)) + - Adjust to renaming of `git-commitgraph` to `gix-commitgraph` ([`f1dd0a3`](https://github.com/Byron/gitoxide/commit/f1dd0a3366e31259af029da73228e8af2f414244)) + - Adjust to renaming of `git-mailmap` to `gix-mailmap` ([`2e28c56`](https://github.com/Byron/gitoxide/commit/2e28c56bb9f70de6f97439818118d3a25859698f)) + - Adjust to renaming of `git-discover` to `gix-discover` ([`53adfe1`](https://github.com/Byron/gitoxide/commit/53adfe1c34e9ea3b27067a97b5e7ac80b351c441)) + - Adjust to renaming of `git-chunk` to `gix-chunk` ([`59194e3`](https://github.com/Byron/gitoxide/commit/59194e3a07853eae0624ebc4907478d1de4f7599)) + - Adjust to renaming of `git-bitmap` to `gix-bitmap` ([`75f2a07`](https://github.com/Byron/gitoxide/commit/75f2a079b17489f62bc43e1f1d932307375c4f9d)) + - Adjust to renaming for `git-protocol` to `gix-protocol` ([`823795a`](https://github.com/Byron/gitoxide/commit/823795addea3810243cab7936cd8ec0137cbc224)) + - Adjust to renaming of `git-refspec` to `gix-refspec` ([`c958802`](https://github.com/Byron/gitoxide/commit/c9588020561577736faa065e7e5b5bb486ca8fe1)) + - Adjust to renaming of `git-revision` to `gix-revision` ([`ee0ee84`](https://github.com/Byron/gitoxide/commit/ee0ee84607c2ffe11ee75f27a31903db68afed02)) + - Adjust to renaming of `git-transport` to `gix-transport` ([`b2ccf71`](https://github.com/Byron/gitoxide/commit/b2ccf716dc4425bb96651d4d58806a3cc2da219e)) + - Adjust to renaming of `git-credentials` to `gix-credentials` ([`6b18abc`](https://github.com/Byron/gitoxide/commit/6b18abcf2856f02ab938d535a65e51ac282bf94a)) + - Adjust to renaming of `git-prompt` to `gix-prompt` ([`6a4654e`](https://github.com/Byron/gitoxide/commit/6a4654e0d10ab773dd219cb4b731c0fc1471c36d)) + - Adjust to renaming of `git-command` to `gix-command` ([`d26b8e0`](https://github.com/Byron/gitoxide/commit/d26b8e046496894ae06b0bbfdba77196976cd975)) + - Adjust to renaming of `git-packetline` to `gix-packetline` ([`5cbd22c`](https://github.com/Byron/gitoxide/commit/5cbd22cf42efb760058561c6c3bbcd4dab8c8be1)) + - Adjust to renaming of `git-worktree` to `gix-worktree` ([`73a1282`](https://github.com/Byron/gitoxide/commit/73a12821b3d9b66ec1714d07dd27eb7a73e3a544)) + - Adjust to renamining of `git-hashtable` to `gix-hashtable` ([`26a0c98`](https://github.com/Byron/gitoxide/commit/26a0c98d0a389b03e3dc7bfc758b37155e285244)) + - Adjust to renamining of `git-worktree` to `gix-worktree` ([`108bb1a`](https://github.com/Byron/gitoxide/commit/108bb1a634f4828853fb590e9fc125f79441dd38)) + - Adjust to renaming of `git-url` to `gix-url` ([`b50817a`](https://github.com/Byron/gitoxide/commit/b50817aadb143e19f61f64e19b19ec1107d980c6)) + - Adjust to renaming of `git-date` to `gix-date` ([`9a79ff2`](https://github.com/Byron/gitoxide/commit/9a79ff2d5cc74c1efad9f41e21095ae498cce00b)) + - Adjust to renamining of `git-attributes` to `gix-attributes` ([`4a8b3b8`](https://github.com/Byron/gitoxide/commit/4a8b3b812ac26f2a2aee8ce8ca81591273383c84)) + - Adjust to renaminig of `git-quote` to `gix-quote` ([`648025b`](https://github.com/Byron/gitoxide/commit/648025b7ca94411fdd0d90c53e5faede5fde6c8d)) + - Adjust to renaming of `git-config` to `gix-config` ([`3a861c8`](https://github.com/Byron/gitoxide/commit/3a861c8f049f6502d3bcbdac752659aa1aeda46a)) + - Adjust to renaming of `git-ref` to `gix-ref` ([`1f5f695`](https://github.com/Byron/gitoxide/commit/1f5f695407b034377d94b172465ff573562b3fc3)) + - Adjust to renaming of `git-lock` to `gix-lock` ([`2028e78`](https://github.com/Byron/gitoxide/commit/2028e7884ae1821edeec81612f501e88e4722b17)) + - Adjust to renaming of `git-tempfile` to `gix-tempfile` ([`b6cc3eb`](https://github.com/Byron/gitoxide/commit/b6cc3ebb5137084a6327af16a7d9364d8f092cc9)) + - Adjust to renaming of `git-object` to `gix-object` ([`fc86a1e`](https://github.com/Byron/gitoxide/commit/fc86a1e710ad7bf076c25cc6f028ddcf1a5a4311)) + - Adjust to renaming of `git-actor` to `gix-actor` ([`4dc9b44`](https://github.com/Byron/gitoxide/commit/4dc9b44dc52f2486ffa2040585c6897c1bf55df4)) + - Adjust to renaming of `git-validate` to `gix-validate` ([`5e40ad0`](https://github.com/Byron/gitoxide/commit/5e40ad078af3d08cbc2ca81ce755c0ed8a065b4f)) + - Adjust to renaming of `git-hash` to `gix-hash` ([`4a9d025`](https://github.com/Byron/gitoxide/commit/4a9d0257110c3efa61d08c8457c4545b200226d1)) + - Adjust to renaming of `git-features` to `gix-features` ([`e2dd68a`](https://github.com/Byron/gitoxide/commit/e2dd68a417aad229e194ff20dbbfd77668096ec6)) + - Rename `git-features` to `gix-features` ([`85f7e1a`](https://github.com/Byron/gitoxide/commit/85f7e1a97c936f7cbebfbb3b2952f965601a7cbb)) + - Adjust to renaming of `git-glob` to `gix-glob` ([`35b2a3a`](https://github.com/Byron/gitoxide/commit/35b2a3acbc8f2a03f151bc0a3863163844e0ca86)) + - Adjust to renaming of `git-sec` to `gix-sec` ([`eabbb92`](https://github.com/Byron/gitoxide/commit/eabbb923bd5a32fc80fa80f96cfdc2ab7bb2ed17)) + - Adapt to renaming of `git-path` to `gix-path` ([`d3bbcfc`](https://github.com/Byron/gitoxide/commit/d3bbcfccad80fc44ea8e7bf819f23adaca06ba2d)) + - Adjust to rename of `git-config-value` to `gix-config-value` ([`622b3e1`](https://github.com/Byron/gitoxide/commit/622b3e1d0bffa0f8db73697960f9712024fac430)) + - Release git-features v0.26.4 ([`109f434`](https://github.com/Byron/gitoxide/commit/109f434e66559a791d541f86876ded8df10766f1)) + - Re-export `prodash::progress::(Task|Value)` directly under `progress` ([`a3bd14a`](https://github.com/Byron/gitoxide/commit/a3bd14a7753716e7ad67cd56d24eee1fa099a6fd)) + - Release git-features v0.26.3 ([`1ecfb7f`](https://github.com/Byron/gitoxide/commit/1ecfb7f8bfb24432690d8f31367488f2e59a642a)) + - Re-export `prodash` in `progress` module. ([`4260572`](https://github.com/Byron/gitoxide/commit/426057247a80821b3da22b4ae5d67bda89ce0631)) + - Release git-date v0.4.2, git-hash v0.10.2, git-features v0.26.2, git-actor v0.17.1, git-glob v0.5.3, git-path v0.7.1, git-quote v0.4.1, git-attributes v0.8.2, git-config-value v0.10.1, git-tempfile v3.0.2, git-lock v3.0.2, git-validate v0.7.2, git-object v0.26.1, git-ref v0.24.0, git-sec v0.6.2, git-config v0.16.0, git-command v0.2.3, git-prompt v0.3.2, git-url v0.13.2, git-credentials v0.9.1, git-diff v0.26.1, git-discover v0.13.0, git-hashtable v0.1.1, git-bitmap v0.2.1, git-traverse v0.22.1, git-index v0.12.3, git-mailmap v0.9.2, git-chunk v0.4.1, git-pack v0.30.2, git-odb v0.40.2, git-packetline v0.14.2, git-transport v0.25.4, git-protocol v0.26.3, git-revision v0.10.2, git-refspec v0.7.2, git-worktree v0.12.2, git-repository v0.34.0, safety bump 3 crates ([`c196d20`](https://github.com/Byron/gitoxide/commit/c196d206d57a310b1ce974a1cf0e7e6d6db5c4d6)) + - Prepare changelogs prior to release ([`7c846d2`](https://github.com/Byron/gitoxide/commit/7c846d2102dc767366771925212712ef8cc9bf07)) + - Merge branch 'Lioness100/main' ([`1e544e8`](https://github.com/Byron/gitoxide/commit/1e544e82455bf9ecb5e3c2146280eaf7ecd81f16)) + - Fix typos ([`39ed9ed`](https://github.com/Byron/gitoxide/commit/39ed9eda62b7718d5109135e5ad406fb1fe2978c)) + - Make fmt ([`e22080e`](https://github.com/Byron/gitoxide/commit/e22080e4a29d0bad15a99d565a5e3e304a8743ec)) + - Merge branch 'adjustments-for-cargo' ([`7bba270`](https://github.com/Byron/gitoxide/commit/7bba2709488b7eb999b8136dbab03af977241678)) + - Export `prodash::progress::Id` in the `progress` module for convenience. ([`c4a7634`](https://github.com/Byron/gitoxide/commit/c4a7634b0b29c74625e183953e59c65987e9d66c)) + - Release git-date v0.4.1, git-features v0.26.1, git-glob v0.5.2, git-attributes v0.8.1, git-tempfile v3.0.1, git-ref v0.23.1, git-sec v0.6.1, git-config v0.15.1, git-prompt v0.3.1, git-url v0.13.1, git-discover v0.12.1, git-index v0.12.2, git-mailmap v0.9.1, git-pack v0.30.1, git-odb v0.40.1, git-transport v0.25.3, git-protocol v0.26.2, git-revision v0.10.1, git-refspec v0.7.1, git-worktree v0.12.1, git-repository v0.33.0 ([`5b5b380`](https://github.com/Byron/gitoxide/commit/5b5b3809faa71c658db38b40dfc410224d08a367)) + - Prepare changelogs prior to release ([`93bef97`](https://github.com/Byron/gitoxide/commit/93bef97b3c0c75d4bf7119fdd787516e1efc77bf)) + - Merge branch 'patch-1' ([`b93f0c4`](https://github.com/Byron/gitoxide/commit/b93f0c49fc677b6c19aea332cbfc1445ce475375)) + - Thanks clippy ([`9e04685`](https://github.com/Byron/gitoxide/commit/9e04685dd3f109bfb27663f9dc7c04102e660bf2)) + - Release git-features v0.26.0, git-actor v0.16.0, git-attributes v0.8.0, git-object v0.25.0, git-ref v0.22.0, git-config v0.14.0, git-command v0.2.1, git-url v0.13.0, git-credentials v0.9.0, git-diff v0.25.0, git-discover v0.11.0, git-traverse v0.21.0, git-index v0.11.0, git-mailmap v0.8.0, git-pack v0.29.0, git-odb v0.39.0, git-transport v0.25.0, git-protocol v0.26.0, git-revision v0.9.0, git-refspec v0.6.0, git-worktree v0.11.0, git-repository v0.31.0, safety bump 24 crates ([`5ac9fbe`](https://github.com/Byron/gitoxide/commit/5ac9fbe265a5b61c533a2a6b3abfed2bdf7f89ad)) + - Prepare changelogs prior to release ([`30d8ca1`](https://github.com/Byron/gitoxide/commit/30d8ca19284049dcfbb0de2698cafae1d1a16b0c)) + - Make fmt ([`511ed00`](https://github.com/Byron/gitoxide/commit/511ed0000397a5b268530c8f5362e7d25b7c1594)) + - Merge branch 'adjustments-for-cargo' ([`f8c562a`](https://github.com/Byron/gitoxide/commit/f8c562a559e6dc3377583cc7200585dad7c3d481)) + - Upgrade to prodash v23 ([`5bf0034`](https://github.com/Byron/gitoxide/commit/5bf0034fb3918e57562b7089ceba83d63a1854bf)) + - Release git-features v0.25.1, git-url v0.12.2, git-odb v0.38.1, git-transport v0.24.2, git-repository v0.30.2 ([`bb0a07b`](https://github.com/Byron/gitoxide/commit/bb0a07b5edd5f980989d1a92e74df7f183febe87)) + - Merge branch 'loose-find-panic' ([`95cccdd`](https://github.com/Byron/gitoxide/commit/95cccddd3c181eb2a85b12823c27beb054adf5d8)) + - Zlib::inflate::Error can now represent zlib status codes that represent failure. ([`25ad372`](https://github.com/Byron/gitoxide/commit/25ad372bf500b851105f53b10369b5a689ba167e)) + - Release git-date v0.3.1, git-features v0.25.0, git-actor v0.15.0, git-glob v0.5.1, git-path v0.7.0, git-attributes v0.7.0, git-config-value v0.10.0, git-lock v3.0.1, git-validate v0.7.1, git-object v0.24.0, git-ref v0.21.0, git-sec v0.6.0, git-config v0.13.0, git-prompt v0.3.0, git-url v0.12.0, git-credentials v0.8.0, git-diff v0.24.0, git-discover v0.10.0, git-traverse v0.20.0, git-index v0.10.0, git-mailmap v0.7.0, git-pack v0.28.0, git-odb v0.38.0, git-packetline v0.14.1, git-transport v0.24.0, git-protocol v0.25.0, git-revision v0.8.0, git-refspec v0.5.0, git-worktree v0.10.0, git-repository v0.30.0, safety bump 26 crates ([`e6b9906`](https://github.com/Byron/gitoxide/commit/e6b9906c486b11057936da16ed6e0ec450a0fb83)) + - Prepare chnagelogs prior to git-repository release ([`7114bbb`](https://github.com/Byron/gitoxide/commit/7114bbb6732aa8571d4ab74f28ed3e26e9fbe4d0)) + - Merge branch 'main' into read-split-index ([`c57bdde`](https://github.com/Byron/gitoxide/commit/c57bdde6de37eca9672ea715962bbd02aa3eb055)) + - Merge branch 'adjustments-for-cargo' ([`083909b`](https://github.com/Byron/gitoxide/commit/083909bc7eb902eeee2002034fdb6ed88280dc5c)) + - Thanks clippy ([`f1160fb`](https://github.com/Byron/gitoxide/commit/f1160fb42acf59b37cbeda546a7079af3c9bc050)) + - Add support for explicit non-parallel iteration. ([`0f27c67`](https://github.com/Byron/gitoxide/commit/0f27c67c92fc0bc23a6712b5c4c730ad6a0156bf)) + - Merge branch 'adjustments-for-cargo' ([`70ccbb2`](https://github.com/Byron/gitoxide/commit/70ccbb21b1113bdeb20b52d274141a9fdb75f579)) + - Upgrade to prodash v22 for API improvements ([`77ab98d`](https://github.com/Byron/gitoxide/commit/77ab98dd41c3849b674d8b3794ef29219ca1447d)) + - Release git-hash v0.10.1, git-hashtable v0.1.0 ([`7717170`](https://github.com/Byron/gitoxide/commit/771717095d9a67b0625021eb0928828ab686e772)) + - Merge branch 'main' into http-config ([`6b9632e`](https://github.com/Byron/gitoxide/commit/6b9632e16c416841ffff1b767ee7a6c89b421220)) + - Release git-features v0.24.1, git-actor v0.14.1, git-index v0.9.1 ([`7893502`](https://github.com/Byron/gitoxide/commit/789350208efc9d5fc6f9bc4f113f77f9cb445156)) + - Merge branch 'named-threads' ([`726dd87`](https://github.com/Byron/gitoxide/commit/726dd87b5db45c333ccad898338a1cacea9e3269)) + - Name spawned threads ([`6d530a1`](https://github.com/Byron/gitoxide/commit/6d530a1dc77f0f4ac00622a2fd47c7bdb731a77a)) + - Upgrade to `prodash 21.1` and add `Ids` to all progress instances. ([`c8835c6`](https://github.com/Byron/gitoxide/commit/c8835c6edae784c9ffcb69a674c0a6545dbb2af3)) + - Merge branch 'main' into http-config ([`bcd9654`](https://github.com/Byron/gitoxide/commit/bcd9654e56169799eb706646da6ee1f4ef2021a9)) + - Release git-hash v0.10.0, git-features v0.24.0, git-date v0.3.0, git-actor v0.14.0, git-glob v0.5.0, git-path v0.6.0, git-quote v0.4.0, git-attributes v0.6.0, git-config-value v0.9.0, git-tempfile v3.0.0, git-lock v3.0.0, git-validate v0.7.0, git-object v0.23.0, git-ref v0.20.0, git-sec v0.5.0, git-config v0.12.0, git-command v0.2.0, git-prompt v0.2.0, git-url v0.11.0, git-credentials v0.7.0, git-diff v0.23.0, git-discover v0.9.0, git-bitmap v0.2.0, git-traverse v0.19.0, git-index v0.9.0, git-mailmap v0.6.0, git-chunk v0.4.0, git-pack v0.27.0, git-odb v0.37.0, git-packetline v0.14.0, git-transport v0.23.0, git-protocol v0.24.0, git-revision v0.7.0, git-refspec v0.4.0, git-worktree v0.9.0, git-repository v0.29.0, git-commitgraph v0.11.0, gitoxide-core v0.21.0, gitoxide v0.19.0, safety bump 28 crates ([`b2c301e`](https://github.com/Byron/gitoxide/commit/b2c301ef131ffe1871314e19f387cf10a8d2ac16)) + - Prepare changelogs prior to release ([`e4648f8`](https://github.com/Byron/gitoxide/commit/e4648f827c97e9d13636d1bbdc83dd63436e6e5c)) + - Release git-features v0.23.1, git-glob v0.4.1, git-config-value v0.8.1, git-tempfile v2.0.6, git-object v0.22.1, git-ref v0.18.0, git-sec v0.4.2, git-config v0.10.0, git-prompt v0.1.1, git-url v0.10.1, git-credentials v0.6.1, git-diff v0.21.0, git-discover v0.7.0, git-index v0.7.0, git-pack v0.25.0, git-odb v0.35.0, git-transport v0.21.1, git-protocol v0.22.0, git-refspec v0.3.1, git-worktree v0.7.0, git-repository v0.26.0, git-commitgraph v0.10.0, gitoxide-core v0.19.0, gitoxide v0.17.0, safety bump 9 crates ([`d071583`](https://github.com/Byron/gitoxide/commit/d071583c5576fdf5f7717765ffed5681792aa81f)) + - Prepare changelogs prior to release ([`423af90`](https://github.com/Byron/gitoxide/commit/423af90c8202d62dc1ea4a76a0df6421d1f0aa06)) + - Merge branch 'main' into write-sparse-index ([`c4e6849`](https://github.com/Byron/gitoxide/commit/c4e68496c368611ebe17c6693d06c8147c28c717)) + - Merge branch 'gix-clone' ([`def53b3`](https://github.com/Byron/gitoxide/commit/def53b36c3dec26fa78939ab0584fe4ff930909c)) + - Thanks clippy ([`ad96233`](https://github.com/Byron/gitoxide/commit/ad96233e1aa77fb7d9185f653f3e9519128cf20f)) + - Release git-hash v0.9.11, git-features v0.23.0, git-actor v0.13.0, git-attributes v0.5.0, git-object v0.22.0, git-ref v0.17.0, git-sec v0.4.1, git-config v0.9.0, git-url v0.10.0, git-credentials v0.6.0, git-diff v0.20.0, git-discover v0.6.0, git-traverse v0.18.0, git-index v0.6.0, git-mailmap v0.5.0, git-pack v0.24.0, git-odb v0.34.0, git-packetline v0.13.1, git-transport v0.21.0, git-protocol v0.21.0, git-revision v0.6.0, git-refspec v0.3.0, git-worktree v0.6.0, git-repository v0.25.0, safety bump 24 crates ([`104d922`](https://github.com/Byron/gitoxide/commit/104d922add61ab21c534c24ce8ed37cddf3e275a)) + - Prepare changelogs for release ([`d232567`](https://github.com/Byron/gitoxide/commit/d23256701a95284857dc8d1cb37c7c94cada973c)) + - Remove `fs-jwalk-single-threaded` in favor of `fs-walkdir-parallel`. ([`38446dc`](https://github.com/Byron/gitoxide/commit/38446dc8824afef30ef121598de3451d13b9262c)) + - Make jwalk fully optional ([`3b29fc1`](https://github.com/Byron/gitoxide/commit/3b29fc18672c0176684c797a0f16f85d09369bf8)) + - Merge branch 'main' into new-http-impl ([`702a161`](https://github.com/Byron/gitoxide/commit/702a161ef11fc959611bf44b70e9ffe04561c7ad)) + - Merge branch 'main' into clone ([`acb0738`](https://github.com/Byron/gitoxide/commit/acb07382a9306d6962bea60e8977d83d021743f4)) + - Merge branch 'delta-tree-parallelization' ([`cca2ad5`](https://github.com/Byron/gitoxide/commit/cca2ad5ee9483d7da968658e0a4d610dbc4ad4d6)) + - Don't enforce Send bounds in serial version of `in_parallel_with_slice()` ([`dda661e`](https://github.com/Byron/gitoxide/commit/dda661e1b7cc0ace6cd9504233f20980e1e52387)) + - Allow discarding the state which could otherwise be used for aggregation. ([`56792fb`](https://github.com/Byron/gitoxide/commit/56792fb53299d52073555c8646360ec0ae88c86d)) + - Allow input for `in_parallel_with_slice` to be mutable. ([`e928bf7`](https://github.com/Byron/gitoxide/commit/e928bf7c699a7e48ad283c2cf7fd7479c37c70fc)) + - Perfect granularity for threads processing with `in_parallel_with_slice()` ([`a7c11d2`](https://github.com/Byron/gitoxide/commit/a7c11d2cb5f88a4ff322d9a9848459062790d8b3)) + - Add `progress::Step|StepShared` as types of `prodash` ([`ff1db66`](https://github.com/Byron/gitoxide/commit/ff1db66f2dad3afc8bc77610006bca9fea5947d2)) + - Merge branch 'fix-git-features' ([`82fd251`](https://github.com/Byron/gitoxide/commit/82fd251ac80d07bc9da8a4d36e517aa35580d188)) + - Merge branch 'diff' ([`25a7726`](https://github.com/Byron/gitoxide/commit/25a7726377fbe400ea3c4927d04e9dec99802b7b)) + - Release git-hash v0.9.10, git-features v0.22.5, git-date v0.2.0, git-actor v0.12.0, git-glob v0.4.0, git-path v0.5.0, git-quote v0.3.0, git-attributes v0.4.0, git-config-value v0.8.0, git-tempfile v2.0.5, git-validate v0.6.0, git-object v0.21.0, git-ref v0.16.0, git-sec v0.4.0, git-config v0.8.0, git-discover v0.5.0, git-traverse v0.17.0, git-index v0.5.0, git-worktree v0.5.0, git-testtools v0.9.0, git-command v0.1.0, git-prompt v0.1.0, git-url v0.9.0, git-credentials v0.5.0, git-diff v0.19.0, git-mailmap v0.4.0, git-chunk v0.3.2, git-pack v0.23.0, git-odb v0.33.0, git-packetline v0.13.0, git-transport v0.20.0, git-protocol v0.20.0, git-revision v0.5.0, git-refspec v0.2.0, git-repository v0.24.0, git-commitgraph v0.9.0, gitoxide-core v0.18.0, gitoxide v0.16.0, safety bump 28 crates ([`29a043b`](https://github.com/Byron/gitoxide/commit/29a043be6808a3e9199a9b26bd076fe843afe4f4)) + - Release git-features v0.22.6 ([`c9eda72`](https://github.com/Byron/gitoxide/commit/c9eda729d8f8bc266c7516c613d38acfb83a4743)) + - Update changelog prior to release ([`ff80042`](https://github.com/Byron/gitoxide/commit/ff80042c9691e5dba5834c674174fdf6d3bdfe7d)) + - Fix git-features docs build ([`e5963fe`](https://github.com/Byron/gitoxide/commit/e5963fea183d81db1fe502121b494146a58bd86e)) + - Upgrade all dependencies, except for `windows` ([`2968181`](https://github.com/Byron/gitoxide/commit/29681819ffe53d3926d631dc482f71d6200cb549)) + - Merge branch 'dep-upgrade' ([`59767b1`](https://github.com/Byron/gitoxide/commit/59767b1fc1d07b8a7a9333a719e3716746611bc4)) + - Upgrade prodash and crosstermion to latest versions ([`ab7ee5b`](https://github.com/Byron/gitoxide/commit/ab7ee5b5d5c15771f431ada9c3b4f53e4be2afdd)) + - Add zlib-ng feature to allow linking against system libz-ng ([`cfe46b5`](https://github.com/Byron/gitoxide/commit/cfe46b502afc3ecb312849ddbd7748007d432cd1)) + - Merge branch 'main' into filter-refs-by-spec ([`9aa1d3d`](https://github.com/Byron/gitoxide/commit/9aa1d3dc46d4b1c76af257f573aff3aeef2d3fa8)) + - Release git-features v0.22.4, git-url v0.8.0, safety bump 4 crates ([`1d4600a`](https://github.com/Byron/gitoxide/commit/1d4600ae51475c2e225f96c16c41e2c4a2b3f2aa)) + - Merge branch 'main' into filter-refs-by-spec ([`1f6e5ab`](https://github.com/Byron/gitoxide/commit/1f6e5ab15f5fd8d23719b13e6aea59cd231ac0fe)) + - Merge branch 'fix-522' ([`5869e9f`](https://github.com/Byron/gitoxide/commit/5869e9ff2508d5a93c07635277af8764fcb57713)) + - Release git-hash v0.9.9 ([`da0716f`](https://github.com/Byron/gitoxide/commit/da0716f8c27b4f29cfff0e5ce7fcb3d7240f4aeb)) + - Merge branch 'main' into index-from-tree ([`bc64b96`](https://github.com/Byron/gitoxide/commit/bc64b96a2ec781c72d1d4daad38aa7fb8b74f99b)) + - Merge branch 'main' into filter-refs-by-spec ([`cef0b51`](https://github.com/Byron/gitoxide/commit/cef0b51ade2a3301fa09ede7a425aa1fe3527e78)) + - Release git-features v0.22.3, git-revision v0.4.4 ([`c2660e2`](https://github.com/Byron/gitoxide/commit/c2660e2503323531ba02519eaa51124ee22fec51)) + - Merge branch 'main' into filter-refs-by-spec ([`dbfa328`](https://github.com/Byron/gitoxide/commit/dbfa3282cf876596b250b2040c1ec0b761741796)) + - Merge branch 'zlib-sys' ([`7b48297`](https://github.com/Byron/gitoxide/commit/7b482977a556d28f5d9759e1be33cdf3d85c8665)) + - Restrict `sha1` `asm` to supported archs ([`b383fab`](https://github.com/Byron/gitoxide/commit/b383fabbe10868317be51b99cfdd9b0981816042)) + - Add feature to link to traditional zlib for dynamic linking support ([`c954bbf`](https://github.com/Byron/gitoxide/commit/c954bbff60ba70a0f1680e3978dd1f8fc1e3a0e7)) + - Merge branch 'main' into filter-refs-by-spec ([`cfa1440`](https://github.com/Byron/gitoxide/commit/cfa144031dbcac2707ab0cec012bc35e78f9c475)) + - Release git-date v0.0.5, git-hash v0.9.8, git-features v0.22.2, git-actor v0.11.3, git-glob v0.3.2, git-quote v0.2.1, git-attributes v0.3.2, git-tempfile v2.0.4, git-lock v2.1.1, git-validate v0.5.5, git-object v0.20.2, git-ref v0.15.2, git-sec v0.3.1, git-config v0.7.0, git-credentials v0.4.0, git-diff v0.17.2, git-discover v0.4.1, git-bitmap v0.1.2, git-index v0.4.2, git-mailmap v0.3.2, git-chunk v0.3.1, git-traverse v0.16.2, git-pack v0.21.2, git-odb v0.31.2, git-packetline v0.12.7, git-url v0.7.2, git-transport v0.19.2, git-protocol v0.19.0, git-revision v0.4.2, git-refspec v0.1.0, git-worktree v0.4.2, git-repository v0.22.0, safety bump 4 crates ([`4974eca`](https://github.com/Byron/gitoxide/commit/4974eca96d525d1ee4f8cad79bb713af7a18bf9d)) + - Merge branch 'main' into remote-ls-refs ([`e2ee3de`](https://github.com/Byron/gitoxide/commit/e2ee3ded97e5c449933712883535b30d151c7c78)) + - Merge branch 'docsrs-show-features' ([`31c2351`](https://github.com/Byron/gitoxide/commit/31c235140cad212d16a56195763fbddd971d87ce)) + - Use docsrs feature in code to show what is feature-gated automatically on docs.rs ([`b1c40b0`](https://github.com/Byron/gitoxide/commit/b1c40b0364ef092cd52d03b34f491b254816b18d)) + - Uniformize deny attributes ([`f7f136d`](https://github.com/Byron/gitoxide/commit/f7f136dbe4f86e7dee1d54835c420ec07c96cd78)) + - Pass --cfg docsrs when compiling for https://docs.rs ([`5176771`](https://github.com/Byron/gitoxide/commit/517677147f1c17304c62cf97a1dd09f232ebf5db)) + - Merge branch 'main' into remote-ls-refs ([`bd5f3e8`](https://github.com/Byron/gitoxide/commit/bd5f3e8db7e0bb4abfb7b0f79f585ab82c3a14ab)) + - Release git-hash v0.9.7, git-features v0.22.1 ([`232784a`](https://github.com/Byron/gitoxide/commit/232784a59ded3e8016e4257c7e146ad385cdd64a)) + - Add `fs-jwalk-single-threaded` feature to specifically decouple `jwalk` from rayon ([`f498d35`](https://github.com/Byron/gitoxide/commit/f498d35baba52e40ecd47381e87c1ce49cf13285)) + - Merge branch 'rev-parse-delegate' ([`2f506c7`](https://github.com/Byron/gitoxide/commit/2f506c7c2988477b0f97d272a9ac9ed47b236457)) + - Thanks clippy! ([`c072dbb`](https://github.com/Byron/gitoxide/commit/c072dbb3e203e4a42843895b7d99404d900fdccd)) + - Merge pull request #2 from SidneyDouw/main ([`ce885ad`](https://github.com/Byron/gitoxide/commit/ce885ad4c3324c09c83751c32e014f246c748766)) + - Merge branch 'Byron:main' into main ([`9b9ea02`](https://github.com/Byron/gitoxide/commit/9b9ea0275f8ff5862f24cf5a4ca53bb1cd610709)) + - Merge branch 'main' into rev-parse-delegate ([`6da8250`](https://github.com/Byron/gitoxide/commit/6da82507588d3bc849217c11d9a1d398b67f2ed6)) + - Merge branch 'main' into pathspec ([`7b61506`](https://github.com/Byron/gitoxide/commit/7b615060712565f515515e35a3e8346278ad770c)) + - Merge branch 'kianmeng-fix-typos' ([`4e7b343`](https://github.com/Byron/gitoxide/commit/4e7b34349c0a01ad8686bbb4eb987e9338259d9c)) + - Fix typos ([`e9fcb70`](https://github.com/Byron/gitoxide/commit/e9fcb70e429edb2974afa3f58d181f3ef14c3da3)) + - Release git-hash v0.9.6, git-features v0.22.0, git-date v0.0.2, git-actor v0.11.0, git-glob v0.3.1, git-path v0.4.0, git-attributes v0.3.0, git-tempfile v2.0.2, git-object v0.20.0, git-ref v0.15.0, git-sec v0.3.0, git-config v0.6.0, git-credentials v0.3.0, git-diff v0.17.0, git-discover v0.3.0, git-index v0.4.0, git-mailmap v0.3.0, git-traverse v0.16.0, git-pack v0.21.0, git-odb v0.31.0, git-url v0.7.0, git-transport v0.19.0, git-protocol v0.18.0, git-revision v0.3.0, git-worktree v0.4.0, git-repository v0.20.0, git-commitgraph v0.8.0, gitoxide-core v0.15.0, gitoxide v0.13.0, safety bump 22 crates ([`4737b1e`](https://github.com/Byron/gitoxide/commit/4737b1eea1d4c9a8d5a69fb63ecac5aa5d378ae5)) + - Prepare changelog prior to release ([`3c50625`](https://github.com/Byron/gitoxide/commit/3c50625fa51350ec885b0f38ec9e92f9444df0f9)) + - Merge branch 'config-cascade' ([`f144eaf`](https://github.com/Byron/gitoxide/commit/f144eaf5863ae5cac63103f0db51c35fcf03a948)) + - Merge pull request #1 from Byron/main ([`085e76b`](https://github.com/Byron/gitoxide/commit/085e76b121291ed9bd324139105d2bd4117bedf8)) + - Git-features' walkdir: 2.3.1 -> 2.3.2 ([`41dd754`](https://github.com/Byron/gitoxide/commit/41dd7545234e6d2637d2bca5bb6d4f6d8bfc8f57)) + - Merge branch 'main' into pathspec ([`89ea12b`](https://github.com/Byron/gitoxide/commit/89ea12b558bcc056b892193ee8fb44b8664b5da4)) + - Merge branch 'main' into cont_include_if ([`41ea8ba`](https://github.com/Byron/gitoxide/commit/41ea8ba78e74f5c988148367386a1f4f304cb951)) + - Release git-date v0.0.1, git-hash v0.9.5, git-features v0.21.1, git-actor v0.10.1, git-path v0.2.0, git-attributes v0.2.0, git-ref v0.14.0, git-sec v0.2.0, git-config v0.5.0, git-credentials v0.2.0, git-discover v0.2.0, git-pack v0.20.0, git-odb v0.30.0, git-url v0.6.0, git-transport v0.18.0, git-protocol v0.17.0, git-revision v0.2.1, git-worktree v0.3.0, git-repository v0.19.0, safety bump 13 crates ([`a417177`](https://github.com/Byron/gitoxide/commit/a41717712578f590f04a33d27adaa63171f25267)) + - Update changelogs prior to release ([`bb424f5`](https://github.com/Byron/gitoxide/commit/bb424f51068b8a8e762696890a55ab48900ab980)) + - Assure we used most recent version of crossbeam-utils ([`033f0d3`](https://github.com/Byron/gitoxide/commit/033f0d3e0015b7eead6408c775d2101eb413ffbf)) + - Merge branch 'main' into SidneyDouw-pathspec ([`a22b1d8`](https://github.com/Byron/gitoxide/commit/a22b1d88a21311d44509018729c3ef1936cf052a)) + - Merge branch 'main' into git_includeif ([`598c853`](https://github.com/Byron/gitoxide/commit/598c853087fcf8f77299aa5b9803bcec705c0cd0)) + - Release git-hash v0.9.4, git-features v0.21.0, git-actor v0.10.0, git-glob v0.3.0, git-path v0.1.1, git-attributes v0.1.0, git-sec v0.1.0, git-config v0.3.0, git-credentials v0.1.0, git-validate v0.5.4, git-object v0.19.0, git-diff v0.16.0, git-lock v2.1.0, git-ref v0.13.0, git-discover v0.1.0, git-index v0.3.0, git-mailmap v0.2.0, git-traverse v0.15.0, git-pack v0.19.0, git-odb v0.29.0, git-packetline v0.12.5, git-url v0.5.0, git-transport v0.17.0, git-protocol v0.16.0, git-revision v0.2.0, git-worktree v0.2.0, git-repository v0.17.0, safety bump 20 crates ([`654cf39`](https://github.com/Byron/gitoxide/commit/654cf39c92d5aa4c8d542a6cadf13d4acef6a78e)) + - Merge branch 'main' into msrv-for-windows ([`7cb1972`](https://github.com/Byron/gitoxide/commit/7cb19729133325bdfacedf44cdc0500cbcf36684)) + - Merge branch 'worktree-stack' ([`98da8ba`](https://github.com/Byron/gitoxide/commit/98da8ba52cef8ec27f705fcbc84773e5bacc4e10)) + - Thanks clippy ([`380174f`](https://github.com/Byron/gitoxide/commit/380174f0ad9e60ccafcd4cfb24e244f106137964)) + - Release git-features v0.20.0, git-config v0.2.0 ([`a6460db`](https://github.com/Byron/gitoxide/commit/a6460db80ba3c49ea37c712465c7cbdefa5c32b6)) + - Release git-hash v0.9.3, git-features v0.20.0, git-config v0.2.0, safety bump 12 crates ([`f0cbb24`](https://github.com/Byron/gitoxide/commit/f0cbb24b2e3d8f028be0e773f9da530da2656257)) + - Remove 'unused_mut' warning on windows ([`4733e6c`](https://github.com/Byron/gitoxide/commit/4733e6c6f5ea7d5afa4dd171bbba066cf5120ddc)) + - Make fmt ([`7cf3545`](https://github.com/Byron/gitoxide/commit/7cf354509b545f7e7c99e159b5989ddfbe86273d)) + - Commit to using 'unicode' feature of bstr as git-object wants it too ([`471fa62`](https://github.com/Byron/gitoxide/commit/471fa62b142ba744541d7472464d62826f5c6b93)) + - Assure std::io::copy() doesn't hang when we cause an interrupt ([`234cd10`](https://github.com/Byron/gitoxide/commit/234cd10ca55482ce1a840ce3244308d249895bcc)) + - Upgrade to prodash 19 ([`90c6c5a`](https://github.com/Byron/gitoxide/commit/90c6c5aec4015ff969d6e2514fa4d49873ee80f5)) + - Thanks clippy ([`07a4094`](https://github.com/Byron/gitoxide/commit/07a4094965ac1b4eb223da8e5ca5cc4a86c5f596)) + - Properly document optional features ([`572e57d`](https://github.com/Byron/gitoxide/commit/572e57d5796692764c5c9633969aad25a6f9221a)) + - Merge branch 'svetli-n-path_value' ([`e8383ca`](https://github.com/Byron/gitoxide/commit/e8383caf6db211beb57d70019fe4ad13ce9066ee)) + - Small refactoring and documentation. ([`fefb01b`](https://github.com/Byron/gitoxide/commit/fefb01b84f954700b19e010282c4b413de8e03d2)) + - Upgrade document-features ([`c35e62e`](https://github.com/Byron/gitoxide/commit/c35e62e0da9ac1f7dcb863f5f9c69108c728d32e)) + - Merge branch 'unify-path-encoding' ([`566ff8a`](https://github.com/Byron/gitoxide/commit/566ff8a3597b889899d41ca15e5b9af7e05f1a4b)) + - Thanks clippy ([`a8e9497`](https://github.com/Byron/gitoxide/commit/a8e9497caebf1c0e9faac537717cd86378f1acf6)) + - Release git-features v0.19.1, git-actor v0.8.0, git-config v0.1.10, git-object v0.17.0, git-diff v0.13.0, git-tempfile v1.0.4, git-chunk v0.3.0, git-traverse v0.12.0, git-pack v0.16.0, git-odb v0.26.0, git-packetline v0.12.3, git-url v0.3.5, git-transport v0.15.0, git-protocol v0.14.0, git-ref v0.11.0, git-repository v0.14.0, cargo-smart-release v0.8.0 ([`d78aab7`](https://github.com/Byron/gitoxide/commit/d78aab7b9c4b431d437ac70a0ef96263acb64e46)) + - Release git-hash v0.9.1, git-features v0.19.1, git-actor v0.8.0, git-config v0.1.10, git-object v0.17.0, git-diff v0.13.0, git-tempfile v1.0.4, git-chunk v0.3.0, git-traverse v0.12.0, git-pack v0.16.0, git-odb v0.26.0, git-packetline v0.12.3, git-url v0.3.5, git-transport v0.15.0, git-protocol v0.14.0, git-ref v0.11.0, git-repository v0.14.0, cargo-smart-release v0.8.0, safety bump 4 crates ([`373cbc8`](https://github.com/Byron/gitoxide/commit/373cbc877f7ad60dac682e57c52a7b90f108ebe3)) + - Prepare changelogs for release ([`674ec73`](https://github.com/Byron/gitoxide/commit/674ec73b0816baa2c63b4ef1b40b7a41849c5e95)) + - Prepar changelogs for cargo-smart-release release ([`8900d69`](https://github.com/Byron/gitoxide/commit/8900d699226eb0995be70d66249827ce348261df)) + - Upgrade to tui 0.17 and prodash 18 ([`eba101a`](https://github.com/Byron/gitoxide/commit/eba101a576ecb7bc0f63357d0dd81eb817b94be4)) + - Release git-bitmap v0.0.1, git-hash v0.9.0, git-features v0.19.0, git-index v0.1.0, safety bump 9 crates ([`4624725`](https://github.com/Byron/gitoxide/commit/4624725f54a34dd6b35d3632fb3516965922f60a)) + - Upgrade dependencies ([`968df47`](https://github.com/Byron/gitoxide/commit/968df4746729556dcf4f5039b1d1ed1a1da2705a)) + - Refactor ([`e7fbd9f`](https://github.com/Byron/gitoxide/commit/e7fbd9f3700496ad7bb7e71226c4d25429f0ccd5)) + - Merge branch 'sync-db-draft' ([`7d2e20c`](https://github.com/Byron/gitoxide/commit/7d2e20c6fedc2c7e71a307d8d072412fa847a4aa)) + - Thanks clippy ([`7dd2313`](https://github.com/Byron/gitoxide/commit/7dd2313d980fe7c058319ae66d313b3097e3ae5f)) + - Release git-features v0.18.0, git-actor v0.7.0, git-config v0.1.9, git-object v0.16.0, git-diff v0.12.0, git-traverse v0.11.0, git-pack v0.15.0, git-odb v0.25.0, git-packetline v0.12.2, git-transport v0.14.0, git-protocol v0.13.0, git-ref v0.10.0, git-repository v0.13.0, cargo-smart-release v0.7.0, safety bump 12 crates ([`acd3737`](https://github.com/Byron/gitoxide/commit/acd37371dcd92ebac3d1f039224d02f2b4e9fa0b)) + - Adjust changelogs prior to release ([`ec38950`](https://github.com/Byron/gitoxide/commit/ec3895005d141abe79764eaff7c0f04153e38d73)) + - Thanks clippy ([`db1bb99`](https://github.com/Byron/gitoxide/commit/db1bb99101a9248b464b0df9f526067b8f2a184e)) + - Merge branch 'pack-consistency' ([`5982406`](https://github.com/Byron/gitoxide/commit/5982406b4e1b26fd383d9ec21a3cf652ec8ab25f)) + - Release git-hash v0.8.0, git-features v0.17.0, git-actor v0.6.0, git-object v0.15.0, git-diff v0.11.0, git-traverse v0.10.0, git-pack v0.13.0, git-odb v0.23.0, git-packetline v0.12.0, git-transport v0.13.0, git-protocol v0.12.0, git-ref v0.9.0, git-repository v0.11.0, git-commitgraph v0.6.0, gitoxide-core v0.12.0, gitoxide v0.10.0, cargo-smart-release v0.5.0, safety bump 16 crates ([`0e02953`](https://github.com/Byron/gitoxide/commit/0e029537a7f6242d02ccf7e63d8d92f5246e6c5e)) + - Release git-hash v0.7.0, git-features v0.16.5, git-actor v0.5.3, git-config v0.1.7, git-validate v0.5.3, git-object v0.14.1, git-diff v0.10.0, git-tempfile v1.0.3, git-lock v1.0.1, git-traverse v0.9.0, git-pack v0.12.0, git-odb v0.22.0, git-packetline v0.11.0, git-url v0.3.4, git-transport v0.12.0, git-protocol v0.11.0, git-ref v0.8.0, git-repository v0.10.0, cargo-smart-release v0.4.0 ([`59ffbd9`](https://github.com/Byron/gitoxide/commit/59ffbd9f15583c8248b7f48b3f55ec6faffe7cfe)) + - Adjusting changelogs prior to release of git-hash v0.7.0, git-features v0.16.5, git-actor v0.5.3, git-validate v0.5.3, git-object v0.14.1, git-diff v0.10.0, git-tempfile v1.0.3, git-lock v1.0.1, git-traverse v0.9.0, git-pack v0.12.0, git-odb v0.22.0, git-packetline v0.11.0, git-url v0.3.4, git-transport v0.12.0, git-protocol v0.11.0, git-ref v0.8.0, git-repository v0.10.0, cargo-smart-release v0.4.0, safety bump 3 crates ([`a474395`](https://github.com/Byron/gitoxide/commit/a47439590e36b1cb8b516b6053fd5cbfc42efed7)) + - Make fmt, but now it picked up some parts that usually don't get altered… ([`01f7b72`](https://github.com/Byron/gitoxide/commit/01f7b729337bd2c99498321c479a9a13b1858e3e)) + - Release git-features v0.16.4 ([`fd189c7`](https://github.com/Byron/gitoxide/commit/fd189c7d973ad2a639d319f3761f37aa90712ef6)) + - Merge branch 'repository-integration' ([`49f5453`](https://github.com/Byron/gitoxide/commit/49f5453629646ac24d752f53c532e5f67eb09374)) + - Bump git-hash v0.6.0 ([`6efd90d`](https://github.com/Byron/gitoxide/commit/6efd90db54f7f7441b76159dba3be80c15657a3d)) + - [features #190] be more explicit about why sha1-asm is disabled ([`507d710`](https://github.com/Byron/gitoxide/commit/507d710d837c3911a9329c1c132eee912a37e1a8)) + - [various #190] rename 'local-offset' to 'local-time-support' ([`3a7d379`](https://github.com/Byron/gitoxide/commit/3a7d3793a235ac872437f3bfedb9dd8fde9b31b1)) + - [actor #190] methods to get an actor signature at the current time ([`6d0bedd`](https://github.com/Byron/gitoxide/commit/6d0beddb20092a80b113a39c862d6b680d79deb6)) + - [features #189] simple UTC-offset support for git-features ([`b58134b`](https://github.com/Byron/gitoxide/commit/b58134bbd132f9e685d1adf7859ec5219c16dd25)) + - [features #???] WIP local time ([`1388ebf`](https://github.com/Byron/gitoxide/commit/1388ebf0925eb326ec3045d7f83bd5beda22a6fe)) + - [#189] Upgrade to prodash 16… ([`8e98418`](https://github.com/Byron/gitoxide/commit/8e98418652926860f58906a6f21a3210e2f0183f)) + - [pack #67] Optimize caches based on cache debugging ([`1271c01`](https://github.com/Byron/gitoxide/commit/1271c01d2635ab49474add61a9feb78b98bd6180)) + - [pack #67] Add cache debugging capabilities to git-features ([`8776c98`](https://github.com/Byron/gitoxide/commit/8776c9834ac4622b3057f5db464a9817ed9acdb0)) + - Merge branch 'main' into 162-repo-design-sketch ([`e63b634`](https://github.com/Byron/gitoxide/commit/e63b63412c02db469fbdb17da82cd1e9fda1ef0f)) + - Thanks clippy ([`d689599`](https://github.com/Byron/gitoxide/commit/d689599d1b819c18a3be60075170dbe00462e216)) + - [features] refactor ([`0958fc8`](https://github.com/Byron/gitoxide/commit/0958fc8dbaa72dda0c1e2d40a88d74b4e18bfe39)) + - [features] refactor ([`d4605cd`](https://github.com/Byron/gitoxide/commit/d4605cde6d825c0bfaf4282c4cbd85d9f07dc43f)) + - Release git-features v0.16.2 ([`42861ca`](https://github.com/Byron/gitoxide/commit/42861ca4f0cc9b741d033d4ffa50147b08513b58)) + - Apply nightly rustfmt rules. ([`5e0edba`](https://github.com/Byron/gitoxide/commit/5e0edbadb39673d4de640f112fa306349fb11814)) + - (cargo-release) version 0.16.1 ([`e10e55c`](https://github.com/Byron/gitoxide/commit/e10e55c1bf1b40965da9b8b6c87953e6eafda09a)) + - (cargo-release) version 0.5.0 ([`ae02dab`](https://github.com/Byron/gitoxide/commit/ae02dabae961089a92a21e6a60a7006de4b56dad)) + - (cargo-release) version 0.16.0 ([`1231dbd`](https://github.com/Byron/gitoxide/commit/1231dbd16dacefb39adec8e067c312d313a82e3c)) + - Upgrade prodash/crosstermion ([`f109409`](https://github.com/Byron/gitoxide/commit/f1094099de028deabbee3587a70291a7e625e328)) + - Clippy on tests and thanks clippy ([`a77a71c`](https://github.com/Byron/gitoxide/commit/a77a71cf02d328a2a964388928d6b2a235a0aa85)) + - [pack] fix build ([`98dd557`](https://github.com/Byron/gitoxide/commit/98dd557b963acfe1c4e717451d222c187c46a5da)) + - [pack] all tests running for now, but… ([`aec8439`](https://github.com/Byron/gitoxide/commit/aec8439683c639f7b6e344cb76bf1dd9fc769d17)) + - Refactor sha-1 specification to avoid duplication ([`e23d19c`](https://github.com/Byron/gitoxide/commit/e23d19cd339f0ca5420c82e8125d2c9c7dfcb0da)) + - Resolver = 2: works! ([`6dc8779`](https://github.com/Byron/gitoxide/commit/6dc877993135ce86649b239821e5b374251743d0)) + - Try windows one more time: resolver = "2" ([`69d52b8`](https://github.com/Byron/gitoxide/commit/69d52b8ed7a733fe7f31826e576ba8b19619b148)) + - Fix windows, leave todo, move on ([`2de9e78`](https://github.com/Byron/gitoxide/commit/2de9e78dba35de31456eb553ae703120de23cba6)) + - See if turning off "asm" support entirely fixes windows ([`b804ef2`](https://github.com/Byron/gitoxide/commit/b804ef2ea6da1ebffaab4d09d0b91eae98ff70c9)) + - Try to fix build, again ([`c616627`](https://github.com/Byron/gitoxide/commit/c616627cc9984e40798120a801387fc179d6640b)) + - Don't use ASM on windows for Sha1 as it fails to build there. ([`ba1fb7a`](https://github.com/Byron/gitoxide/commit/ba1fb7ab5bc03f5a23ece32ff1e144544e1eaeae)) + - [features] enable ASM for everyone… ([`7a1128f`](https://github.com/Byron/gitoxide/commit/7a1128f594c5395a22e5e2b23772bce1d4de7a37)) + - [ref] reproducible loose ref iteration with built-in sorting ([`e138748`](https://github.com/Byron/gitoxide/commit/e13874807ccc3cbc2b4aacccf63ac5c3dd21c445)) + - [features] fix docs in the absence of sha1 related features ([`6ca02ac`](https://github.com/Byron/gitoxide/commit/6ca02ace7552c1ffaead81929bc751d96afa713a)) + - Remove unnecessary pub(crate) exports ([`3d2456e`](https://github.com/Byron/gitoxide/commit/3d2456e11709f0461b37c6df55ecc3861ca4cab5)) + - [ref] first rough implementation of loose ref iteration ([`918af42`](https://github.com/Byron/gitoxide/commit/918af425298a1fdbb8e7dd6328daefe9eaa10cef)) + - Refactor ([`2174513`](https://github.com/Byron/gitoxide/commit/21745135ced62411be535ebbc827b3638726318b)) + - Fix docs ([`e68d460`](https://github.com/Byron/gitoxide/commit/e68d460716dc51c7f4757c11f3c8af6c3881e2cf)) + - Remove mentions of interrupt handling feature toggles ([`833ac04`](https://github.com/Byron/gitoxide/commit/833ac0464b42bd3ecc76c6263b4b06e8ab4ff182)) + - Fix everything up so that… ([`5930563`](https://github.com/Byron/gitoxide/commit/5930563601d6c2148cf39e109f69f8b7c7dfcb36)) + - A first attempt to make intrerupt tools work, but… ([`8fb8d37`](https://github.com/Byron/gitoxide/commit/8fb8d374ecfeffa3ae1bd07bf9bc5014351730f5)) + - First step towards moving git-features::interrupt… ([`8a741d0`](https://github.com/Byron/gitoxide/commit/8a741d0c5423ed7c35d9382307c760a6b9460ccd)) + - Fix build ([`ea2bfac`](https://github.com/Byron/gitoxide/commit/ea2bfac65f742ca7617bc77a50376c29156c4ea5)) + - Refactor ([`7f9be36`](https://github.com/Byron/gitoxide/commit/7f9be36ea909ee67555591287bcb140fdc54c801)) + - And one less usage of the global interrupt handler… ([`5da57a3`](https://github.com/Byron/gitoxide/commit/5da57a3b0efef75ad82cb4d1cd496fc7fc0f1c23)) + - Make most interrupts local to the method or function ([`4588993`](https://github.com/Byron/gitoxide/commit/458899306a3f3c8578f185d7ecbf1ade2a7142dd)) + - Fix build ([`04d919f`](https://github.com/Byron/gitoxide/commit/04d919f9228d287912554275194487870500d18c)) + - Refactor ([`e0b7f69`](https://github.com/Byron/gitoxide/commit/e0b7f695ee6bd1032544a29d91906f9b75e12d46)) + - [features] sketch of iterator to auto-check for interruptions ([`61d3a15`](https://github.com/Byron/gitoxide/commit/61d3a15c66b4c1be1d98715b8a60705a3a314455)) + - [tempfile] integrate with git-features to have a single top-level interrupt… ([`6e9400d`](https://github.com/Byron/gitoxide/commit/6e9400d9cb8e370d870c3aa635718b134c82268f)) + - [features] protect interrupt handler from multi-initialization ([`592404c`](https://github.com/Byron/gitoxide/commit/592404c2b24dc9d24465ff5f73216213436a277a)) + - [interrupt] remove any user mesasages as it can't be done in a handler. ([`8a10af7`](https://github.com/Byron/gitoxide/commit/8a10af77db654ebce940bb05f8eefd171036ef40)) + - [tempfile] a first somewhat working version of signal-hooks for interrupt handling ([`07b3242`](https://github.com/Byron/gitoxide/commit/07b3242e446cb4520dbc54308632ab6221fc19c8)) + - Update to latest prodash to get rid of ctrlc ([`c070d6f`](https://github.com/Byron/gitoxide/commit/c070d6f5273d7ef9049ddd02fd26332623dc0ae6)) + - Refactor ([`2e86723`](https://github.com/Byron/gitoxide/commit/2e8672312a4b1e2638e3ffe82a97cc2f87b496cf)) + - Bump crossbeam-utils from 0.8.4 to 0.8.5 ([`fce4d10`](https://github.com/Byron/gitoxide/commit/fce4d107c7abc778bbdfcd37349c3075e54fd756)) + - (cargo-release) version 0.4.0 ([`866f86f`](https://github.com/Byron/gitoxide/commit/866f86f59e66652968dcafc1a57912f9849cb21d)) + - [git-pack] fix docs ([`efd20d4`](https://github.com/Byron/gitoxide/commit/efd20d4e1afbfbe573d620dea4761c06f948a296)) + - [git-features] fix compilation ([`38c7961`](https://github.com/Byron/gitoxide/commit/38c796142dc5823e1cb14906d9cd4040a8c3be3a)) + - [git-pack] move hash-writer to git-features as it's quite general purpose ([`80e5640`](https://github.com/Byron/gitoxide/commit/80e5640169363910b4189fda58bb495c6677eaaa)) + - [git-features] Remove feature that would break licensing agreements ([`cd6ce67`](https://github.com/Byron/gitoxide/commit/cd6ce673308e7e5b1e86fb682ee3ace2ca9ae18c)) + - [git-features] fix typo ([`c6f342f`](https://github.com/Byron/gitoxide/commit/c6f342f3d29a969a08d037f01eb24555bc03e85e)) + - [git-features] Finally zlib with feature toggles is working… ([`057016e`](https://github.com/Byron/gitoxide/commit/057016e2df3138992c4857f9b65bf19dc2c9a097)) + - [git-features] And now zlib finally works! ([`6d887d5`](https://github.com/Byron/gitoxide/commit/6d887d589a57e159986f049c8a9e19c52ce7b85b)) + - [git-features] simplify even more ([`ca54d97`](https://github.com/Byron/gitoxide/commit/ca54d97d579dd4f16025a2325d5e39431f6e8a36)) + - [git-features] refactor to help understand a zlib-related logic bug ([`ae826e8`](https://github.com/Byron/gitoxide/commit/ae826e8c3240efd14939beedd33a06695a6c112b)) + - [git-features] a first step towards supporting a pure rust zlib backend ([`040cab7`](https://github.com/Byron/gitoxide/commit/040cab7f27de83b283957189244d523d71ca1457)) + - [git-features] Add zlib module to allow changing implementation on the fly ([`4bdf783`](https://github.com/Byron/gitoxide/commit/4bdf7833d99d3c2884b9747614f9c14a06c1e945)) + - (cargo-release) version 0.15.0 ([`d69d9fb`](https://github.com/Byron/gitoxide/commit/d69d9fb0931f8257cef96ef14a89da9340ad9738)) + - Put prodash behind a feature toggle, too ([`966058d`](https://github.com/Byron/gitoxide/commit/966058d611c548e90c050462de52e36f1925e775)) + - Put 'walkdir' behind a feature flag/make it optional. ([`1a3cc5b`](https://github.com/Byron/gitoxide/commit/1a3cc5bea1868ed3ae015403fbe0cdec788be749)) + - Put 'sha1' behind a feature toggle ([`4f326bc`](https://github.com/Byron/gitoxide/commit/4f326bc261c4e7f0d5510df74ad4215da3580696)) + - Use crc32fast instead of `crc` ([`11955f9`](https://github.com/Byron/gitoxide/commit/11955f95e200ef75e752a833952d288fbd0fc389)) + - Put crc functionality behind a feature toggle ([`458fa6e`](https://github.com/Byron/gitoxide/commit/458fa6ec726ec7901c1f6d970cbb1c1ea975dded)) + - (cargo-release) version 0.14.0 ([`a760f8c`](https://github.com/Byron/gitoxide/commit/a760f8c013e13ba82daa1acf1a4a57e0818a008d)) + - Upgrade to prodash 13/tui 0.15 ([`1c99f51`](https://github.com/Byron/gitoxide/commit/1c99f51b35b4ba85792a3b32dbb7e48052facc5e)) + - (cargo-release) version 0.3.0 ([`e9665c7`](https://github.com/Byron/gitoxide/commit/e9665c784ae7e5cdaf662151395ee2355e9b57b6)) + - Allow calling 'finalize()' on the entries iterator ([`3c617bc`](https://github.com/Byron/gitoxide/commit/3c617bc2ae59adbb12c254308269e745149d462b)) + - Git-odb without cargo warnings due to using the same test twice ([`8945f95`](https://github.com/Byron/gitoxide/commit/8945f95364b489e7a639d74dd0f28b17e82e70f3)) + - Fix compile warning for git-features ([`d457faa`](https://github.com/Byron/gitoxide/commit/d457faac6bb56a229b74147c8a4cf2484026bb1a)) + - Fix doc links ([`870af2a`](https://github.com/Byron/gitoxide/commit/870af2a6949bcb1f7f45bc0ff98d9e9a07014b22)) + - Run git-odb tests in parallel, too; improved threaded error handling ([`40802fd`](https://github.com/Byron/gitoxide/commit/40802fd8bbb15b8a61249522d67f3a5b28da64b3)) + - Refactor ([`82c2f42`](https://github.com/Byron/gitoxide/commit/82c2f428e22c3cda79913c9ca2f092c377d692aa)) + - Refactor ([`7a6b514`](https://github.com/Byron/gitoxide/commit/7a6b514a5b9b93bf574cd3a114f27ad5967e89ac)) + - Refactor ([`5ef1f22`](https://github.com/Byron/gitoxide/commit/5ef1f22c1e12ff8d607663d4dfbbbfe426a29e0f)) + - Fix docs #(67) ([`01db10a`](https://github.com/Byron/gitoxide/commit/01db10a27431ad89a68ed3e4eabae810748a6f29)) + - Refactor ([`3e908bd`](https://github.com/Byron/gitoxide/commit/3e908bd4b4077c4a5d113cefc113f9d71f249133)) + - Refactor ([`409d763`](https://github.com/Byron/gitoxide/commit/409d763d2fca974a647487c72d15f568a9b62ccb)) + - Refactor ([`896ab94`](https://github.com/Byron/gitoxide/commit/896ab940bcd475d026e4009b3aa2fa6a025c14bc)) + - Remove unused dependency ([`26beb2a`](https://github.com/Byron/gitoxide/commit/26beb2a5ad87e173fd3d13d17b0e9676a650cac9)) + - Don't finish the computation on drop of SteppedReduce ([`6453633`](https://github.com/Byron/gitoxide/commit/6453633f1420327aee07dca2ad27abd8f96108c0)) + - Thanks clippy ([`c320761`](https://github.com/Byron/gitoxide/commit/c320761821b08946a2b37e219400ded853a86408)) + - Remove unsafe interface for stepped computation #(67) ([`c856613`](https://github.com/Byron/gitoxide/commit/c856613a35aea7dea1d093bfcfe1ddbde93fdf26)) + - A first working version of a static parallel iterator #(67) ([`d7d5c68`](https://github.com/Byron/gitoxide/commit/d7d5c6855a038a8b01571a6a16a61fe0d8036d30)) + - A way iteration won't work with 'static #(67) ([`6fda1f2`](https://github.com/Byron/gitoxide/commit/6fda1f20a57b9dcc1a5818d8d0b656218b383230)) + - Sketch of machinery for producing pack entries #(67) ([`ac8e7fb`](https://github.com/Byron/gitoxide/commit/ac8e7fb6c8ae4ac42f56482d9d7744aa66132702)) + - Less restrictive requirements: Clone instead of Copy #(67) ([`410e7d6`](https://github.com/Byron/gitoxide/commit/410e7d64049b5a749113126f5412a61ae4b79887)) + - Improve Safety docs #(67) ([`15e4748`](https://github.com/Byron/gitoxide/commit/15e47480054d9a517c28f47db3b5fa87968a307e)) + - A test to assure referenced input and references in 'consume' work #(67) ([`4526d82`](https://github.com/Byron/gitoxide/commit/4526d82fab4d6e8f2ab05497aa5893d5a8f8b253)) + - Make iterator creation unsafe and document why #(67) ([`593d5df`](https://github.com/Byron/gitoxide/commit/593d5df478e67e28f9b3d48b201ff6830208726f)) + - First seemingly working version of an iterator which allows controlling threaded work #(67) ([`4a7ef7d`](https://github.com/Byron/gitoxide/commit/4a7ef7d6398c2ff5dd6aac41f8224cd2d61ee189)) + - Make the parallel SteppedReduce compile #(67) ([`017fdf4`](https://github.com/Byron/gitoxide/commit/017fdf48972a6a09e5155bd76bd437d8e195dae3)) + - More docs to differentiate SteppedReduce from in_parallel() #(67) ([`153c083`](https://github.com/Byron/gitoxide/commit/153c0837bbf1df3b5cb386e08265f9b06eaee2a9)) + - Serial version of SteppedReduce seems to be working #(67) ([`779542e`](https://github.com/Byron/gitoxide/commit/779542e4f4c951e9b16d2310146020da9ce36859)) + - Only store thread state #(67) ([`0bf8a9b`](https://github.com/Byron/gitoxide/commit/0bf8a9b3c4a086732ee04f81c6a214296d49eab9)) + - Sketch instantiation of iterator adapter #(67) ([`a3083ad`](https://github.com/Byron/gitoxide/commit/a3083ad3aad7984afc6b6d343ca7453f79897062)) + - A reducer test in preparation for allow it to be used as iterator #(67) ([`1c2adf4`](https://github.com/Byron/gitoxide/commit/1c2adf4a546273489bf8224eb7982dbdf3fb6aca)) + - (cargo-release) version 0.13.0 ([`ac2eddb`](https://github.com/Byron/gitoxide/commit/ac2eddb06eb3d8a9a3dcdcd796eb54a7e45ab935)) + - Allow parallel reducers to produce something during 'feed()' #(67) ([`6c04fcd`](https://github.com/Byron/gitoxide/commit/6c04fcd643083d9db633edd3bb838b4f5de8f0db)) + - (cargo-release) version 0.12.0 ([`3b71e7e`](https://github.com/Byron/gitoxide/commit/3b71e7e8416e550b47e5aed2259c1181497ac9e8)) + - (cargo-release) version 0.2.0 ([`4ec09f4`](https://github.com/Byron/gitoxide/commit/4ec09f4d2239ea1d44f7145027e64191bf2c158c)) + - Refactor ([`dee8c66`](https://github.com/Byron/gitoxide/commit/dee8c66e300dc2a2b6e1a6d6c3674a7ce6aac687)) + - (cargo-release) version 0.11.0 ([`1aa1f5e`](https://github.com/Byron/gitoxide/commit/1aa1f5e84a07427d5d7f3231735fe9c1923f506f)) + - (cargo-release) version 0.10.1 ([`0dcdfd7`](https://github.com/Byron/gitoxide/commit/0dcdfd754649240f43fe0f4b6e1245e8c7b89635)) + - Remove usage of gitfeatures::fs in organize subcommand ([`b567d37`](https://github.com/Byron/gitoxide/commit/b567d3709a74e9fdafef54b0fe58ca82721cd773)) + - Assure basic 'organize' operation is working as expected ([`deb6073`](https://github.com/Byron/gitoxide/commit/deb6073671ae95de674aaef7ca01e03f95b41ca8)) + - A first stab at finding git repositories ([`e4dc964`](https://github.com/Byron/gitoxide/commit/e4dc96403894f1fe509335905679347ecdf535c7)) + - Upgrade 'jwalk' ([`cba048f`](https://github.com/Byron/gitoxide/commit/cba048f094858388f4242e37a2409fe0822f8c07)) + - Upgrade 'bytes' ([`3934392`](https://github.com/Byron/gitoxide/commit/39343922b4a1129394aa788a9591920aee077569)) + - Upgrade prodash and friends ([`50755bc`](https://github.com/Byron/gitoxide/commit/50755bc83f73072dc629301bf69c5c065d5c2aa4)) + - Add missing '.' at end of doc comments ([`7136854`](https://github.com/Byron/gitoxide/commit/71368544f97369a4d371d43513607c4805bd0fd0)) + - Use git-hash in git-features ([`5b307e0`](https://github.com/Byron/gitoxide/commit/5b307e076f6f5975592c8b177c122c91c1d809c6)) + - (cargo-release) version 0.9.0 ([`a89fdb9`](https://github.com/Byron/gitoxide/commit/a89fdb98f64bb0ca070fa79a1f58f1232bb14090)) + - (cargo-release) version 0.5.0 ([`fc7d600`](https://github.com/Byron/gitoxide/commit/fc7d600ac2c438c8b6b91f67cb69b0ac5ec37675)) + - More docs for owned git-object ([`b79101d`](https://github.com/Byron/gitoxide/commit/b79101d714f59a42a30eb47776486a212ec0f738)) + - Fix io::pipe tests ([`9604154`](https://github.com/Byron/gitoxide/commit/9604154e687813a11f0eee469e408561a6a74a4e)) + - Uograde everything else ([`0cd79d0`](https://github.com/Byron/gitoxide/commit/0cd79d00bce3f042b5cc849cf48739e29f95fcb0)) + - Upgrade prodash and tui ([`b5eadca`](https://github.com/Byron/gitoxide/commit/b5eadca343bbaa1af86722b5f1bcd33f4e3939a6)) + - Add remaining docs to git-features using the missing_docs directive ([`f8aafd6`](https://github.com/Byron/gitoxide/commit/f8aafd6c78687899a2ca3a3e6147d93fc45b8cb9)) + - (cargo-release) version 0.8.0 ([`47c00c2`](https://github.com/Byron/gitoxide/commit/47c00c2228cf25c79e1fa3eb4229c7ab24de91e5)) + - Finish git-features documentation ([`934a26c`](https://github.com/Byron/gitoxide/commit/934a26c5e254baf2be9178096b6dead0e4c1ed1d)) + - Refactor ([`b3a8bb5`](https://github.com/Byron/gitoxide/commit/b3a8bb5f7f0c6e80259922546928c2739c24f7b5)) + - Refactor ([`f9e8d29`](https://github.com/Byron/gitoxide/commit/f9e8d2932c02c22bf57acd39fb0a9e6d521070bd)) + - Docs for the git-features::pipe module ([`67a950a`](https://github.com/Byron/gitoxide/commit/67a950a2e0fd56b29565668ed0a0f399d5aa989d)) + - Document git-features::parallel ([`b899227`](https://github.com/Byron/gitoxide/commit/b8992275cd4310b05494be41c059e9b6049d06b1)) + - Dependency update ([`fb077f9`](https://github.com/Byron/gitoxide/commit/fb077f9fecb89ed8a60d57b45726401883e838bf)) + - Finish git_features::interrupt docs ([`471a1bf`](https://github.com/Byron/gitoxide/commit/471a1bf24efee70f21b15839cdc9f8ebe319f917)) + - Dependency update ([`b3b4aba`](https://github.com/Byron/gitoxide/commit/b3b4aba5e05596befecd17e225067be9315b74fd)) + - Docs for git-features::hash ([`a3fdecc`](https://github.com/Byron/gitoxide/commit/a3fdecc9a3587b20c01e3b3a2d51190138131c3d)) + - First sketch of filesystem docs for git-features ([`1a8141c`](https://github.com/Byron/gitoxide/commit/1a8141c2c4a8bcc79d68049a35bd8aba5ab822a3)) + - (cargo-release) version 0.7.0 ([`7fa7bae`](https://github.com/Byron/gitoxide/commit/7fa7baeb3e7d008a25e4d714eff908e2516c828b)) + - Merge branch 'commit-graph' into main ([`9cb09b2`](https://github.com/Byron/gitoxide/commit/9cb09b248796f0ff5c9d3f3e857de4731324cfd5)) + - Specify the hash to create with 'hash::bytes_of_file' ([`c000294`](https://github.com/Byron/gitoxide/commit/c000294423ae0759b978399db3b69ac07c20578d)) + - Move 'git_odb::hash::bytes_of_file' into git_features::hash ([`c5f6b45`](https://github.com/Byron/gitoxide/commit/c5f6b4587ee4042a080c0505613b0c72fdfe5273)) + - Remove dash in all repository links ([`98c1360`](https://github.com/Byron/gitoxide/commit/98c1360ba4d2fb3443602b7da8775906224feb1d)) + - Merge branch 'main' into commit-graph ([`ca5b801`](https://github.com/Byron/gitoxide/commit/ca5b80174b73cc9ac162b3f33b5d3721ef936cb1)) + - Use parallel walkdir (via jwalk) when parallel feature is enabled ([`f444c85`](https://github.com/Byron/gitoxide/commit/f444c859f5b215ea70a46d5493a2babbf7a98235)) + - Merge from main. ([`b59bd5e`](https://github.com/Byron/gitoxide/commit/b59bd5e0b0895c7d1d585816cec8be4dea78c278)) + - Refactor ([`e4bcfe6`](https://github.com/Byron/gitoxide/commit/e4bcfe6406b14feffa63598c7cdcc8ecc73222bd)) + - (cargo-release) version 0.6.0 ([`9ef184e`](https://github.com/Byron/gitoxide/commit/9ef184e35712f938fb4f9f6da7390a8777a9284e)) + - Switch to prodash 10 and safe a lot of trait bounds in the process ([`e2fb1d9`](https://github.com/Byron/gitoxide/commit/e2fb1d944b4d803a11c91f868b831d406fb5e35f)) + - (cargo-release) version 0.5.0 ([`82b7313`](https://github.com/Byron/gitoxide/commit/82b73131b79ec3c42a712dad1c0766a72209d737)) + - [clone] This actually works: first MVP of retrieving packs via clone ([`c06d819`](https://github.com/Byron/gitoxide/commit/c06d8194173f9ec468ddd0faf72dd6d8dbf7d35d)) + - [clone] test (and fix) for piped line reading ([`afe2996`](https://github.com/Byron/gitoxide/commit/afe2996689b5bea915ac5f142d320056faf49899)) + - [clone] Send headers with BufReaders ([`6a95aaa`](https://github.com/Byron/gitoxide/commit/6a95aaab582941c6d1697dde6982c0aa8896c73d)) + - [clone] pipe allows to send errors as well ([`69286ec`](https://github.com/Byron/gitoxide/commit/69286ecb3680b5071693ef0d9fb2e9345b2722d4)) + - [clone] BufRead for Reader… ([`bf1d40f`](https://github.com/Byron/gitoxide/commit/bf1d40f2d44a9b04ffe2134ddcd3779985cdafc4)) + - [clone] a piped iterator ([`5148c85`](https://github.com/Byron/gitoxide/commit/5148c85efc70c0ec06be3ebce267ce727c8ee4e1)) + - [clone] pipe probably shouldn't abort on empty writes ([`9cfa9b7`](https://github.com/Byron/gitoxide/commit/9cfa9b79841187167f0f96abfd1c17a37b4c365d)) + - Thanks clippy ([`c4f570f`](https://github.com/Byron/gitoxide/commit/c4f570fcae7e21745a37a4265b05d21e6149157b)) + - [clone] more pipe tests ([`1652a74`](https://github.com/Byron/gitoxide/commit/1652a74761631cadfc6feab366adc0808d83063d)) + - [clone] first working pipe implementation ([`490a9b9`](https://github.com/Byron/gitoxide/commit/490a9b96915a760e339e576d9f49737b43a8739f)) + - [clone] frame for implementing 'pipe' support ([`c555681`](https://github.com/Byron/gitoxide/commit/c55568127ff943cc6749dba5054d7b3e93c049eb)) + - Fix git-features hash tests ([`35e8809`](https://github.com/Byron/gitoxide/commit/35e8809f6bc7d19ed9e0bac8e3af85f433978901)) + - Bump git-features to 0.4 to allow publishes after breaking changes ([`9d6b879`](https://github.com/Byron/gitoxide/commit/9d6b8790e2edd7fa01b3239adff86a7cd2393f10)) + - [protocol] properly implement remote progress reporting ([`a81954a`](https://github.com/Byron/gitoxide/commit/a81954a6a37afacd51add6661a656b8fb663ca54)) + - Allow dual-licensing with Apache 2.0 ([`ea353eb`](https://github.com/Byron/gitoxide/commit/ea353eb02fd4f75508600cc5676107bc7e627f1e)) + - Add 'disable-interrupts' feature flag ([`ccd9c3e`](https://github.com/Byron/gitoxide/commit/ccd9c3e2d37aa6898dc17f47a82c187baa810b03)) + - Refactor ([`b4a6e16`](https://github.com/Byron/gitoxide/commit/b4a6e16364822c0dccb56f98dbfb0ca4c8007069)) + - Bump minor version to 0.3 ([`4351e28`](https://github.com/Byron/gitoxide/commit/4351e2871c9dcf342b8471fffa74cae338a53269)) + - Thanks clippy ([`6725104`](https://github.com/Byron/gitoxide/commit/6725104d2841e6518db641d06e3e107cf4f40f96)) + - First step towards parallelizing file hashes and traversal! ([`9573836`](https://github.com/Byron/gitoxide/commit/95738369e0d3accf7f6239c8cd966a7f5c36825a)) + - Better usability for units ([`b226253`](https://github.com/Byron/gitoxide/commit/b226253636d8146a084a7bcd7c0c320e37f9d2fb)) + - Update dependencie ([`ade06b4`](https://github.com/Byron/gitoxide/commit/ade06b46bb3c16ac1e26dbbb4a7045f0c09f2d8e)) + - Make obvious that interrupt request was received ([`34b2373`](https://github.com/Byron/gitoxide/commit/34b23737f560fe52d4f98fb886eba754652f9a5e)) + - Remove once_cell dependency as it is really not required anymore ([`5ac9538`](https://github.com/Byron/gitoxide/commit/5ac95385cc8d1c50c16da6e5fb0c66ac138f9966)) + - Make interrupt handler work reliably ([`e71da0f`](https://github.com/Byron/gitoxide/commit/e71da0fce6d6eab68f7b81b13cdc78ce8e9b7ee3)) + - Conditionally use an eager iterator… ([`e9b5511`](https://github.com/Byron/gitoxide/commit/e9b5511568f4e64968596994855783f19672d678)) + - Refactor ([`d14f0f6`](https://github.com/Byron/gitoxide/commit/d14f0f6c3b5f303df75b33aadbf16653075d2272)) + - Allow eager iterator to behave properly when used with index writing ([`66ebc5f`](https://github.com/Byron/gitoxide/commit/66ebc5f1ad5f262eb464dc7ca0892ec952d34382)) + - First successful test of moving the streaming iterator into its own thread ([`c9fcb68`](https://github.com/Byron/gitoxide/commit/c9fcb68c644c96a15cb9956a754bec7b65bb5fbd)) + - Now it's order preserving ([`4c8711e`](https://github.com/Byron/gitoxide/commit/4c8711e51efd88e0f159ad02de2692c4cb72ce27)) + - First sketch of order-destroying eager iterator ([`20fca45`](https://github.com/Byron/gitoxide/commit/20fca4515f6e9ea320d0bf21c15cd6d2c3cff742)) + - Print read throughput automatically ([`0a71b48`](https://github.com/Byron/gitoxide/commit/0a71b482310a129aa8757475290b3b24a200b702)) + - Make sure interrupt logic works even without an interrupt handler… ([`66b1644`](https://github.com/Byron/gitoxide/commit/66b164472f5893f9e634ac1f9147a41dc742296d)) + - Add percentage and throughput to tasks that matter ([`763d7ca`](https://github.com/Byron/gitoxide/commit/763d7caa4c70111b7cb3ef5733d2c3c697758c28)) + - Upgrade to latest iteration of prodash ([`3a4faec`](https://github.com/Byron/gitoxide/commit/3a4faecab56e37670c553e6563f11a46d740c333)) + - First part of migration to prodash 8.0, but… ([`6901a09`](https://github.com/Byron/gitoxide/commit/6901a098641820c8d974ce56a24d6cdca779730d)) + - Thanks clippy ([`ed5882d`](https://github.com/Byron/gitoxide/commit/ed5882d75e0a9fceb0628e84302eb49a66277fa6)) + - Write about user interfaces and the use/non-use of async ([`91ba045`](https://github.com/Byron/gitoxide/commit/91ba0457745f860b7a68cb38b13e69754747e8d9)) + - Interrupt support for pretty plumbing ([`bca7ce2`](https://github.com/Byron/gitoxide/commit/bca7ce2e668a4be2600d2d04d00f46b21c82eee2)) + - Support for interruptible operations ([`a025593`](https://github.com/Byron/gitoxide/commit/a02559378f9165df97a217f24834a851be719b08)) + - Refactor ([`413968d`](https://github.com/Byron/gitoxide/commit/413968dfee5e5a66ed9e63823f6bda5a5a22753e)) + - Receive progress information when reading packs in bundle ([`759091d`](https://github.com/Byron/gitoxide/commit/759091d3c6696b427d7b5aab1b6da05a0d268c04)) + - Initial batch of progress usage for index creation… ([`b10e5c6`](https://github.com/Byron/gitoxide/commit/b10e5c664be9bd1bdb2b72b858ebaf35c1ed4cb4)) + - First stab at streaming pack header encoding ([`3c6e78b`](https://github.com/Byron/gitoxide/commit/3c6e78bec9cbd4df842919cc8dc3c575414ed002)) + - We can now restore (possibly half-written) packs ([`b1daa46`](https://github.com/Byron/gitoxide/commit/b1daa465c40ea8c7c9de69a18e467d69459d911e)) + - See how big a Sha1 hasher really is ([`26b271d`](https://github.com/Byron/gitoxide/commit/26b271d44863fb184b0a947c3a9da2b3252f9a78)) + - First sketch of new verify expressed in terms of traversal ([`4cb570f`](https://github.com/Byron/gitoxide/commit/4cb570f96ddd7ee2faa62e54927afd78ba7822af)) + - (cargo-release) version 0.2.0 ([`0bb8314`](https://github.com/Byron/gitoxide/commit/0bb831480d8657e1bb29ee7009aeac673471403e)) + - Incorporate dynamic chunking into 'less-time' algorithm ([`295aa2f`](https://github.com/Byron/gitoxide/commit/295aa2f01dc596a8880cd2f68a8d83bc6913ce48)) + - Integrate new chunk size code into lookup code ([`a8422cf`](https://github.com/Byron/gitoxide/commit/a8422cf0b0c9ff4d3275cc17a68a74811b5bd01f)) + - First round of number tuning done ([`a647b2d`](https://github.com/Byron/gitoxide/commit/a647b2da2905c4079e646ea44cbec778f3f7c71f)) + - Somehow handle chunk size in absence of known chunk amount ([`acfccad`](https://github.com/Byron/gitoxide/commit/acfccadef40ebcc67f8dea4e58c02392b7e2e7de)) + - Chunk computation seems alright, what about realistic values ([`973e6bb`](https://github.com/Byron/gitoxide/commit/973e6bb3d67d89eec2faf2467a129d992b90ed72)) + - Getting there… ([`a1b5d56`](https://github.com/Byron/gitoxide/commit/a1b5d565f305f0f2666fd59272d9bf9c62ae2962)) + - First step towards computing better chunk sizes and thread limits ([`1cdde7d`](https://github.com/Byron/gitoxide/commit/1cdde7d339a6ed3650c54f9b48154089d7da9919)) + - Add 'inc()' convenience methods to progress ([`2e46c9b`](https://github.com/Byron/gitoxide/commit/2e46c9b72a2a5b90bcdac249de07ffbc124cfb04)) + - (more) graceful shutdown of failing parallel tasks ([`163f50f`](https://github.com/Byron/gitoxide/commit/163f50fab81b425e6e306ec54fb1eb60a7c02cf8)) + - Respect thread limit in 'in_parallel' ([`babfd84`](https://github.com/Byron/gitoxide/commit/babfd84cba77ef7a0f541ba921b31ebd3f3c50e3)) + - Make crates publishable ([`5688a34`](https://github.com/Byron/gitoxide/commit/5688a3427ff3673e1422d43106f4d685fa837aed)) + - Flume isn't actually needed for that… ([`c750022`](https://github.com/Byron/gitoxide/commit/c750022394928aa37a8400611f6fdf4ee77c0f69)) + - Don't just ignore send errors - we should panic for now ([`f128117`](https://github.com/Byron/gitoxide/commit/f128117138b24de780a00bb96e7c1c9f987e8aa0)) + - Proper implementation of line renderer into 'lean' CLI ([`e98e7c2`](https://github.com/Byron/gitoxide/commit/e98e7c280d73e9d9ebd13202afb93a56cb2f7c9c)) + - Upgrade to prodash version 7 ([`af02b46`](https://github.com/Byron/gitoxide/commit/af02b46cc1eff5ba1da7da20d3f524a79fad686f)) + - Update prodash to verion 6.0 ([`a4731a3`](https://github.com/Byron/gitoxide/commit/a4731a3aca159f8916b29d9ce5a71856089c5a6b)) + - Add metadata to allow docs.rs build all featueres ([`10f9386`](https://github.com/Byron/gitoxide/commit/10f9386a12decc1f13999aee72be484c8f6d48ce)) + - Switch to prodash 5.0 for windows support ([`88542e1`](https://github.com/Byron/gitoxide/commit/88542e117dd1c2e7606fcbe88b30c51b4c115989)) + - Allow to limit the logging depth for less cluttered output ([`fce7035`](https://github.com/Byron/gitoxide/commit/fce703531d7006f7d961d6ffa66f51f6c9bc0efc)) + - Finally speed up logging progress properly - needs input throttling ([`1a550c6`](https://github.com/Byron/gitoxide/commit/1a550c6458b10fad2e42b641899216c5517c6e26)) + - Avoid calling system time too often in logs, it reduced performance ([`b17bd76`](https://github.com/Byron/gitoxide/commit/b17bd76d35822b3af174c74af3d6fac887889fe2)) + - Revert "ABORT: try-join with static typing works, but…" ([`b8b979b`](https://github.com/Byron/gitoxide/commit/b8b979b99b5f3848e0a6884c58594ba2b481a147)) + - Try-join with static typing works, but… ([`ab6f98b`](https://github.com/Byron/gitoxide/commit/ab6f98b905f13ed2a7c0c483f34fab63141fbc5b)) + - Remove dependency to git-object from git-features - it better remains free ([`67c3a6a`](https://github.com/Byron/gitoxide/commit/67c3a6ab4cc32358a1406c2f863e26a4c2929867)) + - \#[forbid(unsafe)] for all crates ([`afda803`](https://github.com/Byron/gitoxide/commit/afda8039259b7a30cfed5dbcdd9caf4773b4c234)) + - Allow for more screen space when formatting ([`6794300`](https://github.com/Byron/gitoxide/commit/67943002e7f4215b5383bd0538786ce2857f011e)) + - Refactor ([`7add82c`](https://github.com/Byron/gitoxide/commit/7add82c39169e3c2fff76c48cdd318fe6040d7bc)) + - Automatically close the TUI when there is no progress anymore. ([`c416152`](https://github.com/Byron/gitoxide/commit/c416152b04051958de7bd161a8a2ee42ca163275)) + - Pretty progress in a generalized form ([`caa883b`](https://github.com/Byron/gitoxide/commit/caa883b96827deb63b5c8787ed820d22f2c85249)) + - Express DoOrDiscard in terms of Either (progress) ([`cb29a45`](https://github.com/Byron/gitoxide/commit/cb29a45f4e73bfaa25cbf623b1cda2435673028b)) + - Provide 'either' type with implementation for Progress ([`237bb5e`](https://github.com/Byron/gitoxide/commit/237bb5ee1c2b677f5bfd9ca7fdea9d9d2db865b3)) + - Better trait bounds of `in_parallel_if`… ([`6264f2f`](https://github.com/Byron/gitoxide/commit/6264f2f99929ffaa4d50cdcae7bc296e1b4762f4)) + - First implementation of logging per thread ([`477dd90`](https://github.com/Byron/gitoxide/commit/477dd90ce5e102875b19489bf8ae9877522ef9c8)) + - Support for providing progress to threads ([`2815858`](https://github.com/Byron/gitoxide/commit/2815858adf7ac0f7b4cbc88cf05df0ea6aef4116)) + - First very basic progress implementation ([`b820717`](https://github.com/Byron/gitoxide/commit/b8207177daee8a9ffa23c7c052cf9ca651b15804)) + - Pass progress everywhere, for now just to discard it ([`da3ae1c`](https://github.com/Byron/gitoxide/commit/da3ae1c82cd726b8fae9b8d26069719930e9ba99)) + - Implement `Progress` trait for prodash::tree::Item ([`0eeb6d7`](https://github.com/Byron/gitoxide/commit/0eeb6d770d58621427bc88107a20860b89b86a24)) + - Implement progress trait for logs with throttling ([`287eca9`](https://github.com/Byron/gitoxide/commit/287eca91b244ccbc703cb275b1ae032bfeb02532)) + - Add 'fast-sha1' to git-features ([`b22541f`](https://github.com/Byron/gitoxide/commit/b22541f0c39af470877119b136e4eb1b82dff2db)) + - A new crate to represent features that can toggle from the top-level ([`23c420c`](https://github.com/Byron/gitoxide/commit/23c420cc95219dc7c04d3905aaa03281cb51724e)) +</details> + +## 0.26.3 (2023-02-14) + +### New Features + + - <csr-id-426057247a80821b3da22b4ae5d67bda89ce0631/> re-export `prodash` in `progress` module. + That way one can access all types even if they are not re-exported. + +## 0.26.2 (2023-02-09) + +### Documentation + + - <csr-id-39ed9eda62b7718d5109135e5ad406fb1fe2978c/> fix typos + +### New Features + + - <csr-id-c4a7634b0b29c74625e183953e59c65987e9d66c/> export `prodash::progress::Id` in the `progress` module for convenience. + +## 0.26.1 (2023-01-10) + +A maintenance release without user-facing changes. + +## 0.26.0 (2022-12-30) + +<csr-id-5bf0034fb3918e57562b7089ceba83d63a1854bf/> + +### Chore (BREAKING) + + - <csr-id-5bf0034fb3918e57562b7089ceba83d63a1854bf/> upgrade to prodash v23 + +## 0.25.1 (2022-12-26) + +### New Features + + - <csr-id-25ad372bf500b851105f53b10369b5a689ba167e/> zlib::inflate::Error can now represent zlib status codes that represent failure. + +## 0.25.0 (2022-12-19) + +### New Features (BREAKING) + + - <csr-id-0f27c67c92fc0bc23a6712b5c4c730ad6a0156bf/> add support for explicit non-parallel iteration. + That way we can allow the implementation to choose whether they + need greatest speed at some cost or not. + + This also allows us to create a new thread-pool on each iteration + as those who expect high cost or many files will likely chose to do + that instead of single-threaded iteration, which nicely contains the + threads needed and avoids keeping them alive as part of some global pool. + +## 0.24.1 (2022-11-27) + +### New Features + + - <csr-id-6d530a1dc77f0f4ac00622a2fd47c7bdb731a77a/> name spawned threads + That way it's a bit more obvious what's happening when the CPU goes + up in flames. + - <csr-id-c8835c6edae784c9ffcb69a674c0a6545dbb2af3/> upgrade to `prodash 21.1` and add `Ids` to all progress instances. + That way callers can identify progress they are interested in, say, for + selective visualizations. + +## 0.24.0 (2022-11-21) + +A maintenance release without user facing changes. + +## 0.23.1 (2022-11-06) + +### New Features + + - <csr-id-9076ce33ec167e425a0163d3e40a81a3fd0db6cd/> `fs::Snapshot` can `Clone` if `T` can `Clone`. + +## 0.23.0 (2022-10-10) + +### New Features + + - <csr-id-a7c11d2cb5f88a4ff322d9a9848459062790d8b3/> perfect granularity for threads processing with `in_parallel_with_slice()` + - <csr-id-ff1db66f2dad3afc8bc77610006bca9fea5947d2/> add `progress::Step|StepShared` as types of `prodash` + This may help to use the `Progress::counter()` method as part of method + signatures, being an `Option<progress::StepShared>`. + +### Changed (BREAKING) + + - <csr-id-38446dc8824afef30ef121598de3451d13b9262c/> remove `fs-jwalk-single-threaded` in favor of `fs-walkdir-parallel`. + This way, `jwalk` and the dependencies (and troubles) it brings have to + be opted in, but also allow other users to actually opt out while + allowing the `parallel` feature to be in effect. + + In other words, previously the `parallel` feature conflated `jwalk` + dependencies into the tree, which isn't the case anymore. + +### New Features (BREAKING) + + - <csr-id-3b29fc18672c0176684c797a0f16f85d09369bf8/> make jwalk fully optional + +## 0.22.6 (2022-09-16) + +Fix docs.rs rendering. + +### New Features + + - <csr-id-cfe46b502afc3ecb312849ddbd7748007d432cd1/> add zlib-ng feature to allow linking against system libz-ng + Allow to use zlib-ng (zlib-ng-sys) with native API (no compat mode) + that can co-exist with system libz (loaded by e.g. libcurl). + This is used in gitoxide package on Alpine Linux. + +## 0.22.5 (2022-09-20) + +### New Features + + - <csr-id-cfe46b502afc3ecb312849ddbd7748007d432cd1/> add zlib-ng feature to allow linking against system libz-ng + Allow to use zlib-ng (zlib-ng-sys) with native API (no compat mode) + that can co-exist with system libz (loaded by e.g. libcurl). + This is used in gitoxide package on Alpine Linux. + +## 0.22.4 (2022-09-04) + +A maintenance release without breaking changes. + +## 0.22.3 (2022-08-27) + +### Fix + +- restrict `sha1` `asm` to supported archs ([`b383fab`](https://github.com/Byron/gitoxide/commit/b383fabbe10868317be51b99cfdd9b0981816042)) + +## 0.22.2 (2022-08-24) + +<csr-id-f7f136dbe4f86e7dee1d54835c420ec07c96cd78/> + +### Chore + + - <csr-id-f7f136dbe4f86e7dee1d54835c420ec07c96cd78/> uniformize deny attributes + +### New Features + + - <csr-id-b1c40b0364ef092cd52d03b34f491b254816b18d/> use docsrs feature in code to show what is feature-gated automatically on docs.rs + - <csr-id-517677147f1c17304c62cf97a1dd09f232ebf5db/> pass --cfg docsrs when compiling for https://docs.rs + +## 0.22.1 (2022-08-15) + +### New Features + + - <csr-id-f498d35baba52e40ecd47381e87c1ce49cf13285/> add `fs-jwalk-single-threaded` feature to specifically decouple `jwalk` from rayon + It has been an issue in https://github.com/starship/starship/issues/4251 + apparently and rayon interactions can be difficult. + - <csr-id-7f199f0e5246809efde9880110093fbd11a4f8fe/> `fs::Snapshot` to on-demand reload shared resources. + +## 0.22.0 (2022-07-22) + +### New Features + + - <csr-id-c76fde7de278b49ded13b655d5345e4eb8c1b134/> initialize `Time` from `now_utc` and `now_local` + Localtime support depends on some other factors now, but that + will only get better over time. + + We might have to document `unsound_local_time` at some point. + +### Changed (BREAKING) + + - <csr-id-89a41bf2b37db29b9983b4e5492cfd67ed490b23/> remove local-time-support feature toggle. + We treat local time as default feature without a lot of fuzz, and + will eventually document that definitive support needs a compile + time switch in the compiler (`--cfg unsound_local_offset` or something). + + One day it will perish. Failure is possible anyway and we will write + code to deal with it while minimizing the amount of system time + fetches when asking for the current local time. + +## 0.21.1 (2022-06-13) + +A maintenance release without user-facing changes. + +## 0.21.0 (2022-05-18) + +### Changed (BREAKING) + + - <csr-id-90611ce1527618bcc738440bfc1ccc7a45319974/> remove `path` module in favor of `gix-path` crate + +### New Features (BREAKING) + + - <csr-id-d078d6ee76a80d1dfaf71608c12d8a402bd670d4/> mild refactor of paths module to waste less on unix + Previously it might have performed find-and-replace on unix paths even + though they wouldn't have changed afterwards, yet costing an allocation. + + There is also the realization that it should go into its own crate to have + neater import paths and more convenience. + +## 0.20.0 (2022-04-02) + +### New Features + + - <csr-id-e4d6685064ad2b433f8acd3a74b320bf0169a994/> Add `gix_config::values::Path` for a typesafe git path + Add a `Path` type to the `gix_config::values` which + can be interpolated according to gits own path interpolation + rules. + - <csr-id-3c8581fc294c65c9eb42698969fe3263135a864e/> add new 'path' module for all path-related conversions + It's meant to unify all path and byte related handling to help assuring + encoding is handled correctly or at least similarly everywhere. + - <csr-id-15ff212b17087de93f259e366f4e4b821cfbc28e/> in-manifest and in-lib documentation of feature toggles + +### Bug Fixes + + - <csr-id-234cd10ca55482ce1a840ce3244308d249895bcc/> Assure std::io::copy() doesn't hang when we cause an interrupt + The user can ask for interruptions which previously used the + error kind Interrupted. This however has special meaning and + usually means to retry. + +### New Features (BREAKING) + + - <csr-id-8945d95f7fa88562d37ff67ac6e38bead73dd2df/> `interrupt::Iter`, rename `interrupt::Iter` -> `interrupt::IterWithError` + +## 0.19.1 (2022-01-23) + +<csr-id-361892ca15aa648802f6701ab6a5a30aedde3449/> + +A maintenance release thanks to upgrade to `prodash` 18. + +### Changed (BREAKING) + + - <csr-id-61e5cfece4d8f405e35fc1957b00ce1da7526c26/> renamed `progress::Read::reader` -> `progress::Read::inner` + +### New Features + + - <csr-id-cb7e4e784d615f9fa3d6fb9c36240f0592403358/> Add InOrderIter to 'parallel' module + This iterator makes possible identifies results using a sequence id + and returns only consecutive items. + + Use it to collect unordered results produced by threads. + It's advantage to collecting yourself and sorting is the potential + for a smaller memory footprint of in-flight results, one doesn't + have to collect them all for ordering, necessarily. + - <csr-id-ca095ed881db2a8f06a6b067dbaac17e923b0945/> Make a scope-like abstraction available + This allows more delicate threading control like is required for the + index. + - <csr-id-b8400ed80543d67a5895c975ba9b1fc28427411c/> decoding of variable int numbers. + It's here only so that we can share the code across crates, for now + without any feature toggles. + - <csr-id-0a749a22057b5513a8cefa0e26b0a9a268c769d3/> Add `progress::Write` to automatically pass bytes written to a progress instance + +### Chore + + - <csr-id-361892ca15aa648802f6701ab6a5a30aedde3449/> update sha-1 dependency to 0.10 + +## 0.19.0 (2022-01-19) + +<csr-id-361892ca15aa648802f6701ab6a5a30aedde3449/> + +### Chore + + - <csr-id-361892ca15aa648802f6701ab6a5a30aedde3449/> update sha-1 dependency to 0.10 + +### New Features + + - <csr-id-cb7e4e784d615f9fa3d6fb9c36240f0592403358/> Add InOrderIter to 'parallel' module + This iterator makes possible identifies results using a sequence id + and returns only consecutive items. + + Use it to collect unordered results produced by threads. + It's advantage to collecting yourself and sorting is the potential + for a smaller memory footprint of in-flight results, one doesn't + have to collect them all for ordering, necessarily. + - <csr-id-ca095ed881db2a8f06a6b067dbaac17e923b0945/> Make a scope-like abstraction available + This allows more delicate threading control like is required for the + index. + - <csr-id-b8400ed80543d67a5895c975ba9b1fc28427411c/> decoding of variable int numbers. + It's here only so that we can share the code across crates, for now + without any feature toggles. + - <csr-id-0a749a22057b5513a8cefa0e26b0a9a268c769d3/> Add `progress::Write` to automatically pass bytes written to a progress instance + +### Changed (BREAKING) + + - <csr-id-61e5cfece4d8f405e35fc1957b00ce1da7526c26/> renamed `progress::Read::reader` -> `progress::Read::inner` + +## 0.18.0 (2021-11-29) + +### New Features + + - <csr-id-7e95d8ab29051ffc892f2dcbaf5369e8c7e7b294/> add threading primitives with feature toggle + If the `threading` feature is set, the `threading` module will contain thread-safe primitives + for shared ownership and mutation, otherwise these will be their single threaded counterparts. + + This way, single-threaded applications don't have to pay for threaded primitives. + +### Changed (BREAKING) + + - <csr-id-e7526b2a7b51cbac4018e1ab3b623a85987fadc2/> parallel utilities now use `Send + Clone` instead of `Send + Sync` + This helps to assure that thread-local computations always work with the + kind of types we provide. The ones that are carrying out actions are + notably not `Sync` anymore. + + We cater to that by defining our bounds accordingly, but for those + who want to use other utilities that need Sync, using types like + `Repository` and `thread_local!()` is the only way to make this + work. + +## v0.17.0 (2021-10-19) + +A maintenance release due to properly dealing with previously breaking changes in `gix-hash`. + +## v0.16.5 (2021-10-15) + +This release contains no functional changes. + +## v0.16.4 (2021-09-07) + +## v0.16.3 (2021-08-27) + +## v0.16.2 (2021-08-17) + +## v0.16.1 (2021-08-10) + +## v0.16.0 (2021-08-10) + +## v0.14.0 (2021-05-08) + +## v0.13.0 (2021-04-30) + +## v0.12.0 (2021-04-08) + +## v0.11.0 (2021-01-24) + +## v0.10.1 (2021-01-24) + +## v0.10.0 (2020-12-16) + +## v0.9.0 (2020-12-15) + +## v0.8.0 (2020-11-26) + +## v0.7.0 (2020-11-18) + +## v0.6.0 (2020-09-14) + +## v0.5.0 (2020-09-12) + +## v0.4.0 (2020-08-18) + +## v0.3.0 (2020-08-12) + +## v0.2.0 (2020-07-23) + +## v0.1.0 (2020-07-12) + +<csr-id-ab6f98b905f13ed2a7c0c483f34fab63141fbc5b/> + +### Other + + - <csr-id-ab6f98b905f13ed2a7c0c483f34fab63141fbc5b/> try-join with static typing works, but… + …seems like a lot of effort. Probably not worth continuing here + diff --git a/vendor/gix-features/Cargo.toml b/vendor/gix-features/Cargo.toml new file mode 100644 index 000000000..906a114ed --- /dev/null +++ b/vendor/gix-features/Cargo.toml @@ -0,0 +1,180 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.64" +name = "gix-features" +version = "0.28.0" +authors = ["Sebastian Thiel <sebastian.thiel@icloud.com>"] +description = "A crate to integrate various capabilities using compile-time feature flags" +license = "MIT/Apache-2.0" +repository = "https://github.com/Byron/gitoxide" +resolver = "2" + +[package.metadata.docs.rs] +all-features = true +features = ["document-features"] +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[lib] +test = false +doctest = false + +[[test]] +name = "hash" +path = "tests/hash.rs" +required-features = ["rustsha1"] + +[[test]] +name = "parallel" +path = "tests/parallel_threaded.rs" +required-features = [ + "parallel", + "rustsha1", +] + +[[test]] +name = "multi-threaded" +path = "tests/parallel_shared_threaded.rs" +required-features = [ + "parallel", + "rustsha1", +] + +[[test]] +name = "single-threaded" +path = "tests/parallel_shared.rs" +required-features = ["rustsha1"] + +[[test]] +name = "pipe" +path = "tests/pipe.rs" +required-features = ["io-pipe"] + +[dependencies.bytes] +version = "1.0.0" +optional = true + +[dependencies.bytesize] +version = "1.0.1" +optional = true + +[dependencies.crc32fast] +version = "1.2.1" +optional = true + +[dependencies.crossbeam-channel] +version = "0.5.0" +optional = true + +[dependencies.document-features] +version = "0.2.0" +optional = true + +[dependencies.flate2] +version = "1.0.17" +optional = true +default-features = false + +[dependencies.gix-hash] +version = "^0.10.3" + +[dependencies.jwalk] +version = "0.8.1" +optional = true + +[dependencies.once_cell] +version = "1.13.0" +optional = true + +[dependencies.parking_lot] +version = "0.12.0" +optional = true +default-features = false + +[dependencies.prodash] +version = "23.1" +optional = true +default-features = false + +[dependencies.sha1] +version = "0.10.0" +optional = true + +[dependencies.sha1_smol] +version = "1.0.0" +optional = true + +[dependencies.thiserror] +version = "1.0.38" +optional = true + +[dependencies.walkdir] +version = "2.3.2" +optional = true + +[dev-dependencies.bstr] +version = "1.3.0" +default-features = false + +[features] +cache-efficiency-debug = [] +crc32 = ["dep:crc32fast"] +default = [] +fast-sha1 = ["dep:sha1"] +fs-walkdir-parallel = ["dep:jwalk"] +io-pipe = ["dep:bytes"] +once_cell = ["dep:once_cell"] +parallel = [ + "dep:crossbeam-channel", + "dep:parking_lot", +] +progress = ["dep:prodash"] +progress-unit-bytes = [ + "dep:bytesize", + "prodash?/unit-bytes", +] +progress-unit-human-numbers = ["prodash?/unit-human"] +rustsha1 = ["dep:sha1_smol"] +walkdir = ["dep:walkdir"] +zlib = [ + "dep:flate2", + "flate2?/rust_backend", + "dep:thiserror", +] +zlib-ng = [ + "zlib", + "flate2?/zlib-ng", +] +zlib-ng-compat = [ + "zlib", + "flate2?/zlib-ng-compat", +] +zlib-rust-backend = [ + "zlib", + "flate2?/rust_backend", +] +zlib-stock = [ + "zlib", + "flate2?/zlib", +] + +[target."cfg(all(any(target_arch = \"aarch64\", target_arch = \"x86\", target_arch = \"x86_64\"), not(target_env = \"msvc\")))".dependencies.sha1] +version = "0.10.0" +features = ["asm"] +optional = true + +[target."cfg(unix)".dependencies.libc] +version = "0.2.119" diff --git a/vendor/gix-features/src/cache.rs b/vendor/gix-features/src/cache.rs new file mode 100644 index 000000000..f7a2cf005 --- /dev/null +++ b/vendor/gix-features/src/cache.rs @@ -0,0 +1,76 @@ +#[cfg(feature = "cache-efficiency-debug")] +mod impl_ { + /// A helper to collect useful information about cache efficiency. + pub struct Debug { + owner: String, + hits: usize, + puts: usize, + misses: usize, + } + + impl Debug { + /// Create a new instance + #[inline] + pub fn new(owner: impl Into<String>) -> Self { + Debug { + owner: owner.into(), + hits: 0, + puts: 0, + misses: 0, + } + } + /// Count cache insertions + #[inline] + pub fn put(&mut self) { + self.puts += 1; + } + /// Count hits + #[inline] + pub fn hit(&mut self) { + self.hits += 1; + } + /// Count misses + #[inline] + pub fn miss(&mut self) { + self.misses += 1; + } + } + + impl Drop for Debug { + fn drop(&mut self) { + let hits = self.hits; + let misses = self.misses; + let ratio = hits as f32 / misses as f32; + eprintln!( + "{}[{:0x}]: {} / {} (hits/misses) = {:.02}%, puts = {}", + self.owner, + self as *const _ as usize, + hits, + misses, + ratio * 100.0, + self.puts + ); + } + } +} +#[cfg(not(feature = "cache-efficiency-debug"))] +mod impl_ { + /// The disabled, zero size do-nothing equivalent + pub struct Debug; + + impl Debug { + /// Create a new instance + #[inline] + pub fn new(_owner: impl Into<String>) -> Self { + Debug + } + /// noop + pub fn put(&mut self) {} + /// noop + pub fn hit(&mut self) {} + /// noop + pub fn miss(&mut self) {} + } +} + +pub use impl_::Debug; diff --git a/vendor/gix-features/src/decode.rs b/vendor/gix-features/src/decode.rs new file mode 100644 index 000000000..0df38710d --- /dev/null +++ b/vendor/gix-features/src/decode.rs @@ -0,0 +1,38 @@ +use std::io::Read; + +/// Decode variable int numbers from a `Read` implementation. +/// +/// Note: currently overflow checks are only done in debug mode. +#[inline] +pub fn leb64_from_read(mut r: impl Read) -> Result<(u64, usize), std::io::Error> { + let mut b = [0u8; 1]; + let mut i = 0; + r.read_exact(&mut b)?; + i += 1; + let mut value = b[0] as u64 & 0x7f; + while b[0] & 0x80 != 0 { + r.read_exact(&mut b)?; + i += 1; + debug_assert!(i <= 10, "Would overflow value at 11th iteration"); + value += 1; + value = (value << 7) + (b[0] as u64 & 0x7f) + } + Ok((value, i)) +} + +/// Decode variable int numbers. +#[inline] +pub fn leb64(d: &[u8]) -> (u64, usize) { + let mut i = 0; + let mut c = d[i]; + i += 1; + let mut value = c as u64 & 0x7f; + while c & 0x80 != 0 { + c = d[i]; + i += 1; + debug_assert!(i <= 10, "Would overflow value at 11th iteration"); + value += 1; + value = (value << 7) + (c as u64 & 0x7f) + } + (value, i) +} diff --git a/vendor/gix-features/src/fs.rs b/vendor/gix-features/src/fs.rs new file mode 100644 index 000000000..f65779b92 --- /dev/null +++ b/vendor/gix-features/src/fs.rs @@ -0,0 +1,246 @@ +//! Filesystem utilities +//! +//! These are will be parallel if the `parallel` feature is enabled, at the expense of compiling additional dependencies +//! along with runtime costs for maintaining a global [`rayon`](https://docs.rs/rayon) thread pool. +//! +//! For information on how to use the [`WalkDir`] type, have a look at +//! * [`jwalk::WalkDir`](https://docs.rs/jwalk/0.5.1/jwalk/type.WalkDir.html) if `parallel` feature is enabled +//! * [walkdir::WalkDir](https://docs.rs/walkdir/2.3.1/walkdir/struct.WalkDir.html) otherwise + +#[cfg(any(feature = "walkdir", feature = "fs-walkdir-parallel"))] +mod shared { + /// The desired level of parallelism. + pub enum Parallelism { + /// Do not parallelize at all by making a serial traversal on the current thread. + Serial, + /// Create a new thread pool for each traversal with up to 16 threads or the amount of logical cores of the machine. + ThreadPoolPerTraversal { + /// The base name of the threads we create as part of the thread-pool. + thread_name: &'static str, + }, + } +} + +/// +#[cfg(feature = "fs-walkdir-parallel")] +pub mod walkdir { + use std::path::Path; + + pub use jwalk::{DirEntry as DirEntryGeneric, DirEntryIter as DirEntryIterGeneric, Error, WalkDir}; + + pub use super::shared::Parallelism; + + /// An alias for an uncustomized directory entry to match the one of the non-parallel version offered by `walkdir`. + pub type DirEntry = DirEntryGeneric<((), ())>; + + impl From<Parallelism> for jwalk::Parallelism { + fn from(v: Parallelism) -> Self { + match v { + Parallelism::Serial => jwalk::Parallelism::Serial, + Parallelism::ThreadPoolPerTraversal { thread_name } => std::thread::available_parallelism() + .map(|threads| { + let pool = jwalk::rayon::ThreadPoolBuilder::new() + .num_threads(threads.get().min(16)) + .stack_size(128 * 1024) + .thread_name(move |idx| format!("{thread_name} {idx}")) + .build() + .expect("we only set options that can't cause a build failure"); + jwalk::Parallelism::RayonExistingPool { + pool: pool.into(), + busy_timeout: None, + } + }) + .unwrap_or_else(|_| Parallelism::Serial.into()), + } + } + } + + /// Instantiate a new directory iterator which will not skip hidden files, with the given level of `parallelism`. + pub fn walkdir_new(root: impl AsRef<Path>, parallelism: Parallelism) -> WalkDir { + WalkDir::new(root).skip_hidden(false).parallelism(parallelism.into()) + } + + /// Instantiate a new directory iterator which will not skip hidden files and is sorted + pub fn walkdir_sorted_new(root: impl AsRef<Path>, parallelism: Parallelism) -> WalkDir { + WalkDir::new(root) + .skip_hidden(false) + .sort(true) + .parallelism(parallelism.into()) + } + + /// The Iterator yielding directory items + pub type DirEntryIter = DirEntryIterGeneric<((), ())>; +} + +#[cfg(all(feature = "walkdir", not(feature = "fs-walkdir-parallel")))] +/// +pub mod walkdir { + use std::path::Path; + + pub use walkdir::{DirEntry, Error, WalkDir}; + + pub use super::shared::Parallelism; + + /// Instantiate a new directory iterator which will not skip hidden files, with the given level of `parallelism`. + pub fn walkdir_new(root: impl AsRef<Path>, _: Parallelism) -> WalkDir { + WalkDir::new(root) + } + + /// Instantiate a new directory iterator which will not skip hidden files and is sorted, with the given level of `parallelism`. + pub fn walkdir_sorted_new(root: impl AsRef<Path>, _: Parallelism) -> WalkDir { + WalkDir::new(root).sort_by_file_name() + } + + /// The Iterator yielding directory items + pub type DirEntryIter = walkdir::IntoIter; +} + +#[cfg(any(feature = "walkdir", feature = "fs-walkdir-parallel"))] +pub use self::walkdir::{walkdir_new, walkdir_sorted_new, WalkDir}; + +/// Prepare open options which won't follow symlinks when the file is opened. +/// +/// Note: only effective on unix currently. +pub fn open_options_no_follow() -> std::fs::OpenOptions { + #[cfg_attr(not(unix), allow(unused_mut))] + let mut options = std::fs::OpenOptions::new(); + #[cfg(unix)] + { + /// Make sure that it's impossible to follow through to the target of symlinks. + /// Note that this will still follow symlinks in the path, which is what we assume + /// has been checked separately. + use std::os::unix::fs::OpenOptionsExt; + options.custom_flags(libc::O_NOFOLLOW); + } + options +} + +mod snapshot { + use std::ops::Deref; + + use crate::threading::{get_mut, get_ref, MutableOnDemand, OwnShared}; + + /// A structure holding enough information to reload a value if its on-disk representation changes as determined by its modified time. + #[derive(Debug)] + pub struct Snapshot<T: std::fmt::Debug> { + value: T, + modified: std::time::SystemTime, + } + + impl<T: Clone + std::fmt::Debug> Clone for Snapshot<T> { + fn clone(&self) -> Self { + Self { + value: self.value.clone(), + modified: self.modified, + } + } + } + + /// A snapshot of a resource which is up-to-date in the moment it is retrieved. + pub type SharedSnapshot<T> = OwnShared<Snapshot<T>>; + + /// Use this type for fields in structs that are to store the [`Snapshot`], typically behind an [`OwnShared`]. + /// + /// Note that the resource itself is behind another [`OwnShared`] to allow it to be used without holding any kind of lock, hence + /// without blocking updates while it is used. + #[derive(Debug, Default)] + pub struct MutableSnapshot<T: std::fmt::Debug>(pub MutableOnDemand<Option<SharedSnapshot<T>>>); + + impl<T: std::fmt::Debug> Deref for Snapshot<T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.value + } + } + + impl<T: std::fmt::Debug> Deref for MutableSnapshot<T> { + type Target = MutableOnDemand<Option<SharedSnapshot<T>>>; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl<T: std::fmt::Debug> MutableSnapshot<T> { + /// Create a new instance of this type. + /// + /// Useful in case `Default::default()` isn't working for some reason. + pub fn new() -> Self { + MutableSnapshot(MutableOnDemand::new(None)) + } + + /// Refresh `state` forcefully by re-`open`ing the resource. Note that `open()` returns `None` if the resource isn't + /// present on disk, and that it's critical that the modified time is obtained _before_ opening the resource. + pub fn force_refresh<E>( + &self, + open: impl FnOnce() -> Result<Option<(std::time::SystemTime, T)>, E>, + ) -> Result<(), E> { + let mut state = get_mut(&self.0); + *state = open()?.map(|(modified, value)| OwnShared::new(Snapshot { value, modified })); + Ok(()) + } + + /// Assure that the resource in `state` is up-to-date by comparing the `current_modification_time` with the one we know in `state` + /// and by acting accordingly. + /// Returns the potentially updated/reloaded resource if it is still present on disk, which then represents a snapshot that is up-to-date + /// in that very moment, or `None` if the underlying file doesn't exist. + /// + /// Note that even though this is racy, each time a request is made there is a chance to see the actual state. + pub fn recent_snapshot<E>( + &self, + mut current_modification_time: impl FnMut() -> Option<std::time::SystemTime>, + open: impl FnOnce() -> Result<Option<T>, E>, + ) -> Result<Option<SharedSnapshot<T>>, E> { + let state = get_ref(self); + let recent_modification = current_modification_time(); + let buffer = match (&*state, recent_modification) { + (None, None) => (*state).clone(), + (Some(_), None) => { + drop(state); + let mut state = get_mut(self); + *state = None; + (*state).clone() + } + (Some(snapshot), Some(modified_time)) => { + if snapshot.modified < modified_time { + drop(state); + let mut state = get_mut(self); + + if let (Some(_snapshot), Some(modified_time)) = (&*state, current_modification_time()) { + *state = open()?.map(|value| { + OwnShared::new(Snapshot { + value, + modified: modified_time, + }) + }); + } + + (*state).clone() + } else { + // Note that this relies on sub-section precision or else is a race when the packed file was just changed. + // It's nothing we can know though, so… up to the caller unfortunately. + Some(snapshot.clone()) + } + } + (None, Some(_modified_time)) => { + drop(state); + let mut state = get_mut(self); + // Still in the same situation? If so, load the buffer. This compensates for the trampling herd + // during lazy-loading at the expense of another mtime check. + if let (None, Some(modified_time)) = (&*state, current_modification_time()) { + *state = open()?.map(|value| { + OwnShared::new(Snapshot { + value, + modified: modified_time, + }) + }); + } + (*state).clone() + } + }; + Ok(buffer) + } + } +} +pub use snapshot::{MutableSnapshot, SharedSnapshot, Snapshot}; diff --git a/vendor/gix-features/src/hash.rs b/vendor/gix-features/src/hash.rs new file mode 100644 index 000000000..fe064139a --- /dev/null +++ b/vendor/gix-features/src/hash.rs @@ -0,0 +1,190 @@ +//! Hash functions and hash utilities +//! +//! With the `fast-sha1` feature, the `Sha1` hash type will use a more elaborate implementation utilizing hardware support +//! in case it is available. Otherwise the `rustsha1` feature should be set. `fast-sha1` will take precedence. +//! Otherwise, a minimal yet performant implementation is used instead for a decent trade-off between compile times and run-time performance. +#[cfg(all(feature = "rustsha1", not(feature = "fast-sha1")))] +mod _impl { + use super::Sha1Digest; + + /// A implementation of the Sha1 hash, which can be used once. + #[derive(Default, Clone)] + pub struct Sha1(sha1_smol::Sha1); + + impl Sha1 { + /// Digest the given `bytes`. + pub fn update(&mut self, bytes: &[u8]) { + self.0.update(bytes) + } + /// Finalize the hash and produce a digest. + pub fn digest(self) -> Sha1Digest { + self.0.digest().bytes() + } + } +} + +/// A 20 bytes digest produced by a [`Sha1`] hash implementation. +#[cfg(any(feature = "fast-sha1", feature = "rustsha1"))] +pub type Sha1Digest = [u8; 20]; + +#[cfg(feature = "fast-sha1")] +mod _impl { + use sha1::Digest; + + use super::Sha1Digest; + + /// A implementation of the Sha1 hash, which can be used once. + #[derive(Default, Clone)] + pub struct Sha1(sha1::Sha1); + + impl Sha1 { + /// Digest the given `bytes`. + pub fn update(&mut self, bytes: &[u8]) { + self.0.update(bytes) + } + /// Finalize the hash and produce a digest. + pub fn digest(self) -> Sha1Digest { + self.0.finalize().into() + } + } +} + +#[cfg(any(feature = "rustsha1", feature = "fast-sha1"))] +pub use _impl::Sha1; + +/// Compute a CRC32 hash from the given `bytes`, returning the CRC32 hash. +/// +/// When calling this function for the first time, `previous_value` should be `0`. Otherwise it +/// should be the previous return value of this function to provide a hash of multiple sequential +/// chunks of `bytes`. +#[cfg(feature = "crc32")] +pub fn crc32_update(previous_value: u32, bytes: &[u8]) -> u32 { + let mut h = crc32fast::Hasher::new_with_initial(previous_value); + h.update(bytes); + h.finalize() +} + +/// Compute a CRC32 value of the given input `bytes`. +/// +/// In case multiple chunks of `bytes` are present, one should use [`crc32_update()`] instead. +#[cfg(feature = "crc32")] +pub fn crc32(bytes: &[u8]) -> u32 { + let mut h = crc32fast::Hasher::new(); + h.update(bytes); + h.finalize() +} + +/// Produce a hasher suitable for the given kind of hash. +#[cfg(any(feature = "rustsha1", feature = "fast-sha1"))] +pub fn hasher(kind: gix_hash::Kind) -> Sha1 { + match kind { + gix_hash::Kind::Sha1 => Sha1::default(), + } +} + +/// Compute the hash of `kind` for the bytes in the file at `path`, hashing only the first `num_bytes_from_start` +/// while initializing and calling `progress`. +/// +/// `num_bytes_from_start` is useful to avoid reading trailing hashes, which are never part of the hash itself, +/// denoting the amount of bytes to hash starting from the beginning of the file. +/// +/// # Note +/// +/// * Only available with the `gix-object` feature enabled due to usage of the [`gix_hash::Kind`] enum and the +/// [`gix_hash::ObjectId`] return value. +/// * [Interrupts][crate::interrupt] are supported. +#[cfg(all(feature = "progress", any(feature = "rustsha1", feature = "fast-sha1")))] +pub fn bytes_of_file( + path: impl AsRef<std::path::Path>, + num_bytes_from_start: usize, + kind: gix_hash::Kind, + progress: &mut impl crate::progress::Progress, + should_interrupt: &std::sync::atomic::AtomicBool, +) -> std::io::Result<gix_hash::ObjectId> { + bytes( + std::fs::File::open(path)?, + num_bytes_from_start, + kind, + progress, + should_interrupt, + ) +} + +/// Similar to [`bytes_of_file`], but operates on an already open file. +#[cfg(all(feature = "progress", any(feature = "rustsha1", feature = "fast-sha1")))] +pub fn bytes( + mut read: impl std::io::Read, + num_bytes_from_start: usize, + kind: gix_hash::Kind, + progress: &mut impl crate::progress::Progress, + should_interrupt: &std::sync::atomic::AtomicBool, +) -> std::io::Result<gix_hash::ObjectId> { + let mut hasher = hasher(kind); + let start = std::time::Instant::now(); + // init progress before the possibility for failure, as convenience in case people want to recover + progress.init(Some(num_bytes_from_start), crate::progress::bytes()); + + const BUF_SIZE: usize = u16::MAX as usize; + let mut buf = [0u8; BUF_SIZE]; + let mut bytes_left = num_bytes_from_start; + + while bytes_left > 0 { + let out = &mut buf[..BUF_SIZE.min(bytes_left)]; + read.read_exact(out)?; + bytes_left -= out.len(); + progress.inc_by(out.len()); + hasher.update(out); + if should_interrupt.load(std::sync::atomic::Ordering::SeqCst) { + return Err(std::io::Error::new(std::io::ErrorKind::Other, "Interrupted")); + } + } + + let id = gix_hash::ObjectId::from(hasher.digest()); + progress.show_throughput(start); + Ok(id) +} + +#[cfg(any(feature = "rustsha1", feature = "fast-sha1"))] +mod write { + use crate::hash::Sha1; + + /// A utility to automatically generate a hash while writing into an inner writer. + pub struct Write<T> { + /// The hash implementation. + pub hash: Sha1, + /// The inner writer. + pub inner: T, + } + + impl<T> std::io::Write for Write<T> + where + T: std::io::Write, + { + fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { + let written = self.inner.write(buf)?; + self.hash.update(&buf[..written]); + Ok(written) + } + + fn flush(&mut self) -> std::io::Result<()> { + self.inner.flush() + } + } + + impl<T> Write<T> + where + T: std::io::Write, + { + /// Create a new hash writer which hashes all bytes written to `inner` with a hash of `kind`. + pub fn new(inner: T, object_hash: gix_hash::Kind) -> Self { + match object_hash { + gix_hash::Kind::Sha1 => Write { + inner, + hash: Sha1::default(), + }, + } + } + } +} +#[cfg(any(feature = "rustsha1", feature = "fast-sha1"))] +pub use write::Write; diff --git a/vendor/gix-features/src/interrupt.rs b/vendor/gix-features/src/interrupt.rs new file mode 100644 index 000000000..1f78e613a --- /dev/null +++ b/vendor/gix-features/src/interrupt.rs @@ -0,0 +1,125 @@ +//! Utilities to cause interruptions in common traits, like Read/Write and Iterator. +use std::{ + io, + sync::atomic::{AtomicBool, Ordering}, +}; + +/// A wrapper for an inner iterator which will check for interruptions on each iteration, stopping the iteration when +/// that is requested. +pub struct Iter<'a, I> { + /// The actual iterator to yield elements from. + pub inner: I, + should_interrupt: &'a AtomicBool, +} + +impl<'a, I> Iter<'a, I> +where + I: Iterator, +{ + /// Create a new iterator over `inner` which checks for interruptions on each iteration on `should_interrupt`. + /// + /// Note that this means the consumer of the iterator data should also be able to access `should_interrupt` and + /// consider it when producing the final result to avoid claiming success even though the operation is only partially + /// complete. + pub fn new(inner: I, should_interrupt: &'a AtomicBool) -> Self { + Iter { + inner, + should_interrupt, + } + } +} + +impl<'a, I> Iterator for Iter<'a, I> +where + I: Iterator, +{ + type Item = I::Item; + + fn next(&mut self) -> Option<Self::Item> { + if self.should_interrupt.load(Ordering::Relaxed) { + return None; + } + self.inner.next() + } +} + +/// A wrapper for an inner iterator which will check for interruptions on each iteration. +pub struct IterWithErr<'a, I, EFN> { + /// The actual iterator to yield elements from. + pub inner: I, + make_err: Option<EFN>, + should_interrupt: &'a AtomicBool, +} + +impl<'a, I, EFN, E> IterWithErr<'a, I, EFN> +where + I: Iterator, + EFN: FnOnce() -> E, +{ + /// Create a new iterator over `inner` which checks for interruptions on each iteration and calls `make_err()` to + /// signal an interruption happened, causing no further items to be iterated from that point on. + pub fn new(inner: I, make_err: EFN, should_interrupt: &'a AtomicBool) -> Self { + IterWithErr { + inner, + make_err: Some(make_err), + should_interrupt, + } + } +} + +impl<'a, I, EFN, E> Iterator for IterWithErr<'a, I, EFN> +where + I: Iterator, + EFN: FnOnce() -> E, +{ + type Item = Result<I::Item, E>; + + fn next(&mut self) -> Option<Self::Item> { + self.make_err.as_ref()?; + if self.should_interrupt.load(Ordering::Relaxed) { + return self.make_err.take().map(|f| Err(f())); + } + match self.inner.next() { + Some(next) => Some(Ok(next)), + None => { + self.make_err = None; + None + } + } + } +} + +/// A wrapper for implementors of [`std::io::Read`] or [`std::io::BufRead`] with interrupt support. +/// +/// It fails a [read][`std::io::Read::read`] while an interrupt was requested. +pub struct Read<'a, R> { + /// The actual implementor of [`std::io::Read`] to which interrupt support will be added. + pub inner: R, + /// The flag to trigger interruption + pub should_interrupt: &'a AtomicBool, +} + +impl<'a, R> io::Read for Read<'a, R> +where + R: io::Read, +{ + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + if self.should_interrupt.load(Ordering::Relaxed) { + return Err(std::io::Error::new(std::io::ErrorKind::Other, "Interrupted")); + } + self.inner.read(buf) + } +} + +impl<'a, R> io::BufRead for Read<'a, R> +where + R: io::BufRead, +{ + fn fill_buf(&mut self) -> io::Result<&[u8]> { + self.inner.fill_buf() + } + + fn consume(&mut self, amt: usize) { + self.inner.consume(amt) + } +} diff --git a/vendor/gix-features/src/io.rs b/vendor/gix-features/src/io.rs new file mode 100644 index 000000000..405960c0b --- /dev/null +++ b/vendor/gix-features/src/io.rs @@ -0,0 +1,94 @@ +//!A unidirectional pipe for bytes, analogous to a unix pipe. Available with the `io-pipe` feature toggle. + +/// A unidirectional pipe for bytes, analogous to a unix pipe. Available with the `io-pipe` feature toggle. +#[cfg(feature = "io-pipe")] +pub mod pipe { + use std::io; + + use bytes::{Buf, BufMut, BytesMut}; + + /// The write-end of the pipe, receiving items to become available in the [`Reader`]. + /// + /// It's commonly used with the [`std::io::Write`] trait it implements. + pub struct Writer { + /// The channel through which bytes are transferred. Useful for sending [`std::io::Error`]s instead. + pub channel: std::sync::mpsc::SyncSender<io::Result<BytesMut>>, + buf: BytesMut, + } + + /// The read-end of the pipe, implementing the [`std::io::Read`] trait. + pub struct Reader { + channel: std::sync::mpsc::Receiver<io::Result<BytesMut>>, + buf: BytesMut, + } + + impl io::BufRead for Reader { + fn fill_buf(&mut self) -> io::Result<&[u8]> { + if self.buf.is_empty() { + match self.channel.recv() { + Ok(Ok(buf)) => self.buf = buf, + Ok(Err(err)) => return Err(err), + Err(_) => {} + } + }; + Ok(&self.buf) + } + + fn consume(&mut self, amt: usize) { + self.buf.advance(amt.min(self.buf.len())); + } + } + + impl io::Read for Reader { + fn read(&mut self, mut out: &mut [u8]) -> io::Result<usize> { + let mut written = 0; + while !out.is_empty() { + if self.buf.is_empty() { + match self.channel.recv() { + Ok(Ok(buf)) => self.buf = buf, + Ok(Err(err)) => return Err(err), + Err(_) => break, + } + } + let bytes_to_write = self.buf.len().min(out.len()); + let (to_write, rest) = out.split_at_mut(bytes_to_write); + self.buf.split_to(bytes_to_write).copy_to_slice(to_write); + out = rest; + written += bytes_to_write; + } + Ok(written) + } + } + + impl io::Write for Writer { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.buf.put_slice(buf); + self.channel + .send(Ok(self.buf.split())) + .map_err(|err| io::Error::new(io::ErrorKind::BrokenPipe, err))?; + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + } + + /// Returns the _([`write`][Writer], [`read`][Reader])_ ends of a pipe for transferring bytes, analogous to a unix pipe. + /// + /// * `in_flight_writes` defines the amount of chunks of bytes to keep in memory until the `write` end will block when writing. + /// If `None` or `0`, the `write` end will always block until the `read` end consumes the transferred bytes. + pub fn unidirectional(in_flight_writes: impl Into<Option<usize>>) -> (Writer, Reader) { + let (tx, rx) = std::sync::mpsc::sync_channel(in_flight_writes.into().unwrap_or(0)); + ( + Writer { + channel: tx, + buf: BytesMut::with_capacity(4096), + }, + Reader { + channel: rx, + buf: BytesMut::new(), + }, + ) + } +} diff --git a/vendor/gix-features/src/lib.rs b/vendor/gix-features/src/lib.rs new file mode 100644 index 000000000..643320c0f --- /dev/null +++ b/vendor/gix-features/src/lib.rs @@ -0,0 +1,64 @@ +//! A crate providing foundational capabilities to other `git-*` crates with trade-offs between compile time, binary size or speed +//! selectable using cargo feature toggles. +//! +//! It's designed to allow the application level crate to configure feature toggles, affecting all other `git-*` crates using +//! this one. +//! +//! Thus all features provided here commonly have a 'cheap' base implementation, with the option to pull in +//! counterparts with higher performance. +//! ## Feature Flags +#![cfg_attr( + feature = "document-features", + cfg_attr(doc, doc = ::document_features::document_features!()) +)] +#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#![deny(missing_docs, rust_2018_idioms, unsafe_code)] + +/// +pub mod cache; +/// +pub mod decode; +pub mod fs; +pub mod hash; +pub mod interrupt; +#[cfg(feature = "io-pipe")] +pub mod io; +pub mod parallel; +#[cfg(feature = "progress")] +pub mod progress; +pub mod threading; +/// +#[cfg(feature = "zlib")] +pub mod zlib; + +/// +pub mod iter { + /// An iterator over chunks of input, producing `Vec<Item>` with a size of `size`, with the last chunk being the remainder and thus + /// potentially smaller than `size`. + pub struct Chunks<I> { + /// The inner iterator to ask for items. + pub inner: I, + /// The size of chunks to produce + pub size: usize, + } + + impl<I, Item> Iterator for Chunks<I> + where + I: Iterator<Item = Item>, + { + type Item = Vec<Item>; + + fn next(&mut self) -> Option<Self::Item> { + let mut res = Vec::with_capacity(self.size); + let mut items_left = self.size; + for item in &mut self.inner { + res.push(item); + items_left -= 1; + if items_left == 0 { + break; + } + } + (!res.is_empty()).then_some(res) + } + } +} diff --git a/vendor/gix-features/src/parallel/eager_iter.rs b/vendor/gix-features/src/parallel/eager_iter.rs new file mode 100644 index 000000000..60123f54c --- /dev/null +++ b/vendor/gix-features/src/parallel/eager_iter.rs @@ -0,0 +1,124 @@ +/// Evaluate any iterator in their own thread. +/// +/// This is particularly useful if the wrapped iterator performs IO and/or heavy computations. +/// Use [`EagerIter::new()`] for instantiation. +pub struct EagerIter<I: Iterator> { + receiver: std::sync::mpsc::Receiver<Vec<I::Item>>, + chunk: Option<std::vec::IntoIter<I::Item>>, + size_hint: (usize, Option<usize>), +} + +impl<I> EagerIter<I> +where + I: Iterator + Send + 'static, + <I as Iterator>::Item: Send, +{ + /// Return a new `EagerIter` which evaluates `iter` in its own thread, + /// with a given `chunk_size` allowing a maximum `chunks_in_flight`. + /// + /// * `chunk_size` describes how many items returned by `iter` will be a single item of this `EagerIter`. + /// This helps to reduce the overhead imposed by transferring many small items. + /// If this number is 1, each item will become a single chunk. 0 is invalid. + /// * `chunks_in_flight` describes how many chunks can be kept in memory in case the consumer of the `EagerIter`s items + /// isn't consuming them fast enough. Setting this number to 0 effectively turns off any caching, but blocks `EagerIter` + /// if its items aren't consumed fast enough. + pub fn new(iter: I, chunk_size: usize, chunks_in_flight: usize) -> Self { + let (sender, receiver) = std::sync::mpsc::sync_channel(chunks_in_flight); + let size_hint = iter.size_hint(); + assert!(chunk_size > 0, "non-zero chunk size is needed"); + + std::thread::spawn(move || { + let mut out = Vec::with_capacity(chunk_size); + for item in iter { + out.push(item); + if out.len() == chunk_size { + if sender.send(out).is_err() { + return; + } + out = Vec::with_capacity(chunk_size); + } + } + if !out.is_empty() { + sender.send(out).ok(); + } + }); + EagerIter { + receiver, + chunk: None, + size_hint, + } + } + + fn fill_buf_and_pop(&mut self) -> Option<I::Item> { + self.chunk = self.receiver.recv().ok().map(|v| { + assert!(!v.is_empty()); + v.into_iter() + }); + self.chunk.as_mut().and_then(|c| c.next()) + } +} + +impl<I> Iterator for EagerIter<I> +where + I: Iterator + Send + 'static, + <I as Iterator>::Item: Send, +{ + type Item = I::Item; + + fn next(&mut self) -> Option<Self::Item> { + match self.chunk.as_mut() { + Some(chunk) => chunk.next().or_else(|| self.fill_buf_and_pop()), + None => self.fill_buf_and_pop(), + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.size_hint + } +} + +/// An conditional `EagerIter`, which may become a just-in-time iterator running in the main thread depending on a condition. +pub enum EagerIterIf<I: Iterator> { + /// A separate thread will eagerly evaluate iterator `I`. + Eager(EagerIter<I>), + /// The current thread evaluates `I`. + OnDemand(I), +} + +impl<I> EagerIterIf<I> +where + I: Iterator + Send + 'static, + <I as Iterator>::Item: Send, +{ + /// Return a new `EagerIterIf` if `condition()` returns true. + /// + /// For all other parameters, please see [`EagerIter::new()`]. + pub fn new(condition: impl FnOnce() -> bool, iter: I, chunk_size: usize, chunks_in_flight: usize) -> Self { + if condition() { + EagerIterIf::Eager(EagerIter::new(iter, chunk_size, chunks_in_flight)) + } else { + EagerIterIf::OnDemand(iter) + } + } +} +impl<I> Iterator for EagerIterIf<I> +where + I: Iterator + Send + 'static, + <I as Iterator>::Item: Send, +{ + type Item = I::Item; + + fn next(&mut self) -> Option<Self::Item> { + match self { + EagerIterIf::OnDemand(i) => i.next(), + EagerIterIf::Eager(i) => i.next(), + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + match self { + EagerIterIf::OnDemand(i) => i.size_hint(), + EagerIterIf::Eager(i) => i.size_hint(), + } + } +} diff --git a/vendor/gix-features/src/parallel/in_order.rs b/vendor/gix-features/src/parallel/in_order.rs new file mode 100644 index 000000000..7928ac692 --- /dev/null +++ b/vendor/gix-features/src/parallel/in_order.rs @@ -0,0 +1,83 @@ +use std::{cmp::Ordering, collections::BTreeMap}; + +/// A counter for items that are in sequence, to be able to put them back into original order later. +pub type SequenceId = usize; + +/// An iterator which olds iterated items with a **sequential** ID starting at 0 long enough to dispense them in order. +pub struct InOrderIter<T, I> { + /// The iterator yielding the out-of-order elements we are to yield in order. + pub inner: I, + store: BTreeMap<SequenceId, T>, + next_chunk: SequenceId, + is_done: bool, +} + +impl<T, E, I> From<I> for InOrderIter<T, I> +where + I: Iterator<Item = Result<(SequenceId, T), E>>, +{ + fn from(iter: I) -> Self { + InOrderIter { + inner: iter, + store: Default::default(), + next_chunk: 0, + is_done: false, + } + } +} + +impl<T, E, I> Iterator for InOrderIter<T, I> +where + I: Iterator<Item = Result<(SequenceId, T), E>>, +{ + type Item = Result<T, E>; + + fn next(&mut self) -> Option<Self::Item> { + if self.is_done { + return None; + } + 'find_next_in_sequence: loop { + match self.inner.next() { + Some(Ok((c, v))) => match c.cmp(&self.next_chunk) { + Ordering::Equal => { + self.next_chunk += 1; + return Some(Ok(v)); + } + Ordering::Less => { + unreachable!("in a correctly ordered sequence we can never see keys again, got {}", c) + } + Ordering::Greater => { + let previous = self.store.insert(c, v); + assert!( + previous.is_none(), + "Chunks are returned only once, input is an invalid sequence" + ); + if let Some(v) = self.store.remove(&self.next_chunk) { + self.next_chunk += 1; + return Some(Ok(v)); + } + continue 'find_next_in_sequence; + } + }, + Some(Err(e)) => { + self.is_done = true; + self.store.clear(); + return Some(Err(e)); + } + None => match self.store.remove(&self.next_chunk) { + Some(v) => { + self.next_chunk += 1; + return Some(Ok(v)); + } + None => { + debug_assert!( + self.store.is_empty(), + "When iteration is done we should not have stored items left" + ); + return None; + } + }, + } + } + } +} diff --git a/vendor/gix-features/src/parallel/in_parallel.rs b/vendor/gix-features/src/parallel/in_parallel.rs new file mode 100644 index 000000000..e1e2cc3e3 --- /dev/null +++ b/vendor/gix-features/src/parallel/in_parallel.rs @@ -0,0 +1,211 @@ +use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; + +use crate::parallel::{num_threads, Reduce}; + +/// Runs `left` and `right` in parallel, returning their output when both are done. +pub fn join<O1: Send, O2: Send>(left: impl FnOnce() -> O1 + Send, right: impl FnOnce() -> O2 + Send) -> (O1, O2) { + std::thread::scope(|s| { + let left = std::thread::Builder::new() + .name("gitoxide.join.left".into()) + .spawn_scoped(s, left) + .expect("valid name"); + let right = std::thread::Builder::new() + .name("gitoxide.join.right".into()) + .spawn_scoped(s, right) + .expect("valid name"); + (left.join().unwrap(), right.join().unwrap()) + }) +} + +/// Runs `f` with a scope to be used for spawning threads that will not outlive the function call. +/// That way it's possible to handle threads without needing the 'static lifetime for data they interact with. +/// +/// Note that the threads should not rely on actual parallelism as threading might be turned off entirely, hence should not +/// connect each other with channels as deadlock would occur in single-threaded mode. +pub fn threads<'env, F, R>(f: F) -> R +where + F: for<'scope> FnOnce(&'scope std::thread::Scope<'scope, 'env>) -> R, +{ + std::thread::scope(f) +} + +/// Create a builder for threads which allows them to be spawned into a scope and configured prior to spawning. +pub fn build_thread() -> std::thread::Builder { + std::thread::Builder::new() +} + +/// Read items from `input` and `consume` them in multiple threads, +/// whose output output is collected by a `reducer`. Its task is to +/// aggregate these outputs into the final result returned by this function with the benefit of not having to be thread-safe. +/// +/// * if `thread_limit` is `Some`, the given amount of threads will be used. If `None`, all logical cores will be used. +/// * `new_thread_state(thread_number) -> State` produces thread-local state once per thread to be based to `consume` +/// * `consume(Item, &mut State) -> Output` produces an output given an input obtained by `input` along with mutable state initially +/// created by `new_thread_state(…)`. +/// * For `reducer`, see the [`Reduce`] trait +pub fn in_parallel<I, S, O, R>( + input: impl Iterator<Item = I> + Send, + thread_limit: Option<usize>, + new_thread_state: impl Fn(usize) -> S + Send + Clone, + consume: impl Fn(I, &mut S) -> O + Send + Clone, + mut reducer: R, +) -> Result<<R as Reduce>::Output, <R as Reduce>::Error> +where + R: Reduce<Input = O>, + I: Send, + O: Send, +{ + let num_threads = num_threads(thread_limit); + std::thread::scope(move |s| { + let receive_result = { + let (send_input, receive_input) = crossbeam_channel::bounded::<I>(num_threads); + let (send_result, receive_result) = crossbeam_channel::bounded::<O>(num_threads); + for thread_id in 0..num_threads { + std::thread::Builder::new() + .name(format!("gitoxide.in_parallel.produce.{thread_id}")) + .spawn_scoped(s, { + let send_result = send_result.clone(); + let receive_input = receive_input.clone(); + let new_thread_state = new_thread_state.clone(); + let consume = consume.clone(); + move || { + let mut state = new_thread_state(thread_id); + for item in receive_input { + if send_result.send(consume(item, &mut state)).is_err() { + break; + } + } + } + }) + .expect("valid name"); + } + std::thread::Builder::new() + .name("gitoxide.in_parallel.feed".into()) + .spawn_scoped(s, move || { + for item in input { + if send_input.send(item).is_err() { + break; + } + } + }) + .expect("valid name"); + receive_result + }; + + for item in receive_result { + drop(reducer.feed(item)?); + } + reducer.finalize() + }) +} + +/// An experiment to have fine-grained per-item parallelization with built-in aggregation via thread state. +/// This is only good for operations where near-random access isn't detrimental, so it's not usually great +/// for file-io as it won't make use of sorted inputs well. +/// Note that `periodic` is not guaranteed to be called in case other threads come up first and finish too fast. +// TODO: better docs +pub fn in_parallel_with_slice<I, S, R, E>( + input: &mut [I], + thread_limit: Option<usize>, + new_thread_state: impl FnMut(usize) -> S + Send + Clone, + consume: impl FnMut(&mut I, &mut S) -> Result<(), E> + Send + Clone, + mut periodic: impl FnMut() -> Option<std::time::Duration> + Send, + state_to_rval: impl FnOnce(S) -> R + Send + Clone, +) -> Result<Vec<R>, E> +where + I: Send, + E: Send, + R: Send, +{ + let num_threads = num_threads(thread_limit); + let mut results = Vec::with_capacity(num_threads); + let stop_everything = &AtomicBool::default(); + let index = &AtomicUsize::default(); + + // TODO: use std::thread::scope() once Rust 1.63 is available. + std::thread::scope({ + move |s| { + std::thread::Builder::new() + .name("gitoxide.in_parallel_with_slice.watch-interrupts".into()) + .spawn_scoped(s, { + move || loop { + if stop_everything.load(Ordering::Relaxed) { + break; + } + + match periodic() { + Some(duration) => std::thread::sleep(duration), + None => { + stop_everything.store(true, Ordering::Relaxed); + break; + } + } + } + }) + .expect("valid name"); + + let input_len = input.len(); + struct Input<I>(*mut [I]) + where + I: Send; + + // SAFETY: I is Send + Sync, so is a *mut [I] + #[allow(unsafe_code)] + unsafe impl<I> Send for Input<I> where I: Send {} + + let threads: Vec<_> = (0..num_threads) + .map(|thread_id| { + std::thread::Builder::new() + .name(format!("gitoxide.in_parallel_with_slice.produce.{thread_id}")) + .spawn_scoped(s, { + let mut new_thread_state = new_thread_state.clone(); + let state_to_rval = state_to_rval.clone(); + let mut consume = consume.clone(); + let input = Input(input as *mut [I]); + move || { + let mut state = new_thread_state(thread_id); + while let Ok(input_index) = + index.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { + (x < input_len).then_some(x + 1) + }) + { + if stop_everything.load(Ordering::Relaxed) { + break; + } + // SAFETY: our atomic counter for `input_index` is only ever incremented, yielding + // each item exactly once. + let item = { + #[allow(unsafe_code)] + unsafe { + &mut (&mut *input.0)[input_index] + } + }; + if let Err(err) = consume(item, &mut state) { + stop_everything.store(true, Ordering::Relaxed); + return Err(err); + } + } + Ok(state_to_rval(state)) + } + }) + .expect("valid name") + }) + .collect(); + for thread in threads { + match thread.join() { + Ok(res) => { + results.push(res?); + } + Err(err) => { + // a panic happened, stop the world gracefully (even though we panic later) + stop_everything.store(true, Ordering::Relaxed); + std::panic::resume_unwind(err); + } + } + } + + stop_everything.store(true, Ordering::Relaxed); + Ok(results) + } + }) +} diff --git a/vendor/gix-features/src/parallel/mod.rs b/vendor/gix-features/src/parallel/mod.rs new file mode 100644 index 000000000..c994cb3b8 --- /dev/null +++ b/vendor/gix-features/src/parallel/mod.rs @@ -0,0 +1,179 @@ +//! Run computations in parallel, or not based the `parallel` feature toggle. +//! +//! ### in_parallel(…) +//! +//! The [`in_parallel(…)`][in_parallel()] is the typical fan-out-fan-in mode of parallelism, with thread local storage +//! made available to a `consume(…)` function to process input. The result is sent to the [`Reduce`] running in the calling +//! thread to aggregate the results into a single output, which is returned by [`in_parallel()`]. +//! +//! Interruptions can be achieved by letting the reducers [`feed(…)`][Reduce::feed()]` method fail. +//! +//! It gets a boost in usability as it allows threads to borrow variables from the stack, most commonly the repository itself +//! or the data to work on. +//! +//! This mode of operation doesn't lend itself perfectly to being wrapped for `async` as it appears like a single long-running +//! operation which runs as fast as possible, which is cancellable only by merit of stopping the input or stopping the output +//! aggregation. +//! +//! ### `reduce::Stepwise` +//! +//! The [`Stepwise`][reduce::Stepwise] iterator works exactly as [`in_parallel()`] except that the processing of the output produced by +//! `consume(I, &mut State) -> O` is made accessible by the `Iterator` trait's `next()` method. As produced work is not +//! buffered, the owner of the iterator controls the progress made. +//! +//! Getting the final output of the [`Reduce`] is achieved through the consuming [`Stepwise::finalize()`][reduce::Stepwise::finalize()] method, which +//! is functionally equivalent to calling [`in_parallel()`]. +//! +//! In an `async` context this means that progress is only made each time `next()` is called on the iterator, while merely dropping +//! the iterator will wind down the computation without any result. +//! +//! #### Maintaining Safety +//! +//! In order to assure that threads don't outlive the data they borrow because their handles are leaked, we enforce +//! the `'static` lifetime for its inputs, making it less intuitive to use. It is, however, possible to produce +//! suitable input iterators as long as they can hold something on the heap. +#[cfg(feature = "parallel")] +mod in_parallel; +#[cfg(feature = "parallel")] +pub use in_parallel::{build_thread, in_parallel, in_parallel_with_slice, join, threads}; + +mod serial; +#[cfg(not(feature = "parallel"))] +pub use serial::{build_thread, in_parallel, in_parallel_with_slice, join, threads}; + +mod in_order; +pub use in_order::{InOrderIter, SequenceId}; + +mod eager_iter; +pub use eager_iter::{EagerIter, EagerIterIf}; + +/// A no-op returning the input _(`desired_chunk_size`, `Some(thread_limit)`, `thread_limit)_ used +/// when the `parallel` feature toggle is not set. +#[cfg(not(feature = "parallel"))] +pub fn optimize_chunk_size_and_thread_limit( + desired_chunk_size: usize, + _num_items: Option<usize>, + thread_limit: Option<usize>, + _available_threads: Option<usize>, +) -> (usize, Option<usize>, usize) { + (desired_chunk_size, thread_limit, num_threads(thread_limit)) +} + +/// Return the 'optimal' _(`size of chunks`, `amount of threads as Option`, `amount of threads`)_ to use in [`in_parallel()`] for the given +/// `desired_chunk_size`, `num_items`, `thread_limit` and `available_threads`. +/// +/// * `desired_chunk_size` is the amount of items per chunk you think should be used. +/// * `num_items` is the total amount of items in the iteration, if `Some`. +/// Otherwise this knowledge will not affect the output of this function. +/// * `thread_limit` is the amount of threads to use at most, if `Some`. +/// Otherwise this knowledge will not affect the output of this function. +/// * `available_threads` is the total amount of threads available, if `Some`. +/// Otherwise the actual amount of available threads is determined by querying the system. +/// +/// `Note` that this implementation is available only if the `parallel` feature toggle is set. +#[cfg(feature = "parallel")] +pub fn optimize_chunk_size_and_thread_limit( + desired_chunk_size: usize, + num_items: Option<usize>, + thread_limit: Option<usize>, + available_threads: Option<usize>, +) -> (usize, Option<usize>, usize) { + let available_threads = + available_threads.unwrap_or_else(|| std::thread::available_parallelism().map(|n| n.get()).unwrap_or(1)); + let available_threads = thread_limit + .map(|l| if l == 0 { available_threads } else { l }) + .unwrap_or(available_threads); + + let (lower, upper) = (50, 1000); + let (chunk_size, thread_limit) = num_items + .map(|num_items| { + let desired_chunks_per_thread_at_least = 2; + let items = num_items; + let chunk_size = (items / (available_threads * desired_chunks_per_thread_at_least)).clamp(1, upper); + let num_chunks = items / chunk_size; + let thread_limit = if num_chunks <= available_threads { + (num_chunks / desired_chunks_per_thread_at_least).max(1) + } else { + available_threads + }; + (chunk_size, thread_limit) + }) + .unwrap_or({ + let chunk_size = if available_threads == 1 { + desired_chunk_size + } else if desired_chunk_size < lower { + lower + } else { + desired_chunk_size.min(upper) + }; + (chunk_size, available_threads) + }); + (chunk_size, Some(thread_limit), thread_limit) +} + +/// Always returns 1, available when the `parallel` feature toggle is unset. +#[cfg(not(feature = "parallel"))] +pub fn num_threads(_thread_limit: Option<usize>) -> usize { + 1 +} + +/// Returns the amount of threads the system can effectively use as the amount of its logical cores. +/// +/// Only available with the `parallel` feature toggle set. +#[cfg(feature = "parallel")] +pub fn num_threads(thread_limit: Option<usize>) -> usize { + let logical_cores = std::thread::available_parallelism().map(|n| n.get()).unwrap_or(1); + thread_limit + .map(|l| if l == 0 { logical_cores } else { l }) + .unwrap_or(logical_cores) +} + +/// Run [`in_parallel()`] only if the given `condition()` returns true when eagerly evaluated. +/// +/// For parameters, see the documentation of [`in_parallel()`] +#[cfg(feature = "parallel")] +pub fn in_parallel_if<I, S, O, R>( + condition: impl FnOnce() -> bool, + input: impl Iterator<Item = I> + Send, + thread_limit: Option<usize>, + new_thread_state: impl Fn(usize) -> S + Send + Clone, + consume: impl Fn(I, &mut S) -> O + Send + Clone, + reducer: R, +) -> Result<<R as Reduce>::Output, <R as Reduce>::Error> +where + R: Reduce<Input = O>, + I: Send, + O: Send, +{ + if num_threads(thread_limit) > 1 && condition() { + in_parallel(input, thread_limit, new_thread_state, consume, reducer) + } else { + serial::in_parallel(input, thread_limit, new_thread_state, consume, reducer) + } +} + +/// Run [`in_parallel()`] only if the given `condition()` returns true when eagerly evaluated. +/// +/// For parameters, see the documentation of [`in_parallel()`] +/// +/// Note that the non-parallel version is equivalent to [`in_parallel()`]. +#[cfg(not(feature = "parallel"))] +pub fn in_parallel_if<I, S, O, R>( + _condition: impl FnOnce() -> bool, + input: impl Iterator<Item = I>, + thread_limit: Option<usize>, + new_thread_state: impl Fn(usize) -> S, + consume: impl Fn(I, &mut S) -> O, + reducer: R, +) -> Result<<R as Reduce>::Output, <R as Reduce>::Error> +where + R: Reduce<Input = O>, + I: Send, + O: Send, +{ + serial::in_parallel(input, thread_limit, new_thread_state, consume, reducer) +} + +/// +pub mod reduce; +pub use reduce::Reduce; diff --git a/vendor/gix-features/src/parallel/reduce.rs b/vendor/gix-features/src/parallel/reduce.rs new file mode 100644 index 000000000..f9992cfd2 --- /dev/null +++ b/vendor/gix-features/src/parallel/reduce.rs @@ -0,0 +1,279 @@ +#[cfg(feature = "parallel")] +mod stepped { + use crate::parallel::num_threads; + + /// An iterator adaptor to allow running computations using [`in_parallel()`][crate::parallel::in_parallel()] in a step-wise manner, see the [module docs][crate::parallel] + /// for details. + pub struct Stepwise<Reduce: super::Reduce> { + /// This field is first to assure it's dropped first and cause threads that are dropped next to stop their loops + /// as sending results fails when the receiver is dropped. + receive_result: std::sync::mpsc::Receiver<Reduce::Input>, + /// `join()` will be called on these guards to assure every thread tries to send through a closed channel. When + /// that happens, they break out of their loops. + threads: Vec<std::thread::JoinHandle<()>>, + /// The reducer is called only in the thread using the iterator, dropping it has no side effects. + reducer: Option<Reduce>, + } + + impl<Reduce: super::Reduce> Drop for Stepwise<Reduce> { + fn drop(&mut self) { + let (_, sink) = std::sync::mpsc::channel(); + drop(std::mem::replace(&mut self.receive_result, sink)); + + let mut last_err = None; + for handle in std::mem::take(&mut self.threads) { + if let Err(err) = handle.join() { + last_err = Some(err); + }; + } + if let Some(thread_err) = last_err { + std::panic::resume_unwind(thread_err); + } + } + } + + impl<Reduce: super::Reduce> Stepwise<Reduce> { + /// Instantiate a new iterator and start working in threads. + /// For a description of parameters, see [`in_parallel()`][crate::parallel::in_parallel()]. + pub fn new<InputIter, ThreadStateFn, ConsumeFn, I, O, S>( + input: InputIter, + thread_limit: Option<usize>, + new_thread_state: ThreadStateFn, + consume: ConsumeFn, + reducer: Reduce, + ) -> Self + where + InputIter: Iterator<Item = I> + Send + 'static, + ThreadStateFn: Fn(usize) -> S + Send + Clone + 'static, + ConsumeFn: Fn(I, &mut S) -> O + Send + Clone + 'static, + Reduce: super::Reduce<Input = O> + 'static, + I: Send + 'static, + O: Send + 'static, + { + let num_threads = num_threads(thread_limit); + let mut threads = Vec::with_capacity(num_threads + 1); + let receive_result = { + let (send_input, receive_input) = crossbeam_channel::bounded::<I>(num_threads); + let (send_result, receive_result) = std::sync::mpsc::sync_channel::<O>(num_threads); + for thread_id in 0..num_threads { + let handle = std::thread::spawn({ + let send_result = send_result.clone(); + let receive_input = receive_input.clone(); + let new_thread_state = new_thread_state.clone(); + let consume = consume.clone(); + move || { + let mut state = new_thread_state(thread_id); + for item in receive_input { + if send_result.send(consume(item, &mut state)).is_err() { + break; + } + } + } + }); + threads.push(handle); + } + threads.push(std::thread::spawn(move || { + for item in input { + if send_input.send(item).is_err() { + break; + } + } + })); + receive_result + }; + Stepwise { + threads, + receive_result, + reducer: Some(reducer), + } + } + + /// Consume the iterator by finishing its iteration and calling [`Reduce::finalize()`][crate::parallel::Reduce::finalize()]. + pub fn finalize(mut self) -> Result<Reduce::Output, Reduce::Error> { + for value in self.by_ref() { + drop(value?); + } + self.reducer + .take() + .expect("this is the last call before consumption") + .finalize() + } + } + + impl<Reduce: super::Reduce> Iterator for Stepwise<Reduce> { + type Item = Result<Reduce::FeedProduce, Reduce::Error>; + + fn next(&mut self) -> Option<<Self as Iterator>::Item> { + self.receive_result + .recv() + .ok() + .and_then(|input| self.reducer.as_mut().map(|r| r.feed(input))) + } + } + + impl<R: super::Reduce> super::Finalize for Stepwise<R> { + type Reduce = R; + + fn finalize( + self, + ) -> Result< + <<Self as super::Finalize>::Reduce as super::Reduce>::Output, + <<Self as super::Finalize>::Reduce as super::Reduce>::Error, + > { + Stepwise::finalize(self) + } + } +} + +#[cfg(not(feature = "parallel"))] +mod stepped { + /// An iterator adaptor to allow running computations using [`in_parallel()`][crate::parallel::in_parallel()] in a step-wise manner, see the [module docs][crate::parallel] + /// for details. + pub struct Stepwise<InputIter, ConsumeFn, ThreadState, Reduce> { + input: InputIter, + consume: ConsumeFn, + thread_state: ThreadState, + reducer: Reduce, + } + + impl<InputIter, ConsumeFn, Reduce, I, O, S> Stepwise<InputIter, ConsumeFn, S, Reduce> + where + InputIter: Iterator<Item = I>, + ConsumeFn: Fn(I, &mut S) -> O, + Reduce: super::Reduce<Input = O>, + { + /// Instantiate a new iterator. + /// For a description of parameters, see [`in_parallel()`][crate::parallel::in_parallel()]. + pub fn new<ThreadStateFn>( + input: InputIter, + _thread_limit: Option<usize>, + new_thread_state: ThreadStateFn, + consume: ConsumeFn, + reducer: Reduce, + ) -> Self + where + ThreadStateFn: Fn(usize) -> S, + { + Stepwise { + input, + consume, + thread_state: new_thread_state(0), + reducer, + } + } + + /// Consume the iterator by finishing its iteration and calling [`Reduce::finalize()`][crate::parallel::Reduce::finalize()]. + pub fn finalize(mut self) -> Result<Reduce::Output, Reduce::Error> { + for value in self.by_ref() { + drop(value?); + } + self.reducer.finalize() + } + } + + impl<InputIter, ConsumeFn, ThreadState, Reduce, I, O> Iterator for Stepwise<InputIter, ConsumeFn, ThreadState, Reduce> + where + InputIter: Iterator<Item = I>, + ConsumeFn: Fn(I, &mut ThreadState) -> O, + Reduce: super::Reduce<Input = O>, + { + type Item = Result<Reduce::FeedProduce, Reduce::Error>; + + fn next(&mut self) -> Option<<Self as Iterator>::Item> { + self.input + .next() + .map(|input| self.reducer.feed((self.consume)(input, &mut self.thread_state))) + } + } + + impl<InputIter, ConsumeFn, R, I, O, S> super::Finalize for Stepwise<InputIter, ConsumeFn, S, R> + where + InputIter: Iterator<Item = I>, + ConsumeFn: Fn(I, &mut S) -> O, + R: super::Reduce<Input = O>, + { + type Reduce = R; + + fn finalize( + self, + ) -> Result< + <<Self as super::Finalize>::Reduce as super::Reduce>::Output, + <<Self as super::Finalize>::Reduce as super::Reduce>::Error, + > { + Stepwise::finalize(self) + } + } +} + +use std::marker::PhantomData; + +pub use stepped::Stepwise; + +/// An trait for aggregating items commonly produced in threads into a single result, without itself +/// needing to be thread safe. +pub trait Reduce { + /// The type fed to the reducer in the [`feed()`][Reduce::feed()] method. + /// + /// It's produced by a function that may run on multiple threads. + type Input; + /// The type produced in Ok(…) by [`feed()`][Reduce::feed()]. + /// Most reducers by nature use `()` here as the value is in the aggregation. + /// However, some may use it to collect statistics only and return their Input + /// in some form as a result here for [`Stepwise`] to be useful. + type FeedProduce; + /// The type produced once by the [`finalize()`][Reduce::finalize()] method. + /// + /// For traditional reducers, this is the value produced by the entire operation. + /// For those made for step-wise iteration this may be aggregated statistics. + type Output; + /// The error type to use for all methods of this trait. + type Error; + /// Called each time a new `item` was produced in order to aggregate it into the final result. + /// + /// If an `Error` is returned, the entire operation will be stopped. + fn feed(&mut self, item: Self::Input) -> Result<Self::FeedProduce, Self::Error>; + /// Called once once all items where passed to `feed()`, producing the final `Output` of the operation or an `Error`. + fn finalize(self) -> Result<Self::Output, Self::Error>; +} + +/// An identity reducer for those who want to use [`Stepwise`] or [`in_parallel()`][crate::parallel::in_parallel()] +/// without the use of non-threaded reduction of products created in threads. +pub struct IdentityWithResult<Input, Error> { + _input: PhantomData<Input>, + _error: PhantomData<Error>, +} + +impl<Input, Error> Default for IdentityWithResult<Input, Error> { + fn default() -> Self { + IdentityWithResult { + _input: Default::default(), + _error: Default::default(), + } + } +} + +impl<Input, Error> Reduce for IdentityWithResult<Input, Error> { + type Input = Result<Input, Self::Error>; + type FeedProduce = Input; + type Output = (); + type Error = Error; + + fn feed(&mut self, item: Self::Input) -> Result<Self::FeedProduce, Self::Error> { + item + } + + fn finalize(self) -> Result<Self::Output, Self::Error> { + Ok(()) + } +} + +/// A trait reflecting the `finalize()` method of [`Reduce`] implementations +pub trait Finalize { + /// An implementation of [`Reduce`] + type Reduce: self::Reduce; + + /// Similar to the [`Reduce::finalize()`] method + fn finalize( + self, + ) -> Result<<<Self as Finalize>::Reduce as self::Reduce>::Output, <<Self as Finalize>::Reduce as self::Reduce>::Error>; +} diff --git a/vendor/gix-features/src/parallel/serial.rs b/vendor/gix-features/src/parallel/serial.rs new file mode 100644 index 000000000..00723b2c3 --- /dev/null +++ b/vendor/gix-features/src/parallel/serial.rs @@ -0,0 +1,135 @@ +use crate::parallel::Reduce; + +#[cfg(not(feature = "parallel"))] +mod not_parallel { + /// Runs `left` and then `right`, one after another, returning their output when both are done. + pub fn join<O1, O2>(left: impl FnOnce() -> O1, right: impl FnOnce() -> O2) -> (O1, O2) { + (left(), right()) + } + + /// A scope for spawning threads. + pub struct Scope<'env> { + _marker: std::marker::PhantomData<&'env mut &'env ()>, + } + + pub struct ThreadBuilder; + + /// Create a builder for threads which allows them to be spawned into a scope and configured prior to spawning. + pub fn build_thread() -> ThreadBuilder { + ThreadBuilder + } + + #[allow(unsafe_code)] + unsafe impl Sync for Scope<'_> {} + + impl ThreadBuilder { + pub fn name(self, _new: String) -> Self { + self + } + pub fn spawn_scoped<'a, 'env, F, T>( + &self, + scope: &'a Scope<'env>, + f: F, + ) -> std::io::Result<ScopedJoinHandle<'a, T>> + where + F: FnOnce() -> T, + F: Send + 'env, + T: Send + 'env, + { + Ok(scope.spawn(f)) + } + } + + impl<'env> Scope<'env> { + pub fn spawn<'scope, F, T>(&'scope self, f: F) -> ScopedJoinHandle<'scope, T> + where + F: FnOnce() -> T, + F: Send + 'env, + T: Send + 'env, + { + ScopedJoinHandle { + result: f(), + _marker: Default::default(), + } + } + } + + /// Runs `f` with a scope to be used for spawning threads that will not outlive the function call. + /// Note that this implementation will run the spawned functions immediately. + pub fn threads<'env, F, R>(f: F) -> R + where + F: FnOnce(&Scope<'env>) -> R, + { + f(&Scope { + _marker: Default::default(), + }) + } + + /// A handle that can be used to join its scoped thread. + /// + /// This struct is created by the [`Scope::spawn`] method and the + /// [`ScopedThreadBuilder::spawn`] method. + pub struct ScopedJoinHandle<'scope, T> { + /// Holds the result of the inner closure. + result: T, + _marker: std::marker::PhantomData<&'scope mut &'scope ()>, + } + + impl<T> ScopedJoinHandle<'_, T> { + pub fn join(self) -> std::thread::Result<T> { + Ok(self.result) + } + } + + /// An experiment to have fine-grained per-item parallelization with built-in aggregation via thread state. + /// This is only good for operations where near-random access isn't detrimental, so it's not usually great + /// for file-io as it won't make use of sorted inputs well. + // TODO: better docs + pub fn in_parallel_with_slice<I, S, R, E>( + input: &mut [I], + _thread_limit: Option<usize>, + mut new_thread_state: impl FnMut(usize) -> S + Clone, + mut consume: impl FnMut(&mut I, &mut S) -> Result<(), E> + Clone, + mut periodic: impl FnMut() -> Option<std::time::Duration>, + state_to_rval: impl FnOnce(S) -> R + Clone, + ) -> Result<Vec<R>, E> { + let mut state = new_thread_state(0); + for item in input { + consume(item, &mut state)?; + if periodic().is_none() { + break; + } + } + Ok(vec![state_to_rval(state)]) + } +} + +#[cfg(not(feature = "parallel"))] +pub use not_parallel::{build_thread, in_parallel_with_slice, join, threads, Scope, ScopedJoinHandle}; + +/// Read items from `input` and `consume` them in a single thread, producing an output to be collected by a `reducer`, +/// whose task is to aggregate these outputs into the final result returned by this function. +/// +/// * `new_thread_state(thread_number) -> State` produces thread-local state once per thread to be based to `consume` +/// * `consume(Item, &mut State) -> Output` produces an output given an input along with mutable state. +/// * For `reducer`, see the [`Reduce`] trait +/// * if `thread_limit` has no effect as everything is run on the main thread, but is present to keep the signature +/// similar to the parallel version. +/// +/// **This serial version performing all calculations on the current thread.** +pub fn in_parallel<I, S, O, R>( + input: impl Iterator<Item = I>, + _thread_limit: Option<usize>, + new_thread_state: impl Fn(usize) -> S, + consume: impl Fn(I, &mut S) -> O, + mut reducer: R, +) -> Result<<R as Reduce>::Output, <R as Reduce>::Error> +where + R: Reduce<Input = O>, +{ + let mut state = new_thread_state(0); + for item in input { + drop(reducer.feed(consume(item, &mut state))?); + } + reducer.finalize() +} diff --git a/vendor/gix-features/src/progress.rs b/vendor/gix-features/src/progress.rs new file mode 100644 index 000000000..b6e56895b --- /dev/null +++ b/vendor/gix-features/src/progress.rs @@ -0,0 +1,139 @@ +//! Various `prodash` types along with various utilities for comfort. +use std::io; + +pub use prodash::{ + self, + messages::MessageLevel, + progress::{Discard, DoOrDiscard, Either, Id, Step, StepShared, Task, ThroughputOnDrop, Value, UNKNOWN}, + unit, Progress, Unit, +}; + +#[cfg(feature = "progress-unit-bytes")] +pub use bytesize; +/// A stub for the portions of the `bytesize` crate that we use internally in `gitoxide`. +#[cfg(not(feature = "progress-unit-bytes"))] +pub mod bytesize { + /// A stub for the `ByteSize` wrapper. + pub struct ByteSize(pub u64); + + impl std::fmt::Display for ByteSize { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } + } +} + +/// A unit for displaying bytes with throughput and progress percentage. +#[cfg(feature = "progress-unit-bytes")] +pub fn bytes() -> Option<Unit> { + Some(unit::dynamic_and_mode( + unit::Bytes, + unit::display::Mode::with_throughput().and_percentage(), + )) +} + +/// A unit for displaying bytes with throughput and progress percentage. +#[cfg(not(feature = "progress-unit-bytes"))] +pub fn bytes() -> Option<Unit> { + Some(unit::label_and_mode( + "B", + unit::display::Mode::with_throughput().and_percentage(), + )) +} + +/// A unit for displaying human readable numbers with throughput and progress percentage, and a single decimal place. +pub fn count(name: &'static str) -> Option<Unit> { + count_with_decimals(name, 1) +} + +/// A unit for displaying human readable numbers with `name` suffix, +/// with throughput and progress percentage, and `decimals` decimal places. +#[cfg(feature = "progress-unit-human-numbers")] +pub fn count_with_decimals(name: &'static str, decimals: usize) -> Option<Unit> { + Some(unit::dynamic_and_mode( + unit::Human::new( + { + let mut f = unit::human::Formatter::new(); + f.with_decimals(decimals); + f + }, + name, + ), + unit::display::Mode::with_throughput().and_percentage(), + )) +} + +/// A unit for displaying human readable numbers with `name` suffix, +/// with throughput and progress percentage, and `decimals` decimal places. +#[cfg(not(feature = "progress-unit-human-numbers"))] +pub fn count_with_decimals(name: &'static str, _decimals: usize) -> Option<Unit> { + Some(unit::label_and_mode( + name, + unit::display::Mode::with_throughput().and_percentage(), + )) +} + +/// A predefined unit for displaying a multi-step progress +pub fn steps() -> Option<Unit> { + Some(unit::dynamic(unit::Range::new("steps"))) +} + +/// A structure passing every [`read`][std::io::Read::read()] call through to the contained Progress instance using [`inc_by(bytes_read)`][Progress::inc_by()]. +pub struct Read<T, P> { + /// The implementor of [`std::io::Read`] to which progress is added + pub inner: T, + /// The progress instance receiving progress information on each invocation of `reader` + pub progress: P, +} + +impl<T, P> io::Read for Read<T, P> +where + T: io::Read, + P: Progress, +{ + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + let bytes_read = self.inner.read(buf)?; + self.progress.inc_by(bytes_read); + Ok(bytes_read) + } +} + +impl<T, P> io::BufRead for Read<T, P> +where + T: io::BufRead, + P: Progress, +{ + fn fill_buf(&mut self) -> io::Result<&[u8]> { + self.inner.fill_buf() + } + + fn consume(&mut self, amt: usize) { + self.inner.consume(amt) + } +} + +/// A structure passing every [`write`][std::io::Write::write()] call through to the contained Progress instance using [`inc_by(bytes_written)`][Progress::inc_by()]. +/// +/// This is particularly useful if the final size of the bytes to write is known or can be estimated precisely enough. +pub struct Write<T, P> { + /// The implementor of [`std::io::Write`] to which progress is added + pub inner: T, + /// The progress instance receiving progress information on each invocation of `reader` + pub progress: P, +} + +impl<T, P> io::Write for Write<T, P> +where + T: io::Write, + P: Progress, +{ + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + let written = self.inner.write(buf)?; + self.progress.inc_by(written); + Ok(written) + } + + fn flush(&mut self) -> io::Result<()> { + self.inner.flush() + } +} diff --git a/vendor/gix-features/src/threading.rs b/vendor/gix-features/src/threading.rs new file mode 100644 index 000000000..ff0c819a5 --- /dev/null +++ b/vendor/gix-features/src/threading.rs @@ -0,0 +1,100 @@ +//! Type definitions for putting shared ownership and synchronized mutation behind the `threading` feature toggle. +//! +//! That way, single-threaded applications will not have to use thread-safe primitives, and simply do not specify the 'threading' feature. + +#[cfg(feature = "parallel")] +mod _impl { + use std::sync::Arc; + + /// A thread-safe cell which can be written to only once. + #[cfg(feature = "once_cell")] + pub type OnceCell<T> = once_cell::sync::OnceCell<T>; + /// A reference counted pointer type for shared ownership. + pub type OwnShared<T> = Arc<T>; + /// A synchronization primitive which can start read-only and transition to support mutation. + pub type MutableOnDemand<T> = parking_lot::RwLock<T>; + /// A synchronization primitive which provides read-write access right away. + pub type Mutable<T> = parking_lot::Mutex<T>; + /// A guarded reference suitable for safekeeping in a struct. + pub type RefGuard<'a, T> = parking_lot::RwLockReadGuard<'a, T>; + /// A mapped reference created from a RefGuard + pub type MappedRefGuard<'a, U> = parking_lot::MappedRwLockReadGuard<'a, U>; + + /// Get a shared reference through a [`MutableOnDemand`] for read-only access. + pub fn get_ref<T>(v: &MutableOnDemand<T>) -> RefGuard<'_, T> { + v.read() + } + + /// Get a mutable reference through a [`MutableOnDemand`] for read-write access. + pub fn get_mut<T>(v: &MutableOnDemand<T>) -> parking_lot::RwLockWriteGuard<'_, T> { + v.write() + } + + /// Get a mutable reference through a [`Mutable`] for read-write access. + pub fn lock<T>(v: &Mutable<T>) -> parking_lot::MutexGuard<'_, T> { + v.lock() + } + + /// Downgrade a handle previously obtained with [`get_mut()`] to drop mutation support. + pub fn downgrade_mut_to_ref<'a, T>( + v: parking_lot::RwLockWriteGuard<'a, T>, + _orig: &'a MutableOnDemand<T>, + ) -> RefGuard<'a, T> { + parking_lot::RwLockWriteGuard::downgrade(v) + } + + /// Map a read guard into a sub-type it contains. + pub fn map_ref<T, U: ?Sized>(v: RefGuard<'_, T>, f: impl FnOnce(&T) -> &U) -> MappedRefGuard<'_, U> { + parking_lot::RwLockReadGuard::map(v, f) + } +} + +#[cfg(not(feature = "parallel"))] +mod _impl { + use std::{ + cell::{Ref, RefCell, RefMut}, + rc::Rc, + }; + + /// A thread-safe cell which can be written to only once. + #[cfg(feature = "once_cell")] + pub type OnceCell<T> = once_cell::unsync::OnceCell<T>; + /// A reference counted pointer type for shared ownership. + pub type OwnShared<T> = Rc<T>; + /// A synchronization primitive which can start read-only and transition to support mutation. + pub type MutableOnDemand<T> = RefCell<T>; + /// A synchronization primitive which provides read-write access right away. + pub type Mutable<T> = RefCell<T>; + /// A guarded reference suitable for safekeeping in a struct. + pub type RefGuard<'a, T> = Ref<'a, T>; + /// A mapped reference created from a RefGuard + pub type MappedRefGuard<'a, U> = Ref<'a, U>; + + /// Get a shared reference through a [`MutableOnDemand`] for read-only access. + pub fn get_mut<T>(v: &RefCell<T>) -> RefMut<'_, T> { + v.borrow_mut() + } + + /// Get a mutable reference through a [`Mutable`] for read-write access. + pub fn lock<T>(v: &Mutable<T>) -> RefMut<'_, T> { + v.borrow_mut() + } + + /// Get a mutable reference through a [`MutableOnDemand`] for read-write access. + pub fn get_ref<T>(v: &RefCell<T>) -> RefGuard<'_, T> { + v.borrow() + } + + /// Downgrade a handle previously obtained with [`upgrade_ref_to_mut()`] to drop mutation support. + pub fn downgrade_mut_to_ref<'a, T>(v: RefMut<'a, T>, orig: &'a RefCell<T>) -> RefGuard<'a, T> { + drop(v); + orig.borrow() + } + + /// Map a read guard into a sub-type it contains. + pub fn map_ref<T, U: ?Sized>(v: RefGuard<'_, T>, f: impl FnOnce(&T) -> &U) -> MappedRefGuard<'_, U> { + Ref::map(v, f) + } +} + +pub use _impl::*; diff --git a/vendor/gix-features/src/zlib/mod.rs b/vendor/gix-features/src/zlib/mod.rs new file mode 100644 index 000000000..8dcdfd93f --- /dev/null +++ b/vendor/gix-features/src/zlib/mod.rs @@ -0,0 +1,47 @@ +pub use flate2::{Decompress, Status}; + +/// non-streaming interfaces for decompression +pub mod inflate { + /// The error returned by various [Inflate methods][super::Inflate] + #[derive(Debug, thiserror::Error)] + #[allow(missing_docs)] + pub enum Error { + #[error("Could not write all bytes when decompressing content")] + WriteInflated(#[from] std::io::Error), + #[error("Could not decode zip stream, status was '{0:?}'")] + Inflate(#[from] flate2::DecompressError), + #[error("The zlib status indicated an error, status was '{0:?}'")] + Status(flate2::Status), + } +} + +/// Decompress a few bytes of a zlib stream without allocation +pub struct Inflate { + /// The actual decompressor doing all the work. + pub state: Decompress, +} + +impl Default for Inflate { + fn default() -> Self { + Inflate { + state: Decompress::new(true), + } + } +} + +impl Inflate { + /// Run the decompressor exactly once. Cannot be run multiple times + pub fn once(&mut self, input: &[u8], out: &mut [u8]) -> Result<(flate2::Status, usize, usize), inflate::Error> { + let before_in = self.state.total_in(); + let before_out = self.state.total_out(); + let status = self.state.decompress(input, out, flate2::FlushDecompress::None)?; + Ok(( + status, + (self.state.total_in() - before_in) as usize, + (self.state.total_out() - before_out) as usize, + )) + } +} + +/// +pub mod stream; diff --git a/vendor/gix-features/src/zlib/stream/deflate/mod.rs b/vendor/gix-features/src/zlib/stream/deflate/mod.rs new file mode 100644 index 000000000..55f575ea4 --- /dev/null +++ b/vendor/gix-features/src/zlib/stream/deflate/mod.rs @@ -0,0 +1,96 @@ +use flate2::Compress; + +const BUF_SIZE: usize = 4096 * 8; + +/// A utility to zlib compress anything that is written via its [Write][std::io::Write] implementation. +/// +/// Be sure to call `flush()` when done to finalize the deflate stream. +pub struct Write<W> { + compressor: Compress, + inner: W, + buf: [u8; BUF_SIZE], +} + +mod impls { + use std::io; + + use flate2::{Compress, Compression, FlushCompress, Status}; + + use crate::zlib::stream::deflate; + + impl<W> deflate::Write<W> + where + W: io::Write, + { + /// Create a new instance writing compressed bytes to `inner`. + pub fn new(inner: W) -> deflate::Write<W> { + deflate::Write { + compressor: Compress::new(Compression::fast(), true), + inner, + buf: [0; deflate::BUF_SIZE], + } + } + + /// Reset the compressor, starting a new compression stream. + /// + /// That way multiple streams can be written to the same inner writer. + pub fn reset(&mut self) { + self.compressor.reset(); + } + + /// Consume `self` and return the inner writer. + pub fn into_inner(self) -> W { + self.inner + } + + fn write_inner(&mut self, mut buf: &[u8], flush: FlushCompress) -> io::Result<usize> { + let total_in_when_start = self.compressor.total_in(); + loop { + let last_total_in = self.compressor.total_in(); + let last_total_out = self.compressor.total_out(); + + let status = self + .compressor + .compress(buf, &mut self.buf, flush) + .map_err(|err| io::Error::new(io::ErrorKind::Other, err))?; + + let written = self.compressor.total_out() - last_total_out; + if written > 0 { + self.inner.write_all(&self.buf[..written as usize])?; + } + + match status { + Status::StreamEnd => return Ok((self.compressor.total_in() - total_in_when_start) as usize), + Status::Ok | Status::BufError => { + let consumed = self.compressor.total_in() - last_total_in; + buf = &buf[consumed as usize..]; + + // output buffer still makes progress + if self.compressor.total_out() > last_total_out { + continue; + } + // input still makes progress + if self.compressor.total_in() > last_total_in { + continue; + } + // input also makes no progress anymore, need more so leave with what we have + return Ok((self.compressor.total_in() - total_in_when_start) as usize); + } + } + } + } + } + + impl<W: io::Write> io::Write for deflate::Write<W> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.write_inner(buf, FlushCompress::None) + } + + fn flush(&mut self) -> io::Result<()> { + self.write_inner(&[], FlushCompress::Finish).map(|_| ()) + } + } +} + +#[cfg(test)] +mod tests; diff --git a/vendor/gix-features/src/zlib/stream/deflate/tests.rs b/vendor/gix-features/src/zlib/stream/deflate/tests.rs new file mode 100644 index 000000000..ba0dd2a2c --- /dev/null +++ b/vendor/gix-features/src/zlib/stream/deflate/tests.rs @@ -0,0 +1,101 @@ +mod deflate_stream { + use std::{ + io, + io::{Read, Write}, + }; + + use bstr::ByteSlice; + use flate2::Decompress; + + use crate::zlib::stream::deflate; + + /// Provide streaming decompression using the `std::io::Read` trait. + /// If `std::io::BufReader` is used, an allocation for the input buffer will be performed. + struct InflateReader<R> { + inner: R, + decompressor: Decompress, + } + + impl<R> InflateReader<R> + where + R: io::BufRead, + { + pub fn from_read(read: R) -> InflateReader<R> { + InflateReader { + decompressor: Decompress::new(true), + inner: read, + } + } + } + + impl<R> io::Read for InflateReader<R> + where + R: io::BufRead, + { + fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { + crate::zlib::stream::inflate::read(&mut self.inner, &mut self.decompressor, into) + } + } + + #[test] + fn small_file_decompress() -> Result<(), Box<dyn std::error::Error>> { + fn fixture_path(path: &str) -> std::path::PathBuf { + std::path::PathBuf::from("tests/fixtures").join(path) + } + let r = InflateReader::from_read(io::BufReader::new(std::fs::File::open(fixture_path( + "objects/37/d4e6c5c48ba0d245164c4e10d5f41140cab980", + ))?)); + let mut bytes = r.bytes(); + let content = bytes.by_ref().take(16).collect::<Result<Vec<_>, _>>()?; + assert_eq!(content.as_slice().as_bstr(), b"blob 9\0hi there\n".as_bstr()); + assert!(bytes.next().is_none()); + Ok(()) + } + + #[test] + fn all_at_once() -> Result<(), Box<dyn std::error::Error>> { + let mut w = deflate::Write::new(Vec::new()); + assert_eq!(w.write(b"hello")?, 5); + w.flush()?; + + let out = w.inner; + assert!(out.len() == 12 || out.len() == 13); + + assert_deflate_buffer(out, b"hello") + } + + fn assert_deflate_buffer(out: Vec<u8>, expected: &[u8]) -> Result<(), Box<dyn std::error::Error>> { + let mut actual = Vec::new(); + InflateReader::from_read(out.as_slice()).read_to_end(&mut actual)?; + assert_eq!(actual, expected); + Ok(()) + } + + #[test] + fn big_file_small_writes() -> Result<(), Box<dyn std::error::Error>> { + let mut w = deflate::Write::new(Vec::new()); + let bytes = include_bytes!( + "../../../../tests/fixtures/objects/pack/pack-11fdfa9e156ab73caae3b6da867192221f2089c2.pack" + ); + for chunk in bytes.chunks(2) { + assert_eq!(w.write(chunk)?, chunk.len()); + } + w.flush()?; + + assert_deflate_buffer(w.inner, bytes) + } + + #[test] + fn big_file_a_few_big_writes() -> Result<(), Box<dyn std::error::Error>> { + let mut w = deflate::Write::new(Vec::new()); + let bytes = include_bytes!( + "../../../../tests/fixtures/objects/pack/pack-11fdfa9e156ab73caae3b6da867192221f2089c2.pack" + ); + for chunk in bytes.chunks(4096 * 9) { + assert_eq!(w.write(chunk)?, chunk.len()); + } + w.flush()?; + + assert_deflate_buffer(w.inner, bytes) + } +} diff --git a/vendor/gix-features/src/zlib/stream/inflate.rs b/vendor/gix-features/src/zlib/stream/inflate.rs new file mode 100644 index 000000000..007ecedc6 --- /dev/null +++ b/vendor/gix-features/src/zlib/stream/inflate.rs @@ -0,0 +1,57 @@ +use std::{io, io::BufRead}; + +use flate2::{Decompress, FlushDecompress, Status}; + +/// The boxed variant is faster for what we do (moving the decompressor in and out a lot) +pub struct ReadBoxed<R> { + /// The reader from which bytes should be decompressed. + pub inner: R, + /// The decompressor doing all the work. + pub decompressor: Box<Decompress>, +} + +impl<R> io::Read for ReadBoxed<R> +where + R: BufRead, +{ + fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { + read(&mut self.inner, &mut self.decompressor, into) + } +} + +/// Read bytes from `rd` and decompress them using `state` into a pre-allocated fitting buffer `dst`, returning the amount of bytes written. +pub fn read(rd: &mut impl BufRead, state: &mut Decompress, mut dst: &mut [u8]) -> io::Result<usize> { + let mut total_written = 0; + loop { + let (written, consumed, ret, eof); + { + let input = rd.fill_buf()?; + eof = input.is_empty(); + let before_out = state.total_out(); + let before_in = state.total_in(); + let flush = if eof { + FlushDecompress::Finish + } else { + FlushDecompress::None + }; + ret = state.decompress(input, dst, flush); + written = (state.total_out() - before_out) as usize; + total_written += written; + dst = &mut dst[written..]; + consumed = (state.total_in() - before_in) as usize; + } + rd.consume(consumed); + + match ret { + // The stream has officially ended, nothing more to do here. + Ok(Status::StreamEnd) => return Ok(total_written), + // Either input our output are depleted even though the stream is not depleted yet. + Ok(Status::Ok) | Ok(Status::BufError) if eof || dst.is_empty() => return Ok(total_written), + // Some progress was made in both the input and the output, it must continue to reach the end. + Ok(Status::Ok) | Ok(Status::BufError) if consumed != 0 || written != 0 => continue, + // A strange state, where zlib makes no progress but isn't done either. Call it out. + Ok(Status::Ok) | Ok(Status::BufError) => unreachable!("Definitely a bug somewhere"), + Err(..) => return Err(io::Error::new(io::ErrorKind::InvalidInput, "corrupt deflate stream")), + } + } +} diff --git a/vendor/gix-features/src/zlib/stream/mod.rs b/vendor/gix-features/src/zlib/stream/mod.rs new file mode 100644 index 000000000..7fb239d36 --- /dev/null +++ b/vendor/gix-features/src/zlib/stream/mod.rs @@ -0,0 +1,4 @@ +/// +pub mod deflate; +/// +pub mod inflate; diff --git a/vendor/gix-features/tests/hash.rs b/vendor/gix-features/tests/hash.rs new file mode 100644 index 000000000..c8e48da57 --- /dev/null +++ b/vendor/gix-features/tests/hash.rs @@ -0,0 +1,13 @@ +use gix_features::hash::Sha1; + +#[cfg(not(feature = "fast-sha1"))] +#[test] +fn size_of_sha1() { + assert_eq!(std::mem::size_of::<Sha1>(), 96) +} + +#[cfg(feature = "fast-sha1")] +#[test] +fn size_of_sha1() { + assert_eq!(std::mem::size_of::<Sha1>(), 104) +} diff --git a/vendor/gix-features/tests/parallel/in_order_iter.rs b/vendor/gix-features/tests/parallel/in_order_iter.rs new file mode 100644 index 000000000..9e1881215 --- /dev/null +++ b/vendor/gix-features/tests/parallel/in_order_iter.rs @@ -0,0 +1,54 @@ +use std::convert::Infallible; + +use gix_features::parallel::InOrderIter; + +#[test] +fn in_order_stays_in_order() { + assert_eq!( + InOrderIter::from(vec![Ok::<_, Infallible>((0usize, 'a')), Ok((1, 'b')), Ok((2, 'c'))].into_iter()) + .collect::<Result<Vec<_>, _>>() + .expect("infallible"), + vec!['a', 'b', 'c'] + ) +} + +#[test] +fn out_of_order_items_are_held_until_the_sequence_is_complete() { + assert_eq!( + InOrderIter::from( + vec![ + Ok::<_, Infallible>((2usize, 'c')), + Ok((1, 'b')), + Ok((0, 'a')), + Ok((3, 'd')) + ] + .into_iter() + ) + .collect::<Result<Vec<_>, _>>() + .expect("infallible"), + vec!['a', 'b', 'c', 'd'] + ) +} + +#[test] +fn in_sequence_errors_immediately_trigger_a_fuse() { + let mut iter = InOrderIter::from(vec![Ok::<_, &'static str>((0usize, 'a')), Err("err"), Ok((1, 'b'))].into_iter()); + assert_eq!(iter.next(), Some(Ok('a'))); + assert_eq!(iter.next(), Some(Err("err"))); + assert_eq!( + iter.next(), + None, + "fuse should have triggered so we don't see anything else" + ); +} + +#[test] +fn out_of_sequence_errors_immediately_trigger_a_fuse() { + let mut iter = InOrderIter::from(vec![Ok::<_, &'static str>((1usize, 'b')), Err("err"), Ok((0, 'a'))].into_iter()); + assert_eq!(iter.next(), Some(Err("err"))); + assert_eq!( + iter.next(), + None, + "fuse should have triggered so we don't see anything else" + ); +} diff --git a/vendor/gix-features/tests/parallel/mod.rs b/vendor/gix-features/tests/parallel/mod.rs new file mode 100644 index 000000000..b4b4236f8 --- /dev/null +++ b/vendor/gix-features/tests/parallel/mod.rs @@ -0,0 +1,125 @@ +//! Tests that are working similarly in parallel and serial mode +use gix_features::parallel; + +mod in_order_iter; + +#[derive(Default)] +struct Adder { + count: usize, +} + +impl parallel::Reduce for Adder { + type Input = usize; + type FeedProduce = usize; + type Output = usize; + type Error = (); + + fn feed(&mut self, item: Self::Input) -> Result<Self::FeedProduce, Self::Error> { + self.count += item; + Ok(item) + } + + fn finalize(self) -> Result<Self::Output, Self::Error> { + Ok(self.count) + } +} + +#[test] +fn in_parallel() { + let res = parallel::in_parallel( + std::iter::from_fn(|| Some(1)).take(100), + None, + |_n| (), + |input, _state| input, + Adder::default(), + ) + .expect("successful computation"); + assert_eq!(res, 100); +} + +#[test] +fn in_parallel_with_mut_slice_in_chunks() { + let num_items = 33; + let mut input: Vec<_> = std::iter::repeat(1).take(num_items).collect(); + let counts = parallel::in_parallel_with_slice( + &mut input, + None, + |_| 0usize, + |item, acc| { + *acc += *item; + *item += 1; + Ok::<_, ()>(()) + }, + || Some(std::time::Duration::from_millis(10)), + std::convert::identity, + ) + .unwrap(); + let expected = std::iter::repeat(1).take(num_items).sum::<usize>(); + assert_eq!(counts.iter().sum::<usize>(), expected); + assert_eq!(input.iter().sum::<usize>(), expected * 2, "we increment each entry"); +} + +#[test] +fn stepped_reduce_next() { + let mut iter = parallel::reduce::Stepwise::new( + std::iter::from_fn(|| Some(1)).take(100), + None, + |_n| (), + |input, _state| input, + Adder::default(), + ); + + let mut aggregate = 0; + for value in iter.by_ref() { + aggregate += value.expect("success"); + } + assert_eq!(aggregate, 100); +} + +#[test] +fn stepped_reduce_ref_input_and_consume() { + let seq = std::sync::Arc::new(vec![0usize, 1, 2]); + struct ArcIter(std::sync::Arc<Vec<usize>>, usize); + impl Iterator for ArcIter { + type Item = usize; + + fn next(&mut self) -> Option<Self::Item> { + let n = self.0.get(self.1).copied(); + self.1 += 1; + n + } + } + + let mut iter = parallel::reduce::Stepwise::new( + ArcIter(seq.clone(), 0).enumerate(), + None, + { + let seq = std::sync::Arc::clone(&seq); + move |_n| seq.len() + }, + { + let seq = std::sync::Arc::clone(&seq); + move |(idx, ref_val): (usize, usize), _state| seq[idx] * ref_val + }, + Adder::default(), + ); + + let mut aggregate = 0; + for value in iter.by_ref() { + aggregate += value.expect("success"); + } + assert_eq!(aggregate, 5); +} + +#[test] +fn stepped_reduce_finalize() { + let iter = parallel::reduce::Stepwise::new( + std::iter::from_fn(|| Some(1)).take(100), + None, + |_n| (), + |input, _state| input, + Adder::default(), + ); + + assert_eq!(iter.finalize().expect("success"), 100); +} diff --git a/vendor/gix-features/tests/parallel_shared.rs b/vendor/gix-features/tests/parallel_shared.rs new file mode 100644 index 000000000..055a899ea --- /dev/null +++ b/vendor/gix-features/tests/parallel_shared.rs @@ -0,0 +1 @@ +mod parallel; diff --git a/vendor/gix-features/tests/parallel_shared_threaded.rs b/vendor/gix-features/tests/parallel_shared_threaded.rs new file mode 100644 index 000000000..055a899ea --- /dev/null +++ b/vendor/gix-features/tests/parallel_shared_threaded.rs @@ -0,0 +1 @@ +mod parallel; diff --git a/vendor/gix-features/tests/parallel_threaded.rs b/vendor/gix-features/tests/parallel_threaded.rs new file mode 100644 index 000000000..05f49d195 --- /dev/null +++ b/vendor/gix-features/tests/parallel_threaded.rs @@ -0,0 +1,122 @@ +mod optimize_chunk_size_and_thread_limit { + use gix_features::parallel::optimize_chunk_size_and_thread_limit; + + #[test] + fn not_enough_chunks_for_threads() { + assert_eq!( + optimize_chunk_size_and_thread_limit(1, Some(10), None, Some(10)), + (1, Some(5), 5) + ); + assert_eq!( + optimize_chunk_size_and_thread_limit(1, Some(10), Some(3), Some(10)), + (1, Some(3), 3), + "the thread limit is always respected" + ); + } + + #[test] + fn some_more_chunks_per_thread() { + assert_eq!( + optimize_chunk_size_and_thread_limit(1, Some(30), None, Some(10)), + (1, Some(10), 10) + ); + assert_eq!( + optimize_chunk_size_and_thread_limit(1, Some(30), Some(5), Some(10)), + (3, Some(5), 5), + "the thread limit is always respected" + ); + } + + #[test] + fn chunk_size_too_small() { + assert_eq!( + optimize_chunk_size_and_thread_limit(1, Some(100), None, Some(10)), + (5, Some(10), 10) + ); + assert_eq!( + optimize_chunk_size_and_thread_limit(1, Some(100), Some(5), Some(10)), + (10, Some(5), 5), + "the thread limit is always respected" + ); + } + + #[test] + fn chunk_size_too_big() { + assert_eq!( + optimize_chunk_size_and_thread_limit(50, Some(100), None, Some(10)), + (5, Some(10), 10) + ); + assert_eq!( + optimize_chunk_size_and_thread_limit(50, Some(100), Some(5), Some(10)), + (10, Some(5), 5), + "the thread limit is always respected" + ); + } + + mod unknown_chunk_count { + use gix_features::parallel::optimize_chunk_size_and_thread_limit; + + #[test] + fn medium_chunk_size_many_threads() { + assert_eq!( + optimize_chunk_size_and_thread_limit(50, None, None, Some(4)), + (50, Some(4), 4), + "really, what do we know" + ); + } + + #[test] + fn medium_chunk_size_single_thread() { + assert_eq!( + optimize_chunk_size_and_thread_limit(50, None, None, Some(1)), + (50, Some(1), 1), + "single threaded - we don't touch that" + ); + } + + #[test] + fn small_chunk_size_single_thread() { + assert_eq!( + optimize_chunk_size_and_thread_limit(1, None, None, Some(1)), + (1, Some(1), 1), + "single threaded - we don't touch that" + ); + } + + #[test] + fn small_chunk_size_many_threads() { + assert_eq!( + optimize_chunk_size_and_thread_limit(1, None, None, Some(4)), + (50, Some(4), 4), + "we prefer an arbitrary number, which should really be based on effort, but the caller has to adjust for that" + ); + } + } + + mod real_values { + use gix_features::parallel::optimize_chunk_size_and_thread_limit; + + #[test] + fn linux_kernel_pack_my_machine_lookup() { + assert_eq!( + optimize_chunk_size_and_thread_limit(10000, Some(7_500_000), None, Some(4)), + (1000, Some(4), 4), + "the bucket size is capped actually, somewhat arbitrarily" + ); + } + + #[test] + fn linux_kernel_pack_my_machine_indexed() { + assert_eq!( + optimize_chunk_size_and_thread_limit(1, None, None, Some(4)), + (50, Some(4), 4), + "low values are raised to arbitrary value" + ); + assert_eq!( + optimize_chunk_size_and_thread_limit(10000, None, None, Some(4)), + (1000, Some(4), 4), + "high values are capped" + ); + } + } +} diff --git a/vendor/gix-features/tests/pipe.rs b/vendor/gix-features/tests/pipe.rs new file mode 100644 index 000000000..4815000bf --- /dev/null +++ b/vendor/gix-features/tests/pipe.rs @@ -0,0 +1,117 @@ +mod io { + use std::io::{BufRead, ErrorKind, Read, Write}; + + use gix_features::io; + + #[test] + fn threaded_read_to_end() { + let (mut writer, mut reader) = gix_features::io::pipe::unidirectional(0); + + let message = "Hello, world!"; + std::thread::spawn(move || { + writer + .write_all(message.as_bytes()) + .expect("writes to work if reader is present") + }); + + let mut received = String::new(); + reader.read_to_string(&mut received).unwrap(); + + assert_eq!(&received, message); + } + + #[test] + fn lack_of_reader_fails_with_broken_pipe() { + let (mut writer, _) = io::pipe::unidirectional(None); + assert_eq!( + writer.write_all(b"must fail").unwrap_err().kind(), + ErrorKind::BrokenPipe + ); + } + #[test] + fn line_reading_one_by_one() { + let (mut writer, mut reader) = io::pipe::unidirectional(2); + writer.write_all(b"a\n").expect("success"); + writer.write_all(b"b\nc").expect("success"); + drop(writer); + let mut buf = String::new(); + for expected in &["a\n", "b\n", "c"] { + buf.clear(); + assert_eq!(reader.read_line(&mut buf).expect("success"), expected.len()); + assert_eq!(buf, *expected); + } + } + + #[test] + fn line_reading() { + let (mut writer, reader) = io::pipe::unidirectional(2); + writer.write_all(b"a\n").expect("success"); + writer.write_all(b"b\nc\n").expect("success"); + drop(writer); + assert_eq!( + reader.lines().flat_map(Result::ok).collect::<Vec<_>>(), + vec!["a", "b", "c"] + ) + } + + #[test] + fn writer_can_inject_errors() { + let (writer, mut reader) = io::pipe::unidirectional(1); + writer + .channel + .send(Err(std::io::Error::new(std::io::ErrorKind::Other, "the error"))) + .expect("send success"); + let mut buf = [0]; + assert_eq!( + reader.read(&mut buf).unwrap_err().to_string(), + "the error", + "using Read trait, errors are propagated" + ); + + writer + .channel + .send(Err(std::io::Error::new(std::io::ErrorKind::Other, "the error"))) + .expect("send success"); + assert_eq!( + reader.fill_buf().unwrap_err().to_string(), + "the error", + "using BufRead trait, errors are propagated" + ); + } + + #[test] + fn continue_on_empty_writes() { + let (mut writer, mut reader) = io::pipe::unidirectional(2); + writer.write_all(&[]).expect("write successful and non-blocking"); + let input = b"hello"; + writer + .write_all(input) + .expect("second write works as well as there is capacity"); + let mut buf = vec![0u8; input.len()]; + assert_eq!(reader.read(&mut buf).expect("read succeeds"), input.len()); + assert_eq!(buf, &input[..]); + } + + #[test] + fn small_reads() { + const BLOCK_SIZE: usize = 20; + let block_count = 20; + let (mut writer, mut reader) = io::pipe::unidirectional(Some(4)); + std::thread::spawn(move || { + for _ in 0..block_count { + let data = &[0; BLOCK_SIZE]; + writer.write_all(data).unwrap(); + } + }); + + let mut small_read_buf = [0; BLOCK_SIZE / 2]; + let mut bytes_read = 0; + while let Ok(size) = reader.read(&mut small_read_buf) { + if size == 0 { + break; + } + bytes_read += size; + } + assert_eq!(block_count * BLOCK_SIZE, bytes_read); + } +} |