summaryrefslogtreecommitdiffstats
path: root/vendor/gix-refspec
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
commit10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch)
treebdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/gix-refspec
parentReleasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff)
downloadrustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz
rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix-refspec')
-rw-r--r--vendor/gix-refspec/.cargo-checksum.json1
-rw-r--r--vendor/gix-refspec/CHANGELOG.md511
-rw-r--r--vendor/gix-refspec/Cargo.toml51
-rw-r--r--vendor/gix-refspec/README.md11
-rw-r--r--vendor/gix-refspec/src/instruction.rs68
-rw-r--r--vendor/gix-refspec/src/lib.rs39
-rw-r--r--vendor/gix-refspec/src/match_group/mod.rs112
-rw-r--r--vendor/gix-refspec/src/match_group/types.rs104
-rw-r--r--vendor/gix-refspec/src/match_group/util.rs162
-rw-r--r--vendor/gix-refspec/src/match_group/validate.rs141
-rw-r--r--vendor/gix-refspec/src/parse.rs255
-rw-r--r--vendor/gix-refspec/src/spec.rs257
-rw-r--r--vendor/gix-refspec/src/types.rs21
-rw-r--r--vendor/gix-refspec/src/write.rs74
14 files changed, 1807 insertions, 0 deletions
diff --git a/vendor/gix-refspec/.cargo-checksum.json b/vendor/gix-refspec/.cargo-checksum.json
new file mode 100644
index 000000000..9024c8d9e
--- /dev/null
+++ b/vendor/gix-refspec/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"b0693420b49e9c32ee14d249c7d1b434e14b137d59b3517a585881799b7e30e1","Cargo.toml":"8581b00d978480f6bfef66106a7aeba52ee50c83f9261242ccf26180b674a30c","README.md":"1b08787d12bb32a8b5a3a48c3198435d9691d15c3b623727a6ff6188b4106d65","src/instruction.rs":"a1f989da75ad1cb774171c905241f541ca2a68f2b365f54dd3cf3f247615caa4","src/lib.rs":"493fe85e248c19665667a44d445314c4536fe197eafac92c65e12d2a9ded44f6","src/match_group/mod.rs":"256a496434ab4d1723611fd19f3b4f81d780e0a1b92ee6878450cba73068737c","src/match_group/types.rs":"a3e0bb1d555955e9415c26b011cc0e84f8b07166479ae09861dc988d453476e5","src/match_group/util.rs":"4b325f879883244c0692cdc2c43674cc1e69574b542bcccaba93dea3e4c62e64","src/match_group/validate.rs":"1203deb9a0d2e81ba6eb6f28f5d2249bac8f88482e7db42d824331b679083254","src/parse.rs":"956f2894ad2ff345f1e55e80e67eb552eda2dc61b7e7f1f72ecf4ed15a2c9da3","src/spec.rs":"99c52b4c52074555a9932beb1f992d540e640375bdc36cf2cb84fdb048aa4b6f","src/types.rs":"af5efab6fc8179262d0a368f72624efe68f48dec7afb74f2e7ef932f140d42ff","src/write.rs":"1871ac43652b6ae6b5b453f7d79d88f4652294937d005e20227be8660d2e551f"},"package":"aba332462bda2e8efeae4302b39a6ed01ad56ef772fd5b7ef197cf2798294d65"} \ No newline at end of file
diff --git a/vendor/gix-refspec/CHANGELOG.md b/vendor/gix-refspec/CHANGELOG.md
new file mode 100644
index 000000000..e7e8b57db
--- /dev/null
+++ b/vendor/gix-refspec/CHANGELOG.md
@@ -0,0 +1,511 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## 0.9.0 (2023-03-04)
+
+A maintenance release without user-facing changes.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 2 commits contributed to the release.
+ - 3 days passed between releases.
+ - 0 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Prepare changelogs prior to release ([`895e482`](https://github.com/Byron/gitoxide/commit/895e482badf01e953bb9144001eebd5e1b1c4d84))
+ - Release gix-features v0.28.0, gix-actor v0.19.0, gix-object v0.28.0, gix-diff v0.28.0, gix-traverse v0.24.0, gix-pack v0.32.0, safety bump 20 crates ([`0f411e9`](https://github.com/Byron/gitoxide/commit/0f411e93ec812592bb9d3a52b751399dd86f76f7))
+</details>
+
+## 0.8.0 (2023-03-01)
+
+A maintenance release without user-facing changes.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 4 commits contributed to the release.
+ - 8 days passed between releases.
+ - 0 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-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))
+ - Release gix-features v0.27.0, gix-actor v0.18.0, gix-quote v0.4.3, gix-attributes v0.9.0, gix-object v0.27.0, gix-ref v0.25.0, gix-config v0.17.0, gix-url v0.14.0, gix-credentials v0.10.0, gix-diff v0.27.0, gix-discover v0.14.0, gix-hashtable v0.1.2, gix-bitmap v0.2.2, gix-traverse v0.23.0, gix-index v0.13.0, gix-mailmap v0.10.0, gix-pack v0.31.0, gix-odb v0.41.0, gix-transport v0.26.0, gix-protocol v0.27.0, gix-revision v0.11.0, gix-refspec v0.8.0, gix-worktree v0.13.0, gix v0.38.0 ([`e6cc618`](https://github.com/Byron/gitoxide/commit/e6cc6184a7a49dbc2503c1c1bdd3688ca5cec5fe))
+ - Adjust manifests prior to release ([`addd789`](https://github.com/Byron/gitoxide/commit/addd78958fdd1e54eb702854e96079539d01965a))
+ - Prepare changelogs prior to release ([`94c99c7`](https://github.com/Byron/gitoxide/commit/94c99c71520f33269cc8dbc26f82a74747cc7e16))
+</details>
+
+## 0.7.3 (2023-02-20)
+
+### Bug Fixes
+
+ - <csr-id-135d317065aae87af302beb6c26bb6ca8e30b6aa/> compatibility with `bstr` v1.3, use `*.as_bytes()` instead of `.as_ref()`.
+ `as_ref()` relies on a known target type which isn't always present. However, once
+ there is only one implementation, that's no problem, but when that changes compilation
+ fails due to ambiguity.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 2 commits contributed to the release.
+ - 3 days passed between releases.
+ - 1 commit was understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-date v0.4.3, gix-hash v0.10.3, gix-features v0.26.5, gix-actor v0.17.2, gix-glob v0.5.5, gix-path v0.7.2, gix-quote v0.4.2, gix-attributes v0.8.3, gix-validate v0.7.3, gix-object v0.26.2, gix-ref v0.24.1, gix-config v0.16.2, gix-command v0.2.4, gix-url v0.13.3, gix-credentials v0.9.2, gix-discover v0.13.1, gix-index v0.12.4, gix-mailmap v0.9.3, gix-pack v0.30.3, gix-packetline v0.14.3, gix-transport v0.25.6, gix-protocol v0.26.4, gix-revision v0.10.4, gix-refspec v0.7.3, gix-worktree v0.12.3, gix v0.36.1 ([`9604783`](https://github.com/Byron/gitoxide/commit/96047839a20a657a559376b0b14c65aeab96acbd))
+ - Compatibility with `bstr` v1.3, use `*.as_bytes()` instead of `.as_ref()`. ([`135d317`](https://github.com/Byron/gitoxide/commit/135d317065aae87af302beb6c26bb6ca8e30b6aa))
+</details>
+
+## 0.7.2 (2023-02-17)
+
+<csr-id-f7f136dbe4f86e7dee1d54835c420ec07c96cd78/>
+<csr-id-533e887e80c5f7ede8392884562e1c5ba56fb9a8/>
+
+### 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.
+
+### Changed (BREAKING)
+
+ - <csr-id-2a0a87a04e7b4d6ed3be3d8adc89917576727686/> remove lifetime of `match_group::Fix`, keeping `RefSpec` instances instead
+ That lifetime unnecessarily complicated things and wasn't worth keeping
+ due to being a premature optimization.
+ - <csr-id-4c4f82170d08b910a7f64482431c99956b1a04c3/> reject all invalid negative refspec patterns.
+ Git is more lenient, but will then fail to match against such patterns
+ which seems like avoidable surprising behaviour.
+ - <csr-id-99905bacace8aed42b16d43f0f04cae996cb971c/> upgrade `bstr` to `1.0.1`
+
+### New Features
+
+ - <csr-id-21b21b6c25e1d8d1da9464b7bef06a795f679210/> add `RefSpecRef::expand_prefix()` method to avoid missing prefixes.
+ The current implementation might cause refspecs to end up ignored as
+ they don't have a prefix, and in protocol V2 it would then fail
+ to add a ref-spec filter which causes them to be missed.
+
+ With `expand_prefix()`, we assure that there are all possible prefixes
+ that can contain partial names, similar to what git does.
+ - <csr-id-d7f63a6c60a826dc862bd13adbef041e4ac6d8ab/> `RefSpec::allow_non_fast_forward()` to get information about 'force' quickly.
+ - <csr-id-6df179b5cf831402444cc78429a57f835358376e/> `RefSpecRef::prefix()` to return the two-component prefix of a refspec's source. #(450)
+ - <csr-id-abdf83f494e2a9fba4a8d9fcb776f2c84baebd3e/> Simple serialization for `Instruction` and `RefSpecRef` type.
+ It's also a way to normalize input strings as there is only one way
+ to serialize instructions, which themselves are already normalized
+ towards what's possible.
+
+### Chore
+
+ - <csr-id-f7f136dbe4f86e7dee1d54835c420ec07c96cd78/> uniformize deny attributes
+ - <csr-id-533e887e80c5f7ede8392884562e1c5ba56fb9a8/> remove default link to cargo doc everywhere
+
+### Documentation
+
+ - <csr-id-39ed9eda62b7718d5109135e5ad406fb1fe2978c/> fix typos
+
+### Bug Fixes
+
+ - <csr-id-d34292294a0c41991aebd5af46e7bd7e3ad7324d/> Fixes build for parsing fuzz harness
+ - <csr-id-d53ddcde948cfbd7773eb830cbb636626b32debb/> `HEAD` may now return itself as prefix in `RefSpecRef::prefix()` and `expanded_prefix()`.
+ Previously, the expanded prefix would be a list of possibilities, even
+ though it's such a common case that we really want to avoid spamming the
+ remote about it when asking for HEAD during clone for instance.
+ - <csr-id-278ff7a6ee084ea864193a5ca25b6cd0f18e19a0/> `RefSpecRef` instruction uses the correct lifetime.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 234 commits contributed to the release over the course of 196 calendar days.
+ - 14 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 5 unique issues were worked on: [#450](https://github.com/Byron/gitoxide/issues/450), [#470](https://github.com/Byron/gitoxide/issues/470), [#571](https://github.com/Byron/gitoxide/issues/571), [#691](https://github.com/Byron/gitoxide/issues/691), [#XXX](https://github.com/Byron/gitoxide/issues/XXX)
+
+### Thanks Clippy
+
+<csr-read-only-do-not-edit/>
+
+[Clippy](https://github.com/rust-lang/rust-clippy) helped 10 times to make code idiomatic.
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **[#450](https://github.com/Byron/gitoxide/issues/450)**
+ - Improve docs for `Instruction` ([`911f68f`](https://github.com/Byron/gitoxide/commit/911f68fe099e3eac7dd4a0f15fcd682657564389))
+ - `HEAD` may now return itself as prefix in `RefSpecRef::prefix()` and `expanded_prefix()`. ([`d53ddcd`](https://github.com/Byron/gitoxide/commit/d53ddcde948cfbd7773eb830cbb636626b32debb))
+ - Fix docs ([`9d0f31e`](https://github.com/Byron/gitoxide/commit/9d0f31e4bea4b47f1a91fa4dc38f592bdbf976a8))
+ - Add `RefSpecRef::expand_prefix()` method to avoid missing prefixes. ([`21b21b6`](https://github.com/Byron/gitoxide/commit/21b21b6c25e1d8d1da9464b7bef06a795f679210))
+ - `RefSpec::allow_non_fast_forward()` to get information about 'force' quickly. ([`d7f63a6`](https://github.com/Byron/gitoxide/commit/d7f63a6c60a826dc862bd13adbef041e4ac6d8ab))
+ - `RefSpecRef` instruction uses the correct lifetime. ([`278ff7a`](https://github.com/Byron/gitoxide/commit/278ff7a6ee084ea864193a5ca25b6cd0f18e19a0))
+ - A more efficient representation for `validate::Fix` ([`e819fc6`](https://github.com/Byron/gitoxide/commit/e819fc68531e2d2de3d7df782f63f84941eeef57))
+ - Make `specs` in `MatchGroup` public to reduce API surface. ([`2a7df32`](https://github.com/Byron/gitoxide/commit/2a7df323b15678aee3e61a41908aceb644873b11))
+ - Allow `match_group::Fix` to be cloned. ([`85c49ec`](https://github.com/Byron/gitoxide/commit/85c49ec16ac7eeb2175fa43545c72b81da693ab1))
+ - Fix `match_group::Item` to make it uniform with how we typically name refs ([`21420da`](https://github.com/Byron/gitoxide/commit/21420dacb485795e80baabf2a300ff900036ba7b))
+ - Remote todo with note about our current understanding ([`9dc7a3f`](https://github.com/Byron/gitoxide/commit/9dc7a3f40dbf3d4802ed095fc21dfb3da67acfea))
+ - Actually assure we don't try to write into the HEAD ref, which git avoids as well ([`1335618`](https://github.com/Byron/gitoxide/commit/13356184c735d72edb891d64b3de1bb5c981a6ad))
+ - Allow 'HEAD' based refspecs to match correctly ([`7432a2b`](https://github.com/Byron/gitoxide/commit/7432a2bb5d11e9991ed5f9d1b29ecf79b10c676a))
+ - Tests to show that empty remotes actually work ([`2fdec73`](https://github.com/Byron/gitoxide/commit/2fdec7315a65117095f909b4d7d57a91ba666a43))
+ - Another test which doesn't manage to trigger a certain message from git. ([`4f48095`](https://github.com/Byron/gitoxide/commit/4f48095566fc1e2b440d542ef2c5118c3e37fddd))
+ - Fully drop 'funny' names ([`f137d60`](https://github.com/Byron/gitoxide/commit/f137d6010610d98de32edb4501053d7786181217))
+ - A first version of the 'funny name' sanitization ([`c81e418`](https://github.com/Byron/gitoxide/commit/c81e418ae7f90b674ad005e4b42816c35332a417))
+ - Frame for testing of fixes ([`9148102`](https://github.com/Byron/gitoxide/commit/91481020c87cfa0cae9dd497fb87e7fb9dd33c8a))
+ - Refactor ([`d37fd04`](https://github.com/Byron/gitoxide/commit/d37fd044df2cc5355735121e63fcc3c54b8ea4cb))
+ - All baseline specs are tested and pass ([`afc0a3d`](https://github.com/Byron/gitoxide/commit/afc0a3da864362ec7a0ab243f72daba4713db569))
+ - The first test to validate conflict reporting ([`aef0a46`](https://github.com/Byron/gitoxide/commit/aef0a464811ce98e81d44d1417098c9adef035f5))
+ - Sketch of validation API along with test suite integration ([`70a765e`](https://github.com/Byron/gitoxide/commit/70a765e295295f87f8550453452d2ffe95b177be))
+ - Refactor ([`547129e`](https://github.com/Byron/gitoxide/commit/547129e98dfcac32ebc83e743f9aee05d038629b))
+ - Sketch `Outcome` type which can be used for later sanitization and validation. ([`53e17c1`](https://github.com/Byron/gitoxide/commit/53e17c10f663bc3c389a13cdfec3716da34dd311))
+ - Prepare first test for conflicts and validation ([`508a33a`](https://github.com/Byron/gitoxide/commit/508a33a5f279c9a6f29e98f560fcd54cea1ed77d))
+ - Just-in-time deduplication of mappings ([`8ed5d01`](https://github.com/Byron/gitoxide/commit/8ed5d01a75ceb03083b2bddc58b1e9dc26a66cd0))
+ - Adjust expectations to make first exclusion tests work ([`6e1b19b`](https://github.com/Byron/gitoxide/commit/6e1b19b7f07050c3fcb70187a4d6a4e4210d3343))
+ - Reject all invalid negative refspec patterns. ([`4c4f821`](https://github.com/Byron/gitoxide/commit/4c4f82170d08b910a7f64482431c99956b1a04c3))
+ - Basic negation implementation along with first failure. ([`e4931d0`](https://github.com/Byron/gitoxide/commit/e4931d0205c9b8e8e859e8ea940b67483e62a07e))
+ - First tests for multiple refspecs ([`77db112`](https://github.com/Byron/gitoxide/commit/77db1127a8ccd71c75670b5d803cabcf93cbcedc))
+ - Refactor ([`4c73a19`](https://github.com/Byron/gitoxide/commit/4c73a19ae4b044df816e95a4fc19dc6481222a4c))
+ - Refactor ([`00401be`](https://github.com/Byron/gitoxide/commit/00401bef4279d4b8152ea4c149a00ddf50f518e3))
+ - Improved glob matching ([`eaf36e7`](https://github.com/Byron/gitoxide/commit/eaf36e7d0336be8398d0b1d9414d3ad73afbb393))
+ - Basic glob matching. ([`a93628c`](https://github.com/Byron/gitoxide/commit/a93628cb404987c498779b35994db0a05b3dbc0a))
+ - Type-system supprots glob matching ([`4b73d11`](https://github.com/Byron/gitoxide/commit/4b73d11a4f0bef8db374cde567547a9ba7097719))
+ - More tests for simple 1:1 fetch and update specs ([`74de83c`](https://github.com/Byron/gitoxide/commit/74de83cbea30b84136bfa191f471e137ae7af5c3))
+ - Make it easy to obtain the local and remote sides of RefSpecs ([`67506b1`](https://github.com/Byron/gitoxide/commit/67506b1b1997c2b5951f0e1320b0459eac1366e2))
+ - Don't reject object-id like heads on the receiving side. ([`6668c3f`](https://github.com/Byron/gitoxide/commit/6668c3f418663ed6f2ed56efd3d7e78d27124296))
+ - Make object-ids in the source position type-safe ([`413051d`](https://github.com/Byron/gitoxide/commit/413051d03c843c9c99dbc67f4a5f48d6f2b1aeb2))
+ - Prepare for dual-sided ref mapping to realize that it needs a special case. ([`7368fe4`](https://github.com/Byron/gitoxide/commit/7368fe4ee38bbd34bd811310afa8eeb78c475fda))
+ - Refactor ([`579e891`](https://github.com/Byron/gitoxide/commit/579e89188679942508f9da107d856ab782a512a1))
+ - Support testing source-only object names ([`bb61c49`](https://github.com/Byron/gitoxide/commit/bb61c49a9b6a3a109d7af3ddde43fc98bb712ec7))
+ - Preliminary matching of refs by name ([`426107f`](https://github.com/Byron/gitoxide/commit/426107fea911a2f75d3b624a1c7279cac4edc12e))
+ - Handle partial names as well ([`dc7f162`](https://github.com/Byron/gitoxide/commit/dc7f1620cb6d00af60cf78e02b4c2949a3e260e4))
+ - Generalize baseline assertion to support multiple input specs ([`b752e48`](https://github.com/Byron/gitoxide/commit/b752e48b4201c1f26401af39de0a7312b158607b))
+ - First successful test ([`3625d5a`](https://github.com/Byron/gitoxide/commit/3625d5a0abb109270b046e2dc206d6f870164306))
+ - Top-level match-group loop without negation ([`c915a5f`](https://github.com/Byron/gitoxide/commit/c915a5f5f0d771e704b108b9442a605d62f0945e))
+ - Refactor to use a match-group instead. ([`4ba31c5`](https://github.com/Byron/gitoxide/commit/4ba31c55b57f644361e18e5d31d5df514cddd58a))
+ - Not using a matchgroup right away seems like the wrong approach ([`7f3bc30`](https://github.com/Byron/gitoxide/commit/7f3bc300dfb980d6e6aa72f8c22edd58fa9351fb))
+ - Actual expectation for first simple test ([`cec6905`](https://github.com/Byron/gitoxide/commit/cec69057585796ec7bc69f5a6295b97cddb8cb4f))
+ - Get to the point where the matcher is invoked ([`cbbdf59`](https://github.com/Byron/gitoxide/commit/cbbdf59290d6c3fb4936b31e3b7836becb126ce4))
+ - Simple serialization for `Instruction` and `RefSpecRef` type. ([`abdf83f`](https://github.com/Byron/gitoxide/commit/abdf83f494e2a9fba4a8d9fcb776f2c84baebd3e))
+ - Ground work for matcher tests ([`509764c`](https://github.com/Byron/gitoxide/commit/509764c95978115da129b8bb9baeb304634fa10c))
+ - Tag specific tests ([`4f35485`](https://github.com/Byron/gitoxide/commit/4f354852e15b469260bd3553e4f615f9612fabcc))
+ - More tests to investigate conflict handling ([`192d4f7`](https://github.com/Byron/gitoxide/commit/192d4f78ba611f090dafda7ef5014efb900d2115))
+ - A more realistic sketch for `Matcher`, which will need a surrounding `MatchGroup` ([`dd1d824`](https://github.com/Byron/gitoxide/commit/dd1d8244c8708bbc3583cc0f3f42ad967d5ad524))
+ - More robust baseline tests on windows ([`54ca267`](https://github.com/Byron/gitoxide/commit/54ca267138a5116aa2215109b4abe00a64518feb))
+ - Pares FETCH_HEAD (as specs without local sides); sketch `Match` type ([`44228a0`](https://github.com/Byron/gitoxide/commit/44228a0b9c057bcc915bc0ade43b4ccb3cb916f2))
+ - Restore full ref names for baseline ([`f6124db`](https://github.com/Byron/gitoxide/commit/f6124db39dc0e828801a59310265d95a755ea46a))
+ - Parse basline mapping ([`3000a14`](https://github.com/Byron/gitoxide/commit/3000a14c1eed4a543fdef2fd8bcbacba2742aece))
+ - Parse baseline reflist which serves as input to the matcher ([`fce877f`](https://github.com/Byron/gitoxide/commit/fce877f8d2112fafdb71208784104a66b2313a40))
+ - Frame for baseline for fetch-matching ([`2569da5`](https://github.com/Byron/gitoxide/commit/2569da5988a055372a1b85660f93185603900dbe))
+ - Upgrade `bstr` to `1.0.1` ([`99905ba`](https://github.com/Byron/gitoxide/commit/99905bacace8aed42b16d43f0f04cae996cb971c))
+ - Prefer to represent instructions with Matchers ([`0887e2e`](https://github.com/Byron/gitoxide/commit/0887e2e0b7ebdcad30606a2633794ac8ff586091))
+ - More examples using fully spelled out object names as fetch destination ([`095a099`](https://github.com/Byron/gitoxide/commit/095a09918dc080ba7794c6ff13db0ef0ead20d0d))
+ - Get more clarity about `git ls-remote` and `git fetch` ([`1b15fe8`](https://github.com/Byron/gitoxide/commit/1b15fe80817d600f39090848c7d144ff94ac398c))
+ - A tiny sketch of a possible matching API ([`39d5ff3`](https://github.com/Byron/gitoxide/commit/39d5ff39ac58ec2abf2b55ee69df9905a4f303c2))
+ - Assure ref-specs handle equality, ordering and hashing according to their instruction ([`b4bf7d0`](https://github.com/Byron/gitoxide/commit/b4bf7d015a5d0d48bf7d0509d2fd930a1cb6f398))
+ - Cleanup crate structure ([`f0163c9`](https://github.com/Byron/gitoxide/commit/f0163c99bccfb7d6719217a8fa773667cabe95fd))
+ - Don't expose mode() as it's kind of messy and should be left as implementation detail ([`6278966`](https://github.com/Byron/gitoxide/commit/627896655ce04e1a306c5bf3970ebd6e73bb1a5d))
+ - Improve docs ([`c695a7e`](https://github.com/Byron/gitoxide/commit/c695a7e9716262d885c3ccfde68eb2077650b8ce))
+ - Add fuzz target and basic docs on how to run it ([`febf070`](https://github.com/Byron/gitoxide/commit/febf0706b83b36a71efbe669ee760c2d4ef14b72))
+ - Add fuzz target ([`62d721a`](https://github.com/Byron/gitoxide/commit/62d721a5a7260adb408415810899bcf11d524d0c))
+ - More push-spec restrictions ([`bb992ac`](https://github.com/Byron/gitoxide/commit/bb992acc13fc2a63ec5098e9fa8954909ef486ca))
+ - More detailed tests of what's allowed and where ([`57a6e69`](https://github.com/Byron/gitoxide/commit/57a6e695697744459149dd6400c54b9c4c88a365))
+ - Disallow excludes in push mode ([`9c280b2`](https://github.com/Byron/gitoxide/commit/9c280b2de59773c6d13134e3257cf1da5731e35d))
+ - Don't allow object hashes in excludes ([`b889953`](https://github.com/Byron/gitoxide/commit/b8899532b461ebcdc0ecd33e54a8721e69136c22))
+ - Negative must not be empty ([`79e0eaf`](https://github.com/Byron/gitoxide/commit/79e0eaf4c754da47731f8c5ed3635339586b3d00))
+ - Support for `@` shortcut. ([`32d98e9`](https://github.com/Byron/gitoxide/commit/32d98e9c5db402bbfc04394218c0de30bfa64808))
+ - And the entire test-suite passes ([`3fa52f8`](https://github.com/Byron/gitoxide/commit/3fa52f8ffd04721e1367706318542cf6d4e71f3b))
+ - Handle ref-name validation mostly correctly ([`d7c2789`](https://github.com/Byron/gitoxide/commit/d7c27899c76092bdc8e86f2784aaf67666f117dd))
+ - Refactor ([`e8c072e`](https://github.com/Byron/gitoxide/commit/e8c072e99e845ed1b4a0cc0a0ec7146c53561dcd))
+ - Tests causing all instrucitons ([`c23a21d`](https://github.com/Byron/gitoxide/commit/c23a21d3e50e62d29bef4e638049b0398d3fb20e))
+ - Tests for handling exclusions ([`c4499ce`](https://github.com/Byron/gitoxide/commit/c4499ce13aa9e71c7b0024ad8658bdbcbccf5c14))
+ - Better handling of special cases ([`c99f575`](https://github.com/Byron/gitoxide/commit/c99f5750967a835afd9a99211b3520b441ae1881))
+ - Basic validation and detection of patterns ([`e4227d6`](https://github.com/Byron/gitoxide/commit/e4227d6ddd4cd021245bf6f352a0798457c37aae))
+ - Handle colon and empty on the right side ([`7afebb7`](https://github.com/Byron/gitoxide/commit/7afebb778b93611d924843c95acfd6b36f284fb2))
+ - Support for deletion ([`966a9e9`](https://github.com/Byron/gitoxide/commit/966a9e93b3afdcdc15af95c9fa3037d71af6e0ee))
+ - Add include directive ([`701d46f`](https://github.com/Byron/gitoxide/commit/701d46f020db5c5f86a0184ff345f30d077be8ed))
+ - First successful test for returning a refspec. ([`6e5bd5c`](https://github.com/Byron/gitoxide/commit/6e5bd5c152403d76ba1cf3da2b984689cb6fe8c5))
+ - Sort out how expectations can be expressed in test suite ([`3f264af`](https://github.com/Byron/gitoxide/commit/3f264afda02235dbcdf712d957e37c71ce749f01))
+ - Refactor ([`6713793`](https://github.com/Byron/gitoxide/commit/6713793dca4054a7f8717e70c8e9e4b7e625e9b4))
+ - Sketch all possible instructions of fetch and push refspecs ([`0ba1b73`](https://github.com/Byron/gitoxide/commit/0ba1b73bf988357f4b27753b87432618edec697a))
+ - Run the baseline test and gather some information ([`5e4ee9b`](https://github.com/Byron/gitoxide/commit/5e4ee9ba422cac9eef2b558746f3a3aa4b67a5e4))
+ - First few bits of error handling in parser ([`9c5fed2`](https://github.com/Byron/gitoxide/commit/9c5fed2e2a6ea388acde73be32f8b7f8687c415b))
+ - Frame for basic parsing ([`b9a4bdc`](https://github.com/Byron/gitoxide/commit/b9a4bdca41c074364b7bc26523784c35ac3196ce))
+ - Sketch data structure that should do the trick ([`5c823dc`](https://github.com/Byron/gitoxide/commit/5c823dcbfd3aca0a8846300629e01aed8d7b7e66))
+ - All baseline test cases from git's test-suite ([`362bd46`](https://github.com/Byron/gitoxide/commit/362bd4651751960b3062fd1c65d58b986b46cc97))
+ - Prepare git-refspec changelog prior to release ([`3383408`](https://github.com/Byron/gitoxide/commit/3383408ce22ca9c7502ad2d1fab51cf12dc5ee72))
+ - Empty `git-refspec` crate for name reservation prior to implementation ([`871a3c0`](https://github.com/Byron/gitoxide/commit/871a3c054d4fe6c1e92b6f2e260b19463404509f))
+ * **[#470](https://github.com/Byron/gitoxide/issues/470)**
+ - Update changelogs prior to release ([`caa7a1b`](https://github.com/Byron/gitoxide/commit/caa7a1bdef74d7d3166a7e38127a59f5ab3cfbdd))
+ * **[#571](https://github.com/Byron/gitoxide/issues/571)**
+ - Refactor ([`ef7467c`](https://github.com/Byron/gitoxide/commit/ef7467cd61762dc4206fa82e66adc287ba2f7f52))
+ - Assure sub-branches can be matched correctly ([`c9383c6`](https://github.com/Byron/gitoxide/commit/c9383c693e0b3c506c9b1c42f339f40c1145f998))
+ * **[#691](https://github.com/Byron/gitoxide/issues/691)**
+ - Set `rust-version` to 1.64 ([`55066ce`](https://github.com/Byron/gitoxide/commit/55066ce5fd71209abb5d84da2998b903504584bb))
+ * **[#XXX](https://github.com/Byron/gitoxide/issues/XXX)**
+ - Prepare changelogs prior to release ([`8c0bca3`](https://github.com/Byron/gitoxide/commit/8c0bca37ff9fbaadbe55561fb2b0d649980c95b1))
+ * **Uncategorized**
+ - Release 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 ([`7fc00f8`](https://github.com/Byron/gitoxide/commit/7fc00f87d74aedf631ce4032be1cdfe1804c7e7d))
+ - Release 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 ([`59e9fac`](https://github.com/Byron/gitoxide/commit/59e9fac67d1b353e124300435b55f6b5468d7deb))
+ - Release 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 ([`48f5bd2`](https://github.com/Byron/gitoxide/commit/48f5bd2014fa3dda6fbd60d091065c5537f69453))
+ - Release 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 ([`a5869e0`](https://github.com/Byron/gitoxide/commit/a5869e0b223406820bca836e3e3a7fae2bfd9b04))
+ - Release 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 ([`41d57b9`](https://github.com/Byron/gitoxide/commit/41d57b98964094fc1528adb09f69ca824229bf25))
+ - 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))
+ - Rename `git-refspec` to `gix-refspec` ([`3c56012`](https://github.com/Byron/gitoxide/commit/3c56012d7ba0e82ca566c0de9ad9dc2966f3a34f))
+ - Adjust to renaming of `git-revision` to `gix-revision` ([`ee0ee84`](https://github.com/Byron/gitoxide/commit/ee0ee84607c2ffe11ee75f27a31903db68afed02))
+ - Adjust to renaming of `git-transport` to `gix-transport` ([`b2ccf71`](https://github.com/Byron/gitoxide/commit/b2ccf716dc4425bb96651d4d58806a3cc2da219e))
+ - Adjust to renaming of `git-credentials` to `gix-credentials` ([`6b18abc`](https://github.com/Byron/gitoxide/commit/6b18abcf2856f02ab938d535a65e51ac282bf94a))
+ - Adjust to renaming of `git-prompt` to `gix-prompt` ([`6a4654e`](https://github.com/Byron/gitoxide/commit/6a4654e0d10ab773dd219cb4b731c0fc1471c36d))
+ - Adjust to renaming of `git-command` to `gix-command` ([`d26b8e0`](https://github.com/Byron/gitoxide/commit/d26b8e046496894ae06b0bbfdba77196976cd975))
+ - Adjust to renaming of `git-packetline` to `gix-packetline` ([`5cbd22c`](https://github.com/Byron/gitoxide/commit/5cbd22cf42efb760058561c6c3bbcd4dab8c8be1))
+ - Adjust to renaming of `git-worktree` to `gix-worktree` ([`73a1282`](https://github.com/Byron/gitoxide/commit/73a12821b3d9b66ec1714d07dd27eb7a73e3a544))
+ - Adjust to renamining of `git-hashtable` to `gix-hashtable` ([`26a0c98`](https://github.com/Byron/gitoxide/commit/26a0c98d0a389b03e3dc7bfc758b37155e285244))
+ - Adjust to renamining of `git-worktree` to `gix-worktree` ([`108bb1a`](https://github.com/Byron/gitoxide/commit/108bb1a634f4828853fb590e9fc125f79441dd38))
+ - Adjust to renaming of `git-url` to `gix-url` ([`b50817a`](https://github.com/Byron/gitoxide/commit/b50817aadb143e19f61f64e19b19ec1107d980c6))
+ - Adjust to renaming of `git-date` to `gix-date` ([`9a79ff2`](https://github.com/Byron/gitoxide/commit/9a79ff2d5cc74c1efad9f41e21095ae498cce00b))
+ - Adjust to renamining of `git-attributes` to `gix-attributes` ([`4a8b3b8`](https://github.com/Byron/gitoxide/commit/4a8b3b812ac26f2a2aee8ce8ca81591273383c84))
+ - Adjust to renaminig of `git-quote` to `gix-quote` ([`648025b`](https://github.com/Byron/gitoxide/commit/648025b7ca94411fdd0d90c53e5faede5fde6c8d))
+ - Adjust to renaming of `git-config` to `gix-config` ([`3a861c8`](https://github.com/Byron/gitoxide/commit/3a861c8f049f6502d3bcbdac752659aa1aeda46a))
+ - Adjust to renaming of `git-ref` to `gix-ref` ([`1f5f695`](https://github.com/Byron/gitoxide/commit/1f5f695407b034377d94b172465ff573562b3fc3))
+ - Adjust to renaming of `git-lock` to `gix-lock` ([`2028e78`](https://github.com/Byron/gitoxide/commit/2028e7884ae1821edeec81612f501e88e4722b17))
+ - Adjust to renaming of `git-tempfile` to `gix-tempfile` ([`b6cc3eb`](https://github.com/Byron/gitoxide/commit/b6cc3ebb5137084a6327af16a7d9364d8f092cc9))
+ - Adjust to renaming of `git-object` to `gix-object` ([`fc86a1e`](https://github.com/Byron/gitoxide/commit/fc86a1e710ad7bf076c25cc6f028ddcf1a5a4311))
+ - Adjust to renaming of `git-actor` to `gix-actor` ([`4dc9b44`](https://github.com/Byron/gitoxide/commit/4dc9b44dc52f2486ffa2040585c6897c1bf55df4))
+ - Adjust to renaming of `git-validate` to `gix-validate` ([`5e40ad0`](https://github.com/Byron/gitoxide/commit/5e40ad078af3d08cbc2ca81ce755c0ed8a065b4f))
+ - Adjust to renaming of `git-hash` to `gix-hash` ([`4a9d025`](https://github.com/Byron/gitoxide/commit/4a9d0257110c3efa61d08c8457c4545b200226d1))
+ - Adjust to renaming of `git-features` to `gix-features` ([`e2dd68a`](https://github.com/Byron/gitoxide/commit/e2dd68a417aad229e194ff20dbbfd77668096ec6))
+ - Adjust to renaming of `git-glob` to `gix-glob` ([`35b2a3a`](https://github.com/Byron/gitoxide/commit/35b2a3acbc8f2a03f151bc0a3863163844e0ca86))
+ - Adjust to renaming of `git-sec` to `gix-sec` ([`eabbb92`](https://github.com/Byron/gitoxide/commit/eabbb923bd5a32fc80fa80f96cfdc2ab7bb2ed17))
+ - Adapt to renaming of `git-path` to `gix-path` ([`d3bbcfc`](https://github.com/Byron/gitoxide/commit/d3bbcfccad80fc44ea8e7bf819f23adaca06ba2d))
+ - Adjust to rename of `git-config-value` to `gix-config-value` ([`622b3e1`](https://github.com/Byron/gitoxide/commit/622b3e1d0bffa0f8db73697960f9712024fac430))
+ - Release git-refspec v0.7.2, git-repository v0.34.0 ([`1210c19`](https://github.com/Byron/gitoxide/commit/1210c1926851495df5d6fd3f6906602a7e423548))
+ - 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))
+ - Merge remote-tracking branch 'origin/main' ([`f5fbcfb`](https://github.com/Byron/gitoxide/commit/f5fbcfbcf281429d56c46f815ca86da848410083))
+ - Fixes build for parsing fuzz harness ([`d342922`](https://github.com/Byron/gitoxide/commit/d34292294a0c41991aebd5af46e7bd7e3ad7324d))
+ - Release git-date v0.4.1, git-features v0.26.1, git-glob v0.5.2, git-attributes v0.8.1, git-tempfile v3.0.1, git-ref v0.23.1, git-sec v0.6.1, git-config v0.15.1, git-prompt v0.3.1, git-url v0.13.1, git-discover v0.12.1, git-index v0.12.2, git-mailmap v0.9.1, git-pack v0.30.1, git-odb v0.40.1, git-transport v0.25.3, git-protocol v0.26.2, git-revision v0.10.1, git-refspec v0.7.1, git-worktree v0.12.1, git-repository v0.33.0 ([`5b5b380`](https://github.com/Byron/gitoxide/commit/5b5b3809faa71c658db38b40dfc410224d08a367))
+ - Prepare changelogs prior to release ([`93bef97`](https://github.com/Byron/gitoxide/commit/93bef97b3c0c75d4bf7119fdd787516e1efc77bf))
+ - Merge branch 'patch-1' ([`b93f0c4`](https://github.com/Byron/gitoxide/commit/b93f0c49fc677b6c19aea332cbfc1445ce475375))
+ - Thanks clippy ([`9e04685`](https://github.com/Byron/gitoxide/commit/9e04685dd3f109bfb27663f9dc7c04102e660bf2))
+ - Release git-ref v0.23.0, git-config v0.15.0, git-command v0.2.2, git-diff v0.26.0, git-discover v0.12.0, git-mailmap v0.9.0, git-pack v0.30.0, git-odb v0.40.0, git-transport v0.25.2, git-protocol v0.26.1, git-revision v0.10.0, git-refspec v0.7.0, git-worktree v0.12.0, git-repository v0.32.0 ([`ffb5b6a`](https://github.com/Byron/gitoxide/commit/ffb5b6a21cb415315db6fd5294940c7c6deb4538))
+ - Prepare changelogs prior to release ([`4381a03`](https://github.com/Byron/gitoxide/commit/4381a03a34c305f31713cce234c2afbf8ac60f01))
+ - Release git-date v0.4.0, git-actor v0.17.0, git-object v0.26.0, git-traverse v0.22.0, git-index v0.12.0, safety bump 15 crates ([`0e3d0a5`](https://github.com/Byron/gitoxide/commit/0e3d0a56d7e6a60c6578138f2690b4fa54a2072d))
+ - Release git-features v0.26.0, git-actor v0.16.0, git-attributes v0.8.0, git-object v0.25.0, git-ref v0.22.0, git-config v0.14.0, git-command v0.2.1, git-url v0.13.0, git-credentials v0.9.0, git-diff v0.25.0, git-discover v0.11.0, git-traverse v0.21.0, git-index v0.11.0, git-mailmap v0.8.0, git-pack v0.29.0, git-odb v0.39.0, git-transport v0.25.0, git-protocol v0.26.0, git-revision v0.9.0, git-refspec v0.6.0, git-worktree v0.11.0, git-repository v0.31.0, safety bump 24 crates ([`5ac9fbe`](https://github.com/Byron/gitoxide/commit/5ac9fbe265a5b61c533a2a6b3abfed2bdf7f89ad))
+ - Prepare changelogs prior to release ([`30d8ca1`](https://github.com/Byron/gitoxide/commit/30d8ca19284049dcfbb0de2698cafae1d1a16b0c))
+ - Release git-date v0.3.1, git-features v0.25.0, git-actor v0.15.0, git-glob v0.5.1, git-path v0.7.0, git-attributes v0.7.0, git-config-value v0.10.0, git-lock v3.0.1, git-validate v0.7.1, git-object v0.24.0, git-ref v0.21.0, git-sec v0.6.0, git-config v0.13.0, git-prompt v0.3.0, git-url v0.12.0, git-credentials v0.8.0, git-diff v0.24.0, git-discover v0.10.0, git-traverse v0.20.0, git-index v0.10.0, git-mailmap v0.7.0, git-pack v0.28.0, git-odb v0.38.0, git-packetline v0.14.1, git-transport v0.24.0, git-protocol v0.25.0, git-revision v0.8.0, git-refspec v0.5.0, git-worktree v0.10.0, git-repository v0.30.0, safety bump 26 crates ([`e6b9906`](https://github.com/Byron/gitoxide/commit/e6b9906c486b11057936da16ed6e0ec450a0fb83))
+ - Prepare chnagelogs prior to git-repository release ([`7114bbb`](https://github.com/Byron/gitoxide/commit/7114bbb6732aa8571d4ab74f28ed3e26e9fbe4d0))
+ - Merge branch 'main' into read-split-index ([`c57bdde`](https://github.com/Byron/gitoxide/commit/c57bdde6de37eca9672ea715962bbd02aa3eb055))
+ - Merge branch 'adjustments-for-cargo' ([`083909b`](https://github.com/Byron/gitoxide/commit/083909bc7eb902eeee2002034fdb6ed88280dc5c))
+ - Adjust to changes in `git-testtools` ([`4eb842c`](https://github.com/Byron/gitoxide/commit/4eb842c7150b980e1c2637217e1f9657a671cea7))
+ - Release git-hash v0.10.1, git-hashtable v0.1.0 ([`7717170`](https://github.com/Byron/gitoxide/commit/771717095d9a67b0625021eb0928828ab686e772))
+ - Merge branch 'main' into http-config ([`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 ([`c4e6849`](https://github.com/Byron/gitoxide/commit/c4e68496c368611ebe17c6693d06c8147c28c717))
+ - Merge branch 'gix-clone' ([`def53b3`](https://github.com/Byron/gitoxide/commit/def53b36c3dec26fa78939ab0584fe4ff930909c))
+ - Merge branch 'main' into gix-clone ([`91bf67a`](https://github.com/Byron/gitoxide/commit/91bf67af9751d1e6beb78fb77b40f05352b98215))
+ - Merge branch 'fix-571' ([`2514334`](https://github.com/Byron/gitoxide/commit/2514334c17f543e3e18ac43261990ad412b7c7ae))
+ - Release git-hash v0.9.11, git-features v0.23.0, git-actor v0.13.0, git-attributes v0.5.0, git-object v0.22.0, git-ref v0.17.0, git-sec v0.4.1, git-config v0.9.0, git-url v0.10.0, git-credentials v0.6.0, git-diff v0.20.0, git-discover v0.6.0, git-traverse v0.18.0, git-index v0.6.0, git-mailmap v0.5.0, git-pack v0.24.0, git-odb v0.34.0, git-packetline v0.13.1, git-transport v0.21.0, git-protocol v0.21.0, git-revision v0.6.0, git-refspec v0.3.0, git-worktree v0.6.0, git-repository v0.25.0, safety bump 24 crates ([`104d922`](https://github.com/Byron/gitoxide/commit/104d922add61ab21c534c24ce8ed37cddf3e275a))
+ - Prepare changelogs for release ([`d232567`](https://github.com/Byron/gitoxide/commit/d23256701a95284857dc8d1cb37c7c94cada973c))
+ - Merge branch 'clone' ([`507dc7e`](https://github.com/Byron/gitoxide/commit/507dc7e706cb3c9d89d048b3aff5df239a9b6788))
+ - Remove lifetime of `match_group::Fix`, keeping `RefSpec` instances instead ([`2a0a87a`](https://github.com/Byron/gitoxide/commit/2a0a87a04e7b4d6ed3be3d8adc89917576727686))
+ - Another test to validate components must not be empty ([`b2c9af1`](https://github.com/Byron/gitoxide/commit/b2c9af1cf7eedfb618c47d0598cfcef636e793ff))
+ - Merge branch 'main' into new-http-impl ([`702a161`](https://github.com/Byron/gitoxide/commit/702a161ef11fc959611bf44b70e9ffe04561c7ad))
+ - Make fmt ([`53acf25`](https://github.com/Byron/gitoxide/commit/53acf2565743eff7cead7a42011107b2fc8d7e0e))
+ - Merge branch 'fetch-pack' ([`3c49400`](https://github.com/Byron/gitoxide/commit/3c49400809c7c2120f4ce704c19a0421545b5acd))
+ - `RefSpecRef::prefix()` to return the two-component prefix of a refspec's source. #(450) ([`6df179b`](https://github.com/Byron/gitoxide/commit/6df179b5cf831402444cc78429a57f835358376e))
+ - Merge branch 'diff' ([`25a7726`](https://github.com/Byron/gitoxide/commit/25a7726377fbe400ea3c4927d04e9dec99802b7b))
+ - Release 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 ([`f5c36d8`](https://github.com/Byron/gitoxide/commit/f5c36d85755d1f0f503b77d9a565fad6aecf6728))
+ - 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))
+ - Make fmt ([`429cccc`](https://github.com/Byron/gitoxide/commit/429cccc5831c25a7205a12dc7a0443ac48616e2c))
+ - Merge branch 'filter-refs' ([`3773b92`](https://github.com/Byron/gitoxide/commit/3773b92b8372c9a40a74d281149ca65b057a7da9))
+ - Merge branch 'filter-refs' ([`fd14489`](https://github.com/Byron/gitoxide/commit/fd14489f729172d615d0fa1e8dbd605e9eacf69d))
+ - Thanks clippy ([`74a5f22`](https://github.com/Byron/gitoxide/commit/74a5f2262154c5cb5434c1ef2854c4ec3d839f89))
+ - Thanks clippy ([`016cd1f`](https://github.com/Byron/gitoxide/commit/016cd1f70a536ac95eaa8b80958110caa096d875))
+ - Thanks clippy ([`b8ac13e`](https://github.com/Byron/gitoxide/commit/b8ac13e5074fa08111fcef1092432ed3a2326c6e))
+ - Thanks clippy ([`73b405f`](https://github.com/Byron/gitoxide/commit/73b405fe70cf7d53e5e011cf69ea654f4bd96dd2))
+ - Make fmt ([`535e967`](https://github.com/Byron/gitoxide/commit/535e967666c6da657ff1b7eff7c64ab27cafb182))
+ - Merge branch 'main' into filter-refs-by-spec ([`1f6e5ab`](https://github.com/Byron/gitoxide/commit/1f6e5ab15f5fd8d23719b13e6aea59cd231ac0fe))
+ - Merge branch 'fix-522' ([`5869e9f`](https://github.com/Byron/gitoxide/commit/5869e9ff2508d5a93c07635277af8764fcb57713))
+ - Release git-hash v0.9.9 ([`da0716f`](https://github.com/Byron/gitoxide/commit/da0716f8c27b4f29cfff0e5ce7fcb3d7240f4aeb))
+ - Merge branch 'main' into index-from-tree ([`bc64b96`](https://github.com/Byron/gitoxide/commit/bc64b96a2ec781c72d1d4daad38aa7fb8b74f99b))
+ - Merge branch 'main' into filter-refs-by-spec ([`cef0b51`](https://github.com/Byron/gitoxide/commit/cef0b51ade2a3301fa09ede7a425aa1fe3527e78))
+ - Release git-object v0.20.3, git-ref v0.15.4, git-config v0.7.1, git-diff v0.18.0, git-traverse v0.16.3, git-pack v0.22.0, git-odb v0.32.0, git-url v0.7.3, git-transport v0.19.3, git-protocol v0.19.1, git-refspec v0.1.1, git-repository v0.23.0, safety bump 6 crates ([`85a3bed`](https://github.com/Byron/gitoxide/commit/85a3bedd68d2e5f36592a2f691c977dc55298279))
+ - Release git-features v0.22.3, git-revision v0.4.4 ([`c2660e2`](https://github.com/Byron/gitoxide/commit/c2660e2503323531ba02519eaa51124ee22fec51))
+ - Merge branch 'main' into filter-refs-by-spec ([`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 'remote-ls-refs' ([`39d585d`](https://github.com/Byron/gitoxide/commit/39d585d9f9ac6f3ecf51359c8e37f0a50e21ed45))
+ - 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 ([`c82bbfa`](https://github.com/Byron/gitoxide/commit/c82bbfaddc45bf9b5b55f056613046d977d9ef09))
+ - Prepare for release of git-repository ([`8aa5389`](https://github.com/Byron/gitoxide/commit/8aa5389d5a1bdd3a07f1caa1c2f55c8af4f9844a))
+ - 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))
+ - Release git-hash v0.9.7, git-features v0.22.1 ([`232784a`](https://github.com/Byron/gitoxide/commit/232784a59ded3e8016e4257c7e146ad385cdd64a))
+ - Merge branch 'main' into write-index-v2 ([`a938986`](https://github.com/Byron/gitoxide/commit/a938986877302c197d1aed087594c5605416fe5f))
+ - Merge branch 'main' into remote-ls-refs ([`de61c4d`](https://github.com/Byron/gitoxide/commit/de61c4db7855d6925d66961f62ae3d12cc4acf78))
+ - Thanks clippy ([`4bd747c`](https://github.com/Byron/gitoxide/commit/4bd747cb3e126fe5b1d540270cfbd731cffd42ef))
+ - Thanks clippy ([`b9e1cdb`](https://github.com/Byron/gitoxide/commit/b9e1cdbf19045816387d922abd9c886419ff6bf2))
+ - Merge branch 'parse-refspec' ([`2ba338e`](https://github.com/Byron/gitoxide/commit/2ba338e28eb45d4d3215dd6ff9882611880d4cd9))
+ - Thanks clippy ([`6c963b0`](https://github.com/Byron/gitoxide/commit/6c963b022e48854001353f8909c3e8314c2e5861))
+ - Thanks clippy ([`b62ee56`](https://github.com/Byron/gitoxide/commit/b62ee56b5bf468b9673b01034ec284faf1a7c7c2))
+ - Release git-refspec v0.0.0 ([`d406689`](https://github.com/Byron/gitoxide/commit/d406689f01c8fa7cc81b52d6500a44303e719ec2))
+</details>
+
+## 0.7.1 (2023-01-10)
+
+A maintenance release without user-facing changes.
+
+## 0.7.0 (2023-01-09)
+
+A maintenance release without user-facing changes.
+
+## 0.6.0 (2022-12-30)
+
+A maintenance release without user-facing changes.
+
+## 0.5.0 (2022-12-19)
+
+A maintenance release without user-facing changes.
+
+## 0.4.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.
+
+## 0.3.1 (2022-11-06)
+
+### New Features
+
+ - <csr-id-21b21b6c25e1d8d1da9464b7bef06a795f679210/> add `RefSpecRef::expand_prefix()` method to avoid missing prefixes.
+ The current implementation might cause refspecs to end up ignored as
+ they don't have a prefix, and in protocol V2 it would then fail
+ to add a ref-spec filter which causes them to be missed.
+
+ With `expand_prefix()`, we assure that there are all possible prefixes
+ that can contain partial names, similar to what git does.
+
+### Bug Fixes
+
+ - <csr-id-d53ddcde948cfbd7773eb830cbb636626b32debb/> `HEAD` may now return itself as prefix in `RefSpecRef::prefix()` and `expanded_prefix()`.
+ Previously, the expanded prefix would be a list of possibilities, even
+ though it's such a common case that we really want to avoid spamming the
+ remote about it when asking for HEAD during clone for instance.
+
+## 0.3.0 (2022-10-10)
+
+### New Features
+
+ - <csr-id-d7f63a6c60a826dc862bd13adbef041e4ac6d8ab/> `RefSpec::allow_non_fast_forward()` to get information about 'force' quickly.
+ - <csr-id-6df179b5cf831402444cc78429a57f835358376e/> `RefSpecRef::prefix()` to return the two-component prefix of a refspec's source. #(450)
+
+### Bug Fixes
+
+ - <csr-id-278ff7a6ee084ea864193a5ca25b6cd0f18e19a0/> `RefSpecRef` instruction uses the correct lifetime.
+
+### Changed (BREAKING)
+
+ - <csr-id-2a0a87a04e7b4d6ed3be3d8adc89917576727686/> remove lifetime of `match_group::Fix`, keeping `RefSpec` instances instead
+ That lifetime unnecessarily complicated things and wasn't worth keeping
+ due to being a premature optimization.
+
+## 0.2.0 (2022-09-20)
+
+### New Features
+
+ - <csr-id-abdf83f494e2a9fba4a8d9fcb776f2c84baebd3e/> Simple serialization for `Instruction` and `RefSpecRef` type.
+ It's also a way to normalize input strings as there is only one way
+ to serialize instructions, which themselves are already normalized
+ towards what's possible.
+
+### Changed (BREAKING)
+
+ - <csr-id-4c4f82170d08b910a7f64482431c99956b1a04c3/> reject all invalid negative refspec patterns.
+ Git is more lenient, but will then fail to match against such patterns
+ which seems like avoidable surprising behaviour.
+ - <csr-id-99905bacace8aed42b16d43f0f04cae996cb971c/> upgrade `bstr` to `1.0.1`
+
+## 0.1.1 (2022-08-28)
+
+Maintenance release without user-facing changes.
+
+## 0.1.0 (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
+
+## 0.0.0 (2022-08-05)
+
+Initial release for name reservation.
+
diff --git a/vendor/gix-refspec/Cargo.toml b/vendor/gix-refspec/Cargo.toml
new file mode 100644
index 000000000..acc79c110
--- /dev/null
+++ b/vendor/gix-refspec/Cargo.toml
@@ -0,0 +1,51 @@
+# 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-refspec"
+version = "0.9.0"
+authors = ["Sebastian Thiel <sebastian.thiel@icloud.com>"]
+include = [
+ "src/**/*",
+ "CHANGELOG.md",
+ "README.md",
+]
+description = "A WIP crate of the gitoxide project for parsing and representing refspecs"
+readme = "README.md"
+license = "MIT/Apache-2.0"
+repository = "https://github.com/Byron/gitoxide"
+
+[lib]
+doctest = false
+
+[dependencies.bstr]
+version = "1.3.0"
+features = ["std"]
+default-features = false
+
+[dependencies.gix-hash]
+version = "^0.10.3"
+
+[dependencies.gix-revision]
+version = "^0.12.0"
+
+[dependencies.gix-validate]
+version = "^0.7.3"
+
+[dependencies.smallvec]
+version = "1.9.0"
+
+[dependencies.thiserror]
+version = "1.0.26"
+
+[dev-dependencies]
diff --git a/vendor/gix-refspec/README.md b/vendor/gix-refspec/README.md
new file mode 100644
index 000000000..371337b98
--- /dev/null
+++ b/vendor/gix-refspec/README.md
@@ -0,0 +1,11 @@
+# `gix-refspec`
+
+### Testing
+
+#### Fuzzing
+
+`cargo fuzz` is used for fuzzing, installable with `cargo install cargo-fuzz`.
+
+Targets can be listed with `cargo fuzz list` and executed via `cargo +nightly fuzz run <target>`,
+where `<target>` can be `parse` for example.
+
diff --git a/vendor/gix-refspec/src/instruction.rs b/vendor/gix-refspec/src/instruction.rs
new file mode 100644
index 000000000..990d0debc
--- /dev/null
+++ b/vendor/gix-refspec/src/instruction.rs
@@ -0,0 +1,68 @@
+use bstr::BStr;
+
+use crate::{parse::Operation, Instruction};
+
+impl Instruction<'_> {
+ /// Derive the mode of operation from this instruction.
+ pub fn operation(&self) -> Operation {
+ match self {
+ Instruction::Push(_) => Operation::Push,
+ Instruction::Fetch(_) => Operation::Fetch,
+ }
+ }
+}
+
+/// Note that all sources can either be a ref-name, partial or full, or a rev-spec, unless specified otherwise, on the local side.
+/// Destinations can only be a partial or full ref names on the remote side.
+#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Hash, Debug)]
+pub enum Push<'a> {
+ /// Push all local branches to the matching destination on the remote, which has to exist to be updated.
+ AllMatchingBranches {
+ /// If true, allow non-fast-forward updates of the matched destination branch.
+ allow_non_fast_forward: bool,
+ },
+ /// Delete the destination ref or glob pattern, with only a single `*` allowed.
+ Delete {
+ /// The reference or pattern to delete on the remote.
+ ref_or_pattern: &'a BStr,
+ },
+ /// Push a single ref or refspec to a known destination ref.
+ Matching {
+ /// The source ref or refspec to push. If pattern, it contains a single `*`.
+ /// Examples are refnames like `HEAD` or `refs/heads/main`, or patterns like `refs/heads/*`.
+ src: &'a BStr,
+ /// The ref to update with the object from `src`. If `src` is a pattern, this is a pattern too.
+ /// Examples are refnames like `HEAD` or `refs/heads/main`, or patterns like `refs/heads/*`.
+ dst: &'a BStr,
+ /// If true, allow non-fast-forward updates of `dest`.
+ allow_non_fast_forward: bool,
+ },
+}
+
+/// Any source can either be a ref name (full or partial) or a fully spelled out hex-sha for an object, on the remote side.
+///
+/// Destinations can only be a partial or full ref-names on the local side.
+#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Hash, Debug)]
+pub enum Fetch<'a> {
+ /// Fetch a ref or refs, without updating local branches.
+ Only {
+ /// The partial or full ref name to fetch on the remote side or the full object hex-name, without updating the local side.
+ /// Note that this may not be a glob pattern, as those need to be matched by a destination which isn't present here.
+ src: &'a BStr,
+ },
+ /// Exclude a single ref.
+ Exclude {
+ /// A single partial or full ref name to exclude on the remote, or a pattern with a single `*`. It cannot be a spelled out object hash.
+ src: &'a BStr,
+ },
+ /// Fetch from `src` and update the corresponding destination branches in `dst` accordingly.
+ AndUpdate {
+ /// The ref name to fetch on the remote side, or a pattern with a single `*` to match against.
+ src: &'a BStr,
+ /// The local destination to update with what was fetched, or a pattern whose single `*` will be replaced with the matching portion
+ /// of the `*` from `src`.
+ dst: &'a BStr,
+ /// If true, allow non-fast-forward updates of `dest`.
+ allow_non_fast_forward: bool,
+ },
+}
diff --git a/vendor/gix-refspec/src/lib.rs b/vendor/gix-refspec/src/lib.rs
new file mode 100644
index 000000000..54d5f3057
--- /dev/null
+++ b/vendor/gix-refspec/src/lib.rs
@@ -0,0 +1,39 @@
+//! Parse git ref-specs and represent them.
+#![deny(missing_docs, rust_2018_idioms)]
+#![forbid(unsafe_code)]
+
+///
+pub mod parse;
+pub use parse::function::parse;
+
+///
+pub mod instruction;
+
+/// A refspec with references to the memory it was parsed from.
+#[derive(Eq, Copy, Clone, Debug)]
+pub struct RefSpecRef<'a> {
+ mode: types::Mode,
+ op: parse::Operation,
+ src: Option<&'a bstr::BStr>,
+ dst: Option<&'a bstr::BStr>,
+}
+
+/// An owned refspec.
+#[derive(Eq, Clone, Debug)]
+pub struct RefSpec {
+ mode: types::Mode,
+ op: parse::Operation,
+ src: Option<bstr::BString>,
+ dst: Option<bstr::BString>,
+}
+
+mod spec;
+
+mod write;
+
+///
+pub mod match_group;
+pub use match_group::types::MatchGroup;
+
+mod types;
+pub use types::Instruction;
diff --git a/vendor/gix-refspec/src/match_group/mod.rs b/vendor/gix-refspec/src/match_group/mod.rs
new file mode 100644
index 000000000..c53b5b531
--- /dev/null
+++ b/vendor/gix-refspec/src/match_group/mod.rs
@@ -0,0 +1,112 @@
+use std::collections::BTreeSet;
+
+use crate::{parse::Operation, types::Mode, MatchGroup, RefSpecRef};
+
+pub(crate) mod types;
+pub use types::{Item, Mapping, Outcome, Source, SourceRef};
+
+///
+pub mod validate;
+
+/// Initialization
+impl<'a> MatchGroup<'a> {
+ /// Take all the fetch ref specs from `specs` get a match group ready.
+ pub fn from_fetch_specs(specs: impl IntoIterator<Item = RefSpecRef<'a>>) -> Self {
+ MatchGroup {
+ specs: specs.into_iter().filter(|s| s.op == Operation::Fetch).collect(),
+ }
+ }
+}
+
+/// Matching
+impl<'a> MatchGroup<'a> {
+ /// Match all `items` against all fetch specs present in this group, returning deduplicated mappings from source to destination.
+ /// Note that this method only makes sense if the specs are indeed fetch specs and may panic otherwise.
+ ///
+ /// Note that negative matches are not part of the return value, so they are not observable but will be used to remove mappings.
+ pub fn match_remotes<'item>(self, mut items: impl Iterator<Item = Item<'item>> + Clone) -> Outcome<'a, 'item> {
+ let mut out = Vec::new();
+ let mut seen = BTreeSet::default();
+ let mut push_unique = |mapping| {
+ if seen.insert(calculate_hash(&mapping)) {
+ out.push(mapping);
+ }
+ };
+ let mut matchers: Vec<Option<Matcher<'_>>> = self
+ .specs
+ .iter()
+ .copied()
+ .map(Matcher::from)
+ .enumerate()
+ .map(|(idx, m)| match m.lhs {
+ Some(Needle::Object(id)) => {
+ push_unique(Mapping {
+ item_index: None,
+ lhs: SourceRef::ObjectId(id),
+ rhs: m.rhs.map(|n| n.to_bstr()),
+ spec_index: idx,
+ });
+ None
+ }
+ _ => Some(m),
+ })
+ .collect();
+
+ let mut has_negation = false;
+ for (spec_index, (spec, matcher)) in self.specs.iter().zip(matchers.iter_mut()).enumerate() {
+ for (item_index, item) in items.clone().enumerate() {
+ if spec.mode == Mode::Negative {
+ has_negation = true;
+ continue;
+ }
+ if let Some(matcher) = matcher {
+ let (matched, rhs) = matcher.matches_lhs(item);
+ if matched {
+ push_unique(Mapping {
+ item_index: Some(item_index),
+ lhs: SourceRef::FullName(item.full_ref_name),
+ rhs,
+ spec_index,
+ })
+ }
+ }
+ }
+ }
+
+ if let Some(id) = has_negation.then(|| items.next().map(|i| i.target)).flatten() {
+ let null_id = gix_hash::ObjectId::null(id.kind());
+ for matcher in matchers
+ .into_iter()
+ .zip(self.specs.iter())
+ .filter_map(|(m, spec)| m.and_then(|m| (spec.mode == Mode::Negative).then_some(m)))
+ {
+ out.retain(|m| match m.lhs {
+ SourceRef::ObjectId(_) => true,
+ SourceRef::FullName(name) => {
+ !matcher
+ .matches_lhs(Item {
+ full_ref_name: name,
+ target: &null_id,
+ object: None,
+ })
+ .0
+ }
+ });
+ }
+ }
+ Outcome {
+ group: self,
+ mappings: out,
+ }
+ }
+}
+
+fn calculate_hash<T: std::hash::Hash>(t: &T) -> u64 {
+ use std::hash::Hasher;
+ let mut s = std::collections::hash_map::DefaultHasher::new();
+ t.hash(&mut s);
+ s.finish()
+}
+
+mod util;
+use util::{Matcher, Needle};
diff --git a/vendor/gix-refspec/src/match_group/types.rs b/vendor/gix-refspec/src/match_group/types.rs
new file mode 100644
index 000000000..6be601dd5
--- /dev/null
+++ b/vendor/gix-refspec/src/match_group/types.rs
@@ -0,0 +1,104 @@
+use std::borrow::Cow;
+
+use bstr::{BStr, BString};
+use gix_hash::oid;
+
+use crate::RefSpecRef;
+
+/// A match group is able to match a list of ref specs in order while handling negation, conflicts and one to many mappings.
+#[derive(Default, Debug, Clone)]
+pub struct MatchGroup<'a> {
+ /// The specs that take part in item matching.
+ pub specs: Vec<RefSpecRef<'a>>,
+}
+
+/// The outcome of any matching operation of a [`MatchGroup`].
+///
+/// It's used to validate and process the contained [mappings][Mapping].
+#[derive(Debug, Clone)]
+pub struct Outcome<'spec, 'item> {
+ /// The match group that produced this outcome.
+ pub group: MatchGroup<'spec>,
+ /// The mappings derived from matching [items][Item].
+ pub mappings: Vec<Mapping<'item, 'spec>>,
+}
+
+/// An item to match, input to various matching operations.
+#[derive(Debug, Copy, Clone)]
+pub struct Item<'a> {
+ /// The full name of the references, like `refs/heads/main`
+ pub full_ref_name: &'a BStr,
+ /// The id that `full_ref_name` points to, which typically is a commit, but can also be a tag object (or anything else).
+ pub target: &'a oid,
+ /// The object an annotated tag is pointing to, if `target` is an annotated tag.
+ pub object: Option<&'a oid>,
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+/// The source (or left-hand) side of a mapping, which references its name.
+pub enum SourceRef<'a> {
+ /// A full reference name, which is expected to be valid.
+ ///
+ /// Validity, however, is not enforced here.
+ FullName(&'a BStr),
+ /// The name of an object that is expected to exist on the remote side.
+ /// Note that it might not be advertised by the remote but part of the object graph,
+ /// and thus gets sent in the pack. The server is expected to fail unless the desired
+ /// object is present but at some time it is merely a request by the user.
+ ObjectId(gix_hash::ObjectId),
+}
+
+impl SourceRef<'_> {
+ /// Create a fully owned instance from this one.
+ pub fn to_owned(&self) -> Source {
+ match self {
+ SourceRef::ObjectId(id) => Source::ObjectId(*id),
+ SourceRef::FullName(name) => Source::FullName((*name).to_owned()),
+ }
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+/// The source (or left-hand) side of a mapping, which owns its name.
+pub enum Source {
+ /// A full reference name, which is expected to be valid.
+ ///
+ /// Validity, however, is not enforced here.
+ FullName(BString),
+ /// The name of an object that is expected to exist on the remote side.
+ /// Note that it might not be advertised by the remote but part of the object graph,
+ /// and thus gets sent in the pack. The server is expected to fail unless the desired
+ /// object is present but at some time it is merely a request by the user.
+ ObjectId(gix_hash::ObjectId),
+}
+
+impl std::fmt::Display for Source {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Source::FullName(name) => name.fmt(f),
+ Source::ObjectId(id) => id.fmt(f),
+ }
+ }
+}
+
+/// A mapping from a remote to a local refs for fetches or local to remote refs for pushes.
+///
+/// Mappings are like edges in a graph, initially without any constraints.
+#[derive(Debug, Clone)]
+pub struct Mapping<'a, 'b> {
+ /// The index into the initial `items` list that matched against a spec.
+ pub item_index: Option<usize>,
+ /// The name of the remote side for fetches or the local one for pushes that matched.
+ pub lhs: SourceRef<'a>,
+ /// The name of the local side for fetches or the remote one for pushes that corresponds to `lhs`, if available.
+ pub rhs: Option<Cow<'b, BStr>>,
+ /// The index of the matched ref-spec as seen from the match group.
+ pub spec_index: usize,
+}
+
+impl std::hash::Hash for Mapping<'_, '_> {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ self.lhs.hash(state);
+ self.rhs.hash(state);
+ }
+}
diff --git a/vendor/gix-refspec/src/match_group/util.rs b/vendor/gix-refspec/src/match_group/util.rs
new file mode 100644
index 000000000..5339aef32
--- /dev/null
+++ b/vendor/gix-refspec/src/match_group/util.rs
@@ -0,0 +1,162 @@
+use std::{borrow::Cow, ops::Range};
+
+use bstr::{BStr, BString, ByteSlice, ByteVec};
+use gix_hash::ObjectId;
+
+use crate::{match_group::Item, RefSpecRef};
+
+/// A type keeping enough information about a ref-spec to be able to efficiently match it against multiple matcher items.
+pub struct Matcher<'a> {
+ pub(crate) lhs: Option<Needle<'a>>,
+ pub(crate) rhs: Option<Needle<'a>>,
+}
+
+impl<'a> Matcher<'a> {
+ /// Match `item` against this spec and return `(true, Some<rhs>)` to gain the other side of the match as configured, or `(true, None)`
+ /// if there was no `rhs`.
+ ///
+ /// This may involve resolving a glob with an allocation, as the destination is built using the matching portion of a glob.
+ pub fn matches_lhs(&self, item: Item<'_>) -> (bool, Option<Cow<'a, BStr>>) {
+ match (self.lhs, self.rhs) {
+ (Some(lhs), None) => (lhs.matches(item).is_match(), None),
+ (Some(lhs), Some(rhs)) => lhs.matches(item).into_match_outcome(rhs, item),
+ (None, None) | (None, Some(_)) => {
+ unreachable!("For all we know, the lefthand side is never empty. Push specs might change that.")
+ }
+ }
+ }
+}
+
+#[derive(Debug, Copy, Clone)]
+pub(crate) enum Needle<'a> {
+ FullName(&'a BStr),
+ PartialName(&'a BStr),
+ Glob { name: &'a BStr, asterisk_pos: usize },
+ Object(ObjectId),
+}
+
+enum Match {
+ /// There was no match.
+ None,
+ /// No additional data is provided as part of the match.
+ Normal,
+ /// The range of text to copy from the originating item name
+ GlobRange(Range<usize>),
+}
+
+impl Match {
+ fn is_match(&self) -> bool {
+ !matches!(self, Match::None)
+ }
+ fn into_match_outcome<'a>(self, destination: Needle<'a>, item: Item<'_>) -> (bool, Option<Cow<'a, BStr>>) {
+ let arg = match self {
+ Match::None => return (false, None),
+ Match::Normal => None,
+ Match::GlobRange(range) => Some((range, item)),
+ };
+ (true, destination.to_bstr_replace(arg).into())
+ }
+}
+
+impl<'a> Needle<'a> {
+ #[inline]
+ fn matches(&self, item: Item<'_>) -> Match {
+ match self {
+ Needle::FullName(name) => {
+ if *name == item.full_ref_name {
+ Match::Normal
+ } else {
+ Match::None
+ }
+ }
+ Needle::PartialName(name) => crate::spec::expand_partial_name(name, |expanded| {
+ (expanded == item.full_ref_name).then_some(Match::Normal)
+ })
+ .unwrap_or(Match::None),
+ Needle::Glob { name, asterisk_pos } => {
+ match item.full_ref_name.get(..*asterisk_pos) {
+ Some(full_name_portion) if full_name_portion != name[..*asterisk_pos] => {
+ return Match::None;
+ }
+ None => return Match::None,
+ _ => {}
+ };
+ let tail = &name[*asterisk_pos + 1..];
+ if !item.full_ref_name.ends_with(tail) {
+ return Match::None;
+ }
+ let end = item.full_ref_name.len() - tail.len();
+ Match::GlobRange(*asterisk_pos..end)
+ }
+ Needle::Object(id) => {
+ if *id == item.target {
+ return Match::Normal;
+ }
+ match item.object {
+ Some(object) if object == *id => Match::Normal,
+ _ => Match::None,
+ }
+ }
+ }
+ }
+
+ fn to_bstr_replace(self, range: Option<(Range<usize>, Item<'_>)>) -> Cow<'a, BStr> {
+ match (self, range) {
+ (Needle::FullName(name), None) => Cow::Borrowed(name),
+ (Needle::PartialName(name), None) => Cow::Owned({
+ let mut base: BString = "refs/".into();
+ if !(name.starts_with(b"tags/") || name.starts_with(b"remotes/")) {
+ base.push_str("heads/");
+ }
+ base.push_str(name);
+ base
+ }),
+ (Needle::Glob { name, asterisk_pos }, Some((range, item))) => {
+ let mut buf = Vec::with_capacity(name.len() + range.len() - 1);
+ buf.push_str(&name[..asterisk_pos]);
+ buf.push_str(&item.full_ref_name[range]);
+ buf.push_str(&name[asterisk_pos + 1..]);
+ Cow::Owned(buf.into())
+ }
+ (Needle::Object(id), None) => {
+ let mut name = id.to_string();
+ name.insert_str(0, "refs/heads/");
+ Cow::Owned(name.into())
+ }
+ (Needle::Glob { .. }, None) => unreachable!("BUG: no range provided for glob pattern"),
+ (_, Some(_)) => {
+ unreachable!("BUG: range provided even though needle wasn't a glob. Globs are symmetric.")
+ }
+ }
+ }
+
+ pub fn to_bstr(self) -> Cow<'a, BStr> {
+ self.to_bstr_replace(None)
+ }
+}
+
+impl<'a> From<&'a BStr> for Needle<'a> {
+ fn from(v: &'a BStr) -> Self {
+ if let Some(pos) = v.find_byte(b'*') {
+ Needle::Glob {
+ name: v,
+ asterisk_pos: pos,
+ }
+ } else if v.starts_with(b"refs/") {
+ Needle::FullName(v)
+ } else if let Ok(id) = gix_hash::ObjectId::from_hex(v) {
+ Needle::Object(id)
+ } else {
+ Needle::PartialName(v)
+ }
+ }
+}
+
+impl<'a> From<RefSpecRef<'a>> for Matcher<'a> {
+ fn from(v: RefSpecRef<'a>) -> Self {
+ Matcher {
+ lhs: v.src.map(Into::into),
+ rhs: v.dst.map(Into::into),
+ }
+ }
+}
diff --git a/vendor/gix-refspec/src/match_group/validate.rs b/vendor/gix-refspec/src/match_group/validate.rs
new file mode 100644
index 000000000..097a64587
--- /dev/null
+++ b/vendor/gix-refspec/src/match_group/validate.rs
@@ -0,0 +1,141 @@
+use std::collections::BTreeMap;
+
+use bstr::BString;
+
+use crate::{
+ match_group::{Outcome, Source},
+ RefSpec,
+};
+
+/// All possible issues found while validating matched mappings.
+#[derive(Debug, PartialEq, Eq)]
+pub enum Issue {
+ /// Multiple sources try to write the same destination.
+ ///
+ /// Note that this issue doesn't take into consideration that these sources might contain the same object behind a reference.
+ Conflict {
+ /// The unenforced full name of the reference to be written.
+ destination_full_ref_name: BString,
+ /// The list of sources that map to this destination.
+ sources: Vec<Source>,
+ /// The list of specs that caused the mapping conflict, each matching the respective one in `sources` to allow both
+ /// `sources` and `specs` to be zipped together.
+ specs: Vec<BString>,
+ },
+}
+
+impl std::fmt::Display for Issue {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Issue::Conflict {
+ destination_full_ref_name,
+ sources,
+ specs,
+ } => {
+ write!(
+ f,
+ "Conflicting destination {destination_full_ref_name:?} would be written by {}",
+ sources
+ .iter()
+ .zip(specs.iter())
+ .map(|(src, spec)| format!("{src} ({spec:?})"))
+ .collect::<Vec<_>>()
+ .join(", ")
+ )
+ }
+ }
+ }
+}
+
+/// All possible fixes corrected while validating matched mappings.
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub enum Fix {
+ /// Removed a mapping that contained a partial destination entirely.
+ MappingWithPartialDestinationRemoved {
+ /// The destination ref name that was ignored.
+ name: BString,
+ /// The spec that defined the mapping
+ spec: RefSpec,
+ },
+}
+
+/// The error returned [outcome validation][Outcome::validated()].
+#[derive(Debug)]
+pub struct Error {
+ /// All issues discovered during validation.
+ pub issues: Vec<Issue>,
+}
+
+impl std::fmt::Display for Error {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(
+ f,
+ "Found {} {} the refspec mapping to be used: \n\t{}",
+ self.issues.len(),
+ if self.issues.len() == 1 {
+ "issue that prevents"
+ } else {
+ "issues that prevent"
+ },
+ self.issues
+ .iter()
+ .map(|issue| issue.to_string())
+ .collect::<Vec<_>>()
+ .join("\n\t")
+ )
+ }
+}
+
+impl std::error::Error for Error {}
+
+impl<'spec, 'item> Outcome<'spec, 'item> {
+ /// Validate all mappings or dissolve them into an error stating the discovered issues.
+ /// Return `(modified self, issues)` providing a fixed-up set of mappings in `self` with the fixed `issues`
+ /// provided as part of it.
+ /// Terminal issues are communicated using the [`Error`] type accordingly.
+ pub fn validated(mut self) -> Result<(Self, Vec<Fix>), Error> {
+ let mut sources_by_destinations = BTreeMap::new();
+ for (dst, (spec_index, src)) in self
+ .mappings
+ .iter()
+ .filter_map(|m| m.rhs.as_ref().map(|dst| (dst.as_ref(), (m.spec_index, &m.lhs))))
+ {
+ let sources = sources_by_destinations.entry(dst).or_insert_with(Vec::new);
+ if !sources.iter().any(|(_, lhs)| lhs == &src) {
+ sources.push((spec_index, src))
+ }
+ }
+ let mut issues = Vec::new();
+ for (dst, conflicting_sources) in sources_by_destinations.into_iter().filter(|(_, v)| v.len() > 1) {
+ issues.push(Issue::Conflict {
+ destination_full_ref_name: dst.to_owned(),
+ specs: conflicting_sources
+ .iter()
+ .map(|(spec_idx, _)| self.group.specs[*spec_idx].to_bstring())
+ .collect(),
+ sources: conflicting_sources.into_iter().map(|(_, src)| src.to_owned()).collect(),
+ })
+ }
+ if !issues.is_empty() {
+ Err(Error { issues })
+ } else {
+ let mut fixed = Vec::new();
+ let group = &self.group;
+ self.mappings.retain(|m| match m.rhs.as_ref() {
+ Some(dst) => {
+ if dst.starts_with(b"refs/") || dst.as_ref() == "HEAD" {
+ true
+ } else {
+ fixed.push(Fix::MappingWithPartialDestinationRemoved {
+ name: dst.as_ref().to_owned(),
+ spec: group.specs[m.spec_index].to_owned(),
+ });
+ false
+ }
+ }
+ None => true,
+ });
+ Ok((self, fixed))
+ }
+ }
+}
diff --git a/vendor/gix-refspec/src/parse.rs b/vendor/gix-refspec/src/parse.rs
new file mode 100644
index 000000000..390db13fa
--- /dev/null
+++ b/vendor/gix-refspec/src/parse.rs
@@ -0,0 +1,255 @@
+/// The error returned by the [`parse()`][crate::parse()] function.
+#[derive(Debug, thiserror::Error)]
+#[allow(missing_docs)]
+pub enum Error {
+ #[error("Empty refspecs are invalid")]
+ Empty,
+ #[error("Negative refspecs cannot have destinations as they exclude sources")]
+ NegativeWithDestination,
+ #[error("Negative specs must not be empty")]
+ NegativeEmpty,
+ #[error("Negative specs are only supported when fetching")]
+ NegativeUnsupported,
+ #[error("Negative specs must be object hashes")]
+ NegativeObjectHash,
+ #[error("Negative specs must be full ref names, starting with \"refs/\"")]
+ NegativePartialName,
+ #[error("Negative glob patterns are not allowed")]
+ NegativeGlobPattern,
+ #[error("Fetch destinations must be ref-names, like 'HEAD:refs/heads/branch'")]
+ InvalidFetchDestination,
+ #[error("Cannot push into an empty destination")]
+ PushToEmpty,
+ #[error("glob patterns may only involved a single '*' character, found {pattern:?}")]
+ PatternUnsupported { pattern: bstr::BString },
+ #[error("Both sides of the specification need a pattern, like 'a/*:b/*'")]
+ PatternUnbalanced,
+ #[error(transparent)]
+ ReferenceName(#[from] gix_validate::refname::Error),
+ #[error(transparent)]
+ RevSpec(#[from] gix_revision::spec::parse::Error),
+}
+
+/// Define how the parsed refspec should be used.
+#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Hash, Debug)]
+pub enum Operation {
+ /// The `src` side is local and the `dst` side is remote.
+ Push,
+ /// The `src` side is remote and the `dst` side is local.
+ Fetch,
+}
+
+pub(crate) mod function {
+ use bstr::{BStr, ByteSlice};
+
+ use crate::{
+ parse::{Error, Operation},
+ types::Mode,
+ RefSpecRef,
+ };
+
+ /// Parse `spec` for use in `operation` and return it if it is valid.
+ pub fn parse(mut spec: &BStr, operation: Operation) -> Result<RefSpecRef<'_>, Error> {
+ fn fetch_head_only(mode: Mode) -> RefSpecRef<'static> {
+ RefSpecRef {
+ mode,
+ op: Operation::Fetch,
+ src: Some("HEAD".into()),
+ dst: None,
+ }
+ }
+
+ let mode = match spec.first() {
+ Some(&b'^') => {
+ spec = &spec[1..];
+ if operation == Operation::Push {
+ return Err(Error::NegativeUnsupported);
+ }
+ Mode::Negative
+ }
+ Some(&b'+') => {
+ spec = &spec[1..];
+ Mode::Force
+ }
+ Some(_) => Mode::Normal,
+ None => {
+ return match operation {
+ Operation::Push => Err(Error::Empty),
+ Operation::Fetch => Ok(fetch_head_only(Mode::Normal)),
+ }
+ }
+ };
+
+ let (mut src, dst) = match spec.find_byte(b':') {
+ Some(pos) => {
+ if mode == Mode::Negative {
+ return Err(Error::NegativeWithDestination);
+ }
+
+ let (src, dst) = spec.split_at(pos);
+ let dst = &dst[1..];
+ let src = (!src.is_empty()).then(|| src.as_bstr());
+ let dst = (!dst.is_empty()).then(|| dst.as_bstr());
+ match (src, dst) {
+ (None, None) => match operation {
+ Operation::Push => (None, None),
+ Operation::Fetch => (Some("HEAD".into()), None),
+ },
+ (None, Some(dst)) => match operation {
+ Operation::Push => (None, Some(dst)),
+ Operation::Fetch => (Some("HEAD".into()), Some(dst)),
+ },
+ (Some(src), None) => match operation {
+ Operation::Push => return Err(Error::PushToEmpty),
+ Operation::Fetch => (Some(src), None),
+ },
+ (Some(src), Some(dst)) => (Some(src), Some(dst)),
+ }
+ }
+ None => {
+ let src = (!spec.is_empty()).then_some(spec);
+ if Operation::Fetch == operation && mode != Mode::Negative && src.is_none() {
+ return Ok(fetch_head_only(mode));
+ } else {
+ (src, None)
+ }
+ }
+ };
+
+ if let Some(spec) = src.as_mut() {
+ if *spec == "@" {
+ *spec = "HEAD".into();
+ }
+ }
+ let (src, src_had_pattern) = validated(src, operation == Operation::Push && dst.is_some())?;
+ let (dst, dst_had_pattern) = validated(dst, false)?;
+ if mode != Mode::Negative && src_had_pattern != dst_had_pattern {
+ return Err(Error::PatternUnbalanced);
+ }
+
+ if mode == Mode::Negative {
+ match src {
+ Some(spec) => {
+ if src_had_pattern {
+ return Err(Error::NegativeGlobPattern);
+ } else if looks_like_object_hash(spec) {
+ return Err(Error::NegativeObjectHash);
+ } else if !spec.starts_with(b"refs/") && spec != "HEAD" {
+ return Err(Error::NegativePartialName);
+ }
+ }
+ None => return Err(Error::NegativeEmpty),
+ }
+ }
+
+ Ok(RefSpecRef {
+ op: operation,
+ mode,
+ src,
+ dst,
+ })
+ }
+
+ fn looks_like_object_hash(spec: &BStr) -> bool {
+ spec.len() >= gix_hash::Kind::shortest().len_in_hex() && spec.iter().all(|b| b.is_ascii_hexdigit())
+ }
+
+ fn validated(spec: Option<&BStr>, allow_revspecs: bool) -> Result<(Option<&BStr>, bool), Error> {
+ match spec {
+ Some(spec) => {
+ let glob_count = spec.iter().filter(|b| **b == b'*').take(2).count();
+ if glob_count > 1 {
+ return Err(Error::PatternUnsupported { pattern: spec.into() });
+ }
+ let has_globs = glob_count == 1;
+ if has_globs {
+ let mut buf = smallvec::SmallVec::<[u8; 256]>::with_capacity(spec.len());
+ buf.extend_from_slice(spec);
+ let glob_pos = buf.find_byte(b'*').expect("glob present");
+ buf[glob_pos] = b'a';
+ gix_validate::reference::name_partial(buf.as_bstr())?;
+ } else {
+ gix_validate::reference::name_partial(spec)
+ .map_err(Error::from)
+ .or_else(|err| {
+ if allow_revspecs {
+ match gix_revision::spec::parse(spec, &mut super::revparse::Noop) {
+ Ok(_) => {
+ if spec.iter().any(|b| b.is_ascii_whitespace()) {
+ Err(err)
+ } else {
+ Ok(spec)
+ }
+ }
+ Err(err) => Err(err.into()),
+ }
+ } else {
+ Err(err)
+ }
+ })?;
+ }
+ Ok((Some(spec), has_globs))
+ }
+ None => Ok((None, false)),
+ }
+ }
+}
+
+mod revparse {
+ use bstr::BStr;
+ use gix_revision::spec::parse::delegate::{
+ Kind, Navigate, PeelTo, PrefixHint, ReflogLookup, Revision, SiblingBranch, Traversal,
+ };
+
+ pub(crate) struct Noop;
+
+ impl Revision for Noop {
+ fn find_ref(&mut self, _name: &BStr) -> Option<()> {
+ Some(())
+ }
+
+ fn disambiguate_prefix(&mut self, _prefix: gix_hash::Prefix, _hint: Option<PrefixHint<'_>>) -> Option<()> {
+ Some(())
+ }
+
+ fn reflog(&mut self, _query: ReflogLookup) -> Option<()> {
+ Some(())
+ }
+
+ fn nth_checked_out_branch(&mut self, _branch_no: usize) -> Option<()> {
+ Some(())
+ }
+
+ fn sibling_branch(&mut self, _kind: SiblingBranch) -> Option<()> {
+ Some(())
+ }
+ }
+
+ impl Navigate for Noop {
+ fn traverse(&mut self, _kind: Traversal) -> Option<()> {
+ Some(())
+ }
+
+ fn peel_until(&mut self, _kind: PeelTo<'_>) -> Option<()> {
+ Some(())
+ }
+
+ fn find(&mut self, _regex: &BStr, _negated: bool) -> Option<()> {
+ Some(())
+ }
+
+ fn index_lookup(&mut self, _path: &BStr, _stage: u8) -> Option<()> {
+ Some(())
+ }
+ }
+
+ impl Kind for Noop {
+ fn kind(&mut self, _kind: gix_revision::spec::Kind) -> Option<()> {
+ Some(())
+ }
+ }
+
+ impl gix_revision::spec::parse::Delegate for Noop {
+ fn done(&mut self) {}
+ }
+}
diff --git a/vendor/gix-refspec/src/spec.rs b/vendor/gix-refspec/src/spec.rs
new file mode 100644
index 000000000..9361ae682
--- /dev/null
+++ b/vendor/gix-refspec/src/spec.rs
@@ -0,0 +1,257 @@
+use bstr::{BStr, BString, ByteSlice};
+
+use crate::{
+ instruction::{Fetch, Push},
+ parse::Operation,
+ types::Mode,
+ Instruction, RefSpec, RefSpecRef,
+};
+
+/// Conversion. Use the [RefSpecRef][RefSpec::to_ref()] type for more usage options.
+impl RefSpec {
+ /// Return ourselves as reference type.
+ pub fn to_ref(&self) -> RefSpecRef<'_> {
+ RefSpecRef {
+ mode: self.mode,
+ op: self.op,
+ src: self.src.as_ref().map(|b| b.as_ref()),
+ dst: self.dst.as_ref().map(|b| b.as_ref()),
+ }
+ }
+
+ /// Return true if the spec stats with a `+` and thus forces setting the reference.
+ pub fn allow_non_fast_forward(&self) -> bool {
+ matches!(self.mode, Mode::Force)
+ }
+}
+
+mod impls {
+ use std::{
+ cmp::Ordering,
+ hash::{Hash, Hasher},
+ };
+
+ use crate::{RefSpec, RefSpecRef};
+
+ impl From<RefSpecRef<'_>> for RefSpec {
+ fn from(v: RefSpecRef<'_>) -> Self {
+ v.to_owned()
+ }
+ }
+
+ impl Hash for RefSpec {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.to_ref().hash(state)
+ }
+ }
+
+ impl Hash for RefSpecRef<'_> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.instruction().hash(state)
+ }
+ }
+
+ impl PartialEq for RefSpec {
+ fn eq(&self, other: &Self) -> bool {
+ self.to_ref().eq(&other.to_ref())
+ }
+ }
+
+ impl PartialEq for RefSpecRef<'_> {
+ fn eq(&self, other: &Self) -> bool {
+ self.instruction().eq(&other.instruction())
+ }
+ }
+
+ impl PartialOrd for RefSpecRef<'_> {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ self.instruction().partial_cmp(&other.instruction())
+ }
+ }
+
+ impl PartialOrd for RefSpec {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ self.to_ref().partial_cmp(&other.to_ref())
+ }
+ }
+
+ impl Ord for RefSpecRef<'_> {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.instruction().cmp(&other.instruction())
+ }
+ }
+
+ impl Ord for RefSpec {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.to_ref().cmp(&other.to_ref())
+ }
+ }
+}
+
+/// Access
+impl<'a> RefSpecRef<'a> {
+ /// Return the left-hand side of the spec, typically the source.
+ /// It takes many different forms so don't rely on this being a ref name.
+ ///
+ /// It's not present in case of deletions.
+ pub fn source(&self) -> Option<&BStr> {
+ self.src
+ }
+
+ /// Return the right-hand side of the spec, typically the destination.
+ /// It takes many different forms so don't rely on this being a ref name.
+ ///
+ /// It's not present in case of source-only specs.
+ pub fn destination(&self) -> Option<&BStr> {
+ self.dst
+ }
+
+ /// Always returns the remote side, whose actual side in the refspec depends on how it was parsed.
+ pub fn remote(&self) -> Option<&BStr> {
+ match self.op {
+ Operation::Push => self.dst,
+ Operation::Fetch => self.src,
+ }
+ }
+
+ /// Always returns the local side, whose actual side in the refspec depends on how it was parsed.
+ pub fn local(&self) -> Option<&BStr> {
+ match self.op {
+ Operation::Push => self.src,
+ Operation::Fetch => self.dst,
+ }
+ }
+
+ /// Derive the prefix from the [`source`][Self::source()] side of this spec if this is a fetch spec,
+ /// or the [`destination`][Self::destination()] side if it is a push spec, if it is possible to do so without ambiguity.
+ ///
+ /// This means it starts with `refs/`. Note that it won't contain more than two components, like `refs/heads/`
+ pub fn prefix(&self) -> Option<&BStr> {
+ if self.mode == Mode::Negative {
+ return None;
+ }
+ let source = match self.op {
+ Operation::Fetch => self.source(),
+ Operation::Push => self.destination(),
+ }?;
+ if source == "HEAD" {
+ return source.into();
+ }
+ let suffix = source.strip_prefix(b"refs/")?;
+ let slash_pos = suffix.find_byte(b'/')?;
+ let prefix = source[..="refs/".len() + slash_pos].as_bstr();
+ (!prefix.contains(&b'*')).then_some(prefix)
+ }
+
+ /// As opposed to [`prefix()`][Self::prefix], if the latter is `None` it will expand to all possible prefixes and place them in `out`.
+ ///
+ /// Note that only the `source` side is considered.
+ pub fn expand_prefixes(&self, out: &mut Vec<BString>) {
+ match self.prefix() {
+ Some(prefix) => out.push(prefix.into()),
+ None => {
+ let source = match match self.op {
+ Operation::Fetch => self.source(),
+ Operation::Push => self.destination(),
+ } {
+ Some(source) => source,
+ None => return,
+ };
+ if let Some(rest) = source.strip_prefix(b"refs/") {
+ if !rest.contains(&b'/') {
+ out.push(source.into());
+ }
+ return;
+ } else if gix_hash::ObjectId::from_hex(source).is_ok() {
+ return;
+ }
+ expand_partial_name(source, |expanded| {
+ out.push(expanded.into());
+ None::<()>
+ });
+ }
+ }
+ }
+
+ /// Transform the state of the refspec into an instruction making clear what to do with it.
+ pub fn instruction(&self) -> Instruction<'a> {
+ match self.op {
+ Operation::Fetch => match (self.mode, self.src, self.dst) {
+ (Mode::Normal | Mode::Force, Some(src), None) => Instruction::Fetch(Fetch::Only { src }),
+ (Mode::Normal | Mode::Force, Some(src), Some(dst)) => Instruction::Fetch(Fetch::AndUpdate {
+ src,
+ dst,
+ allow_non_fast_forward: matches!(self.mode, Mode::Force),
+ }),
+ (Mode::Negative, Some(src), None) => Instruction::Fetch(Fetch::Exclude { src }),
+ (mode, src, dest) => {
+ unreachable!(
+ "BUG: fetch instructions with {:?} {:?} {:?} are not possible",
+ mode, src, dest
+ )
+ }
+ },
+ Operation::Push => match (self.mode, self.src, self.dst) {
+ (Mode::Normal | Mode::Force, Some(src), None) => Instruction::Push(Push::Matching {
+ src,
+ dst: src,
+ allow_non_fast_forward: matches!(self.mode, Mode::Force),
+ }),
+ (Mode::Normal | Mode::Force, None, Some(dst)) => {
+ Instruction::Push(Push::Delete { ref_or_pattern: dst })
+ }
+ (Mode::Normal | Mode::Force, None, None) => Instruction::Push(Push::AllMatchingBranches {
+ allow_non_fast_forward: matches!(self.mode, Mode::Force),
+ }),
+ (Mode::Normal | Mode::Force, Some(src), Some(dst)) => Instruction::Push(Push::Matching {
+ src,
+ dst,
+ allow_non_fast_forward: matches!(self.mode, Mode::Force),
+ }),
+ (mode, src, dest) => {
+ unreachable!(
+ "BUG: push instructions with {:?} {:?} {:?} are not possible",
+ mode, src, dest
+ )
+ }
+ },
+ }
+ }
+}
+
+/// Conversion
+impl RefSpecRef<'_> {
+ /// Convert this ref into a standalone, owned copy.
+ pub fn to_owned(&self) -> RefSpec {
+ RefSpec {
+ mode: self.mode,
+ op: self.op,
+ src: self.src.map(ToOwned::to_owned),
+ dst: self.dst.map(ToOwned::to_owned),
+ }
+ }
+}
+
+pub(crate) fn expand_partial_name<T>(name: &BStr, mut cb: impl FnMut(&BStr) -> Option<T>) -> Option<T> {
+ use bstr::ByteVec;
+ let mut buf = BString::from(Vec::with_capacity(128));
+ for (base, append_head) in [
+ ("", false),
+ ("refs/", false),
+ ("refs/tags/", false),
+ ("refs/heads/", false),
+ ("refs/remotes/", false),
+ ("refs/remotes/", true),
+ ] {
+ buf.clear();
+ buf.push_str(base);
+ buf.push_str(name);
+ if append_head {
+ buf.push_str("/HEAD");
+ }
+ if let Some(res) = cb(buf.as_ref()) {
+ return Some(res);
+ }
+ }
+ None
+}
diff --git a/vendor/gix-refspec/src/types.rs b/vendor/gix-refspec/src/types.rs
new file mode 100644
index 000000000..0a0e24e36
--- /dev/null
+++ b/vendor/gix-refspec/src/types.rs
@@ -0,0 +1,21 @@
+use crate::instruction;
+
+/// The way to interpret a refspec.
+#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Hash, Debug)]
+pub(crate) enum Mode {
+ /// Apply standard rules for refspecs which are including refs with specific rules related to allowing fast forwards of destinations.
+ Normal,
+ /// Even though according to normal rules a non-fastforward would be denied, override this and reset a ref forcefully in the destination.
+ Force,
+ /// Instead of considering matching refs included, we consider them excluded. This applies only to the source side of a refspec.
+ Negative,
+}
+
+/// Tells what to do and is derived from a [`RefSpec`][crate::RefSpecRef].
+#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Hash, Debug)]
+pub enum Instruction<'a> {
+ /// An instruction for pushing.
+ Push(instruction::Push<'a>),
+ /// An instruction for fetching.
+ Fetch(instruction::Fetch<'a>),
+}
diff --git a/vendor/gix-refspec/src/write.rs b/vendor/gix-refspec/src/write.rs
new file mode 100644
index 000000000..74c71c6e1
--- /dev/null
+++ b/vendor/gix-refspec/src/write.rs
@@ -0,0 +1,74 @@
+use bstr::BString;
+
+use crate::{
+ instruction::{Fetch, Push},
+ Instruction, RefSpecRef,
+};
+
+impl RefSpecRef<'_> {
+ /// Reproduce ourselves in parseable form.
+ pub fn to_bstring(&self) -> BString {
+ let mut buf = Vec::with_capacity(128);
+ self.write_to(&mut buf).expect("no io error");
+ buf.into()
+ }
+
+ /// Serialize ourselves in a parseable format to `out`.
+ pub fn write_to(&self, out: impl std::io::Write) -> std::io::Result<()> {
+ self.instruction().write_to(out)
+ }
+}
+
+impl Instruction<'_> {
+ /// Reproduce ourselves in parseable form.
+ pub fn to_bstring(&self) -> BString {
+ let mut buf = Vec::with_capacity(128);
+ self.write_to(&mut buf).expect("no io error");
+ buf.into()
+ }
+
+ /// Serialize ourselves in a parseable format to `out`.
+ pub fn write_to(&self, mut out: impl std::io::Write) -> std::io::Result<()> {
+ match self {
+ Instruction::Push(Push::Matching {
+ src,
+ dst,
+ allow_non_fast_forward,
+ }) => {
+ if *allow_non_fast_forward {
+ out.write_all(&[b'+'])?;
+ }
+ out.write_all(src)?;
+ out.write_all(&[b':'])?;
+ out.write_all(dst)
+ }
+ Instruction::Push(Push::AllMatchingBranches { allow_non_fast_forward }) => {
+ if *allow_non_fast_forward {
+ out.write_all(&[b'+'])?;
+ }
+ out.write_all(&[b':'])
+ }
+ Instruction::Push(Push::Delete { ref_or_pattern }) => {
+ out.write_all(&[b':'])?;
+ out.write_all(ref_or_pattern)
+ }
+ Instruction::Fetch(Fetch::Only { src }) => out.write_all(src),
+ Instruction::Fetch(Fetch::Exclude { src }) => {
+ out.write_all(&[b'^'])?;
+ out.write_all(src)
+ }
+ Instruction::Fetch(Fetch::AndUpdate {
+ src,
+ dst,
+ allow_non_fast_forward,
+ }) => {
+ if *allow_non_fast_forward {
+ out.write_all(&[b'+'])?;
+ }
+ out.write_all(src)?;
+ out.write_all(&[b':'])?;
+ out.write_all(dst)
+ }
+ }
+ }
+}