diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:35 +0000 |
commit | 7e5d7eea9c580ef4b41a765bde624af431942b96 (patch) | |
tree | 2c0d9ca12878fc4525650aa4e54d77a81a07cc09 /vendor/gix-tempfile | |
parent | Adding debian version 1.70.0+dfsg1-9. (diff) | |
download | rustc-7e5d7eea9c580ef4b41a765bde624af431942b96.tar.xz rustc-7e5d7eea9c580ef4b41a765bde624af431942b96.zip |
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix-tempfile')
-rw-r--r-- | vendor/gix-tempfile/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/gix-tempfile/CHANGELOG.md | 579 | ||||
-rw-r--r-- | vendor/gix-tempfile/Cargo.lock | 283 | ||||
-rw-r--r-- | vendor/gix-tempfile/Cargo.toml | 97 | ||||
-rw-r--r-- | vendor/gix-tempfile/LICENSE-APACHE | 191 | ||||
-rw-r--r-- | vendor/gix-tempfile/LICENSE-MIT | 21 | ||||
-rw-r--r-- | vendor/gix-tempfile/README.md | 12 | ||||
-rw-r--r-- | vendor/gix-tempfile/src/forksafe.rs | 107 | ||||
-rw-r--r-- | vendor/gix-tempfile/src/fs/create_dir.rs | 202 | ||||
-rw-r--r-- | vendor/gix-tempfile/src/fs/mod.rs | 2 | ||||
-rw-r--r-- | vendor/gix-tempfile/src/fs/remove_dir.rs | 108 | ||||
-rw-r--r-- | vendor/gix-tempfile/src/handle.rs | 319 | ||||
-rw-r--r-- | vendor/gix-tempfile/src/lib.rs | 216 | ||||
-rw-r--r-- | vendor/gix-tempfile/src/registry.rs | 67 | ||||
-rw-r--r-- | vendor/gix-tempfile/src/signal.rs | 100 |
15 files changed, 2305 insertions, 0 deletions
diff --git a/vendor/gix-tempfile/.cargo-checksum.json b/vendor/gix-tempfile/.cargo-checksum.json new file mode 100644 index 000000000..336aec6e0 --- /dev/null +++ b/vendor/gix-tempfile/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"8e84348c84cbacca0a00f9e4e961f0080a65d07915906faeafe05d8d89881f59","Cargo.lock":"9e94cbd0fee1702d881d6ae5964a7b6714a9af1bde7cf1b0cedb32e0398be6a3","Cargo.toml":"c1e4ca420265b3d1bf3fd14d46f5421126cabed082cc1f24cbc5601cba357882","LICENSE-APACHE":"cb4780590812826851ba250f90bed0ed19506ec98f6865a0e2e20bbf62391ff9","LICENSE-MIT":"49df47913ab2beafe8dc45607877ae64198bf0eee64aaad3e82ed9e4d27424e8","README.md":"48a31dad99a7ea256f4b0eb80726e12c77d3796069d3d40c0dada3790520617c","src/forksafe.rs":"654a2309e91e9e3761b9354ef2ffbc88bae65befb63deff5d7103b76613c043d","src/fs/create_dir.rs":"f06c1b0166b841b86ffb1bf443cdbfbde68f7b77b7f846f4ada106a1b9bc5578","src/fs/mod.rs":"3fb683d1373f4839b6e0e0440f59b208246b79a2d997906cd125bae42e9615ec","src/fs/remove_dir.rs":"0e4f9236826598a7c048476c2f8c6674bb6dbdb9b6ae7d6373ac97f38aa7bf4b","src/handle.rs":"77c242edd62d576e266c9bd2472037a535a732d6826d91ba75d835f9a0e6d387","src/lib.rs":"862e84f45b8468983d779b2363ecf479461175eaec2d94aefa1c5959eadf8fa3","src/registry.rs":"7ca1b062ef696d9cfbd92d162c14820b15891e845556cb8b68b5e120635de6d8","src/signal.rs":"b6551e99f675a1ff82de9b882524800844484c72ad3ad9d15b8ca0f545420074"},"package":"88751f247234b1f73c8e8056fd835a0999b04e596e052302cb71186005dc4b27"}
\ No newline at end of file diff --git a/vendor/gix-tempfile/CHANGELOG.md b/vendor/gix-tempfile/CHANGELOG.md new file mode 100644 index 000000000..7e85250af --- /dev/null +++ b/vendor/gix-tempfile/CHANGELOG.md @@ -0,0 +1,579 @@ +# 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). + +## 4.1.1 (2023-03-07) + +### Bug Fixes + + - <csr-id-6778c5f6874ec2a44859de25428e6603dd4e9e8a/> switch `tempfile` to `~3.3.0` to help with `cargo` build. + `gix-tempfile` is now used in `cargo`, and `tempfile` seems to cause trouble + in at least one tier (see https://github.com/rust-lang/rust/pull/108665#issuecomment-1457677883). + + This change pins `tempfile` to a working version until this is sorted out together with + the tempfile maintainers. + +### Commit Statistics + +<csr-read-only-do-not-edit/> + + - 1 commit contributed to the release. + - 6 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** + - Switch `tempfile` to `~3.3.0` to help with `cargo` build. ([`6778c5f`](https://github.com/Byron/gitoxide/commit/6778c5f6874ec2a44859de25428e6603dd4e9e8a)) +</details> + +## 4.1.0 (2023-03-01) + +### New Features + + - <csr-id-1ff1342da793442859526df3dd0ec1ed968a6ded/> add `hp-hashmap` feature toggle (enabled by default). + This allows avoiding the `dashmap` dependency, and to optimize load + for different applications. It seems that this simple implementation + has performance benefits in some situations at least even though it + may leave all tempfiles in place if a signal handler tries to cleanup + while a lock is held. + +### Commit Statistics + +<csr-read-only-do-not-edit/> + + - 5 commits contributed to the release over the course of 1 calendar day. + - 2 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-tempfile v4.1.0, gix-lock v4.0.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, safety bump 6 crates ([`ea9fd1d`](https://github.com/Byron/gitoxide/commit/ea9fd1d9b60e1e9e17042e9e37c06525823c40a5)) + - 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)) + - Add `hp-hashmap` feature toggle (enabled by default). ([`1ff1342`](https://github.com/Byron/gitoxide/commit/1ff1342da793442859526df3dd0ec1ed968a6ded)) + - Avoid clearing the registry while running tests ([`d635fb7`](https://github.com/Byron/gitoxide/commit/d635fb7a060bfbc5b584bec9976549383d369f47)) +</details> + +## 4.0.0 (2023-02-26) + +### New Features (BREAKING) + + - <csr-id-441f5ac4dd2f0636ec07065f8095e8bae5ce6985/> gate all signal handling behind the `signals` feature toggle. + This change also consolidates all signal handling into its own module called + `signal` to provide reusable handlers and as well as well as signal initialization. + + Note that the functions to cleanup tempfiles don't interact with the signal registry, + hence they still can be called without the `signals` feature enabled. + + Note that this change sneakily fixes a bug that could have caused a `write_all()` + on a tempfile that was removed by a signal to enter an infinite loop. + +### Commit Statistics + +<csr-read-only-do-not-edit/> + + - 5 commits contributed to the release. + - 9 days passed between releases. + - 1 commit was understood as [conventional](https://www.conventionalcommits.org). + - 1 unique issue was worked on: [#339](https://github.com/Byron/gitoxide/issues/339) + +### Commit Details + +<csr-read-only-do-not-edit/> + +<details><summary>view details</summary> + + * **[#339](https://github.com/Byron/gitoxide/issues/339)** + - Gate all signal handling behind the `signals` feature toggle. ([`441f5ac`](https://github.com/Byron/gitoxide/commit/441f5ac4dd2f0636ec07065f8095e8bae5ce6985)) + * **Uncategorized** + - Release gix-tempfile v4.0.0 ([`ad23f1d`](https://github.com/Byron/gitoxide/commit/ad23f1dd58b3eabf5a12d02c4a1de8b1835051d5)) + - Prepare for git-tempfile release ([`56c005b`](https://github.com/Byron/gitoxide/commit/56c005b13c44376f71e61781e73c0bf93416d0e4)) + - Merge branch 'tempfile-upgrades' ([`3522cba`](https://github.com/Byron/gitoxide/commit/3522cbaac721c8079605be51b9053014bc5e863a)) + - Upgrade `tempfile` to `3.4` ([`2670938`](https://github.com/Byron/gitoxide/commit/2670938df5f6a3ed155b793e301ea0ab64b8cec1)) +</details> + +## 3.0.3 (2023-02-17) + +### 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. + +## 3.0.2 (2023-02-17) + +<csr-id-f7f136dbe4f86e7dee1d54835c420ec07c96cd78/> +<csr-id-533e887e80c5f7ede8392884562e1c5ba56fb9a8/> +<csr-id-25209454d3f7e27e12e8ddca92e43b1ff01d58aa/> + +### Bug Fixes (BREAKING) + + - <csr-id-c863ea5b34fa9ee3dac21c1f85587da16045f8d8/> do not install signal handlers by default + The previous behaviour is meant to be convenient for the casual + user even though it + ends up being surprising when used in applications that install + their own signal handlers and need more control over how the program + shuts down. + + This is now fixed by **requiring an explicit `setup()`** call before + the first tempfile is created, which makes it a breaking change. + +### New Features (BREAKING) + + - <csr-id-3d8fa8fef9800b1576beab8a5bc39b821157a5ed/> upgrade edition to 2021 in most crates. + MSRV for this is 1.56, and we are now at 1.60 so should be compatible. + This isn't more than a patch release as it should break nobody + who is adhering to the MSRV, but let's be careful and mark it + breaking. + + Note that `git-features` and `git-pack` are still on edition 2018 + as they make use of a workaround to support (safe) mutable access + to non-overlapping entries in a slice which doesn't work anymore + in edition 2021. + +### Bug Fixes + + - <csr-id-81ed5f5e7a3634f0fab681ca59e40099f0118f75/> Assure interrupt based tempfile cleanup can't deadlock + We do this by using the `try_entry()` API provided by the most recent + dashmap, at the cost of potentially trying to access a lot of indices + that don't exist in the map anymore. The cost of this are expected + to be low though especially since interrupts are the uncommmon case. + + A side-effect of this is that tempfiles that are currently being + removed for writing to them, for example, won't be cleaned up. + + It will be up to the code running after the interrupt, if the case + at all, to deal with the tempfile, which is what it does anyway. + - <csr-id-d9451e8d7fc39c252042f9d2447061262c16ae7a/> downgrade dashmap to 4.0 to avoid unsoundness. + See https://github.com/xacrimon/dashmap/issues/167 for tracking + progress on resolving the issue. + +### Chore + + - <csr-id-f7f136dbe4f86e7dee1d54835c420ec07c96cd78/> uniformize deny attributes + - <csr-id-533e887e80c5f7ede8392884562e1c5ba56fb9a8/> remove default link to cargo doc everywhere + - <csr-id-25209454d3f7e27e12e8ddca92e43b1ff01d58aa/> upgrade dashmap to 5.1.0 (with security fix) + +### Documentation + + - <csr-id-39ed9eda62b7718d5109135e5ad406fb1fe2978c/> fix typos + +### Commit Statistics + +<csr-read-only-do-not-edit/> + + - 238 commits contributed to the release over the course of 612 calendar days. + - 8 commits were understood as [conventional](https://www.conventionalcommits.org). + - 9 unique issues were worked on: [#198](https://github.com/Byron/gitoxide/issues/198), [#266](https://github.com/Byron/gitoxide/issues/266), [#298](https://github.com/Byron/gitoxide/issues/298), [#328](https://github.com/Byron/gitoxide/issues/328), [#336](https://github.com/Byron/gitoxide/issues/336), [#364](https://github.com/Byron/gitoxide/issues/364), [#450](https://github.com/Byron/gitoxide/issues/450), [#470](https://github.com/Byron/gitoxide/issues/470), [#691](https://github.com/Byron/gitoxide/issues/691) + +### Thanks Clippy + +<csr-read-only-do-not-edit/> + +[Clippy](https://github.com/rust-lang/rust-clippy) helped 8 times to make code idiomatic. + +### Commit Details + +<csr-read-only-do-not-edit/> + +<details><summary>view details</summary> + + * **[#198](https://github.com/Byron/gitoxide/issues/198)** + - Adjust all changelogs to fulfil requirements for publishing ([`04b9ca0`](https://github.com/Byron/gitoxide/commit/04b9ca025a1667529b2221ab4280bd3c8dae01cf)) + - 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)) + - Respect release-wide ignore list to allow removing entire conventional headlines ([`145103d`](https://github.com/Byron/gitoxide/commit/145103d4aa715386da9d4953f7f85fadc49fff9a)) + - Rebuild all changelogs to assure properly ordered headlines ([`4a9a05f`](https://github.com/Byron/gitoxide/commit/4a9a05f95930bad5938d4ce9c517ebf0e0b990f1)) + - Sort all commits by time, descending… ([`f536bad`](https://github.com/Byron/gitoxide/commit/f536bad20ffbac4dc353dfeb1a917bb88becbb78)) + - Greatly reduce changelog size now that the traversal fix is applied ([`a0bc98c`](https://github.com/Byron/gitoxide/commit/a0bc98c06c349de2fd6e0d4593606e68b98def72)) + - Fixup remaining changelogs… ([`2f75db2`](https://github.com/Byron/gitoxide/commit/2f75db294fcf20c325555822f65629611be52971)) + * **[#266](https://github.com/Byron/gitoxide/issues/266)** + - Upgrade dashmap to latest version ([`52d4fe5`](https://github.com/Byron/gitoxide/commit/52d4fe55b6dd88f72479abd4015cab063ddaaf97)) + * **[#298](https://github.com/Byron/gitoxide/issues/298)** + - Refactor ([`591b533`](https://github.com/Byron/gitoxide/commit/591b5338ecdc0da33151baa0781fd8dc1ee8d5a9)) + - Use hash_hasher based hash state for better keys/less collisions ([`814de07`](https://github.com/Byron/gitoxide/commit/814de079f4226f42efa49ad334a348bce67184e4)) + * **[#328](https://github.com/Byron/gitoxide/issues/328)** + - A stress test to try conjure deadlocks in handlers ([`3bdecb5`](https://github.com/Byron/gitoxide/commit/3bdecb54570b46e4c140e783f49ff23ef465582d)) + - Prepare changelog ([`8e92494`](https://github.com/Byron/gitoxide/commit/8e924948dfa366d3d39227b63053c7ff00a5382a)) + - Assure interrupt based tempfile cleanup can't deadlock ([`81ed5f5`](https://github.com/Byron/gitoxide/commit/81ed5f5e7a3634f0fab681ca59e40099f0118f75)) + * **[#336](https://github.com/Byron/gitoxide/issues/336)** + - Update changelog ([`2cfbe9c`](https://github.com/Byron/gitoxide/commit/2cfbe9ce81f611c0b541b9c0fd4fffd2d99dfa0a)) + - Do not install signal handlers by default ([`c863ea5`](https://github.com/Byron/gitoxide/commit/c863ea5b34fa9ee3dac21c1f85587da16045f8d8)) + * **[#364](https://github.com/Byron/gitoxide/issues/364)** + - Update changelogs prior to release ([`746a676`](https://github.com/Byron/gitoxide/commit/746a676056cd4907da7137a00798344b5bdb4419)) + * **[#450](https://github.com/Byron/gitoxide/issues/450)** + - Add safety notes ([`910fa06`](https://github.com/Byron/gitoxide/commit/910fa06f39c9839c58d59467bca05ad511c23bef)) + * **[#470](https://github.com/Byron/gitoxide/issues/470)** + - Update changelogs prior to release ([`caa7a1b`](https://github.com/Byron/gitoxide/commit/caa7a1bdef74d7d3166a7e38127a59f5ab3cfbdd)) + * **[#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-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 ([`e313112`](https://github.com/Byron/gitoxide/commit/e31311257bd138b52042dea5fc40c3abab7f269b)) + - 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-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)) + - Rename `git-tempfile` to `gix-tempfile` ([`192ed5d`](https://github.com/Byron/gitoxide/commit/192ed5d15c04fdfb330b3ab553eeaaf09f7fccd4)) + - 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)) + - 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)) + - Merge branch 'rename-crates' ([`6461c3d`](https://github.com/Byron/gitoxide/commit/6461c3da4d6daee857606d94294c3f87fc36965a)) + - Rename `git-repository` to `gix` ([`7bed2a9`](https://github.com/Byron/gitoxide/commit/7bed2a96604397fa990f427b1a970ddeb6f09f1c)) + - 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)) + - Thanks clippy ([`bac57dd`](https://github.com/Byron/gitoxide/commit/bac57dd05ea2d5a4ee45ef9350fa3f2e19474bc0)) + - 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)) + - 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)) + - Merge branch 'version2021' ([`0e4462d`](https://github.com/Byron/gitoxide/commit/0e4462df7a5166fe85c23a779462cdca8ee013e8)) + - Upgrade edition to 2021 in most crates. ([`3d8fa8f`](https://github.com/Byron/gitoxide/commit/3d8fa8fef9800b1576beab8a5bc39b821157a5ed)) + - 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 (upgrade to Rust 1.65) ([`5406630`](https://github.com/Byron/gitoxide/commit/5406630466145990b5adbdadb59151036993060d)) + - Thanks clippy ([`04cfa63`](https://github.com/Byron/gitoxide/commit/04cfa635a65ae34ad6d22391f2febd2ca7eabca9)) + - 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)) + - Merge branch 'filter-refs-by-spec' ([`5c05198`](https://github.com/Byron/gitoxide/commit/5c051986bd89590a9287d85d84c713d83dfab83a)) + - Merge branch 'main' into index-from-tree ([`bc64b96`](https://github.com/Byron/gitoxide/commit/bc64b96a2ec781c72d1d4daad38aa7fb8b74f99b)) + - 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 ([`95f2f4f`](https://github.com/Byron/gitoxide/commit/95f2f4f17f7eae174a64c7d9f6a1513d73b21bbb)) + - Thanks clippy ([`f90d772`](https://github.com/Byron/gitoxide/commit/f90d772cf625afea605e42c92db15ed870d7e120)) + - 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)) + - Uniformize deny attributes ([`f7f136d`](https://github.com/Byron/gitoxide/commit/f7f136dbe4f86e7dee1d54835c420ec07c96cd78)) + - Remove default link to cargo doc everywhere ([`533e887`](https://github.com/Byron/gitoxide/commit/533e887e80c5f7ede8392884562e1c5ba56fb9a8)) + - Merge branch 'main' into remote-ls-refs ([`bd5f3e8`](https://github.com/Byron/gitoxide/commit/bd5f3e8db7e0bb4abfb7b0f79f585ab82c3a14ab)) + - Release git-date v0.0.3, git-actor v0.11.1, git-attributes v0.3.1, git-tempfile v2.0.3, git-object v0.20.1, git-ref v0.15.1, git-config v0.6.1, git-diff v0.17.1, git-discover v0.4.0, git-bitmap v0.1.1, git-index v0.4.1, git-mailmap v0.3.1, git-traverse v0.16.1, git-pack v0.21.1, git-odb v0.31.1, git-packetline v0.12.6, git-url v0.7.1, git-transport v0.19.1, git-protocol v0.18.1, git-revision v0.4.0, git-worktree v0.4.1, git-repository v0.21.0, safety bump 5 crates ([`c96473d`](https://github.com/Byron/gitoxide/commit/c96473dce21c3464aacbc0a62d520c1a33172611)) + - Prepare changelogs prior to reelase ([`c06ae1c`](https://github.com/Byron/gitoxide/commit/c06ae1c606b6af9c2a12021103d99c2810750d60)) + - 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 pull request #1 from Byron/main ([`085e76b`](https://github.com/Byron/gitoxide/commit/085e76b121291ed9bd324139105d2bd4117bedf8)) + - Merge branch 'main' into pathspec ([`89ea12b`](https://github.com/Byron/gitoxide/commit/89ea12b558bcc056b892193ee8fb44b8664b5da4)) + - Merge branch 'main' into cont_include_if ([`daa71c3`](https://github.com/Byron/gitoxide/commit/daa71c3b753c6d76a3d652c29237906b3e28728f)) + - Thanks clippy ([`e1003d5`](https://github.com/Byron/gitoxide/commit/e1003d5fdee5d4439c0cf0286c67dec9b5e34f53)) + - Release git-diff v0.14.0, git-bitmap v0.1.0, git-index v0.2.0, git-tempfile v2.0.1, git-lock v2.0.0, git-mailmap v0.1.0, git-traverse v0.13.0, git-pack v0.17.0, git-quote v0.2.0, git-odb v0.27.0, git-packetline v0.12.4, git-url v0.4.0, git-transport v0.16.0, git-protocol v0.15.0, git-ref v0.12.0, git-worktree v0.1.0, git-repository v0.15.0, cargo-smart-release v0.9.0, safety bump 5 crates ([`e58dc30`](https://github.com/Byron/gitoxide/commit/e58dc3084cf17a9f618ae3a6554a7323e44428bf)) + - Make fmt ([`7cf3545`](https://github.com/Byron/gitoxide/commit/7cf354509b545f7e7c99e159b5989ddfbe86273d)) + - Merge branch 'short-id' ([`5849d5b`](https://github.com/Byron/gitoxide/commit/5849d5b326b83f98a16cf1d956c720c7f0fd4445)) + - Release git-tempfile v2.0.0, safety bump 6 crates ([`90b1c42`](https://github.com/Byron/gitoxide/commit/90b1c42d5487904a9f329362d185b035d0ddb975)) + - Release git-tempfile v1.0.6 ([`bd3f8ee`](https://github.com/Byron/gitoxide/commit/bd3f8ee28b51fa556a0f37c9bd62569f0ce7d49d)) + - Upgrade dashmap to 5.1.0 (with security fix) ([`2520945`](https://github.com/Byron/gitoxide/commit/25209454d3f7e27e12e8ddca92e43b1ff01d58aa)) + - Release git-tempfile v1.0.5 ([`d811154`](https://github.com/Byron/gitoxide/commit/d81115473cf04f5c3ae25b657b88c3f049451227)) + - Downgrade dashmap to 4.0 to avoid unsoundness. ([`d9451e8`](https://github.com/Byron/gitoxide/commit/d9451e8d7fc39c252042f9d2447061262c16ae7a)) + - Release 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 ([`1b76119`](https://github.com/Byron/gitoxide/commit/1b76119259b8168aeb99cbbec233f7ddaa2d7d2c)) + - Release 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 ([`8f57c29`](https://github.com/Byron/gitoxide/commit/8f57c297d7d6ed68cf51415ea7ede4bf9263326e)) + - 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)) + - 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)) + - Update changelogs just for fun ([`21541b3`](https://github.com/Byron/gitoxide/commit/21541b3301de1e053fc0e84373be60d2162fbaae)) + - Release git-tempfile v1.0.2 ([`310ea73`](https://github.com/Byron/gitoxide/commit/310ea7336e78fbedb2cefa1ecb773b25e6a77e0a)) + - Update changelogs once more… ([`d57d279`](https://github.com/Byron/gitoxide/commit/d57d279dc603cf450c151bbb6dc6c6505cc6da10)) + - Update changelogs retro-actively… ([`78cfe0a`](https://github.com/Byron/gitoxide/commit/78cfe0ac341c6c2257743d913884b50042078e6c)) + - Release git-tempfile v1.0.1 ([`295eb37`](https://github.com/Byron/gitoxide/commit/295eb374d104ac2775b9f864ef3234e2c5832b54)) + - [tempfile #195] adapt to Rust 1.55 ([`d9e71ac`](https://github.com/Byron/gitoxide/commit/d9e71acc5d619b5e78673da4fbb5a531c97ad6dd)) + - Thanks clippy ([`4701296`](https://github.com/Byron/gitoxide/commit/4701296bd5e2c4ad2f80f4e1de498db49f93385a)) + - Release git-tempfile v1.0.0 ([`1238535`](https://github.com/Byron/gitoxide/commit/123853539dc30ddea2d822ab177ee09b191bdf1b)) + - [stability #171] prepare git-lock and git-tempfile release ([`3a1cf4d`](https://github.com/Byron/gitoxide/commit/3a1cf4d441b53c880b5c887916302a493ad28b41)) + - [stability #171] Prime git-tempfile and git-lock for release ([`01278fe`](https://github.com/Byron/gitoxide/commit/01278fe4e28bf97ce6a2b8947198683646e361ee)) + - Release git-tempfile v0.6.1 ([`eda952f`](https://github.com/Byron/gitoxide/commit/eda952f95e9ece78bbdbe6c26dd78f7ac5365d86)) + - Apply nightly rustfmt rules. ([`5e0edba`](https://github.com/Byron/gitoxide/commit/5e0edbadb39673d4de640f112fa306349fb11814)) + - (cargo-release) version 0.6.0 ([`d58f37e`](https://github.com/Byron/gitoxide/commit/d58f37e3b5a000fbe069aa869bd84f66d5c3210b)) + - [utils #154] refactor: bool.then(||this) - neat ([`1dec1c4`](https://github.com/Byron/gitoxide/commit/1dec1c49032c8acb449e463fde41f403cb640e45)) + - (cargo-release) version 0.5.0 ([`0e11e98`](https://github.com/Byron/gitoxide/commit/0e11e98f0562c7baa9c90e18db6240731d165217)) + - [pack #153] implement io traits for tempfiles ([`59d03d6`](https://github.com/Byron/gitoxide/commit/59d03d6133b301a19adfab212cf2c946110fc53b)) + - Clippy on tests and thanks clippy ([`a77a71c`](https://github.com/Byron/gitoxide/commit/a77a71cf02d328a2a964388928d6b2a235a0aa85)) + - Thanks clippy ([`e1964e4`](https://github.com/Byron/gitoxide/commit/e1964e43979b3e32a5d4bfbe377a842d2c0b10ea)) + - Remove unnecessary pub(crate) exports ([`3d2456e`](https://github.com/Byron/gitoxide/commit/3d2456e11709f0461b37c6df55ecc3861ca4cab5)) + - [lock] support recoverable commits ([`b2217e7`](https://github.com/Byron/gitoxide/commit/b2217e7d25df9801354f702b0625d3168f8d3271)) + - [ref] support for persistence with recovery ([`d8b2d66`](https://github.com/Byron/gitoxide/commit/d8b2d661b9cf644b52950b9dedf8dbce0d348098)) + - [ref] refactor ([`a261b82`](https://github.com/Byron/gitoxide/commit/a261b82c1ee7ebdbbc82ce1c8286ca6a0f221cea)) + - [ref] allow reflogs to be created in place of empty directory trees ([`80a6e0e`](https://github.com/Byron/gitoxide/commit/80a6e0e1ff2321d9162e799d5fc0f457e7de4ade)) + - [tempfile] a way to delete empty dirs recursively ([`6025aa0`](https://github.com/Byron/gitoxide/commit/6025aa08d93cd5124c8df38c51b795b9c7d1c911)) + - Bump libc from 0.2.97 to 0.2.98 ([`caf6495`](https://github.com/Byron/gitoxide/commit/caf6495b08f77d7e4eaa058074693fffb5c5644b)) + - [tempfile] close a tempfile while keeping track of it ([`aa96ed1`](https://github.com/Byron/gitoxide/commit/aa96ed1776a615446b9864b1231f9f33805ab178)) + - (cargo-release) version 0.4.0 ([`4512798`](https://github.com/Byron/gitoxide/commit/45127986daba0a409f5b405d463fa23f5c4a053b)) + - [lock] add [must_use = "reason"] attribute where it matters ([`813c46b`](https://github.com/Byron/gitoxide/commit/813c46b1ac9ed5454c7832a6bad5a112f145b565)) + - [lock] refactor, remaining docs ([`956e69f`](https://github.com/Byron/gitoxide/commit/956e69fcb96085d96124b6c56d829607b36adf9f)) + - [lock] tests green ([`3706b26`](https://github.com/Byron/gitoxide/commit/3706b2669ebee5cd25a75a42d9b0a4a380707ee1)) + - [lock] cleanup signal handling even more… ([`9fb13d2`](https://github.com/Byron/gitoxide/commit/9fb13d27ccce5b0742ee9289fca891dbeb8a65de)) + - [lock] first tests and a lot of refactoring ([`3c34194`](https://github.com/Byron/gitoxide/commit/3c34194b6c0fd5ab22eb91081a563ba3bfa19110)) + - [lock] refactor; Marker is definitely not necessary… ([`6af84c9`](https://github.com/Byron/gitoxide/commit/6af84c92dbe049068be795ef4870fd830baf5384)) + - [lock] test what happens if multiple tempfiles are created ([`17942c7`](https://github.com/Byron/gitoxide/commit/17942c7960f25ad1f8f7fb2c94f251d39bb03c6e)) + - [lock] sketch API ([`f0e1427`](https://github.com/Byron/gitoxide/commit/f0e142734c1b09e6c4175b3c1b232d886449e280)) + - (cargo-release) version 0.3.0 ([`92f3a83`](https://github.com/Byron/gitoxide/commit/92f3a830457766c88c68f8424828bfd9b5145f86)) + - [tempfile] refactor ([`f3144a8`](https://github.com/Byron/gitoxide/commit/f3144a897b4e10742fef47fadd350b4e9ddf316a)) + - [tempfile] remaining tests ([`450db66`](https://github.com/Byron/gitoxide/commit/450db6609eb3dad10deed3f9769a21ae8c4b3be8)) + - [tempfile] refactor ([`3bafa7b`](https://github.com/Byron/gitoxide/commit/3bafa7b2a3cf8efd0769564026ce7b757cb8c09b)) + - [tempfile] implement 'closed' version of tempfile ([`d4bb61d`](https://github.com/Byron/gitoxide/commit/d4bb61dbc99b4270464d903978222d31c7e7dc5e)) + - [tempfile] refactor ([`4788222`](https://github.com/Byron/gitoxide/commit/4788222c28605118c03ce9f3a4dfccc26e7f7b60)) + - [tempfile] fix docs ([`3cd6712`](https://github.com/Byron/gitoxide/commit/3cd6712c22dae2e804573bca0b7a687c36066c29)) + - [tempfile] sketch of a closed registration with different types ([`db9bb11`](https://github.com/Byron/gitoxide/commit/db9bb11a3132961029e04f1cf761bfc3c96ec33d)) + - [tempfile] refactor ([`8a0ce64`](https://github.com/Byron/gitoxide/commit/8a0ce64baf5a3d77a08aa68c3245be8e7964be70)) + - [tempfile] typesafe diffentiation between writable tempfiles and closed ones ([`3b424b1`](https://github.com/Byron/gitoxide/commit/3b424b1cc071580303d37b7459e80036635eb4aa)) + - [tempfile] refactor ([`913f301`](https://github.com/Byron/gitoxide/commit/913f3014313fe0c03cd8f0af88944d8d514d89d9)) + - [tempfile] refactor ([`9384617`](https://github.com/Byron/gitoxide/commit/9384617dbe00dd59726cc418f23fb0a6e6dde415)) + - [tempfile] implement 'map' on tempfile to realize that 'close()' can't be done… ([`f4a1d33`](https://github.com/Byron/gitoxide/commit/f4a1d33e994e986604d18a85b7f85e1cea063dcf)) + - (cargo-release) version 0.2.0 ([`7c2eb36`](https://github.com/Byron/gitoxide/commit/7c2eb36274d13646956ac850bee90abbbac91c5b)) + - [tempfile] improve docs ([`d311b08`](https://github.com/Byron/gitoxide/commit/d311b082cdec323eb76363d986064fe771aa2bfd)) + - Thanks clippy ([`a0f9803`](https://github.com/Byron/gitoxide/commit/a0f9803533e5684cfed5ab50cd8145d071e978b2)) + - [tempfile] refactor ([`3a0f1ad`](https://github.com/Byron/gitoxide/commit/3a0f1ad0963c77a07f1984c39b127337463c030b)) + - [tempfile] refactor ([`9b8abd0`](https://github.com/Byron/gitoxide/commit/9b8abd0336d6ea1d7c088c78fc09fa935408896f)) + - [tempfile] cleanup control for named and unnamed tempfiles ([`0ef85a2`](https://github.com/Byron/gitoxide/commit/0ef85a247d60332ca232d6d993987c0b89e34466)) + - [tempfile] all remaining remove_dir tests I can think of ([`3e45e5f`](https://github.com/Byron/gitoxide/commit/3e45e5fef4f0bbd8736ae3f197f15813290fe8dc)) + - [tempfile] first bunch of tests for error handling and basic function of rmdir ([`ba41a15`](https://github.com/Byron/gitoxide/commit/ba41a15d874a2709ab92a8680d9e168ece7b4676)) + - [tempfile] quick impl of remove-dir iter without tests ([`bf48913`](https://github.com/Byron/gitoxide/commit/bf48913b3bc1a8c3ebaa230880f573ad01982f08)) + - [tempfile] refactor ([`9226dbe`](https://github.com/Byron/gitoxide/commit/9226dbe18127d7e85ba2779393cb7263e87cfbf8)) + - [tempfile] refactor ([`730b733`](https://github.com/Byron/gitoxide/commit/730b733a1a5b2c3911849eef6ffe0833e12daf73)) + - [tempfile] refactor ([`1da35ce`](https://github.com/Byron/gitoxide/commit/1da35ce045609296c189133ca439a74b550ccc6c)) + - [tempfile] improve Retries documentation; retries docs for remove_dir ([`e665a5f`](https://github.com/Byron/gitoxide/commit/e665a5fcd38c7002545079c63f0bf35dee11876d)) + - [tempfile] sketch how tempfile cleanup should be configured… ([`71acede`](https://github.com/Byron/gitoxide/commit/71acede9cba6fc222d0bde1a3fd0c232d3c877ab)) + - [tempfile] logic fixed, it's working ([`6ad4946`](https://github.com/Byron/gitoxide/commit/6ad4946e2ee603c69dad1da3e1e996cd1d4ca075)) + - [tempfile] better counting, but… ([`972113f`](https://github.com/Byron/gitoxide/commit/972113f1ea72674db61867b14f0eed0de498b310)) + - [tempfile] better retry counts ([`c7a35ca`](https://github.com/Byron/gitoxide/commit/c7a35caa295580a1b9d4f8b77eb8ded9d9c88703)) + - [tempfile] refactor ([`273d722`](https://github.com/Byron/gitoxide/commit/273d72276a73d49a633b9be1c66f1a2357dfcb0f)) + - [tempfile] a better way to count retries… ([`e110b97`](https://github.com/Byron/gitoxide/commit/e110b97b4925a10fa9a62576daf9f078508b6760)) + - [tempfile] trying to implement remove_dir really shows that… ([`1319b90`](https://github.com/Byron/gitoxide/commit/1319b908cc42ef5114d22957ebed9ed2ced11391)) + - [tempfile] docs for create_dir; frame for remove_dir; ([`aa6b6d1`](https://github.com/Byron/gitoxide/commit/aa6b6d14236c817ecc64390b110069c4c1340c03)) + - [tempfile] tests for automatic directory creation ([`3bd5cee`](https://github.com/Byron/gitoxide/commit/3bd5cee0dc0811ff3b1ab3d1a93e7dca8ae06b69)) + - [tempfile] refactor ([`d441312`](https://github.com/Byron/gitoxide/commit/d4413125c432da2e7ef809aca61973f5f55dbd5c)) + - [tempfile] use create_dir::all based on configuration… ([`156c021`](https://github.com/Byron/gitoxide/commit/156c021ac8aaabe8fed60ac4681f365c75e0e165)) + - [tempfile] remove todo ([`5a14ab6`](https://github.com/Byron/gitoxide/commit/5a14ab63555d6e3a58ce32b68d4b47287869b73f)) + - [tempfile] more information about error cases, too ([`7415141`](https://github.com/Byron/gitoxide/commit/74151415f0019a32b4759cf01873acb4102f2d1e)) + - [tempfile] refactor ([`ae0c97a`](https://github.com/Byron/gitoxide/commit/ae0c97a59d9cc56e19d3ce6fcc12b4564a66298a)) + - [tempfile] refactor ([`7c7658d`](https://github.com/Byron/gitoxide/commit/7c7658d3390fdf1b5348a482c71a9fb20a815cca)) + - [tempfile] test for racy directory creation… ([`c9073bf`](https://github.com/Byron/gitoxide/commit/c9073bf0d6dff3165cfd43733a602127b8835727)) + - [tempfile] verify existing files are handled correctly ([`28fee55`](https://github.com/Byron/gitoxide/commit/28fee552718cbbed067b8a16631aaa1080886e00)) + - [tempfile] a test for directory creation limits ([`584b4b7`](https://github.com/Byron/gitoxide/commit/584b4b7a1e6997594f1234d5feab1bc82a83b859)) + - [tempfile] limit retries for directory creation… ([`1536c7a`](https://github.com/Byron/gitoxide/commit/1536c7a58f1da4b80e83f1169b3f865f12a3d9a2)) + - [tempfile] refactor ([`fa7b8e9`](https://github.com/Byron/gitoxide/commit/fa7b8e99d2613297127b044605a2314b878d3ab9)) + - [tempfile] handle interrupts and assure there is an end to it ([`dc0afbd`](https://github.com/Byron/gitoxide/commit/dc0afbdf08c44237b6749426ebacbded6cf8a647)) + - [tempfile] first recursive directory creation ([`b01faa9`](https://github.com/Byron/gitoxide/commit/b01faa9fdc371c1226978e32a3c71dbf3be600ec)) + - [tempfile] refactor ([`7b59392`](https://github.com/Byron/gitoxide/commit/7b59392fec4c80eddd9f82271eb1a5671e44aa5a)) + - [tempfile] another test ([`9e4834d`](https://github.com/Byron/gitoxide/commit/9e4834df1142fd0ffdbf5ffba1aed63bc67b66b3)) + - [tempfile] first sketch of iterator based create directory all… ([`314693c`](https://github.com/Byron/gitoxide/commit/314693c6a4577f0b2b00274a55ec99e87c17918f)) + - [lock] frame for git-lock crate ([`e6bc87d`](https://github.com/Byron/gitoxide/commit/e6bc87d77f9b397b25694f58d347de2fc38bf71d)) + - [tempfile] add journey test to validate operation on process level ([`2d1efd4`](https://github.com/Byron/gitoxide/commit/2d1efd4915d66890b1132d5b39e08027a83047ba)) + - [tempfile] more docs ([`d0c5e6b`](https://github.com/Byron/gitoxide/commit/d0c5e6b96f27d7ae708e7182b4cd5dbaceecd3cd)) + - Refactor ([`e0b7f69`](https://github.com/Byron/gitoxide/commit/e0b7f695ee6bd1032544a29d91906f9b75e12d46)) + - [tempfile] clean cargo manifest ([`d43f514`](https://github.com/Byron/gitoxide/commit/d43f51438937d5bdd2bb2e02c355dcd4ee2b8680)) + - [tempfile] fix windows for good ([`3192a47`](https://github.com/Byron/gitoxide/commit/3192a47b730245f2656ccf8cd82394ec31e13126)) + - [tempfile] fix windows build (hopefully) ([`6c1df66`](https://github.com/Byron/gitoxide/commit/6c1df667031084a9e6fe9676534f80aae9a95789)) + - [tempfile] refactor ([`4a45df0`](https://github.com/Byron/gitoxide/commit/4a45df02340b55d34534be89934d2201dda261f9)) + - [tempfile] prepare release ([`c0f7fde`](https://github.com/Byron/gitoxide/commit/c0f7fde70b28526ad52dce9e2314a25af1531689)) + - [tempfile] an example to show off signal handlers ([`f325e69`](https://github.com/Byron/gitoxide/commit/f325e696c64e3f61f64c0a8d8c4e8af38104a713)) + - [tempfile] remaining docs ([`d334dc0`](https://github.com/Byron/gitoxide/commit/d334dc004d8b8eea5b586c6ada173d28d380ccce)) + - [tempfile] restore original signal handler behaviour. ([`9f91dd8`](https://github.com/Byron/gitoxide/commit/9f91dd8e95e1e51a8e0a4f7ba45628b3d93fc5de)) + - [tempfile] process-id filter on deletion to support forks ([`611056f`](https://github.com/Byron/gitoxide/commit/611056f431dc793684efad668d40b93b1cfec21e)) + - [tempfile] implement handler correctly, probably. ([`8cb0bbc`](https://github.com/Byron/gitoxide/commit/8cb0bbcf2d022401886071f9c91498977cea185c)) + - [tempfile] remove tempfiles on shutdown, but… ([`954b760`](https://github.com/Byron/gitoxide/commit/954b76029e4d9e331738137ec2c9804b0e06a890)) + - [tempfile] switch to dashmap as slab ([`6164719`](https://github.com/Byron/gitoxide/commit/61647195ce8fd0be1b3b63f19e8aaec392f33f19)) + - [tempfile] a more realistic slab test shows the index can get quite high. ([`915f14c`](https://github.com/Byron/gitoxide/commit/915f14c41145dbd3f63bd798e6d0cc18d51fef6f)) + - [tempfile] first step towards clearing tempfiles… ([`b0e0cee`](https://github.com/Byron/gitoxide/commit/b0e0cee866b643f9f9e4ebdc495abed5f5c6abf9)) + - [tempfile] precisely named tempfiles ([`edc74f0`](https://github.com/Byron/gitoxide/commit/edc74f0e8f04f45661d4909bb3e6c62f4ac1b453)) + - [tempfile] `take()` method ([`d377397`](https://github.com/Byron/gitoxide/commit/d3773976b86ad294528997104b9cfa0c803f9d6a)) + - [tempfile] basic operation of a tempfile ([`a692950`](https://github.com/Byron/gitoxide/commit/a692950ae7c32ed9dd040c0aebde494ef3029a30)) + - [tempfile] show that slabs can store a lot actually ([`0cc5b33`](https://github.com/Byron/gitoxide/commit/0cc5b33f0e421ed761e5c350fb4d3ad85ef3e884)) + - [tempfile] initial docs as there is a lot to consider ([`9dffc2b`](https://github.com/Byron/gitoxide/commit/9dffc2b918178650a3b40adfcc35730e48f46951)) + - [tempfile] crate frame ([`1b04c39`](https://github.com/Byron/gitoxide/commit/1b04c39030b436fb6850fbfa0c39a4fed7df727c)) +</details> + +## 3.0.1 (2023-01-10) + +A maintenance release without user-facing changes. + +## 3.0.0 (2022-11-21) + +### New Features (BREAKING) + + - <csr-id-3d8fa8fef9800b1576beab8a5bc39b821157a5ed/> upgrade edition to 2021 in most crates. + MSRV for this is 1.56, and we are now at 1.60 so should be compatible. + This isn't more than a patch release as it should break nobody + who is adhering to the MSRV, but let's be careful and mark it + breaking. + + Note that `gix-features` and `gix-pack` are still on edition 2018 + as they make use of a workaround to support (safe) mutable access + to non-overlapping entries in a slice which doesn't work anymore + in edition 2021. + +## 2.0.6 (2022-11-06) + +A maintenance release without user-facing changes. + +## 2.0.5 (2022-09-20) + +Maintenance release without observable changes. + +## 2.0.4 (2022-08-24) + +<csr-id-f7f136dbe4f86e7dee1d54835c420ec07c96cd78/> +<csr-id-533e887e80c5f7ede8392884562e1c5ba56fb9a8/> + +### Chore + + - <csr-id-f7f136dbe4f86e7dee1d54835c420ec07c96cd78/> uniformize deny attributes + - <csr-id-533e887e80c5f7ede8392884562e1c5ba56fb9a8/> remove default link to cargo doc everywhere + +## 2.0.3 (2022-08-17) + +A maintenance release without user facing changes. + +## 2.0.2 (2022-07-22) + +This is a maintenance release with no functional changes. + +## 2.0.1 (2022-04-03) + +A maintenance release without any changes on the surface. + +## 2.0.0 (2022-02-17) + +### Bug Fixes (BREAKING) + + - <csr-id-c863ea5b34fa9ee3dac21c1f85587da16045f8d8/> do not install signal handlers by default. + + The previous behaviour is meant to be convenient for the casual + user even though it + ends up being surprising when used in applications that install + their own signal handlers and need more control over how the program + shuts down. + + This is now fixed by **requiring an explicit `setup()`** call before + the first tempfile is created, which makes it a breaking change. + +## 1.0.6 (2022-02-07) + +<csr-id-25209454d3f7e27e12e8ddca92e43b1ff01d58aa/> + +Fixes a potential deadlock in in an interrupt handler attempting to cleanup tempfiles. + +### Chore + + - <csr-id-25209454d3f7e27e12e8ddca92e43b1ff01d58aa/> upgrade dashmap to 5.1.0 (with security fix) + +### Bug Fixes + + - <csr-id-81ed5f5e7a3634f0fab681ca59e40099f0118f75/> Assure interrupt based tempfile cleanup can't deadlock. + + We do this by using the `try_entry()` API provided by the most recent + dashmap, at the cost of potentially trying to access a lot of indices + that don't exist in the map anymore. The cost of this are expected + to be low though especially since interrupts are the uncommmon case. + + A side-effect of this is that tempfiles that are currently being + removed for writing to them, for example, won't be cleaned up. + + It will be up to the code running after the interrupt, if the case + at all, to deal with the tempfile, which is what it does anyway. + +## 1.0.5 (2022-02-01) + +### Bug Fixes + + - <csr-id-d9451e8d7fc39c252042f9d2447061262c16ae7a/> downgrade dashmap to 4.0 to avoid unsoundness. + See https://github.com/xacrimon/dashmap/issues/167 for tracking + progress on resolving the issue. + +## 1.0.4 (2022-01-23) + +A maintenance release thanks to upgraded dependencies. + +## v1.0.3 (2021-10-15) + +This release contains no functional changes, but a more useful changelog. + +## v1.0.2 (2021-09-10) + +- Compatibility with Rust 1.55. It informed about the incorrect usage of `std::io::ErrorKind::Other` which this crate also dependent on in its tests. + +## v1.0.1 (2021-09-10) + +## v1.0.0 (2021-08-25) + +- initial release + +## v1.0.0 (2021-08-25) + +## v0.6.1 (2021-08-17) + +## v0.6.0 (2021-08-11) + +## v0.5.0 (2021-08-10) + +## v0.4.0 (2021-06-23) + +## v0.3.0 (2021-06-20) + +## v0.2.0 (2021-06-19) + +## v0.1.0 (2021-06-15) + diff --git a/vendor/gix-tempfile/Cargo.lock b/vendor/gix-tempfile/Cargo.lock new file mode 100644 index 000000000..b07efdf9b --- /dev/null +++ b/vendor/gix-tempfile/Cargo.lock @@ -0,0 +1,283 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "dashmap" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "document-features" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e493c573fce17f00dcab13b6ac057994f3ce17d1af4dc39bfd482b83c6eb6157" +dependencies = [ + "litrs", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "gix-tempfile" +version = "4.1.1" +dependencies = [ + "dashmap", + "document-features", + "libc", + "once_cell", + "parking_lot", + "signal-hook", + "signal-hook-registry", + "tempfile", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "litrs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9275e0933cf8bb20f008924c0cb07a0692fe54d8064996520bf998de9eb79aa" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "signal-hook" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" diff --git a/vendor/gix-tempfile/Cargo.toml b/vendor/gix-tempfile/Cargo.toml new file mode 100644 index 000000000..7dba7fd20 --- /dev/null +++ b/vendor/gix-tempfile/Cargo.toml @@ -0,0 +1,97 @@ +# 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 = "2021" +rust-version = "1.64" +name = "gix-tempfile" +version = "4.1.1" +authors = ["Sebastian Thiel <sebastian.thiel@icloud.com>"] +include = [ + "src/**/*", + "LICENSE-*", + "README.md", + "CHANGELOG.md", +] +description = "A tempfile implementation with a global registry to assure cleanup" +readme = "README.md" +license = "MIT/Apache-2.0" +repository = "https://github.com/Byron/gitoxide" + +[package.metadata.docs.rs] +all-features = true +features = ["document-features"] +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[lib] +test = true +doctest = false + +[[example]] +name = "delete-tempfiles-on-sigterm" +path = "examples/delete-tempfiles-on-sigterm.rs" +required-features = ["signals"] + +[[example]] +name = "delete-tempfiles-on-sigterm-interactive" +path = "examples/delete-tempfiles-on-sigterm-interactive.rs" +required-features = ["signals"] + +[[example]] +name = "try-deadlock-on-cleanup" +path = "examples/try-deadlock-on-cleanup.rs" +required-features = ["signals"] + +[dependencies.dashmap] +version = "5.1.0" +optional = true + +[dependencies.document-features] +version = "0.2.0" +optional = true + +[dependencies.once_cell] +version = "1.8.0" +features = [ + "race", + "std", +] +default-features = false + +[dependencies.parking_lot] +version = "0.12.1" + +[dependencies.signal-hook] +version = "0.3.9" +optional = true +default-features = false + +[dependencies.signal-hook-registry] +version = "1.4.0" +optional = true + +[dependencies.tempfile] +version = "~3.3.0" + +[features] +default = ["hp-hashmap"] +hp-hashmap = ["dep:dashmap"] +signals = [ + "dep:signal-hook", + "dep:signal-hook-registry", +] + +[target."cfg(not(windows))".dependencies.libc] +version = "0.2.98" +default-features = false diff --git a/vendor/gix-tempfile/LICENSE-APACHE b/vendor/gix-tempfile/LICENSE-APACHE new file mode 100644 index 000000000..a51f59a06 --- /dev/null +++ b/vendor/gix-tempfile/LICENSE-APACHE @@ -0,0 +1,191 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2018-2021 Sebastian Thiel, and [contributors](https://github.com/byron/gitoxide/contributors) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/gix-tempfile/LICENSE-MIT b/vendor/gix-tempfile/LICENSE-MIT new file mode 100644 index 000000000..b58e818f1 --- /dev/null +++ b/vendor/gix-tempfile/LICENSE-MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018-2021 Sebastian Thiel, and [contributors](https://github.com/byron/gitoxide/contributors). + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/gix-tempfile/README.md b/vendor/gix-tempfile/README.md new file mode 100644 index 000000000..0de38724b --- /dev/null +++ b/vendor/gix-tempfile/README.md @@ -0,0 +1,12 @@ +Use tempfiles to minimize the risk of resource leakage when preparing to overwrite or create a file with new content +in a signal-safe way, making the change atomic. + +Tempfiles can also be used as locks as only one tempfile can exist at a given path at a time. + +* [x] registered temporary files which are deleted automatically as the process terminates or on drop + * [x] write to temporary file and persist it under new name + * [x] close temporary files to convert them into a marker while saving system resources + * [x] mark paths with a closed temporary file +* [x] persist temporary files to prevent them from perishing. +* [x] signal-handler integration with `gix` to clean lockfiles before the process is aborted. +* [x] use a temporary file transparently due thanks to implementations of `std::io` traits diff --git a/vendor/gix-tempfile/src/forksafe.rs b/vendor/gix-tempfile/src/forksafe.rs new file mode 100644 index 000000000..1da7b2b2c --- /dev/null +++ b/vendor/gix-tempfile/src/forksafe.rs @@ -0,0 +1,107 @@ +use std::path::Path; + +use tempfile::{NamedTempFile, TempPath}; + +use crate::{handle, AutoRemove}; + +enum TempfileOrTemppath { + Tempfile(NamedTempFile), + Temppath(TempPath), +} + +pub(crate) struct ForksafeTempfile { + inner: TempfileOrTemppath, + cleanup: AutoRemove, + pub owning_process_id: u32, +} + +impl ForksafeTempfile { + pub fn new(tempfile: NamedTempFile, cleanup: AutoRemove, mode: handle::Mode) -> Self { + use handle::Mode::*; + ForksafeTempfile { + inner: match mode { + Closed => TempfileOrTemppath::Temppath(tempfile.into_temp_path()), + Writable => TempfileOrTemppath::Tempfile(tempfile), + }, + cleanup, + owning_process_id: std::process::id(), + } + } +} + +impl ForksafeTempfile { + pub fn as_mut_tempfile(&mut self) -> Option<&mut NamedTempFile> { + match &mut self.inner { + TempfileOrTemppath::Tempfile(file) => Some(file), + TempfileOrTemppath::Temppath(_) => None, + } + } + pub fn close(self) -> Self { + if let TempfileOrTemppath::Tempfile(file) = self.inner { + ForksafeTempfile { + inner: TempfileOrTemppath::Temppath(file.into_temp_path()), + cleanup: self.cleanup, + owning_process_id: self.owning_process_id, + } + } else { + self + } + } + pub fn persist(mut self, path: impl AsRef<Path>) -> Result<Option<std::fs::File>, (std::io::Error, Self)> { + match self.inner { + TempfileOrTemppath::Tempfile(file) => match file.persist(path) { + Ok(file) => Ok(Some(file)), + Err(err) => Err((err.error, { + self.inner = TempfileOrTemppath::Tempfile(err.file); + self + })), + }, + TempfileOrTemppath::Temppath(temppath) => match temppath.persist(path) { + Ok(_) => Ok(None), + Err(err) => Err((err.error, { + self.inner = TempfileOrTemppath::Temppath(err.path); + self + })), + }, + } + } + + pub fn into_temppath(self) -> TempPath { + match self.inner { + TempfileOrTemppath::Tempfile(file) => file.into_temp_path(), + TempfileOrTemppath::Temppath(path) => path, + } + } + pub fn into_tempfile(self) -> Option<NamedTempFile> { + match self.inner { + TempfileOrTemppath::Tempfile(file) => Some(file), + TempfileOrTemppath::Temppath(_) => None, + } + } + pub fn drop_impl(self) { + let file_path = match self.inner { + TempfileOrTemppath::Tempfile(file) => file.path().to_owned(), + TempfileOrTemppath::Temppath(path) => path.to_path_buf(), + }; + let parent_directory = file_path.parent().expect("every tempfile has a parent directory"); + self.cleanup.execute_best_effort(parent_directory); + } + + pub fn drop_without_deallocation(self) { + use std::io::Write; + let temppath = match self.inner { + TempfileOrTemppath::Tempfile(file) => { + let (mut file, temppath) = file.into_parts(); + file.flush().ok(); + temppath + } + TempfileOrTemppath::Temppath(path) => path, + }; + std::fs::remove_file(&temppath).ok(); + std::mem::forget( + self.cleanup + .execute_best_effort(temppath.parent().expect("every file has a directory")), + ); + std::mem::forget(temppath); // leak memory to prevent deallocation + } +} diff --git a/vendor/gix-tempfile/src/fs/create_dir.rs b/vendor/gix-tempfile/src/fs/create_dir.rs new file mode 100644 index 000000000..65efdb2b8 --- /dev/null +++ b/vendor/gix-tempfile/src/fs/create_dir.rs @@ -0,0 +1,202 @@ +//! +use std::path::Path; + +/// The amount of retries to do during various aspects of the directory creation. +#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)] +pub struct Retries { + /// How many times the whole directory can be created in the light of racy interference. + /// This count combats racy situations where another process is trying to remove a directory that we want to create, + /// and is deliberately higher than those who do deletion. That way, creation usually wins. + pub to_create_entire_directory: usize, + /// The amount of times we can try to create a directory because we couldn't as the parent didn't exist. + /// This amounts to the maximum subdirectory depth we allow to be created. Counts once per attempt to create the entire directory. + pub on_create_directory_failure: usize, + /// How often to retry to create a single directory if an interrupt happens, as caused by signals. + pub on_interrupt: usize, +} + +impl Default for Retries { + fn default() -> Self { + Retries { + on_interrupt: 10, + to_create_entire_directory: 5, + on_create_directory_failure: 25, + } + } +} + +mod error { + use std::{fmt, path::Path}; + + use crate::fs::create_dir::Retries; + + /// The error returned by [all()][super::all()]. + #[allow(missing_docs)] + #[derive(Debug)] + pub enum Error<'a> { + /// A failure we will probably recover from by trying again. + Intermediate { dir: &'a Path, kind: std::io::ErrorKind }, + /// A failure that ends the operation. + Permanent { + dir: &'a Path, + err: std::io::Error, + /// The retries left after running the operation + retries_left: Retries, + /// The original amount of retries to allow determining how many were actually used + retries: Retries, + }, + } + + impl<'a> fmt::Display for Error<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::Intermediate { dir, kind } => write!( + f, + "Intermediae failure creating {:?} with error: {:?}", + dir.display(), + kind + ), + Error::Permanent { + err: _, + dir, + retries_left, + retries, + } => write!( + f, + "Permanently failing to create directory {dir:?} ({retries_left:?} of {retries:?})", + ), + } + } + } + + impl<'a> std::error::Error for Error<'a> { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Permanent { err, .. } => Some(err), + _ => None, + } + } + } +} +pub use error::Error; + +enum State { + CurrentlyCreatingDirectories, + SearchingUpwardsForExistingDirectory, +} + +/// A special iterator which communicates its operation through results where… +/// +/// * `Some(Ok(created_directory))` is yielded once or more success, followed by `None` +/// * `Some(Err(Error::Intermediate))` is yielded zero or more times while trying to create the directory. +/// * `Some(Err(Error::Permanent))` is yielded exactly once on failure. +pub struct Iter<'a> { + cursors: Vec<&'a Path>, + retries: Retries, + original_retries: Retries, + state: State, +} + +/// Construction +impl<'a> Iter<'a> { + /// Create a new instance that creates `target` when iterated with the default amount of [`Retries`]. + pub fn new(target: &'a Path) -> Self { + Self::new_with_retries(target, Default::default()) + } + + /// Create a new instance that creates `target` when iterated with the specified amount of `retries`. + pub fn new_with_retries(target: &'a Path, retries: Retries) -> Self { + Iter { + cursors: vec![target], + original_retries: retries, + retries, + state: State::SearchingUpwardsForExistingDirectory, + } + } +} + +impl<'a> Iter<'a> { + fn pernanent_failure( + &mut self, + dir: &'a Path, + err: impl Into<std::io::Error>, + ) -> Option<Result<&'a Path, Error<'a>>> { + self.cursors.clear(); + Some(Err(Error::Permanent { + err: err.into(), + dir, + retries_left: self.retries, + retries: self.original_retries, + })) + } + + fn intermediate_failure(&self, dir: &'a Path, err: std::io::Error) -> Option<Result<&'a Path, Error<'a>>> { + Some(Err(Error::Intermediate { dir, kind: err.kind() })) + } +} + +impl<'a> Iterator for Iter<'a> { + type Item = Result<&'a Path, Error<'a>>; + + fn next(&mut self) -> Option<Self::Item> { + use std::io::ErrorKind::*; + match self.cursors.pop() { + Some(dir) => match std::fs::create_dir(dir) { + Ok(()) => { + self.state = State::CurrentlyCreatingDirectories; + Some(Ok(dir)) + } + Err(err) => match err.kind() { + AlreadyExists if dir.is_dir() => { + self.state = State::CurrentlyCreatingDirectories; + Some(Ok(dir)) + } + AlreadyExists => self.pernanent_failure(dir, err), // is non-directory + NotFound => { + self.retries.on_create_directory_failure -= 1; + if let State::CurrentlyCreatingDirectories = self.state { + self.state = State::SearchingUpwardsForExistingDirectory; + self.retries.to_create_entire_directory -= 1; + if self.retries.to_create_entire_directory < 1 { + return self.pernanent_failure(dir, NotFound); + } + self.retries.on_create_directory_failure = + self.original_retries.on_create_directory_failure; + } + if self.retries.on_create_directory_failure < 1 { + return self.pernanent_failure(dir, NotFound); + }; + self.cursors.push(dir); + self.cursors.push(match dir.parent() { + None => return self.pernanent_failure(dir, InvalidInput), + Some(parent) => parent, + }); + self.intermediate_failure(dir, err) + } + Interrupted => { + self.retries.on_interrupt -= 1; + if self.retries.on_interrupt <= 1 { + return self.pernanent_failure(dir, Interrupted); + }; + self.cursors.push(dir); + self.intermediate_failure(dir, err) + } + _unexpected_kind => self.pernanent_failure(dir, err), + }, + }, + None => None, + } + } +} + +/// Create all directories leading to `dir` including `dir` itself with the specified amount of `retries`. +/// Returns the input `dir` on success that make it useful in expressions. +pub fn all(dir: &Path, retries: Retries) -> std::io::Result<&Path> { + for res in Iter::new_with_retries(dir, retries) { + match res { + Err(Error::Permanent { err, .. }) => return Err(err), + Err(Error::Intermediate { .. }) | Ok(_) => continue, + } + } + Ok(dir) +} diff --git a/vendor/gix-tempfile/src/fs/mod.rs b/vendor/gix-tempfile/src/fs/mod.rs new file mode 100644 index 000000000..bf26d819b --- /dev/null +++ b/vendor/gix-tempfile/src/fs/mod.rs @@ -0,0 +1,2 @@ +pub mod create_dir; +pub mod remove_dir; diff --git a/vendor/gix-tempfile/src/fs/remove_dir.rs b/vendor/gix-tempfile/src/fs/remove_dir.rs new file mode 100644 index 000000000..ac7b212fa --- /dev/null +++ b/vendor/gix-tempfile/src/fs/remove_dir.rs @@ -0,0 +1,108 @@ +//! +use std::path::{Path, PathBuf}; + +/// A special iterator which communicates its operation through results where… +/// +/// * `Some(Ok(removed_directory))` is yielded once or more success, followed by `None` +/// * `Some(Err(std::io::Error))` is yielded exactly once on failure. +pub struct Iter<'a> { + cursor: Option<&'a Path>, + boundary: &'a Path, +} + +/// Construction +impl<'a> Iter<'a> { + /// Create a new instance that deletes `target` but will stop at `boundary`, without deleting the latter. + /// Returns an error if `boundary` doesn't contain `target` + /// + /// **Note** that we don't canonicalize the path for performance reasons. + pub fn new(target: &'a Path, boundary: &'a Path) -> std::io::Result<Self> { + if !target.starts_with(boundary) { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + format!("Removal target {target:?} must be contained in boundary {boundary:?}"), + )); + } + let cursor = if target == boundary { + None + } else if target.exists() { + Some(target) + } else { + None + }; + Ok(Iter { cursor, boundary }) + } +} + +impl<'a> Iterator for Iter<'a> { + type Item = std::io::Result<&'a Path>; + + fn next(&mut self) -> Option<Self::Item> { + match self.cursor.take() { + Some(dir) => { + let next = match std::fs::remove_dir(dir) { + Ok(()) => Some(Ok(dir)), + Err(err) => match err.kind() { + std::io::ErrorKind::NotFound => Some(Ok(dir)), + _other_error_kind => return Some(Err(err)), + }, + }; + self.cursor = match dir.parent() { + Some(parent) => (parent != self.boundary).then_some(parent), + None => { + unreachable!("directory {:?} ran out of parents, this really shouldn't happen before hitting the boundary {:?}", dir, self.boundary) + } + }; + next + } + None => None, + } + } +} + +/// Delete all empty directories from `delete_dir` upward and until (not including) the `boundary_dir`. +/// +/// Note that `boundary_dir` must contain `delete_dir` or an error is returned, otherwise `delete_dir` is returned on success. +pub fn empty_upward_until_boundary<'a>(delete_dir: &'a Path, boundary_dir: &'a Path) -> std::io::Result<&'a Path> { + for item in Iter::new(delete_dir, boundary_dir)? { + match item { + Ok(_dir) => continue, + Err(err) => return Err(err), + } + } + Ok(delete_dir) +} + +/// Delete all empty directories reachable from `delete_dir` from empty leaves moving upward to and including `delete_dir`. +/// +/// If any encountered directory contains a file the entire operation is aborted. +/// Please note that this is inherently racy and no attempts are made to counter that, which will allow creators to win +/// as long as they retry. +pub fn empty_depth_first(delete_dir: impl Into<PathBuf>) -> std::io::Result<()> { + let delete_dir = delete_dir.into(); + if let Ok(()) = std::fs::remove_dir(&delete_dir) { + return Ok(()); + } + + let mut stack = vec![delete_dir]; + let mut next_to_push = Vec::new(); + while let Some(dir_to_delete) = stack.pop() { + let mut num_entries = 0; + for entry in std::fs::read_dir(&dir_to_delete)? { + num_entries += 1; + let entry = entry?; + if entry.file_type()?.is_dir() { + next_to_push.push(entry.path()); + } else { + return Err(std::io::Error::new(std::io::ErrorKind::Other, "Directory not empty")); + } + } + if num_entries == 0 { + std::fs::remove_dir(&dir_to_delete)?; + } else { + stack.push(dir_to_delete); + stack.append(&mut next_to_push); + } + } + Ok(()) +} diff --git a/vendor/gix-tempfile/src/handle.rs b/vendor/gix-tempfile/src/handle.rs new file mode 100644 index 000000000..f20e237ee --- /dev/null +++ b/vendor/gix-tempfile/src/handle.rs @@ -0,0 +1,319 @@ +//! +use std::{io, path::Path}; + +use tempfile::{NamedTempFile, TempPath}; + +use crate::{AutoRemove, ContainingDirectory, ForksafeTempfile, Handle, NEXT_MAP_INDEX, REGISTRY}; + +/// Marker to signal the Registration is an open file able to be written to. +#[derive(Debug)] +pub struct Writable; + +/// Marker to signal the Registration is a closed file that consumes no additional process resources. +/// +/// It can't ever be written to unless reopened after persisting it. +#[derive(Debug)] +pub struct Closed; + +pub(crate) enum Mode { + Writable, + Closed, +} + +/// Utilities +impl Handle<()> { + fn at_path( + path: impl AsRef<Path>, + directory: ContainingDirectory, + cleanup: AutoRemove, + mode: Mode, + ) -> io::Result<usize> { + let path = path.as_ref(); + let tempfile = { + let mut builder = tempfile::Builder::new(); + let dot_ext_storage; + match path.file_stem() { + Some(stem) => builder.prefix(stem), + None => builder.prefix(""), + }; + if let Some(ext) = path.extension() { + dot_ext_storage = format!(".{}", ext.to_string_lossy()); + builder.suffix(&dot_ext_storage); + } + let parent_dir = path.parent().expect("parent directory is present"); + let parent_dir = directory.resolve(parent_dir)?; + ForksafeTempfile::new(builder.rand_bytes(0).tempfile_in(parent_dir)?, cleanup, mode) + }; + let id = NEXT_MAP_INDEX.fetch_add(1, std::sync::atomic::Ordering::SeqCst); + expect_none(REGISTRY.insert(id, Some(tempfile))); + Ok(id) + } + + fn new_writable_inner( + containing_directory: impl AsRef<Path>, + directory: ContainingDirectory, + cleanup: AutoRemove, + mode: Mode, + ) -> io::Result<usize> { + let containing_directory = directory.resolve(containing_directory.as_ref())?; + let id = NEXT_MAP_INDEX.fetch_add(1, std::sync::atomic::Ordering::SeqCst); + expect_none(REGISTRY.insert( + id, + Some(ForksafeTempfile::new( + NamedTempFile::new_in(containing_directory)?, + cleanup, + mode, + )), + )); + Ok(id) + } +} + +/// Creation and ownership transfer +impl Handle<Closed> { + /// Create a registered tempfile at the given `path`, where `path` includes the desired filename and close it immediately. + /// + /// Depending on the `directory` configuration, intermediate directories will be created, and depending on `cleanup` empty + /// intermediate directories will be removed. + pub fn at(path: impl AsRef<Path>, directory: ContainingDirectory, cleanup: AutoRemove) -> io::Result<Self> { + Ok(Handle { + id: Handle::<()>::at_path(path, directory, cleanup, Mode::Closed)?, + _marker: Default::default(), + }) + } + + /// Take ownership of the temporary file path, which deletes it when dropped without persisting it beforehand. + /// + /// It's a theoretical possibility that the file isn't present anymore if signals interfere, hence the `Option` + pub fn take(self) -> Option<TempPath> { + let res = REGISTRY.remove(&self.id); + std::mem::forget(self); + res.and_then(|(_k, v)| v.map(|v| v.into_temppath())) + } +} + +/// Creation and ownership transfer +impl Handle<Writable> { + /// Create a registered tempfile at the given `path`, where `path` includes the desired filename. + /// + /// Depending on the `directory` configuration, intermediate directories will be created, and depending on `cleanup` empty + /// intermediate directories will be removed. + pub fn at(path: impl AsRef<Path>, directory: ContainingDirectory, cleanup: AutoRemove) -> io::Result<Self> { + Ok(Handle { + id: Handle::<()>::at_path(path, directory, cleanup, Mode::Writable)?, + _marker: Default::default(), + }) + } + + /// Create a registered tempfile within `containing_directory` with a name that won't clash, and clean it up as specified with `cleanup`. + /// Control how to deal with intermediate directories with `directory`. + /// The temporary file is opened and can be written to using the [`with_mut()`][Handle::with_mut()] method. + pub fn new( + containing_directory: impl AsRef<Path>, + directory: ContainingDirectory, + cleanup: AutoRemove, + ) -> io::Result<Self> { + Ok(Handle { + id: Handle::<()>::new_writable_inner(containing_directory, directory, cleanup, Mode::Writable)?, + _marker: Default::default(), + }) + } + + /// Take ownership of the temporary file. + /// + /// It's a theoretical possibility that the file isn't present anymore if signals interfere, hence the `Option` + pub fn take(self) -> Option<NamedTempFile> { + let res = REGISTRY.remove(&self.id); + std::mem::forget(self); + res.and_then(|(_k, v)| v.map(|v| v.into_tempfile().expect("correct runtime typing"))) + } + + /// Close the underlying file handle but keep track of the temporary file as before for automatic cleanup. + /// + /// This saves system resources in situations where one opens a tempfile file at a time, writes a new value, and closes + /// it right after to perform more updates of this kind in other tempfiles. When all succeed, they can be renamed one after + /// another. + pub fn close(self) -> std::io::Result<Handle<Closed>> { + match REGISTRY.remove(&self.id) { + Some((id, Some(t))) => { + std::mem::forget(self); + expect_none(REGISTRY.insert(id, Some(t.close()))); + Ok(Handle::<Closed> { + id, + _marker: Default::default(), + }) + } + None | Some((_, None)) => Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + format!("The tempfile with id {} wasn't available anymore", self.id), + )), + } + } +} + +/// Mutation +impl Handle<Writable> { + /// Obtain a mutable handler to the underlying named tempfile and call `f(&mut named_tempfile)` on it. + /// + /// Note that for the duration of the call, a signal interrupting the operation will cause the tempfile not to be cleaned up + /// as it is not visible anymore to the signal handler. + /// + /// # Assumptions + /// The caller must assure that the signal handler for cleanup will be followed by an abort call so that + /// this code won't run again on a removed instance. An error will occur otherwise. + pub fn with_mut<T>(&mut self, once: impl FnOnce(&mut NamedTempFile) -> T) -> std::io::Result<T> { + match REGISTRY.remove(&self.id) { + Some((id, Some(mut t))) => { + let res = once(t.as_mut_tempfile().expect("correct runtime typing")); + expect_none(REGISTRY.insert(id, Some(t))); + Ok(res) + } + None | Some((_, None)) => Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + format!("The tempfile with id {} wasn't available anymore", self.id), + )), + } + } +} + +mod io_impls { + use std::{io, io::SeekFrom}; + + use super::{Handle, Writable}; + + impl io::Write for Handle<Writable> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.with_mut(|f| f.write(buf))? + } + + fn flush(&mut self) -> io::Result<()> { + self.with_mut(|f| f.flush())? + } + } + + impl io::Seek for Handle<Writable> { + fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { + self.with_mut(|f| f.seek(pos))? + } + } + + impl io::Read for Handle<Writable> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + self.with_mut(|f| f.read(buf))? + } + } +} + +/// +pub mod persist { + use std::path::Path; + + use crate::{ + handle::{expect_none, Closed, Writable}, + Handle, REGISTRY, + }; + + mod error { + use std::fmt::{self, Debug, Display}; + + use crate::Handle; + + /// The error returned by various [`persist(…)`][Handle<crate::handle::Writable>::persist()] methods + #[derive(Debug)] + pub struct Error<T: Debug> { + /// The io error that prevented the attempt to succeed + pub error: std::io::Error, + /// The registered handle to the tempfile which couldn't be persisted. + pub handle: Handle<T>, + } + + impl<T: Debug> Display for Error<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(&self.error, f) + } + } + + impl<T: Debug> std::error::Error for Error<T> { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.error.source() + } + } + } + pub use error::Error; + + impl Handle<Writable> { + /// Persist this tempfile to replace the file at the given `path` if necessary, in a way that recovers the original instance + /// on error or returns the open now persisted former tempfile. + /// Note that it might not exist anymore if an interrupt handler managed to steal it and allowed the program to return to + /// its normal flow. + pub fn persist(self, path: impl AsRef<Path>) -> Result<Option<std::fs::File>, Error<Writable>> { + let res = REGISTRY.remove(&self.id); + + match res.and_then(|(_k, v)| v.map(|v| v.persist(path))) { + Some(Ok(Some(file))) => { + std::mem::forget(self); + Ok(Some(file)) + } + None => { + std::mem::forget(self); + Ok(None) + } + Some(Err((err, tempfile))) => { + expect_none(REGISTRY.insert(self.id, Some(tempfile))); + Err(Error::<Writable> { + error: err, + handle: self, + }) + } + Some(Ok(None)) => unreachable!("no open files in an open handle"), + } + } + } + + impl Handle<Closed> { + /// Persist this tempfile to replace the file at the given `path` if necessary, in a way that recovers the original instance + /// on error. + pub fn persist(self, path: impl AsRef<Path>) -> Result<(), Error<Closed>> { + let res = REGISTRY.remove(&self.id); + + match res.and_then(|(_k, v)| v.map(|v| v.persist(path))) { + None | Some(Ok(None)) => { + std::mem::forget(self); + Ok(()) + } + Some(Err((err, tempfile))) => { + expect_none(REGISTRY.insert(self.id, Some(tempfile))); + Err(Error::<Closed> { + error: err, + handle: self, + }) + } + Some(Ok(Some(_file))) => unreachable!("no open files in a closed handle"), + } + } + } +} + +impl ContainingDirectory { + fn resolve(self, dir: &Path) -> std::io::Result<&Path> { + match self { + ContainingDirectory::Exists => Ok(dir), + ContainingDirectory::CreateAllRaceProof(retries) => crate::create_dir::all(dir, retries), + } + } +} + +fn expect_none<T>(v: Option<T>) { + assert!( + v.is_none(), + "there should never be conflicts or old values as ids are never reused." + ); +} + +impl<T: std::fmt::Debug> Drop for Handle<T> { + fn drop(&mut self) { + if let Some((_id, Some(tempfile))) = REGISTRY.remove(&self.id) { + tempfile.drop_impl(); + } + } +} diff --git a/vendor/gix-tempfile/src/lib.rs b/vendor/gix-tempfile/src/lib.rs new file mode 100644 index 000000000..8585c60b7 --- /dev/null +++ b/vendor/gix-tempfile/src/lib.rs @@ -0,0 +1,216 @@ +//! git-style registered tempfiles that are removed upon typical termination signals. +//! +//! To register signal handlers in a typical application that doesn't have its own, call +//! [`gix_tempfile::signal::setup(Default::default())`][signal::setup()] before creating the first tempfile. +//! +//! Signal handlers are powered by [`signal-hook`] to get notified when the application is told to shut down +//! to assure tempfiles are deleted. The deletion is filtered by process id to allow forks to have their own +//! set of tempfiles that won't get deleted when the parent process exits. +//! +//! ### Initial Setup +//! +//! As no handlers for `TERMination` are installed, it is required to call [`signal::setup()`] before creating the first tempfile. +//! This also allows to control how `git-tempfiles` integrates with other handlers under application control. +//! +//! As a general rule of thumb, use `Default::default()` as argument to emulate the default behaviour and +//! abort the process after cleaning temporary files. Read more about options in [signal::handler::Mode]. +//! +//! # Limitations +//! +//! ## Tempfiles might remain on disk +//! +//! * Uninterruptible signals are received like `SIGKILL` +//! * The application is performing a write operation on the tempfile when a signal arrives, preventing this tempfile to be removed, +//! but not others. Any other operation dealing with the tempfile suffers from the same issue. +//! +//! [signal-hook]: https://docs.rs/signal-hook +//! +//! ## 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)] + +use std::{ + io, + marker::PhantomData, + path::{Path, PathBuf}, + sync::atomic::AtomicUsize, +}; + +use once_cell::sync::Lazy; + +#[cfg(feature = "hp-hashmap")] +type HashMap<K, V> = dashmap::DashMap<K, V>; + +#[cfg(not(feature = "hp-hashmap"))] +mod hashmap { + use parking_lot::Mutex; + use std::collections::HashMap; + + // TODO(performance): use the `gix-hashtable` slot-map once available. It seems quite fast already though, so experiment. + pub struct Concurrent<K, V> { + inner: Mutex<HashMap<K, V>>, + } + + impl<K, V> Default for Concurrent<K, V> + where + K: Eq + std::hash::Hash, + { + fn default() -> Self { + Concurrent { + inner: Default::default(), + } + } + } + + impl<K, V> Concurrent<K, V> + where + K: Eq + std::hash::Hash + Clone, + { + pub fn insert(&self, key: K, value: V) -> Option<V> { + self.inner.lock().insert(key, value) + } + + pub fn remove(&self, key: &K) -> Option<(K, V)> { + self.inner.lock().remove(key).map(|v| (key.clone(), v)) + } + + pub fn for_each<F>(&self, cb: F) + where + Self: Sized, + F: FnMut(&mut V), + { + if let Some(mut guard) = self.inner.try_lock() { + guard.values_mut().for_each(cb); + } + } + } +} + +#[cfg(not(feature = "hp-hashmap"))] +type HashMap<K, V> = hashmap::Concurrent<K, V>; + +mod fs; +pub use fs::{create_dir, remove_dir}; + +#[cfg(feature = "signals")] +/// signal setup and reusable handlers. +pub mod signal; + +mod forksafe; +use forksafe::ForksafeTempfile; + +pub mod handle; +use crate::handle::{Closed, Writable}; + +/// +pub mod registry; + +static NEXT_MAP_INDEX: AtomicUsize = AtomicUsize::new(0); +static REGISTRY: Lazy<HashMap<usize, Option<ForksafeTempfile>>> = Lazy::new(|| { + #[cfg(feature = "signals")] + if signal::handler::MODE.load(std::sync::atomic::Ordering::SeqCst) != signal::handler::Mode::None as usize { + for sig in signal_hook::consts::TERM_SIGNALS { + // SAFETY: handlers are considered unsafe because a lot can go wrong. See `cleanup_tempfiles()` for details on safety. + #[allow(unsafe_code)] + unsafe { + #[cfg(not(windows))] + { + signal_hook_registry::register_sigaction(*sig, signal::handler::cleanup_tempfiles_nix) + } + #[cfg(windows)] + { + signal_hook::low_level::register(*sig, signal::handler::cleanup_tempfiles_windows) + } + } + .expect("signals can always be installed"); + } + } + HashMap::default() +}); + +/// A type expressing the ways we can deal with directories containing a tempfile. +#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)] +pub enum ContainingDirectory { + /// Assume the directory for the tempfile exists and cause failure if it doesn't + Exists, + /// Create the directory recursively with the given amount of retries in a way that is somewhat race resistant + /// depending on the amount of retries. + CreateAllRaceProof(create_dir::Retries), +} + +/// A type expressing the ways we cleanup after ourselves to remove resources we created. +/// Note that cleanup has no effect if the tempfile is persisted. +#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)] +pub enum AutoRemove { + /// Remove the temporary file after usage if it wasn't persisted. + Tempfile, + /// Remove the temporary file as well the containing directories if they are empty until the given `directory`. + TempfileAndEmptyParentDirectoriesUntil { + /// The directory which shall not be removed even if it is empty. + boundary_directory: PathBuf, + }, +} + +impl AutoRemove { + fn execute_best_effort(self, directory_to_potentially_delete: &Path) -> Option<PathBuf> { + match self { + AutoRemove::Tempfile => None, + AutoRemove::TempfileAndEmptyParentDirectoriesUntil { boundary_directory } => { + remove_dir::empty_upward_until_boundary(directory_to_potentially_delete, &boundary_directory).ok(); + Some(boundary_directory) + } + } + } +} + +/// A registered temporary file which will delete itself on drop or if the program is receiving signals that +/// should cause it to terminate. +/// +/// # Note +/// +/// Signals interrupting the calling thread right after taking ownership of the registered tempfile +/// will cause all but this tempfile to be removed automatically. In the common case it will persist on disk as destructors +/// were not called or didn't get to remove the file. +/// +/// In the best case the file is a true temporary with a non-clashing name that 'only' fills up the disk, +/// in the worst case the temporary file is used as a lock file which may leave the repository in a locked +/// state forever. +/// +/// This kind of raciness exists whenever [`take()`][Handle::take()] is used and can't be circumvented. +#[derive(Debug)] +#[must_use = "A handle that is immediately dropped doesn't lock a resource meaningfully"] +pub struct Handle<Marker: std::fmt::Debug> { + id: usize, + _marker: PhantomData<Marker>, +} + +/// A shortcut to [`Handle::<Writable>::new()`], creating a writable temporary file with non-clashing name in a directory. +pub fn new( + containing_directory: impl AsRef<Path>, + directory: ContainingDirectory, + cleanup: AutoRemove, +) -> io::Result<Handle<Writable>> { + Handle::<Writable>::new(containing_directory, directory, cleanup) +} + +/// A shortcut to [`Handle::<Writable>::at()`] providing a writable temporary file at the given path. +pub fn writable_at( + path: impl AsRef<Path>, + directory: ContainingDirectory, + cleanup: AutoRemove, +) -> io::Result<Handle<Writable>> { + Handle::<Writable>::at(path, directory, cleanup) +} + +/// A shortcut to [`Handle::<Closed>::at()`] providing a closed temporary file to mark the presence of something. +pub fn mark_at( + path: impl AsRef<Path>, + directory: ContainingDirectory, + cleanup: AutoRemove, +) -> io::Result<Handle<Closed>> { + Handle::<Closed>::at(path, directory, cleanup) +} diff --git a/vendor/gix-tempfile/src/registry.rs b/vendor/gix-tempfile/src/registry.rs new file mode 100644 index 000000000..9eaab23a6 --- /dev/null +++ b/vendor/gix-tempfile/src/registry.rs @@ -0,0 +1,67 @@ +use crate::REGISTRY; + +/// Remove all tempfiles still registered on our global registry, and leak their data to be signal-safe. +/// This happens on a best-effort basis with all errors being ignored. +/// +/// # Safety +/// Note that Mutexes of any kind are not allowed, and so aren't allocation or deallocation of memory. +/// We are using lock-free datastructures and sprinkle in `std::mem::forget` to avoid deallocating. +/// Most importantly, we use `try_lock()` which uses an atomic int only without blocking, making our register method safe to use, +/// at the expense of possibly missing a lock file if another thread wants to obtain it or put it back +/// (i.e. mutates the registry shard). +pub fn cleanup_tempfiles_signal_safe() { + let current_pid = std::process::id(); + #[cfg(feature = "hp-hashmap")] + { + use crate::NEXT_MAP_INDEX; + use std::sync::atomic::Ordering; + + let one_past_last_index = NEXT_MAP_INDEX.load(Ordering::SeqCst); + for idx in 0..one_past_last_index { + if let Some(entry) = REGISTRY.try_entry(idx) { + entry.and_modify(|tempfile| { + if tempfile + .as_ref() + .map_or(false, |tf| tf.owning_process_id == current_pid) + { + if let Some(tempfile) = tempfile.take() { + tempfile.drop_without_deallocation(); + } + } + }); + } + } + } + #[cfg(not(feature = "hp-hashmap"))] + { + REGISTRY.for_each(|tf| { + if tf.as_ref().map_or(false, |tf| tf.owning_process_id == current_pid) { + if let Some(tf) = tf.take() { + tf.drop_without_deallocation(); + } + } + }); + } +} + +/// Remove all tempfiles still registered on our global registry. +/// This happens on a best-effort basis with all errors being ignored. +/// +/// # Note +/// +/// Must not be called from within signal hooks. For that, use [`cleanup_tempfiles_signal_safe()`]. +pub fn cleanup_tempfiles() { + let current_pid = std::process::id(); + #[cfg(feature = "hp-hashmap")] + REGISTRY.iter_mut().for_each(|mut tf| { + if tf.as_ref().map_or(false, |tf| tf.owning_process_id == current_pid) { + tf.take(); + } + }); + #[cfg(not(feature = "hp-hashmap"))] + REGISTRY.for_each(|tf| { + if tf.as_ref().map_or(false, |tf| tf.owning_process_id == current_pid) { + tf.take(); + } + }); +} diff --git a/vendor/gix-tempfile/src/signal.rs b/vendor/gix-tempfile/src/signal.rs new file mode 100644 index 000000000..3e0e7729c --- /dev/null +++ b/vendor/gix-tempfile/src/signal.rs @@ -0,0 +1,100 @@ +use crate::REGISTRY; +use once_cell::sync::Lazy; + +/// Initialize signal handlers and other state to keep track of tempfiles, and **must be called before the first tempfile is created**, +/// allowing to set the `mode` in which signal handlers are installed. +/// +/// Only has an effect the first time it is called. +/// +/// Note that it is possible to not call this function and instead call +/// [registry::cleanup_tempfiles_signal_safe()][crate::registry::cleanup_tempfiles_signal_safe()] +/// from a signal handler under the application's control. +pub fn setup(mode: handler::Mode) { + handler::MODE.store(mode as usize, std::sync::atomic::Ordering::SeqCst); + Lazy::force(®ISTRY); +} + +/// +pub mod handler { + use std::sync::atomic::AtomicUsize; + + pub(crate) static MODE: AtomicUsize = AtomicUsize::new(Mode::None as usize); + + /// Define how our signal handlers act + #[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)] + pub enum Mode { + /// Do not install a signal handler at all, but have somebody else call our handler directly. + None = 0, + /// Delete all remaining registered tempfiles on termination. + DeleteTempfilesOnTermination = 1, + /// Delete all remaining registered tempfiles on termination and emulate the default handler behaviour. + /// + /// This typically leads to the process being aborted. + DeleteTempfilesOnTerminationAndRestoreDefaultBehaviour = 2, + } + + impl Default for Mode { + /// By default we will emulate the default behaviour and abort the process. + /// + /// While testing, we will not abort the process. + fn default() -> Self { + if cfg!(test) { + Mode::DeleteTempfilesOnTermination + } else { + Mode::DeleteTempfilesOnTerminationAndRestoreDefaultBehaviour + } + } + } + + /// On linux we can handle the actual signal as we know it. + #[cfg(not(windows))] + pub(crate) fn cleanup_tempfiles_nix(sig: &libc::siginfo_t) { + crate::registry::cleanup_tempfiles_signal_safe(); + let restore_original_behaviour = Mode::DeleteTempfilesOnTerminationAndRestoreDefaultBehaviour as usize; + if MODE.load(std::sync::atomic::Ordering::SeqCst) == restore_original_behaviour { + signal_hook::low_level::emulate_default_handler(sig.si_signo).ok(); + } + } + + /// On windows, assume sig-term and emulate sig-term unconditionally. + #[cfg(windows)] + pub(crate) fn cleanup_tempfiles_windows() { + crate::registry::cleanup_tempfiles_signal_safe(); + let restore_original_behaviour = Mode::DeleteTempfilesOnTerminationAndRestoreDefaultBehaviour as usize; + if MODE.load(std::sync::atomic::Ordering::SeqCst) == restore_original_behaviour { + signal_hook::low_level::emulate_default_handler(signal_hook::consts::SIGTERM).ok(); + } + } + + #[cfg(test)] + mod tests { + use std::path::Path; + + use crate::{AutoRemove, ContainingDirectory}; + + fn filecount_in(path: impl AsRef<Path>) -> usize { + std::fs::read_dir(path).expect("valid dir").count() + } + + #[test] + fn various_termination_signals_remove_tempfiles_unconditionally() -> Result<(), Box<dyn std::error::Error>> { + crate::signal::setup(Default::default()); + let dir = tempfile::tempdir()?; + for sig in signal_hook::consts::TERM_SIGNALS { + let _tempfile = crate::new(dir.path(), ContainingDirectory::Exists, AutoRemove::Tempfile)?; + assert_eq!( + filecount_in(dir.path()), + 1, + "only one tempfile exists no matter the iteration" + ); + signal_hook::low_level::raise(*sig)?; + assert_eq!( + filecount_in(dir.path()), + 0, + "the signal triggers removal but won't terminate the process (anymore)" + ); + } + Ok(()) + } + } +} |