summaryrefslogtreecommitdiffstats
path: root/vendor/gix-credentials
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:35 +0000
commit7e5d7eea9c580ef4b41a765bde624af431942b96 (patch)
tree2c0d9ca12878fc4525650aa4e54d77a81a07cc09 /vendor/gix-credentials
parentAdding debian version 1.70.0+dfsg1-9. (diff)
downloadrustc-7e5d7eea9c580ef4b41a765bde624af431942b96.tar.xz
rustc-7e5d7eea9c580ef4b41a765bde624af431942b96.zip
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix-credentials')
-rw-r--r--vendor/gix-credentials/.cargo-checksum.json1
-rw-r--r--vendor/gix-credentials/CHANGELOG.md561
-rw-r--r--vendor/gix-credentials/Cargo.lock560
-rw-r--r--vendor/gix-credentials/Cargo.toml76
-rw-r--r--vendor/gix-credentials/examples/custom-helper.rs24
-rw-r--r--vendor/gix-credentials/examples/git-credential-lite.rs23
-rw-r--r--vendor/gix-credentials/examples/invoke-git-credential.rs14
-rw-r--r--vendor/gix-credentials/src/helper/cascade.rs161
-rw-r--r--vendor/gix-credentials/src/helper/invoke.rs66
-rw-r--r--vendor/gix-credentials/src/helper/mod.rs174
-rw-r--r--vendor/gix-credentials/src/lib.rs43
-rw-r--r--vendor/gix-credentials/src/program/main.rs110
-rw-r--r--vendor/gix-credentials/src/program/mod.rs131
-rw-r--r--vendor/gix-credentials/src/protocol/context/mod.rs79
-rw-r--r--vendor/gix-credentials/src/protocol/context/serde.rs122
-rw-r--r--vendor/gix-credentials/src/protocol/mod.rs86
-rw-r--r--vendor/gix-credentials/tests/credentials.rs5
-rw-r--r--vendor/gix-credentials/tests/fixtures/all-but-credentials.sh6
-rwxr-xr-xvendor/gix-credentials/tests/fixtures/custom-helper.sh6
-rw-r--r--vendor/gix-credentials/tests/fixtures/fail.sh3
-rw-r--r--vendor/gix-credentials/tests/fixtures/last-pass.sh6
-rw-r--r--vendor/gix-credentials/tests/fixtures/password.sh3
-rw-r--r--vendor/gix-credentials/tests/fixtures/reflect.sh3
-rw-r--r--vendor/gix-credentials/tests/fixtures/url.sh7
-rw-r--r--vendor/gix-credentials/tests/fixtures/username.sh3
-rw-r--r--vendor/gix-credentials/tests/helper/cascade.rs174
-rw-r--r--vendor/gix-credentials/tests/helper/context.rs123
-rw-r--r--vendor/gix-credentials/tests/helper/invoke.rs134
-rw-r--r--vendor/gix-credentials/tests/helper/mod.rs39
-rw-r--r--vendor/gix-credentials/tests/program/from_custom_definition.rs42
-rw-r--r--vendor/gix-credentials/tests/program/mod.rs1
-rw-r--r--vendor/gix-credentials/tests/protocol/context.rs175
-rw-r--r--vendor/gix-credentials/tests/protocol/mod.rs1
33 files changed, 2962 insertions, 0 deletions
diff --git a/vendor/gix-credentials/.cargo-checksum.json b/vendor/gix-credentials/.cargo-checksum.json
new file mode 100644
index 000000000..0c7f9e1e5
--- /dev/null
+++ b/vendor/gix-credentials/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"0ffcf6f33f4701f18747f654ba3b5031d7398d111e89463f35a4211d248827cc","Cargo.lock":"644e2453c93d5b701a73f207d84008ccc13cfd85a528926e54e23c795acd046e","Cargo.toml":"1845ff48e5eb3fa9f4f1f76a32232046c1772c8e0d2a28f9948635aa974906a4","examples/custom-helper.rs":"fadd3fe61cf2d3038cdb6b634e5a52f298d2c156c2317f5e7c703715a9096dff","examples/git-credential-lite.rs":"f25a670f26e3b4ec444afea3354a94ab1c075c6988314e0925e530e6f0dcf46b","examples/invoke-git-credential.rs":"85d2662bcc37fa4425e967149e141caa7e739fe8bc7dc8cdcc872ea5c0c6a6c5","src/helper/cascade.rs":"9b46c0a51e3493c321e67d316687602f31f690af58057819cebbcf9bd7e30a89","src/helper/invoke.rs":"e08b12e518d4e2501c45923ed65af091611678f6d5092321e20a8b7b0515d117","src/helper/mod.rs":"df942a16e9e80b2e63d3fa44c8317e078ed35cc0682ec967d234743529b3dc0e","src/lib.rs":"f99aead3fa9ba153b33c93541c0063550e646d121543d9fb07aa52860100cd48","src/program/main.rs":"31fdace05f1a6b305abdb9f21a89329c538846c350078e55cdd980a607d4c67f","src/program/mod.rs":"ca0619144baf3108358fe3e4ccc6cf6294deeebcb83035b9f7177ab243855762","src/protocol/context/mod.rs":"e7a8c322326832d4935b7daf75d1f8d91852fc9e5204bd61c133df8ba9ac1e75","src/protocol/context/serde.rs":"5e8af0a4cafbf70a92398c9bf7905bedf2b9ddb8b2873a4ab24ab121ae40409e","src/protocol/mod.rs":"acc1bc337267c3f295b5c9570284bb10c2508dd744296a28bdfabb7cd1201586","tests/credentials.rs":"7af4899fa6582525f33a39b3f5874eebc42b3a94788ac4b0180f25aadf9fc0b2","tests/fixtures/all-but-credentials.sh":"df53ad6402be8133c2ea4fa3f3b54471b629dde48f4f0fb3affb770c22961f81","tests/fixtures/custom-helper.sh":"4484e5ab3447136490161cb7cc8c63ee6807b8dec5feed0e95824fb83ae0e044","tests/fixtures/fail.sh":"93f2c30907443ad1411fbba7a1c6be1f05e0a349a7321d764e0f641218c497e6","tests/fixtures/last-pass.sh":"84722968b9e510f37267a97ce6cd29a64b33d228a1b1117958629abcc0c8b8b0","tests/fixtures/password.sh":"0eda11e74bd2603121ee1de795cbb6b7f9055ea4dd5783aa0f82960e7d9c6d05","tests/fixtures/reflect.sh":"104643bd6928f5e0c402f7e4fe5f6f12ad372859737b8a3a24fd5c38dc3a42e5","tests/fixtures/url.sh":"b887d0f70b8d8ea294aba4ebebd9d7edacd87a21413797ea03d2f282ccdc7af3","tests/fixtures/username.sh":"2f0363864dc67df16cb6c71422eee0cd34b4f6230be54206c02ce8b2111c2225","tests/helper/cascade.rs":"40752df9705581ea7c51376cedddc16c7a5f53afe3344f55f37e371a8d15b6c8","tests/helper/context.rs":"efd10518c8b97db402e75004d888cd96d2061a19a2b57e94df26863c6c418b8c","tests/helper/invoke.rs":"26909033ebe2d6f4b683d2e9a1fd572419fa154c95da2f5a2b7d5f8bee26afdc","tests/helper/mod.rs":"4ba9732420f2d0c25199a8a6e4056064c5df753a73dd2c4a4d6163b5b4dc2600","tests/program/from_custom_definition.rs":"b229b88038ed26e6b9984660575f6f488b861bf98f4bac6565130065d9da18a3","tests/program/mod.rs":"a1618f6a32c09ed909204cbb01ddd50c20e481e0a6e8d0b02d23a148b4b12e0f","tests/protocol/context.rs":"19af6d90a7a70fde1d6741f55fbe7445d5b4bdab58b5a70cc26a56f7903e1bf4","tests/protocol/mod.rs":"56b54a6a05c127cfc99fe60bbb24f9cc931b6579e394a5b0079022a8cb6ef3d1"},"package":"5be32b5fe339a31b8e53fa854081dc914c45020dcb64637f3c21baf69c96fc1b"} \ No newline at end of file
diff --git a/vendor/gix-credentials/CHANGELOG.md b/vendor/gix-credentials/CHANGELOG.md
new file mode 100644
index 000000000..6b1c3d2d5
--- /dev/null
+++ b/vendor/gix-credentials/CHANGELOG.md
@@ -0,0 +1,561 @@
+# 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.11.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.10.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.9.2 (2023-02-20)
+
+### Bug Fixes
+
+ - <csr-id-e14dc7d475373d2c266e84ff8f1826c68a34ab92/> note that crates have been renamed from `git-*` to `gix-*`.
+ This also means that the `git-*` prefixed crates of the `gitoxide` project
+ are effectively unmaintained.
+ Use the crates with the `gix-*` prefix instead.
+
+ If you were using `git-repository`, then `gix` is its substitute.
+ - <csr-id-135d317065aae87af302beb6c26bb6ca8e30b6aa/> compatibility with `bstr` v1.3, use `*.as_bytes()` instead of `.as_ref()`.
+ `as_ref()` relies on a known target type which isn't always present. However, once
+ there is only one implementation, that's no problem, but when that changes compilation
+ fails due to ambiguity.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 2 commits contributed to the release.
+ - 3 days passed between releases.
+ - 1 commit was understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-date v0.4.3, gix-hash v0.10.3, gix-features v0.26.5, gix-actor v0.17.2, gix-glob v0.5.5, gix-path v0.7.2, gix-quote v0.4.2, gix-attributes v0.8.3, gix-validate v0.7.3, gix-object v0.26.2, gix-ref v0.24.1, gix-config v0.16.2, gix-command v0.2.4, gix-url v0.13.3, gix-credentials v0.9.2, gix-discover v0.13.1, gix-index v0.12.4, gix-mailmap v0.9.3, gix-pack v0.30.3, gix-packetline v0.14.3, gix-transport v0.25.6, gix-protocol v0.26.4, gix-revision v0.10.4, gix-refspec v0.7.3, gix-worktree v0.12.3, gix v0.36.1 ([`9604783`](https://github.com/Byron/gitoxide/commit/96047839a20a657a559376b0b14c65aeab96acbd))
+ - Compatibility with `bstr` v1.3, use `*.as_bytes()` instead of `.as_ref()`. ([`135d317`](https://github.com/Byron/gitoxide/commit/135d317065aae87af302beb6c26bb6ca8e30b6aa))
+</details>
+
+## 0.9.1 (2023-02-17)
+
+<csr-id-b8c54f03fdb6060caf9c04557c0530c090e7a975/>
+<csr-id-4c39521a47419bb4b0f0edbe51aa509fb4e2a7f1/>
+<csr-id-d95029eac0e9179a7cd730d1d60a08696584bfd1/>
+<csr-id-f7f136dbe4f86e7dee1d54835c420ec07c96cd78/>
+<csr-id-533e887e80c5f7ede8392884562e1c5ba56fb9a8/>
+
+### Other (BREAKING)
+
+ - <csr-id-b8c54f03fdb6060caf9c04557c0530c090e7a975/> `helper::Kind` to `program::Kind`
+ - <csr-id-4c39521a47419bb4b0f0edbe51aa509fb4e2a7f1/> `helper::(encode|decode)_message(…)` to `::message::(encode|decode)(…)`
+
+### 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-99905bacace8aed42b16d43f0f04cae996cb971c/> upgrade `bstr` to `1.0.1`
+ - <csr-id-783a1a7dfd64a64fa765fa3d3ef41b1e954413ee/> rename `git()` to `builtin()`
+ - <csr-id-bfa2545883daf8c4d9e97d2fc91c9328d73ab0eb/> rename `Program::Custom*` variants to `Program::External*`
+ It's more true to what it is.
+ - <csr-id-811985aba024385465104ed826a9989961555201/> differentiate between top-level functions and those which are invoked
+ That way it's easier to use as it can assure an account was actually
+ provided.
+ - <csr-id-49b9bd501f33f1e10ce0180e814b84e293bd3898/> invoke::Outcome can now represent partial identities
+ That way these can be assembled by multiple helpers called in a row.
+ - <csr-id-4b7d0b6d2c43cac9823885bc69510cc4bb6a3f00/> move `helper::(Next)Action` into `helper::invoke::` module
+ These are only relevant for invoke, hence the change.
+ - <csr-id-ddd53988a6d5da17fc65451a059bed1bfa2eb454/> rename `helper::NextAction` variants to `store` and `erase`
+ - <csr-id-2073b583dc2bd83b800584edda6592bb71a01538/> rename `helper::Action` variants to 'Get', 'Store', 'Erase'
+ It's more obvious what it does and is more typical for what credentials
+ helpers do.
+ - <csr-id-9c6f024f838d866645937a67cd67dffb8be17259/> Use `helper::Context` in `helper::Action::Fill()`
+ That way additional information, like from configuration, can be passed
+ as well.
+ - <csr-id-71f651930e6fd53e3c3f9e82dfd95828e4981d92/> move `helper::invoke()` related types into `helper::invoke` module.
+ Also allow to pass arbitrary bytes (more or less) as context by not
+ forcing it all into a string. Values can now be everything, which
+ helps with passing paths or other values.
+ - <csr-id-4c1a1a28558c4f8d084b8046afd5d87a11fd25b7/> use `thiserror` instead of `quickerror`
+ - <csr-id-081934ca4452e550cf2663026905bce67253af81/> hide `helper::action()` in favor of single path via `helper()`
+ - <csr-id-12589cc6f08e4d7aabae30bcdadaa0c2b4850229/> adapt to changes in `git-url` and use `BString` to represent URLs.
+ They can contain paths, which is why `String` can't repsent a URL
+ losslessly.
+
+ For HTTP urls these are ultimately UTF-8 strings though.
+
+### Other
+
+ - <csr-id-d95029eac0e9179a7cd730d1d60a08696584bfd1/> :main::Action::as_str()`
+
+### New Features
+
+ - <csr-id-6b375d3061f6d307101199eff1ecdfdeb6769965/> `helper::Cascade::query_user_only()` can avoid to ask for the password if the transport wouldn't use it.
+ That way, `ssh` while using ssh programs can query the user to try next.
+ - <csr-id-15f1afccb7ed0ebaf217cbbdd58e6ae651a31e42/> `protocol::Context::to_bstring()`, and use it in `example/git-credential-lite`
+ - <csr-id-b1d528ae60001ae51dd89b29c26ea505eacbef45/> an example implementing a custom credential helper program
+ - <csr-id-eaff67c14366f149ccca346acb46af12531a24e6/> `helper::main` to easily create credential helper implementations
+ - <csr-id-a253d30093122e37b5560ff86a7888f8062c7014/> add `helper::Action::get_for_url(…)`
+ - <csr-id-64bc2ec666dacba486bd1de2fbd95f97f2efc7a5/> `helper::invoke(helper, action, context)` function that allows for more flexible helper invocation
+ - <csr-id-b1c40b0364ef092cd52d03b34f491b254816b18d/> use docsrs feature in code to show what is feature-gated automatically on docs.rs
+ - <csr-id-517677147f1c17304c62cf97a1dd09f232ebf5db/> pass --cfg docsrs when compiling for https://docs.rs
+ - <csr-id-3d339d5c24630fac0192b5d27f9b1cbd94418730/> use `git-sec::Identity` type
+ It's shared across crates.
+
+### Chore
+
+ - <csr-id-f7f136dbe4f86e7dee1d54835c420ec07c96cd78/> uniformize deny attributes
+ - <csr-id-533e887e80c5f7ede8392884562e1c5ba56fb9a8/> remove default link to cargo doc everywhere
+
+### Changed
+
+ - <csr-id-43656d5ce84834c847cf8650d4c486c634f209b6/> use `git-config-value` crate
+
+### Documentation
+
+ - <csr-id-39ed9eda62b7718d5109135e5ad406fb1fe2978c/> fix typos
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 222 commits contributed to the release over the course of 308 calendar days.
+ - 30 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 5 unique issues were worked on: [#301](https://github.com/Byron/gitoxide/issues/301), [#386](https://github.com/Byron/gitoxide/issues/386), [#450](https://github.com/Byron/gitoxide/issues/450), [#470](https://github.com/Byron/gitoxide/issues/470), [#691](https://github.com/Byron/gitoxide/issues/691)
+
+### Thanks Clippy
+
+<csr-read-only-do-not-edit/>
+
+[Clippy](https://github.com/rust-lang/rust-clippy) helped 7 times to make code idiomatic.
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **[#301](https://github.com/Byron/gitoxide/issues/301)**
+ - Update changelogs prior to release ([`84cb256`](https://github.com/Byron/gitoxide/commit/84cb25614a5fcddff297c1713eba4efbb6ff1596))
+ * **[#386](https://github.com/Byron/gitoxide/issues/386)**
+ - More details for path permissions ([`ca26659`](https://github.com/Byron/gitoxide/commit/ca26659eb870c8e947962fe0647a07d01b3e95e4))
+ - Adapt to changes in git-sec ([`c5e2346`](https://github.com/Byron/gitoxide/commit/c5e2346cee53019b1b321e45cf080b210e60bb7a))
+ - Use `git-sec::Identity` type ([`3d339d5`](https://github.com/Byron/gitoxide/commit/3d339d5c24630fac0192b5d27f9b1cbd94418730))
+ - Fill git-credentials with existing impleemntation ([`6016c22`](https://github.com/Byron/gitoxide/commit/6016c2252aea6892a813b7dc1b0c870a156b3cfd))
+ - Add frame for git-credentials crate ([`be7a9cf`](https://github.com/Byron/gitoxide/commit/be7a9cf776f958ac7228457bb4e1415f86f8e575))
+ * **[#450](https://github.com/Byron/gitoxide/issues/450)**
+ - Upgrade `bstr` to `1.0.1` ([`99905ba`](https://github.com/Byron/gitoxide/commit/99905bacace8aed42b16d43f0f04cae996cb971c))
+ - :main::Action::as_str()` ([`d95029e`](https://github.com/Byron/gitoxide/commit/d95029eac0e9179a7cd730d1d60a08696584bfd1))
+ - `protocol::Context::to_bstring()`, and use it in `example/git-credential-lite` ([`15f1afc`](https://github.com/Byron/gitoxide/commit/15f1afccb7ed0ebaf217cbbdd58e6ae651a31e42))
+ - Assure that protocol::Context::to_url() never shows passwords ([`e9f4d40`](https://github.com/Byron/gitoxide/commit/e9f4d40b6f04414c04f153f74f13d2e1fe89e43a))
+ - Make sure the helper::Cascade never sends the URL to helper programs ([`9059de8`](https://github.com/Byron/gitoxide/commit/9059de825d310c2c28f28d4009b09115acccc2bf))
+ - Fix docs ([`9a5ec7b`](https://github.com/Byron/gitoxide/commit/9a5ec7bd8b23bbef2c21de07638681160a7bbdee))
+ - Move `program::Cascade` to `helper::Cascade` which is what it is ([`6149a14`](https://github.com/Byron/gitoxide/commit/6149a14af1742bcfc30bfbe65656b411c6f771c9))
+ - An example on how to invoke the git credential helper driver ([`be0f834`](https://github.com/Byron/gitoxide/commit/be0f83411371e445beceabfcc6e0458eedccf31a))
+ - Context has to serialize url or else the builtin credential helper may not work. ([`87ae404`](https://github.com/Byron/gitoxide/commit/87ae40493cc0dbe11e5de5fd21e2391caa7161db))
+ - Credential context won't send url and quit fields to helpers ([`337a53b`](https://github.com/Byron/gitoxide/commit/337a53b945da26e253c9ba1c72b623d6a06d2e7c))
+ - Cascade supports `use_http_path` and respects it when setting up the context ([`959c0bd`](https://github.com/Byron/gitoxide/commit/959c0bdfb6a634f590969f2c26d13ff8c05a4bb8))
+ - Make it less easy to start a cascade with platform_defaults() ([`4b5d63f`](https://github.com/Byron/gitoxide/commit/4b5d63f7e0ea6bc43f54c95dd30f823ead9fa1a2))
+ - Make clearer what platform builtins actually are ([`9788e30`](https://github.com/Byron/gitoxide/commit/9788e3070edc5c1d84099a2fc5fa9262604170e7))
+ - Credential-cascade now passes on prompt options ([`baad8a0`](https://github.com/Byron/gitoxide/commit/baad8a077ffd556cb29da93fb0081b245f4663ff))
+ - Refactor ([`c8f1b41`](https://github.com/Byron/gitoxide/commit/c8f1b41408f2ace5b01292ef95189b9e66ab4d8e))
+ - Always compile prompting support in ([`bd0ea68`](https://github.com/Byron/gitoxide/commit/bd0ea68225a73fb83c9fc1b8594fc6ad288a77a9))
+ - Set version of git-prompt to 0.1 and turn prompting on ([`7657693`](https://github.com/Byron/gitoxide/commit/7657693b8e23dfb69d6da4376bcd1b8e4e264f7e))
+ - Fix warnings ([`e011242`](https://github.com/Byron/gitoxide/commit/e011242c0c9f6779632f5d33dc7b185495f3868e))
+ - More helpful prompt error messages when asking for credentials ([`b0c6863`](https://github.com/Byron/gitoxide/commit/b0c6863e6b91ded34ed1860ed449f797d28be81e))
+ - Use `git-config-value` crate ([`43656d5`](https://github.com/Byron/gitoxide/commit/43656d5ce84834c847cf8650d4c486c634f209b6))
+ - Proper prompt generation ([`63ee38d`](https://github.com/Byron/gitoxide/commit/63ee38dab45fd9d07532f6c01afc2d8dd1c1e904))
+ - Remove rustyline in favor of `git-prompt` ([`b3e5e59`](https://github.com/Byron/gitoxide/commit/b3e5e59cafaab0d4866c52722cd2a67aa313b395))
+ - Add interactive example for prompt, but… ([`a3fadea`](https://github.com/Byron/gitoxide/commit/a3fadea7759a20fe409762e48d0f1bb9c07f39ba))
+ - Blindly implement prompting if it is allowed ([`c78f4b8`](https://github.com/Byron/gitoxide/commit/c78f4b80d1554fdae49d8d5e7d1cfef6c1bf3b05))
+ - Frame to support prompting (as compile-time feature) ([`afaae28`](https://github.com/Byron/gitoxide/commit/afaae2880a77c30f845ccf2b3c2b7dc5210665f8))
+ - Another test ([`569b7bc`](https://github.com/Byron/gitoxide/commit/569b7bc3d8d8acfe8ad16fe1bc0480e3dbd263d2))
+ - Remove unnecessary `Helper` trait ([`19b84f0`](https://github.com/Byron/gitoxide/commit/19b84f0636f6a8d28e938c3a56b3e2cf0a3b4711))
+ - Use fixtures in all tests ([`24da911`](https://github.com/Byron/gitoxide/commit/24da911f2fcbc0073fcdab1a217686ac3e3b1c79))
+ - Fix tests on linux ([`89db8ee`](https://github.com/Byron/gitoxide/commit/89db8ee938f05f8f9066f34325619f434a5ea00f))
+ - More tests ([`57e9060`](https://github.com/Byron/gitoxide/commit/57e906094683860b43f5b7ff71e0189bd2fd0a91))
+ - Refactor ([`561bb35`](https://github.com/Byron/gitoxide/commit/561bb356850715c2f4377dd36d1daff69126f543))
+ - Another test ([`52d2e54`](https://github.com/Byron/gitoxide/commit/52d2e547b18aa5a00d9d1ada9c88bd84e951e1ed))
+ - Fix CI ([`d526c6d`](https://github.com/Byron/gitoxide/commit/d526c6d111bfa05dfa20aca8426d78217ae41558))
+ - Improve path normalization; a new ignored test ([`ece5a3f`](https://github.com/Byron/gitoxide/commit/ece5a3f16bfbf84eddce42c64c32736ad98b5356))
+ - Parse 'quit' according to spec ([`5e260da`](https://github.com/Byron/gitoxide/commit/5e260dab2edd40092501ab52684f6370104a4eb1))
+ - Allow disabling stderr on credential programs ([`4abec50`](https://github.com/Byron/gitoxide/commit/4abec50dc620e965fc03dda4c801753365839691))
+ - Refactor ([`cdfcea4`](https://github.com/Byron/gitoxide/commit/cdfcea4eb92097927d4c90639fc211e427b6415c))
+ - Url-preprocessing for scripts ([`c00cc35`](https://github.com/Byron/gitoxide/commit/c00cc35493cec8f0b2673248caf1f0d83590dd54))
+ - Breaking credential helpers don't stop everything ([`0cdbde7`](https://github.com/Byron/gitoxide/commit/0cdbde78a200ff8585fb217bab3daf81ff46dd6e))
+ - Refactor; try harder not to spill secrets in errors ([`525fa97`](https://github.com/Byron/gitoxide/commit/525fa9748b966d515fbdeaa48abd34798e97b78e))
+ - First step towards our own `git credential` -like implementation ([`1d1622a`](https://github.com/Byron/gitoxide/commit/1d1622a0dd66ce181d0fa07fc440f85ad0212791))
+ - Refactor ([`ce16f51`](https://github.com/Byron/gitoxide/commit/ce16f513dc0a482583cdff168dcdbe2cdd379ad7))
+ - Platform specific defaults for the program cascade ([`b66258f`](https://github.com/Byron/gitoxide/commit/b66258f3827e8ca4c7da4a5bca7768888a09e6d5))
+ - Refactor ([`85f8cd9`](https://github.com/Byron/gitoxide/commit/85f8cd9b9ef9e93c6495495a83b1ec96437672a5))
+ - Refactor ([`23fb302`](https://github.com/Byron/gitoxide/commit/23fb3025112d2f627896383fb0f74f7e91139116))
+ - A sketch of how a custom 'git credential' could look like ([`4767a14`](https://github.com/Byron/gitoxide/commit/4767a14d2390edacf46d5436a07685b7d7b79cab))
+ - Make 'quit' handler request representable and raise it to an error ([`39b6514`](https://github.com/Byron/gitoxide/commit/39b6514928304807b3d43bd60be716a7f42169c7))
+ - Rename `git()` to `builtin()` ([`783a1a7`](https://github.com/Byron/gitoxide/commit/783a1a7dfd64a64fa765fa3d3ef41b1e954413ee))
+ - Fix docs ([`f86364c`](https://github.com/Byron/gitoxide/commit/f86364c4e2d9efd04027978679232946494a4734))
+ - Rename `Program::Custom*` variants to `Program::External*` ([`bfa2545`](https://github.com/Byron/gitoxide/commit/bfa2545883daf8c4d9e97d2fc91c9328d73ab0eb))
+ - Refactor ([`52e958d`](https://github.com/Byron/gitoxide/commit/52e958d62cdf49c35ed56cb26699b155ee0e7732))
+ - Fix build ([`99958c6`](https://github.com/Byron/gitoxide/commit/99958c6f87a09b99f21b88e42095a1326d6b8a82))
+ - Differentiate between top-level functions and those which are invoked ([`811985a`](https://github.com/Byron/gitoxide/commit/811985aba024385465104ed826a9989961555201))
+ - Invoke::Outcome can now represent partial identities ([`49b9bd5`](https://github.com/Byron/gitoxide/commit/49b9bd501f33f1e10ce0180e814b84e293bd3898))
+ - Make clear what `helper()` does by renaming it to `git` ([`2edb58b`](https://github.com/Byron/gitoxide/commit/2edb58b6c7395b67c8a7f7c9f6162e6e7c290aac))
+ - Make clear in the error type that the helper program couldn't be started ([`c09d223`](https://github.com/Byron/gitoxide/commit/c09d2234cb7e89a2b6ae54e7c8497e86b38621f0))
+ - Improved error when identity could not be obtained ([`08c1287`](https://github.com/Byron/gitoxide/commit/08c12876d763a4ade3d4013ce1be66d9594e4ff1))
+ - Support for `quit` field in context ([`5a50528`](https://github.com/Byron/gitoxide/commit/5a50528a6f2b1a547fdc9a656e5ea2ca07396ecf))
+ - Refactor ([`7487b5a`](https://github.com/Byron/gitoxide/commit/7487b5a4142679ef423c5bd996e40e473c5dfc27))
+ - Support for non-consuming operation of `Program` ([`bcfe5ca`](https://github.com/Byron/gitoxide/commit/bcfe5ca22636114bb232d1208ab7c9d78d1fe1de))
+ - Disable test that seems to fail on linux ([`419ca56`](https://github.com/Byron/gitoxide/commit/419ca56f7a97cdb0c0e18a4a6f8fda6320692518))
+ - More tests for custom helper scripts ([`b396032`](https://github.com/Byron/gitoxide/commit/b3960320d1ef86b42fe8d42c8d7f7abfe66e1710))
+ - Support for script invocations ([`377cf14`](https://github.com/Byron/gitoxide/commit/377cf142996279394af38179ad5b51c419642f90))
+ - Use git_path::is_absolute() ([`2ba836f`](https://github.com/Byron/gitoxide/commit/2ba836f3e9e5231e8bc42d57d8ff939d85acfe16))
+ - Fix tests on windows ([`f4bc860`](https://github.com/Byron/gitoxide/commit/f4bc86011d4aafb5bdeafadd43adb0022ff9b449))
+ - Also fill in the git credential command prefix ([`b2f4fe8`](https://github.com/Byron/gitoxide/commit/b2f4fe8f96785222edc3c0472ccef3acf1f069f8))
+ - Initial version of parsing of custom helper definitions ([`2b2cd00`](https://github.com/Byron/gitoxide/commit/2b2cd0001babdc16e940fa7242c6d723fc9f789b))
+ - `helper::Kind` to `program::Kind` ([`b8c54f0`](https://github.com/Byron/gitoxide/commit/b8c54f03fdb6060caf9c04557c0530c090e7a975))
+ - Sketch additional credentials programs ([`46e3045`](https://github.com/Byron/gitoxide/commit/46e3045e04e5197560d8c786642b8f1924a577f9))
+ - First test for launching the git credential helper ([`4d7b1dd`](https://github.com/Byron/gitoxide/commit/4d7b1ddec6ef747665edcfddbba68ed12e3970c2))
+ - An example implementing a custom credential helper program ([`b1d528a`](https://github.com/Byron/gitoxide/commit/b1d528ae60001ae51dd89b29c26ea505eacbef45))
+ - Add docs ([`a360594`](https://github.com/Byron/gitoxide/commit/a360594fac3102cd48aac0039efbe71693c5fa25))
+ - `helper::main` to easily create credential helper implementations ([`eaff67c`](https://github.com/Byron/gitoxide/commit/eaff67c14366f149ccca346acb46af12531a24e6))
+ - Move `helper::(Next)Action` into `helper::invoke::` module ([`4b7d0b6`](https://github.com/Byron/gitoxide/commit/4b7d0b6d2c43cac9823885bc69510cc4bb6a3f00))
+ - Sketch for helper::invoke (get) test ([`c48eb39`](https://github.com/Byron/gitoxide/commit/c48eb390a2f95954f542992806d4e8667ee97981))
+ - Refactor ([`cb9d32a`](https://github.com/Byron/gitoxide/commit/cb9d32a3611463f983afea3b3ea875c33092207b))
+ - Rename `helper::NextAction` variants to `store` and `erase` ([`ddd5398`](https://github.com/Byron/gitoxide/commit/ddd53988a6d5da17fc65451a059bed1bfa2eb454))
+ - Fix docs ([`d9b4ba5`](https://github.com/Byron/gitoxide/commit/d9b4ba5a00c1c9f9c199ac218da76cb716896b75))
+ - Add `helper::Action::get_for_url(…)` ([`a253d30`](https://github.com/Byron/gitoxide/commit/a253d30093122e37b5560ff86a7888f8062c7014))
+ - Rename `helper::Action` variants to 'Get', 'Store', 'Erase' ([`2073b58`](https://github.com/Byron/gitoxide/commit/2073b583dc2bd83b800584edda6592bb71a01538))
+ - Use `helper::Context` in `helper::Action::Fill()` ([`9c6f024`](https://github.com/Byron/gitoxide/commit/9c6f024f838d866645937a67cd67dffb8be17259))
+ - Remaining decode tests ([`0e76efe`](https://github.com/Byron/gitoxide/commit/0e76efe035a48f9d042096342ac79804f1eeebdc))
+ - Test context value validation ([`20dde9e`](https://github.com/Byron/gitoxide/commit/20dde9eb93ecfb56e72bc5d59caacf31328a55e4))
+ - Basic round-tripping of fully fleshed-out context ([`280e4a3`](https://github.com/Byron/gitoxide/commit/280e4a3f69699e11428decc6858711b35ae8249e))
+ - Flesh out `helper::Context` as it will soon be used. ([`0cb1ed4`](https://github.com/Byron/gitoxide/commit/0cb1ed4600c614169118b2a94fed83699989a6be))
+ - Move `helper::invoke()` related types into `helper::invoke` module. ([`71f6519`](https://github.com/Byron/gitoxide/commit/71f651930e6fd53e3c3f9e82dfd95828e4981d92))
+ - Refactor ([`03bf747`](https://github.com/Byron/gitoxide/commit/03bf747292af7792bc175c4f06939b1e02f7234c))
+ - Express `helper()` in terms of `helper::invoke()` ([`f2a2c5e`](https://github.com/Byron/gitoxide/commit/f2a2c5ebb7d7428460fe22e9b84dec242a992302))
+ - `helper::invoke(helper, action, context)` function that allows for more flexible helper invocation ([`64bc2ec`](https://github.com/Byron/gitoxide/commit/64bc2ec666dacba486bd1de2fbd95f97f2efc7a5))
+ - Refactor ([`af27d20`](https://github.com/Byron/gitoxide/commit/af27d20909d14f2737fbad5edd9a6c9d86c93e24))
+ - Prepare for more additional implementations of helpers ([`486ef98`](https://github.com/Byron/gitoxide/commit/486ef98b792cc57412a4a90d2cf28586a06d7041))
+ - Refactor ([`167b521`](https://github.com/Byron/gitoxide/commit/167b5215326ff2f39e89f2130ff575f4ef6c02d6))
+ - Fix docs ([`db46b60`](https://github.com/Byron/gitoxide/commit/db46b60d8f9b4341cf215da6e2cd74bf554fe4b8))
+ - Re-add `Result` type ([`de92fce`](https://github.com/Byron/gitoxide/commit/de92fce44496b050e5697aab6d6d1ea98a5954dc))
+ - Use `thiserror` instead of `quickerror` ([`4c1a1a2`](https://github.com/Byron/gitoxide/commit/4c1a1a28558c4f8d084b8046afd5d87a11fd25b7))
+ - Hide `helper::action()` in favor of single path via `helper()` ([`081934c`](https://github.com/Byron/gitoxide/commit/081934ca4452e550cf2663026905bce67253af81))
+ - `helper::(encode|decode)_message(…)` to `::message::(encode|decode)(…)` ([`4c39521`](https://github.com/Byron/gitoxide/commit/4c39521a47419bb4b0f0edbe51aa509fb4e2a7f1))
+ - Refactor ([`a395308`](https://github.com/Byron/gitoxide/commit/a395308fdc01b5449a851b1dcb6c3e97a205a5d0))
+ - Adapt to changes in `git-url` and use `BString` to represent URLs. ([`12589cc`](https://github.com/Byron/gitoxide/commit/12589cc6f08e4d7aabae30bcdadaa0c2b4850229))
+ * **[#470](https://github.com/Byron/gitoxide/issues/470)**
+ - Update changelogs prior to release ([`caa7a1b`](https://github.com/Byron/gitoxide/commit/caa7a1bdef74d7d3166a7e38127a59f5ab3cfbdd))
+ * **[#691](https://github.com/Byron/gitoxide/issues/691)**
+ - Set `rust-version` to 1.64 ([`55066ce`](https://github.com/Byron/gitoxide/commit/55066ce5fd71209abb5d84da2998b903504584bb))
+ * **Uncategorized**
+ - Release gix-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))
+ - 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))
+ - Rename `git-credentials` to `gix-credentials` ([`8450d09`](https://github.com/Byron/gitoxide/commit/8450d09a50e350180428076472989db205bc4120))
+ - Adjust to renaming of `git-prompt` to `gix-prompt` ([`6a4654e`](https://github.com/Byron/gitoxide/commit/6a4654e0d10ab773dd219cb4b731c0fc1471c36d))
+ - Adjust to renaming of `git-command` to `gix-command` ([`d26b8e0`](https://github.com/Byron/gitoxide/commit/d26b8e046496894ae06b0bbfdba77196976cd975))
+ - Adjust to renaming of `git-packetline` to `gix-packetline` ([`5cbd22c`](https://github.com/Byron/gitoxide/commit/5cbd22cf42efb760058561c6c3bbcd4dab8c8be1))
+ - Adjust to renaming of `git-worktree` to `gix-worktree` ([`73a1282`](https://github.com/Byron/gitoxide/commit/73a12821b3d9b66ec1714d07dd27eb7a73e3a544))
+ - Adjust to renamining of `git-worktree` to `gix-worktree` ([`108bb1a`](https://github.com/Byron/gitoxide/commit/108bb1a634f4828853fb590e9fc125f79441dd38))
+ - Adjust to renaming of `git-url` to `gix-url` ([`b50817a`](https://github.com/Byron/gitoxide/commit/b50817aadb143e19f61f64e19b19ec1107d980c6))
+ - Adjust to renaming of `git-date` to `gix-date` ([`9a79ff2`](https://github.com/Byron/gitoxide/commit/9a79ff2d5cc74c1efad9f41e21095ae498cce00b))
+ - Adjust to renamining of `git-attributes` to `gix-attributes` ([`4a8b3b8`](https://github.com/Byron/gitoxide/commit/4a8b3b812ac26f2a2aee8ce8ca81591273383c84))
+ - Adjust to renaminig of `git-quote` to `gix-quote` ([`648025b`](https://github.com/Byron/gitoxide/commit/648025b7ca94411fdd0d90c53e5faede5fde6c8d))
+ - Adjust to renaming of `git-config` to `gix-config` ([`3a861c8`](https://github.com/Byron/gitoxide/commit/3a861c8f049f6502d3bcbdac752659aa1aeda46a))
+ - Adjust to renaming of `git-ref` to `gix-ref` ([`1f5f695`](https://github.com/Byron/gitoxide/commit/1f5f695407b034377d94b172465ff573562b3fc3))
+ - Adjust to renaming of `git-lock` to `gix-lock` ([`2028e78`](https://github.com/Byron/gitoxide/commit/2028e7884ae1821edeec81612f501e88e4722b17))
+ - Adjust to renaming of `git-tempfile` to `gix-tempfile` ([`b6cc3eb`](https://github.com/Byron/gitoxide/commit/b6cc3ebb5137084a6327af16a7d9364d8f092cc9))
+ - 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-date v0.4.2, git-hash v0.10.2, git-features v0.26.2, git-actor v0.17.1, git-glob v0.5.3, git-path v0.7.1, git-quote v0.4.1, git-attributes v0.8.2, git-config-value v0.10.1, git-tempfile v3.0.2, git-lock v3.0.2, git-validate v0.7.2, git-object v0.26.1, git-ref v0.24.0, git-sec v0.6.2, git-config v0.16.0, git-command v0.2.3, git-prompt v0.3.2, git-url v0.13.2, git-credentials v0.9.1, git-diff v0.26.1, git-discover v0.13.0, git-hashtable v0.1.1, git-bitmap v0.2.1, git-traverse v0.22.1, git-index v0.12.3, git-mailmap v0.9.2, git-chunk v0.4.1, git-pack v0.30.2, git-odb v0.40.2, git-packetline v0.14.2, git-transport v0.25.4, git-protocol v0.26.3, git-revision v0.10.2, git-refspec v0.7.2, git-worktree v0.12.2, git-repository v0.34.0, safety bump 3 crates ([`c196d20`](https://github.com/Byron/gitoxide/commit/c196d206d57a310b1ce974a1cf0e7e6d6db5c4d6))
+ - Prepare changelogs prior to release ([`7c846d2`](https://github.com/Byron/gitoxide/commit/7c846d2102dc767366771925212712ef8cc9bf07))
+ - Merge branch 'Lioness100/main' ([`1e544e8`](https://github.com/Byron/gitoxide/commit/1e544e82455bf9ecb5e3c2146280eaf7ecd81f16))
+ - Fix typos ([`39ed9ed`](https://github.com/Byron/gitoxide/commit/39ed9eda62b7718d5109135e5ad406fb1fe2978c))
+ - Thanks clippy ([`bac57dd`](https://github.com/Byron/gitoxide/commit/bac57dd05ea2d5a4ee45ef9350fa3f2e19474bc0))
+ - Release git-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))
+ - Merge branch 'adjustments-for-cargo' ([`f8c562a`](https://github.com/Byron/gitoxide/commit/f8c562a559e6dc3377583cc7200585dad7c3d481))
+ - `helper::Cascade::query_user_only()` can avoid to ask for the password if the transport wouldn't use it. ([`6b375d3`](https://github.com/Byron/gitoxide/commit/6b375d3061f6d307101199eff1ecdfdeb6769965))
+ - 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 'http-config' ([`a4ff140`](https://github.com/Byron/gitoxide/commit/a4ff140a0d3607cf282c49228c1248bd36d464fd))
+ - 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))
+ - Improve docs ever so slightly ([`ca5d89c`](https://github.com/Byron/gitoxide/commit/ca5d89c6c94ca5e26098fcbe449a723e6a6b4b69))
+ - Release git-features v0.23.1, git-glob v0.4.1, git-config-value v0.8.1, git-tempfile v2.0.6, git-object v0.22.1, git-ref v0.18.0, git-sec v0.4.2, git-config v0.10.0, git-prompt v0.1.1, git-url v0.10.1, git-credentials v0.6.1, git-diff v0.21.0, git-discover v0.7.0, git-index v0.7.0, git-pack v0.25.0, git-odb v0.35.0, git-transport v0.21.1, git-protocol v0.22.0, git-refspec v0.3.1, git-worktree v0.7.0, git-repository v0.26.0, git-commitgraph v0.10.0, gitoxide-core v0.19.0, gitoxide v0.17.0, safety bump 9 crates ([`d071583`](https://github.com/Byron/gitoxide/commit/d071583c5576fdf5f7717765ffed5681792aa81f))
+ - Prepare changelogs prior to release ([`423af90`](https://github.com/Byron/gitoxide/commit/423af90c8202d62dc1ea4a76a0df6421d1f0aa06))
+ - Merge branch 'main' into write-sparse-index (upgrade to Rust 1.65) ([`5406630`](https://github.com/Byron/gitoxide/commit/5406630466145990b5adbdadb59151036993060d))
+ - Thanks clippy ([`04cfa63`](https://github.com/Byron/gitoxide/commit/04cfa635a65ae34ad6d22391f2febd2ca7eabca9))
+ - 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 '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))
+ - Merge branch 'filter-refs' ([`fd14489`](https://github.com/Byron/gitoxide/commit/fd14489f729172d615d0fa1e8dbd605e9eacf69d))
+ - Make fmt ([`535e967`](https://github.com/Byron/gitoxide/commit/535e967666c6da657ff1b7eff7c64ab27cafb182))
+ - Merge branch 'filter-refs-by-spec' ([`5c05198`](https://github.com/Byron/gitoxide/commit/5c051986bd89590a9287d85d84c713d83dfab83a))
+ - Merge branch 'main' into filter-refs-by-spec ([`9aa1d3d`](https://github.com/Byron/gitoxide/commit/9aa1d3dc46d4b1c76af257f573aff3aeef2d3fa8))
+ - Merge branch 'main' into index-from-tree ([`bc64b96`](https://github.com/Byron/gitoxide/commit/bc64b96a2ec781c72d1d4daad38aa7fb8b74f99b))
+ - Release git-path v0.4.2, git-config-value v0.7.0 ([`c48fb31`](https://github.com/Byron/gitoxide/commit/c48fb3107d29f9a06868b0c6de40567063a656d1))
+ - Thanks clippy ([`c1399d1`](https://github.com/Byron/gitoxide/commit/c1399d155889e6142eafd65b9bbd2ed005f580dd))
+ - Thanks clippy ([`e8e80f5`](https://github.com/Byron/gitoxide/commit/e8e80f5b176ebca4ee81727a551d83383a0b38f8))
+ - Thanks clippy ([`9b8a6d6`](https://github.com/Byron/gitoxide/commit/9b8a6d6afeab13968dea61619b1e742e93f60fab))
+ - Thanks clippy ([`8317b46`](https://github.com/Byron/gitoxide/commit/8317b4672c8cd38520ed90c42eaadd539ea4df66))
+ - Thanks clippy ([`01efe88`](https://github.com/Byron/gitoxide/commit/01efe88cff52e75ba0b76ecc27a41994ee908d2c))
+ - 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))
+ - Refactor ([`1dc342f`](https://github.com/Byron/gitoxide/commit/1dc342f9a60cb20e1fafa8c7e913c4a957367662))
+ - Merge branch 'docsrs-show-features' ([`31c2351`](https://github.com/Byron/gitoxide/commit/31c235140cad212d16a56195763fbddd971d87ce))
+ - Use docsrs feature in code to show what is feature-gated automatically on docs.rs ([`b1c40b0`](https://github.com/Byron/gitoxide/commit/b1c40b0364ef092cd52d03b34f491b254816b18d))
+ - Uniformize deny attributes ([`f7f136d`](https://github.com/Byron/gitoxide/commit/f7f136dbe4f86e7dee1d54835c420ec07c96cd78))
+ - Pass --cfg docsrs when compiling for https://docs.rs ([`5176771`](https://github.com/Byron/gitoxide/commit/517677147f1c17304c62cf97a1dd09f232ebf5db))
+ - Remove default link to cargo doc everywhere ([`533e887`](https://github.com/Byron/gitoxide/commit/533e887e80c5f7ede8392884562e1c5ba56fb9a8))
+ - Merge pull request #2 from SidneyDouw/main ([`ce885ad`](https://github.com/Byron/gitoxide/commit/ce885ad4c3324c09c83751c32e014f246c748766))
+ - Merge branch 'Byron:main' into main ([`9b9ea02`](https://github.com/Byron/gitoxide/commit/9b9ea0275f8ff5862f24cf5a4ca53bb1cd610709))
+ - Merge branch 'main' into rev-parse-delegate ([`6da8250`](https://github.com/Byron/gitoxide/commit/6da82507588d3bc849217c11d9a1d398b67f2ed6))
+ - Merge branch 'main' into pathspec ([`7b61506`](https://github.com/Byron/gitoxide/commit/7b615060712565f515515e35a3e8346278ad770c))
+ - Release git-config v0.6.0, git-credentials v0.3.0, git-diff v0.17.0, git-discover v0.3.0, git-index v0.4.0, git-mailmap v0.3.0, git-traverse v0.16.0, git-pack v0.21.0, git-odb v0.31.0, git-url v0.7.0, git-transport v0.19.0, git-protocol v0.18.0, git-revision v0.3.0, git-worktree v0.4.0, git-repository v0.20.0, git-commitgraph v0.8.0, gitoxide-core v0.15.0, gitoxide v0.13.0 ([`aa639d8`](https://github.com/Byron/gitoxide/commit/aa639d8c43f3098cc4a5b50614c5ae94a8156928))
+ - Release git-hash v0.9.6, git-features v0.22.0, git-date v0.0.2, git-actor v0.11.0, git-glob v0.3.1, git-path v0.4.0, git-attributes v0.3.0, git-tempfile v2.0.2, git-object v0.20.0, git-ref v0.15.0, git-sec v0.3.0, git-config v0.6.0, git-credentials v0.3.0, git-diff v0.17.0, git-discover v0.3.0, git-index v0.4.0, git-mailmap v0.3.0, git-traverse v0.16.0, git-pack v0.21.0, git-odb v0.31.0, git-url v0.7.0, git-transport v0.19.0, git-protocol v0.18.0, git-revision v0.3.0, git-worktree v0.4.0, git-repository v0.20.0, git-commitgraph v0.8.0, gitoxide-core v0.15.0, gitoxide v0.13.0, safety bump 22 crates ([`4737b1e`](https://github.com/Byron/gitoxide/commit/4737b1eea1d4c9a8d5a69fb63ecac5aa5d378ae5))
+ - Prepare changelog prior to release ([`3c50625`](https://github.com/Byron/gitoxide/commit/3c50625fa51350ec885b0f38ec9e92f9444df0f9))
+ - Merge pull request #1 from Byron/main ([`085e76b`](https://github.com/Byron/gitoxide/commit/085e76b121291ed9bd324139105d2bd4117bedf8))
+ - Assure document-features are available in all 'usable' and 'early' crates ([`238581c`](https://github.com/Byron/gitoxide/commit/238581cc46c7288691eed37dc7de5069e3d86721))
+ - Merge branch 'main' into pathspec ([`89ea12b`](https://github.com/Byron/gitoxide/commit/89ea12b558bcc056b892193ee8fb44b8664b5da4))
+ - Merge branch 'main' into cont_include_if ([`41ea8ba`](https://github.com/Byron/gitoxide/commit/41ea8ba78e74f5c988148367386a1f4f304cb951))
+ - Release git-path v0.3.0, safety bump 14 crates ([`400c9be`](https://github.com/Byron/gitoxide/commit/400c9bec49e4ec5351dc9357b246e7677a63ea35))
+ - Release git-date v0.0.1, git-hash v0.9.5, git-features v0.21.1, git-actor v0.10.1, git-path v0.2.0, git-attributes v0.2.0, git-ref v0.14.0, git-sec v0.2.0, git-config v0.5.0, git-credentials v0.2.0, git-discover v0.2.0, git-pack v0.20.0, git-odb v0.30.0, git-url v0.6.0, git-transport v0.18.0, git-protocol v0.17.0, git-revision v0.2.1, git-worktree v0.3.0, git-repository v0.19.0, safety bump 13 crates ([`a417177`](https://github.com/Byron/gitoxide/commit/a41717712578f590f04a33d27adaa63171f25267))
+ - Update changelogs prior to release ([`bb424f5`](https://github.com/Byron/gitoxide/commit/bb424f51068b8a8e762696890a55ab48900ab980))
+ - Merge branch 'main' into SidneyDouw-pathspec ([`a22b1d8`](https://github.com/Byron/gitoxide/commit/a22b1d88a21311d44509018729c3ef1936cf052a))
+ - Merge branch 'main' into git_includeif ([`598c853`](https://github.com/Byron/gitoxide/commit/598c853087fcf8f77299aa5b9803bcec705c0cd0))
+ - Release git-hash v0.9.4, git-features v0.21.0, git-actor v0.10.0, git-glob v0.3.0, git-path v0.1.1, git-attributes v0.1.0, git-sec v0.1.0, git-config v0.3.0, git-credentials v0.1.0, git-validate v0.5.4, git-object v0.19.0, git-diff v0.16.0, git-lock v2.1.0, git-ref v0.13.0, git-discover v0.1.0, git-index v0.3.0, git-mailmap v0.2.0, git-traverse v0.15.0, git-pack v0.19.0, git-odb v0.29.0, git-packetline v0.12.5, git-url v0.5.0, git-transport v0.17.0, git-protocol v0.16.0, git-revision v0.2.0, git-worktree v0.2.0, git-repository v0.17.0, safety bump 20 crates ([`654cf39`](https://github.com/Byron/gitoxide/commit/654cf39c92d5aa4c8d542a6cadf13d4acef6a78e))
+ - Merge branch 'main' into git_includeif ([`05eb340`](https://github.com/Byron/gitoxide/commit/05eb34023933918c51c03cf2afd774db89cc5a33))
+ - Merge branch 'main' into msrv-for-windows ([`7cb1972`](https://github.com/Byron/gitoxide/commit/7cb19729133325bdfacedf44cdc0500cbcf36684))
+ - Make fmt ([`251b6df`](https://github.com/Byron/gitoxide/commit/251b6df5dbdda24b7bdc452085f808f3acef69d8))
+ - Merge branch 'main' into repo-status ([`9679d6b`](https://github.com/Byron/gitoxide/commit/9679d6b0e68c28438e22cb65c554d0b31dfaf159))
+ - Merge branch 'git-sec' ([`cd723b5`](https://github.com/Byron/gitoxide/commit/cd723b5ae11148e7e9fd07daf28bc04455d5c46f))
+ - Release git-credentials v0.0.0 ([`7db45ab`](https://github.com/Byron/gitoxide/commit/7db45abb822b7c28ac84bf0229ec23ce0f46c8f2))
+</details>
+
+## 0.9.0 (2022-12-30)
+
+### New Features
+
+ - <csr-id-6b375d3061f6d307101199eff1ecdfdeb6769965/> `helper::Cascade::query_user_only()` can avoid to ask for the password if the transport wouldn't use it.
+ That way, `ssh` while using ssh programs can query the user to try next.
+
+## 0.8.0 (2022-12-19)
+
+A maintenance release without user-facing changes.
+
+## 0.7.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.6.1 (2022-11-06)
+
+A maintenance release without user-facing changes.
+
+## 0.6.0 (2022-10-10)
+
+Maintenance release without user-facing changes.
+
+## 0.5.0 (2022-09-20)
+
+<csr-id-d95029eac0e9179a7cd730d1d60a08696584bfd1/>
+<csr-id-b8c54f03fdb6060caf9c04557c0530c090e7a975/>
+<csr-id-4c39521a47419bb4b0f0edbe51aa509fb4e2a7f1/>
+
+### Changed
+
+ - <csr-id-43656d5ce84834c847cf8650d4c486c634f209b6/> use `gix-config-value` crate
+
+### New Features
+
+ - <csr-id-15f1afccb7ed0ebaf217cbbdd58e6ae651a31e42/> `protocol::Context::to_bstring()`, and use it in `example/git-credential-lite`
+ - <csr-id-b1d528ae60001ae51dd89b29c26ea505eacbef45/> an example implementing a custom credential helper program
+ - <csr-id-eaff67c14366f149ccca346acb46af12531a24e6/> `helper::main` to easily create credential helper implementations
+ - <csr-id-a253d30093122e37b5560ff86a7888f8062c7014/> add `helper::Action::get_for_url(…)`
+ - <csr-id-64bc2ec666dacba486bd1de2fbd95f97f2efc7a5/> `helper::invoke(helper, action, context)` function that allows for more flexible helper invocation
+
+### Other
+
+ - <csr-id-d95029eac0e9179a7cd730d1d60a08696584bfd1/> :main::Action::as_str()`
+
+### Changed (BREAKING)
+
+ - <csr-id-99905bacace8aed42b16d43f0f04cae996cb971c/> upgrade `bstr` to `1.0.1`
+ - <csr-id-783a1a7dfd64a64fa765fa3d3ef41b1e954413ee/> rename `git()` to `builtin()`
+ - <csr-id-bfa2545883daf8c4d9e97d2fc91c9328d73ab0eb/> rename `Program::Custom*` variants to `Program::External*`
+ It's more true to what it is.
+ - <csr-id-811985aba024385465104ed826a9989961555201/> differentiate between top-level functions and those which are invoked
+ That way it's easier to use as it can assure an account was actually
+ provided.
+ - <csr-id-49b9bd501f33f1e10ce0180e814b84e293bd3898/> invoke::Outcome can now represent partial identities
+ That way these can be assembled by multiple helpers called in a row.
+ - <csr-id-4b7d0b6d2c43cac9823885bc69510cc4bb6a3f00/> move `helper::(Next)Action` into `helper::invoke::` module
+ These are only relevant for invoke, hence the change.
+ - <csr-id-ddd53988a6d5da17fc65451a059bed1bfa2eb454/> rename `helper::NextAction` variants to `store` and `erase`
+ - <csr-id-2073b583dc2bd83b800584edda6592bb71a01538/> rename `helper::Action` variants to 'Get', 'Store', 'Erase'
+ It's more obvious what it does and is more typical for what credentials
+ helpers do.
+ - <csr-id-9c6f024f838d866645937a67cd67dffb8be17259/> Use `helper::Context` in `helper::Action::Fill()`
+ That way additional information, like from configuration, can be passed
+ as well.
+ - <csr-id-71f651930e6fd53e3c3f9e82dfd95828e4981d92/> move `helper::invoke()` related types into `helper::invoke` module.
+ Also allow to pass arbitrary bytes (more or less) as context by not
+ forcing it all into a string. Values can now be everything, which
+ helps with passing paths or other values.
+ - <csr-id-4c1a1a28558c4f8d084b8046afd5d87a11fd25b7/> use `thiserror` instead of `quickerror`
+ - <csr-id-081934ca4452e550cf2663026905bce67253af81/> hide `helper::action()` in favor of single path via `helper()`
+
+### Other (BREAKING)
+
+ - <csr-id-b8c54f03fdb6060caf9c04557c0530c090e7a975/> `helper::Kind` to `program::Kind`
+ - <csr-id-4c39521a47419bb4b0f0edbe51aa509fb4e2a7f1/> `helper::(encode|decode)_message(…)` to `::message::(encode|decode)(…)`
+
+## 0.4.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
+
+### New Features
+
+ - <csr-id-b1c40b0364ef092cd52d03b34f491b254816b18d/> use docsrs feature in code to show what is feature-gated automatically on docs.rs
+ - <csr-id-517677147f1c17304c62cf97a1dd09f232ebf5db/> pass --cfg docsrs when compiling for https://docs.rs
+
+### Changed (BREAKING)
+
+ - <csr-id-12589cc6f08e4d7aabae30bcdadaa0c2b4850229/> adapt to changes in `gix-url` and use `BString` to represent URLs.
+ They can contain paths, which is why `String` can't represent a URL
+ losslessly.
+
+ For HTTP urls these are ultimately UTF-8 strings though.
+
+## 0.3.0 (2022-07-22)
+
+This is a maintenance release with no functional changes.
+
+## 0.2.0 (2022-06-13)
+
+A maintenance release without user-facing changes.
+
+## 0.1.0 (2022-05-18)
+
+### New Features
+
+ - <csr-id-3d339d5c24630fac0192b5d27f9b1cbd94418730/> use `gix-sec::Identity` type
+ It's shared across crates.
+
+## 0.0.0 (2022-04-15)
+
+An empty crate without any content to reserve the name for the gitoxide project.
+
diff --git a/vendor/gix-credentials/Cargo.lock b/vendor/gix-credentials/Cargo.lock
new file mode 100644
index 000000000..9de2f98e5
--- /dev/null
+++ b/vendor/gix-credentials/Cargo.lock
@@ -0,0 +1,560 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bstr"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1"
+dependencies = [
+ "memchr",
+ "once_cell",
+ "regex-automata",
+ "serde",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "dirs"
+version = "4.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
+dependencies = [
+ "dirs-sys",
+]
+
+[[package]]
+name = "dirs-sys"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
+dependencies = [
+ "libc",
+ "redox_users",
+ "winapi",
+]
+
+[[package]]
+name = "document-features"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e493c573fce17f00dcab13b6ac057994f3ce17d1af4dc39bfd482b83c6eb6157"
+dependencies = [
+ "litrs",
+]
+
+[[package]]
+name = "form_urlencoded"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "gix-command"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2c6f75c1e0f924de39e750880a6e21307194bb1ab773efe3c7d2d787277f8ab"
+dependencies = [
+ "bstr",
+]
+
+[[package]]
+name = "gix-config-value"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "693d4a4ba0531e46fe558459557a5b29fb86c3e4b2666c1c0861d93c7c678331"
+dependencies = [
+ "bitflags",
+ "bstr",
+ "gix-path",
+ "libc",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-credentials"
+version = "0.11.0"
+dependencies = [
+ "bstr",
+ "document-features",
+ "gix-command",
+ "gix-config-value",
+ "gix-path",
+ "gix-prompt",
+ "gix-sec",
+ "gix-url",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-features"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e6a9dfa7b3c1a99315203e8b97f8f99f3bd95731590607abeaa5ca31bc41fe3"
+dependencies = [
+ "gix-hash",
+ "libc",
+]
+
+[[package]]
+name = "gix-hash"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c0c5a9f4d621d4f4ea046bb331df5c746ca735b8cae5b234cc2be70ee4dbef0"
+dependencies = [
+ "hex",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-path"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6c104a66dec149cb8f7aaafc6ab797654cf82d67f050fd0cb7e7294e328354b"
+dependencies = [
+ "bstr",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-prompt"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a20cebf73229debaa82574c4fd20dcaf00fa8d4bfce823a862c4e990d7a0b5b4"
+dependencies = [
+ "gix-command",
+ "gix-config-value",
+ "nix",
+ "parking_lot",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-sec"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8ffa5bf0772f9b01de501c035b6b084cf9b8bb07dec41e3afc6a17336a65f47"
+dependencies = [
+ "bitflags",
+ "dirs",
+ "gix-path",
+ "libc",
+ "serde",
+ "windows",
+]
+
+[[package]]
+name = "gix-url"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "044072b7ce8601b62dcec841b92129f5cc677072823324121b395d766ac5f528"
+dependencies = [
+ "bstr",
+ "gix-features",
+ "gix-path",
+ "home",
+ "thiserror",
+ "url",
+]
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "home"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "idna"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.139"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
+
+[[package]]
+name = "litrs"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9275e0933cf8bb20f008924c0cb07a0692fe54d8064996520bf998de9eb79aa"
+
+[[package]]
+name = "lock_api"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "nix"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "libc",
+ "static_assertions",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-sys",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.51"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom",
+ "redox_syscall",
+ "thiserror",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "serde"
+version = "1.0.152"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.152"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "775c11906edafc97bc378816b94585fbd9a054eabaf86fdd0ced94af449efab7"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "url"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows"
+version = "0.43.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
diff --git a/vendor/gix-credentials/Cargo.toml b/vendor/gix-credentials/Cargo.toml
new file mode 100644
index 000000000..9612b7859
--- /dev/null
+++ b/vendor/gix-credentials/Cargo.toml
@@ -0,0 +1,76 @@
+# 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-credentials"
+version = "0.11.0"
+authors = ["Sebastian Thiel <sebastian.thiel@icloud.com>"]
+description = "A WIP crate of the gitoxide project to interact with git credentials helpers"
+license = "MIT/Apache-2.0"
+repository = "https://github.com/Byron/gitoxide"
+
+[package.metadata.docs.rs]
+all-features = true
+features = ["document-features"]
+rustdoc-args = [
+ "--cfg",
+ "docsrs",
+]
+
+[lib]
+doctest = false
+
+[dependencies.bstr]
+version = "1.3.0"
+features = ["std"]
+default-features = false
+
+[dependencies.document-features]
+version = "0.2.1"
+optional = true
+
+[dependencies.gix-command]
+version = "^0.2.4"
+
+[dependencies.gix-config-value]
+version = "^0.10.1"
+
+[dependencies.gix-path]
+version = "^0.7.2"
+
+[dependencies.gix-prompt]
+version = "^0.3.2"
+
+[dependencies.gix-sec]
+version = "^0.6.2"
+
+[dependencies.gix-url]
+version = "^0.15.0"
+
+[dependencies.serde]
+version = "1.0.114"
+features = ["derive"]
+optional = true
+default-features = false
+
+[dependencies.thiserror]
+version = "1.0.32"
+
+[dev-dependencies]
+
+[features]
+serde1 = [
+ "serde",
+ "bstr/serde",
+ "gix-sec/serde1",
+]
diff --git a/vendor/gix-credentials/examples/custom-helper.rs b/vendor/gix-credentials/examples/custom-helper.rs
new file mode 100644
index 000000000..9fc0cbf61
--- /dev/null
+++ b/vendor/gix-credentials/examples/custom-helper.rs
@@ -0,0 +1,24 @@
+use gix_credentials::{program, protocol};
+
+/// Run like this `echo url=https://example.com | cargo run --example custom-helper -- get`
+pub fn main() -> Result<(), gix_credentials::program::main::Error> {
+ gix_credentials::program::main(
+ std::env::args_os().skip(1),
+ std::io::stdin(),
+ std::io::stdout(),
+ |action, context| -> std::io::Result<_> {
+ match action {
+ program::main::Action::Get => Ok(Some(protocol::Context {
+ username: Some("user".into()),
+ password: Some("pass".into()),
+ ..context
+ })),
+ program::main::Action::Erase => Err(std::io::Error::new(
+ std::io::ErrorKind::Other,
+ "Refusing to delete credentials for demo purposes",
+ )),
+ program::main::Action::Store => Ok(None),
+ }
+ },
+ )
+}
diff --git a/vendor/gix-credentials/examples/git-credential-lite.rs b/vendor/gix-credentials/examples/git-credential-lite.rs
new file mode 100644
index 000000000..c4e40c291
--- /dev/null
+++ b/vendor/gix-credentials/examples/git-credential-lite.rs
@@ -0,0 +1,23 @@
+use std::convert::TryInto;
+
+/// Run like this `echo url=https://example.com | cargo run --example git-credential-light -- fill`
+pub fn main() -> Result<(), gix_credentials::program::main::Error> {
+ gix_credentials::program::main(
+ std::env::args_os().skip(1),
+ std::io::stdin(),
+ std::io::stdout(),
+ |action, context| {
+ use gix_credentials::program::main::Action::*;
+ gix_credentials::helper::Cascade::default()
+ .invoke(
+ match action {
+ Get => gix_credentials::helper::Action::Get(context),
+ Erase => gix_credentials::helper::Action::Erase(context.to_bstring()),
+ Store => gix_credentials::helper::Action::Store(context.to_bstring()),
+ },
+ gix_prompt::Options::default().apply_environment(true, true, true),
+ )
+ .map(|outcome| outcome.and_then(|outcome| (&outcome.next).try_into().ok()))
+ },
+ )
+}
diff --git a/vendor/gix-credentials/examples/invoke-git-credential.rs b/vendor/gix-credentials/examples/invoke-git-credential.rs
new file mode 100644
index 000000000..cba3f5f70
--- /dev/null
+++ b/vendor/gix-credentials/examples/invoke-git-credential.rs
@@ -0,0 +1,14 @@
+use std::convert::TryInto;
+
+/// Invokes `git credential` with the passed url as argument and prints obtained credentials.
+pub fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let out = gix_credentials::builtin(gix_credentials::helper::Action::get_for_url(
+ std::env::args()
+ .nth(1)
+ .ok_or("First argument must be the URL to obtain credentials for")?,
+ ))?
+ .ok_or("Did not obtain credentials")?;
+ let ctx: gix_credentials::protocol::Context = (&out.next).try_into()?;
+ ctx.write_to(std::io::stdout())?;
+ Ok(())
+}
diff --git a/vendor/gix-credentials/src/helper/cascade.rs b/vendor/gix-credentials/src/helper/cascade.rs
new file mode 100644
index 000000000..9ec251161
--- /dev/null
+++ b/vendor/gix-credentials/src/helper/cascade.rs
@@ -0,0 +1,161 @@
+use crate::{helper, helper::Cascade, protocol, protocol::Context, Program};
+
+impl Default for Cascade {
+ fn default() -> Self {
+ Cascade {
+ programs: Vec::new(),
+ stderr: true,
+ use_http_path: false,
+ query_user_only: false,
+ }
+ }
+}
+
+/// Initialization
+impl Cascade {
+ /// Return the programs to run for the current platform.
+ ///
+ /// These are typically used as basis for all credential cascade invocations, with configured programs following afterwards.
+ ///
+ /// # Note
+ ///
+ /// These defaults emulate what typical git installations may use these days, as in fact it's a configurable which comes
+ /// from installation-specific configuration files which we cannot know (or guess at best).
+ /// This seems like an acceptable trade-off as helpers are ignored if they fail or are not existing.
+ pub fn platform_builtin() -> Vec<Program> {
+ if cfg!(target_os = "macos") {
+ Some("osxkeychain")
+ } else if cfg!(target_os = "linux") {
+ Some("libsecret")
+ } else if cfg!(target_os = "windows") {
+ Some("manager-core")
+ } else {
+ None
+ }
+ .map(|name| vec![Program::from_custom_definition(name)])
+ .unwrap_or_default()
+ }
+}
+
+/// Builder
+impl Cascade {
+ /// Extend the list of programs to run `programs`.
+ pub fn extend(mut self, programs: impl IntoIterator<Item = Program>) -> Self {
+ self.programs.extend(programs);
+ self
+ }
+ /// If `toggle` is true, http(s) urls will use the path portions of the url to obtain a credential for.
+ ///
+ /// Otherwise, they will only take the user name into account.
+ pub fn use_http_path(mut self, toggle: bool) -> Self {
+ self.use_http_path = toggle;
+ self
+ }
+
+ /// If `toggle` is true, a bogus password will be provided to prevent any helper program from prompting for it, nor will
+ /// we prompt for the password. The resulting identity will have a bogus password and it's expected to not be used by the
+ /// consuming transport.
+ pub fn query_user_only(mut self, toggle: bool) -> Self {
+ self.query_user_only = toggle;
+ self
+ }
+}
+
+/// Finalize
+impl Cascade {
+ /// Invoke the cascade by `invoking` each program with `action`, and configuring potential prompts with `prompt` options.
+ /// The latter can also be used to disable the prompt entirely when setting the `mode` to [`Disable`][gix_prompt::Mode::Disable];=.
+ ///
+ /// When _getting_ credentials, all programs are asked until the credentials are complete, stopping the cascade.
+ /// When _storing_ or _erasing_ all programs are instructed in order.
+ #[allow(clippy::result_large_err)]
+ pub fn invoke(&mut self, mut action: helper::Action, mut prompt: gix_prompt::Options<'_>) -> protocol::Result {
+ let mut url = action
+ .context_mut()
+ .map(|ctx| {
+ ctx.destructure_url_in_place(self.use_http_path).map(|ctx| {
+ if self.query_user_only && ctx.password.is_none() {
+ ctx.password = Some("".into());
+ }
+ ctx
+ })
+ })
+ .transpose()?
+ .and_then(|ctx| ctx.url.take());
+
+ for program in &mut self.programs {
+ program.stderr = self.stderr;
+ match helper::invoke::raw(program, &action) {
+ Ok(None) => {}
+ Ok(Some(stdout)) => {
+ let ctx = Context::from_bytes(&stdout)?;
+ if let Some(dst_ctx) = action.context_mut() {
+ if let Some(src) = ctx.path {
+ dst_ctx.path = Some(src);
+ }
+ for (src, dst) in [
+ (ctx.protocol, &mut dst_ctx.protocol),
+ (ctx.host, &mut dst_ctx.host),
+ (ctx.username, &mut dst_ctx.username),
+ (ctx.password, &mut dst_ctx.password),
+ ] {
+ if let Some(src) = src {
+ *dst = Some(src);
+ }
+ }
+ if let Some(src) = ctx.url {
+ dst_ctx.url = Some(src);
+ url = dst_ctx.destructure_url_in_place(self.use_http_path)?.url.take();
+ }
+ if dst_ctx.username.is_some() && dst_ctx.password.is_some() {
+ break;
+ }
+ if ctx.quit.unwrap_or_default() {
+ dst_ctx.quit = ctx.quit;
+ break;
+ }
+ }
+ }
+ Err(helper::Error::CredentialsHelperFailed { .. }) => continue, // ignore helpers that we can't call
+ Err(err) if action.context().is_some() => return Err(err.into()), // communication errors are fatal when getting credentials
+ Err(_) => {} // for other actions, ignore everything, try the operation
+ }
+ }
+
+ if prompt.mode != gix_prompt::Mode::Disable {
+ if let Some(ctx) = action.context_mut() {
+ ctx.url = url;
+ if ctx.username.is_none() {
+ let message = ctx.to_prompt("Username");
+ prompt.mode = gix_prompt::Mode::Visible;
+ ctx.username = gix_prompt::ask(&message, &prompt)
+ .map_err(|err| protocol::Error::Prompt {
+ prompt: message,
+ source: err,
+ })?
+ .into();
+ }
+ if ctx.password.is_none() {
+ let message = ctx.to_prompt("Password");
+ prompt.mode = gix_prompt::Mode::Hidden;
+ ctx.password = gix_prompt::ask(&message, &prompt)
+ .map_err(|err| protocol::Error::Prompt {
+ prompt: message,
+ source: err,
+ })?
+ .into();
+ }
+ }
+ }
+
+ protocol::helper_outcome_to_result(
+ action.context().map(|ctx| helper::Outcome {
+ username: ctx.username.clone(),
+ password: ctx.password.clone(),
+ quit: ctx.quit.unwrap_or(false),
+ next: ctx.to_owned().into(),
+ }),
+ action,
+ )
+ }
+}
diff --git a/vendor/gix-credentials/src/helper/invoke.rs b/vendor/gix-credentials/src/helper/invoke.rs
new file mode 100644
index 000000000..a543ec761
--- /dev/null
+++ b/vendor/gix-credentials/src/helper/invoke.rs
@@ -0,0 +1,66 @@
+use std::io::Read;
+
+use crate::helper::{Action, Context, Error, NextAction, Outcome, Result};
+
+impl Action {
+ /// Send ourselves to the given `write` which is expected to be credentials-helper compatible
+ pub fn send(&self, mut write: impl std::io::Write) -> std::io::Result<()> {
+ match self {
+ Action::Get(ctx) => ctx.write_to(write),
+ Action::Store(last) | Action::Erase(last) => {
+ write.write_all(last)?;
+ write.write_all(&[b'\n'])
+ }
+ }
+ }
+}
+
+/// Invoke the given `helper` with `action` in `context`.
+///
+/// Usually the first call is performed with [`Action::Get`] to obtain `Some` identity, which subsequently can be used if it is complete.
+/// Note that it may also only contain the username _or_ password, and should start out with everything the helper needs.
+/// On successful usage, use [`NextAction::store()`], otherwise [`NextAction::erase()`], which is when this function
+/// returns `Ok(None)` as no outcome is expected.
+pub fn invoke(helper: &mut crate::Program, action: &Action) -> Result {
+ match raw(helper, action)? {
+ None => Ok(None),
+ Some(stdout) => {
+ let ctx = Context::from_bytes(stdout.as_slice())?;
+ Ok(Some(Outcome {
+ username: ctx.username,
+ password: ctx.password,
+ quit: ctx.quit.unwrap_or(false),
+ next: NextAction {
+ previous_output: stdout.into(),
+ },
+ }))
+ }
+ }
+}
+
+pub(crate) fn raw(helper: &mut crate::Program, action: &Action) -> std::result::Result<Option<Vec<u8>>, Error> {
+ let (stdin, stdout) = helper.start(action)?;
+ if let (Action::Get(_), None) = (&action, &stdout) {
+ panic!("BUG: `Helper` impls must return an output handle to read output from if Action::Get is provided")
+ }
+ action.send(stdin)?;
+ let stdout = stdout
+ .map(|mut stdout| {
+ let mut buf = Vec::new();
+ stdout.read_to_end(&mut buf).map(|_| buf)
+ })
+ .transpose()
+ .map_err(|err| Error::CredentialsHelperFailed { source: err })?;
+ helper.finish().map_err(|err| {
+ if err.kind() == std::io::ErrorKind::Other {
+ Error::CredentialsHelperFailed { source: err }
+ } else {
+ err.into()
+ }
+ })?;
+
+ match matches!(action, Action::Get(_)).then(|| stdout).flatten() {
+ None => Ok(None),
+ Some(stdout) => Ok(Some(stdout)),
+ }
+}
diff --git a/vendor/gix-credentials/src/helper/mod.rs b/vendor/gix-credentials/src/helper/mod.rs
new file mode 100644
index 000000000..107d6db7a
--- /dev/null
+++ b/vendor/gix-credentials/src/helper/mod.rs
@@ -0,0 +1,174 @@
+use std::convert::TryFrom;
+
+use bstr::{BStr, BString};
+
+use crate::{protocol, protocol::Context, Program};
+
+/// A list of helper programs to run in order to obtain credentials.
+#[allow(dead_code)]
+#[derive(Debug)]
+pub struct Cascade {
+ /// The programs to run in order to obtain credentials
+ pub programs: Vec<Program>,
+ /// If true, stderr is enabled when `programs` are run, which is the default.
+ pub stderr: bool,
+ /// If true, http(s) urls will take their path portion into account when obtaining credentials. Default is false.
+ /// Other protocols like ssh will always use the path portion.
+ pub use_http_path: bool,
+ /// If true, default false, when getting credentials, we will set a bogus password to only obtain the user name.
+ /// Storage and cancellation work the same, but without a password set.
+ pub query_user_only: bool,
+}
+
+/// The outcome of the credentials helper [invocation][crate::helper::invoke()].
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct Outcome {
+ /// The username to use in the identity, if set.
+ pub username: Option<String>,
+ /// The password to use in the identity, if set.
+ pub password: Option<String>,
+ /// If set, the helper asked to stop the entire process, whether the identity is complete or not.
+ pub quit: bool,
+ /// A handle to the action to perform next in another call to [`helper::invoke()`][crate::helper::invoke()].
+ pub next: NextAction,
+}
+
+impl Outcome {
+ /// Try to fetch username _and_ password to form an identity. This will fail if one of them is not set.
+ ///
+ /// This does nothing if only one of the fields is set, or consume both.
+ pub fn consume_identity(&mut self) -> Option<gix_sec::identity::Account> {
+ if self.username.is_none() || self.password.is_none() {
+ return None;
+ }
+ self.username
+ .take()
+ .zip(self.password.take())
+ .map(|(username, password)| gix_sec::identity::Account { username, password })
+ }
+}
+
+/// The Result type used in [`invoke()`][crate::helper::invoke()].
+pub type Result = std::result::Result<Option<Outcome>, Error>;
+
+/// The error used in the [credentials helper invocation][crate::helper::invoke()].
+#[derive(Debug, thiserror::Error)]
+#[allow(missing_docs)]
+pub enum Error {
+ #[error(transparent)]
+ ContextDecode(#[from] protocol::context::decode::Error),
+ #[error("An IO error occurred while communicating to the credentials helper")]
+ Io(#[from] std::io::Error),
+ #[error(transparent)]
+ CredentialsHelperFailed { source: std::io::Error },
+}
+
+/// The action to perform by the credentials [helper][`crate::helper::invoke()`].
+#[derive(Clone, Debug)]
+pub enum Action {
+ /// Provide credentials using the given repository context, which must include the repository url.
+ Get(Context),
+ /// Approve the credentials as identified by the previous input provided as `BString`, containing information from [`Context`].
+ Store(BString),
+ /// Reject the credentials as identified by the previous input provided as `BString`. containing information from [`Context`].
+ Erase(BString),
+}
+
+/// Initialization
+impl Action {
+ /// Create a `Get` action with context containing the given URL.
+ /// Note that this creates an `Action` suitable for the credential helper cascade only.
+ pub fn get_for_url(url: impl Into<BString>) -> Action {
+ Action::Get(Context {
+ url: Some(url.into()),
+ ..Default::default()
+ })
+ }
+}
+
+/// Access
+impl Action {
+ /// Return the payload of store or erase actions.
+ pub fn payload(&self) -> Option<&BStr> {
+ use bstr::ByteSlice;
+ match self {
+ Action::Get(_) => None,
+ Action::Store(p) | Action::Erase(p) => Some(p.as_bstr()),
+ }
+ }
+ /// Return the context of a get operation, or `None`.
+ ///
+ /// The opposite of [`payload`][Action::payload()].
+ pub fn context(&self) -> Option<&Context> {
+ match self {
+ Action::Get(ctx) => Some(ctx),
+ Action::Erase(_) | Action::Store(_) => None,
+ }
+ }
+
+ /// Return the mutable context of a get operation, or `None`.
+ pub fn context_mut(&mut self) -> Option<&mut Context> {
+ match self {
+ Action::Get(ctx) => Some(ctx),
+ Action::Erase(_) | Action::Store(_) => None,
+ }
+ }
+
+ /// Returns true if this action expects output from the helper.
+ pub fn expects_output(&self) -> bool {
+ matches!(self, Action::Get(_))
+ }
+
+ /// The name of the argument to describe this action. If `is_external` is true, the target program is
+ /// a custom credentials helper, not a built-in one.
+ pub fn as_arg(&self, is_external: bool) -> &str {
+ match self {
+ Action::Get(_) if is_external => "get",
+ Action::Get(_) => "fill",
+ Action::Store(_) if is_external => "store",
+ Action::Store(_) => "approve",
+ Action::Erase(_) if is_external => "erase",
+ Action::Erase(_) => "reject",
+ }
+ }
+}
+
+/// A handle to [store][NextAction::store()] or [erase][NextAction::erase()] the outcome of the initial action.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct NextAction {
+ previous_output: BString,
+}
+
+impl TryFrom<&NextAction> for Context {
+ type Error = protocol::context::decode::Error;
+
+ fn try_from(value: &NextAction) -> std::result::Result<Self, Self::Error> {
+ Context::from_bytes(value.previous_output.as_ref())
+ }
+}
+
+impl From<Context> for NextAction {
+ fn from(ctx: Context) -> Self {
+ let mut buf = Vec::<u8>::new();
+ ctx.write_to(&mut buf).expect("cannot fail");
+ NextAction {
+ previous_output: buf.into(),
+ }
+ }
+}
+
+impl NextAction {
+ /// Approve the result of the previous [Action] and store for lookup.
+ pub fn store(self) -> Action {
+ Action::Store(self.previous_output)
+ }
+ /// Reject the result of the previous [Action] and erase it as to not be returned when being looked up.
+ pub fn erase(self) -> Action {
+ Action::Erase(self.previous_output)
+ }
+}
+
+mod cascade;
+pub(crate) mod invoke;
+
+pub use invoke::invoke;
diff --git a/vendor/gix-credentials/src/lib.rs b/vendor/gix-credentials/src/lib.rs
new file mode 100644
index 000000000..dfcb4ced7
--- /dev/null
+++ b/vendor/gix-credentials/src/lib.rs
@@ -0,0 +1,43 @@
+//! Interact with git credentials in various ways and launch helper programs.
+//!
+//! ## Feature Flags
+#![cfg_attr(
+ feature = "document-features",
+ cfg_attr(doc, doc = ::document_features::document_features!())
+)]
+#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
+#![deny(missing_docs, rust_2018_idioms)]
+#![forbid(unsafe_code)]
+
+/// A program/executable implementing the credential helper protocol.
+#[derive(Debug)]
+pub struct Program {
+ /// The kind of program, ready for launch.
+ pub kind: program::Kind,
+ /// If true, stderr is enabled, which is the default.
+ pub stderr: bool,
+ /// `Some(…)` if the process is running.
+ child: Option<std::process::Child>,
+}
+
+///
+pub mod helper;
+
+///
+pub mod program;
+
+///
+pub mod protocol;
+
+/// Call the `git credential` helper program performing the given `action`, which reads all context from the git configuration
+/// and does everything `git` typically does. The `action` should have been created with [`helper::Action::get_for_url()`] to
+/// contain only the URL to kick off the process, or should be created by [`helper::NextAction`].
+///
+/// If more control is required, use the [`Cascade`][helper::Cascade] type.
+#[allow(clippy::result_large_err)]
+pub fn builtin(action: helper::Action) -> protocol::Result {
+ protocol::helper_outcome_to_result(
+ helper::invoke(&mut Program::from_kind(program::Kind::Builtin), &action)?,
+ action,
+ )
+}
diff --git a/vendor/gix-credentials/src/program/main.rs b/vendor/gix-credentials/src/program/main.rs
new file mode 100644
index 000000000..062bcfc99
--- /dev/null
+++ b/vendor/gix-credentials/src/program/main.rs
@@ -0,0 +1,110 @@
+use std::{convert::TryFrom, ffi::OsString};
+
+use bstr::BString;
+
+/// The action passed to the credential helper implementation in [`main()`][crate::program::main()].
+#[derive(Debug, Copy, Clone)]
+pub enum Action {
+ /// Get credentials for a url.
+ Get,
+ /// Store credentials provided in the given context.
+ Store,
+ /// Erase credentials identified by the given context.
+ Erase,
+}
+
+impl TryFrom<OsString> for Action {
+ type Error = Error;
+
+ fn try_from(value: OsString) -> Result<Self, Self::Error> {
+ Ok(match value.to_str() {
+ Some("fill") | Some("get") => Action::Get,
+ Some("approve") | Some("store") => Action::Store,
+ Some("reject") | Some("erase") => Action::Erase,
+ _ => return Err(Error::ActionInvalid { name: value }),
+ })
+ }
+}
+
+impl Action {
+ /// Return ourselves as string representation, similar to what would be passed as argument to a credential helper.
+ pub fn as_str(&self) -> &'static str {
+ match self {
+ Action::Get => "get",
+ Action::Store => "store",
+ Action::Erase => "erase",
+ }
+ }
+}
+
+/// The error of [`main()`][crate::program::main()].
+#[derive(Debug, thiserror::Error)]
+#[allow(missing_docs)]
+pub enum Error {
+ #[error("Action named {name:?} is invalid, need 'get', 'store', 'erase' or 'fill', 'approve', 'reject'")]
+ ActionInvalid { name: OsString },
+ #[error("The first argument must be the action to perform")]
+ ActionMissing,
+ #[error(transparent)]
+ Helper {
+ source: Box<dyn std::error::Error + Send + Sync + 'static>,
+ },
+ #[error(transparent)]
+ Io(#[from] std::io::Error),
+ #[error(transparent)]
+ Context(#[from] crate::protocol::context::decode::Error),
+ #[error("Credentials for {url:?} could not be obtained")]
+ CredentialsMissing { url: BString },
+ #[error("The url wasn't provided in input - the git credentials protocol mandates this")]
+ UrlMissing,
+}
+
+pub(crate) mod function {
+ use std::{convert::TryInto, ffi::OsString};
+
+ use crate::{
+ program::main::{Action, Error},
+ protocol::Context,
+ };
+
+ /// Invoke a custom credentials helper which receives program `args`, with the first argument being the
+ /// action to perform (as opposed to the program name).
+ /// Then read context information from `stdin` and if the action is `Action::Get`, then write the result to `stdout`.
+ /// `credentials` is the API version of such call, where`Ok(Some(context))` returns credentials, and `Ok(None)` indicates
+ /// no credentials could be found for `url`, which is always set when called.
+ ///
+ /// Call this function from a programs `main`, passing `std::env::args_os()`, `stdin()` and `stdout` accordingly, along with
+ /// your own helper implementation.
+ pub fn main<CredentialsFn, E>(
+ args: impl IntoIterator<Item = OsString>,
+ mut stdin: impl std::io::Read,
+ stdout: impl std::io::Write,
+ credentials: CredentialsFn,
+ ) -> Result<(), Error>
+ where
+ CredentialsFn: FnOnce(Action, Context) -> Result<Option<Context>, E>,
+ E: std::error::Error + Send + Sync + 'static,
+ {
+ let action: Action = args.into_iter().next().ok_or(Error::ActionMissing)?.try_into()?;
+ let mut buf = Vec::<u8>::with_capacity(512);
+ stdin.read_to_end(&mut buf)?;
+ let ctx = Context::from_bytes(&buf)?;
+ if ctx.url.is_none() {
+ return Err(Error::UrlMissing);
+ }
+ let res = credentials(action, ctx).map_err(|err| Error::Helper { source: Box::new(err) })?;
+ match (action, res) {
+ (Action::Get, None) => {
+ return Err(Error::CredentialsMissing {
+ url: Context::from_bytes(&buf)?.url.expect("present and checked above"),
+ })
+ }
+ (Action::Get, Some(ctx)) => ctx.write_to(stdout)?,
+ (Action::Erase | Action::Store, None) => {}
+ (Action::Erase | Action::Store, Some(_)) => {
+ panic!("BUG: credentials helper must not return context for erase or store actions")
+ }
+ }
+ Ok(())
+ }
+}
diff --git a/vendor/gix-credentials/src/program/mod.rs b/vendor/gix-credentials/src/program/mod.rs
new file mode 100644
index 000000000..e13e0a5ec
--- /dev/null
+++ b/vendor/gix-credentials/src/program/mod.rs
@@ -0,0 +1,131 @@
+use std::process::{Command, Stdio};
+
+use bstr::{BString, ByteSlice, ByteVec};
+
+use crate::{helper, Program};
+
+/// The kind of helper program to use.
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub enum Kind {
+ /// The built-in `git credential` helper program, part of any `git` distribution.
+ Builtin,
+ /// A custom credentials helper, as identified just by the name with optional arguments
+ ExternalName {
+ /// The name like `foo` along with optional args, like `foo --arg --bar="a b"`, with arguments using `sh` shell quoting rules.
+ /// The program executed will be `git-credential-foo` if `name_and_args` starts with `foo`.
+ name_and_args: BString,
+ },
+ /// A custom credentials helper, as identified just by the absolute path to the program and optional arguments. The program is executed through a shell.
+ ExternalPath {
+ /// The absolute path to the executable, like `/path/to/exe` along with optional args, like `/path/to/exe --arg --bar="a b"`, with arguments using `sh`
+ /// shell quoting rules.
+ path_and_args: BString,
+ },
+ /// A script to execute with `sh`.
+ ExternalShellScript(BString),
+}
+
+/// Initialization
+impl Program {
+ /// Create a new program of the given `kind`.
+ pub fn from_kind(kind: Kind) -> Self {
+ Program {
+ kind,
+ child: None,
+ stderr: true,
+ }
+ }
+
+ /// Parse the given input as per the custom helper definition, supporting `!<script>`, `name` and `/absolute/name`, the latter two
+ /// also support arguments which are ignored here.
+ pub fn from_custom_definition(input: impl Into<BString>) -> Self {
+ let mut input = input.into();
+ let kind = if input.starts_with(b"!") {
+ input.remove(0);
+ Kind::ExternalShellScript(input)
+ } else {
+ let path = gix_path::from_bstr(
+ input
+ .find_byte(b' ')
+ .map_or(input.as_slice(), |pos| &input[..pos])
+ .as_bstr(),
+ );
+ if gix_path::is_absolute(path) {
+ Kind::ExternalPath { path_and_args: input }
+ } else {
+ input.insert_str(0, "git credential-");
+ Kind::ExternalName { name_and_args: input }
+ }
+ };
+ Program {
+ kind,
+ child: None,
+ stderr: true,
+ }
+ }
+}
+
+/// Builder
+impl Program {
+ /// By default `stderr` of programs is inherited and typically displayed in the terminal.
+ pub fn suppress_stderr(mut self) -> Self {
+ self.stderr = false;
+ self
+ }
+}
+
+impl Program {
+ pub(crate) fn start(
+ &mut self,
+ action: &helper::Action,
+ ) -> std::io::Result<(std::process::ChildStdin, Option<std::process::ChildStdout>)> {
+ assert!(self.child.is_none(), "BUG: must not call `start()` twice");
+ let mut cmd = match &self.kind {
+ Kind::Builtin => {
+ let mut cmd = Command::new(cfg!(windows).then(|| "git.exe").unwrap_or("git"));
+ cmd.arg("credential").arg(action.as_arg(false));
+ cmd
+ }
+ Kind::ExternalShellScript(for_shell)
+ | Kind::ExternalName {
+ name_and_args: for_shell,
+ }
+ | Kind::ExternalPath {
+ path_and_args: for_shell,
+ } => gix_command::prepare(gix_path::from_bstr(for_shell.as_bstr()).as_ref())
+ .with_shell()
+ .arg(action.as_arg(true))
+ .into(),
+ };
+ cmd.stdin(Stdio::piped())
+ .stdout(if action.expects_output() {
+ Stdio::piped()
+ } else {
+ Stdio::null()
+ })
+ .stderr(if self.stderr { Stdio::inherit() } else { Stdio::null() });
+ let mut child = cmd.spawn()?;
+ let stdin = child.stdin.take().expect("stdin to be configured");
+ let stdout = child.stdout.take();
+
+ self.child = child.into();
+ Ok((stdin, stdout))
+ }
+
+ pub(crate) fn finish(&mut self) -> std::io::Result<()> {
+ let mut child = self.child.take().expect("Call `start()` before calling finish()");
+ let status = child.wait()?;
+ if status.success() {
+ Ok(())
+ } else {
+ Err(std::io::Error::new(
+ std::io::ErrorKind::Other,
+ format!("Credentials helper program failed with status code {:?}", status.code()),
+ ))
+ }
+ }
+}
+
+///
+pub mod main;
+pub use main::function::main;
diff --git a/vendor/gix-credentials/src/protocol/context/mod.rs b/vendor/gix-credentials/src/protocol/context/mod.rs
new file mode 100644
index 000000000..1c578c046
--- /dev/null
+++ b/vendor/gix-credentials/src/protocol/context/mod.rs
@@ -0,0 +1,79 @@
+use bstr::BString;
+
+/// Indicates key or values contain errors that can't be encoded.
+#[derive(Debug, thiserror::Error)]
+#[allow(missing_docs)]
+pub enum Error {
+ #[error("{key:?}={value:?} must not contain null bytes or newlines neither in key nor in value.")]
+ Encoding { key: String, value: BString },
+}
+
+mod access {
+ use bstr::BString;
+
+ use crate::protocol::Context;
+
+ impl Context {
+ /// Convert all relevant fields into a URL for consumption.
+ pub fn to_url(&self) -> Option<BString> {
+ use bstr::{ByteSlice, ByteVec};
+ let mut buf: BString = self.protocol.clone()?.into();
+ buf.push_str(b"://");
+ if let Some(user) = &self.username {
+ buf.push_str(user);
+ buf.push(b'@');
+ }
+ if let Some(host) = &self.host {
+ buf.push_str(host);
+ }
+ if let Some(path) = &self.path {
+ if !path.starts_with_str("/") {
+ buf.push(b'/');
+ }
+ buf.push_str(path);
+ }
+ buf.into()
+ }
+ /// Compute a prompt to obtain the given value.
+ pub fn to_prompt(&self, field: &str) -> String {
+ match self.to_url() {
+ Some(url) => format!("{field} for {url}: "),
+ None => format!("{field}: "),
+ }
+ }
+ }
+}
+
+mod mutate {
+ use bstr::ByteSlice;
+
+ use crate::{protocol, protocol::Context};
+
+ /// In-place mutation
+ impl Context {
+ /// Destructure the url at our `url` field into parts like protocol, host, username and path and store
+ /// them in our respective fields. If `use_http_path` is set, http paths are significant even though
+ /// normally this isn't the case.
+ #[allow(clippy::result_large_err)]
+ pub fn destructure_url_in_place(&mut self, use_http_path: bool) -> Result<&mut Self, protocol::Error> {
+ let url = gix_url::parse(self.url.as_ref().ok_or(protocol::Error::UrlMissing)?.as_ref())?;
+ self.protocol = Some(url.scheme.as_str().into());
+ self.username = url.user().map(ToOwned::to_owned);
+ self.host = url.host().map(ToOwned::to_owned).map(|mut host| {
+ if let Some(port) = url.port {
+ use std::fmt::Write;
+ write!(host, ":{port}").expect("infallible");
+ }
+ host
+ });
+ if !matches!(url.scheme, gix_url::Scheme::Http | gix_url::Scheme::Https) || use_http_path {
+ let path = url.path.trim_with(|b| b == '/');
+ self.path = (!path.is_empty()).then(|| path.into());
+ }
+ Ok(self)
+ }
+ }
+}
+
+mod serde;
+pub use self::serde::decode;
diff --git a/vendor/gix-credentials/src/protocol/context/serde.rs b/vendor/gix-credentials/src/protocol/context/serde.rs
new file mode 100644
index 000000000..964195263
--- /dev/null
+++ b/vendor/gix-credentials/src/protocol/context/serde.rs
@@ -0,0 +1,122 @@
+use bstr::BStr;
+
+use crate::protocol::context::Error;
+
+mod write {
+ use bstr::{BStr, BString};
+
+ use crate::protocol::{context::serde::validate, Context};
+
+ impl Context {
+ /// Write ourselves to `out` such that [`from_bytes()`][Self::from_bytes()] can decode it losslessly.
+ pub fn write_to(&self, mut out: impl std::io::Write) -> std::io::Result<()> {
+ use bstr::ByteSlice;
+ fn write_key(out: &mut impl std::io::Write, key: &str, value: &BStr) -> std::io::Result<()> {
+ out.write_all(key.as_bytes())?;
+ out.write_all(b"=")?;
+ out.write_all(value)?;
+ out.write_all(b"\n")
+ }
+ for (key, value) in [("url", &self.url), ("path", &self.path)] {
+ if let Some(value) = value {
+ validate(key, value.as_slice().into())
+ .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))?;
+ write_key(&mut out, key, value.as_ref())?;
+ }
+ }
+ for (key, value) in [
+ ("protocol", &self.protocol),
+ ("host", &self.host),
+ ("username", &self.username),
+ ("password", &self.password),
+ ] {
+ if let Some(value) = value {
+ validate(key, value.as_str().into())
+ .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))?;
+ write_key(&mut out, key, value.as_bytes().as_bstr())?;
+ }
+ }
+ Ok(())
+ }
+
+ /// Like [`write_to()`][Self::write_to()], but writes infallibly into memory.
+ pub fn to_bstring(&self) -> BString {
+ let mut buf = Vec::<u8>::new();
+ self.write_to(&mut buf).expect("infallible");
+ buf.into()
+ }
+ }
+}
+
+///
+pub mod decode {
+ use std::convert::TryFrom;
+
+ use bstr::{BString, ByteSlice};
+
+ use crate::protocol::{context, context::serde::validate, Context};
+
+ /// The error returned by [`from_bytes()`][Context::from_bytes()].
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error("Illformed UTF-8 in value of key {key:?}: {value:?}")]
+ IllformedUtf8InValue { key: String, value: BString },
+ #[error(transparent)]
+ Encoding(#[from] context::Error),
+ #[error("Invalid format in line {line:?}, expecting key=value")]
+ Syntax { line: BString },
+ }
+
+ impl Context {
+ /// Decode ourselves from `input` which is the format written by [`write_to()`][Self::write_to()].
+ pub fn from_bytes(input: &[u8]) -> Result<Self, Error> {
+ let mut ctx = Context::default();
+ for res in input.lines().take_while(|line| !line.is_empty()).map(|line| {
+ let mut it = line.splitn(2, |b| *b == b'=');
+ match (it.next().and_then(|k| k.to_str().ok()), it.next().map(|v| v.as_bstr())) {
+ (Some(key), Some(value)) => validate(key, value)
+ .map(|_| (key, value.to_owned()))
+ .map_err(Into::into),
+ _ => Err(Error::Syntax { line: line.into() }),
+ }
+ }) {
+ let (key, value) = res?;
+ match key {
+ "protocol" | "host" | "username" | "password" => {
+ if !value.is_utf8() {
+ return Err(Error::IllformedUtf8InValue { key: key.into(), value });
+ }
+ let value = value.to_string();
+ *match key {
+ "protocol" => &mut ctx.protocol,
+ "host" => &mut ctx.host,
+ "username" => &mut ctx.username,
+ "password" => &mut ctx.password,
+ _ => unreachable!("checked field names in match above"),
+ } = Some(value);
+ }
+ "url" => ctx.url = Some(value),
+ "path" => ctx.path = Some(value),
+ "quit" => {
+ ctx.quit = gix_config_value::Boolean::try_from(value.as_ref())
+ .ok()
+ .map(|b| b.into());
+ }
+ _ => {}
+ }
+ }
+ Ok(ctx)
+ }
+ }
+}
+
+fn validate(key: &str, value: &BStr) -> Result<(), Error> {
+ if key.contains('\0') || key.contains('\n') || value.contains(&0) || value.contains(&b'\n') {
+ return Err(Error::Encoding {
+ key: key.to_owned(),
+ value: value.to_owned(),
+ });
+ }
+ Ok(())
+}
diff --git a/vendor/gix-credentials/src/protocol/mod.rs b/vendor/gix-credentials/src/protocol/mod.rs
new file mode 100644
index 000000000..ec168ffb3
--- /dev/null
+++ b/vendor/gix-credentials/src/protocol/mod.rs
@@ -0,0 +1,86 @@
+use bstr::BString;
+
+use crate::helper;
+
+/// The outcome of the credentials top-level functions to obtain a complete identity.
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct Outcome {
+ /// The identity provide by the helper.
+ pub identity: gix_sec::identity::Account,
+ /// A handle to the action to perform next in another call to [`helper::invoke()`][crate::helper::invoke()].
+ pub next: helper::NextAction,
+}
+
+/// The Result type used in credentials top-level functions to obtain a complete identity.
+pub type Result = std::result::Result<Option<Outcome>, Error>;
+
+/// The error returned top-level credential functions.
+#[derive(Debug, thiserror::Error)]
+#[allow(missing_docs)]
+pub enum Error {
+ #[error(transparent)]
+ UrlParse(#[from] gix_url::parse::Error),
+ #[error("The 'url' field must be set when performing a 'get/fill' action")]
+ UrlMissing,
+ #[error(transparent)]
+ ContextDecode(#[from] context::decode::Error),
+ #[error(transparent)]
+ InvokeHelper(#[from] helper::Error),
+ #[error("Could not obtain identity for context: {}", { let mut buf = Vec::<u8>::new(); context.write_to(&mut buf).ok(); String::from_utf8_lossy(&buf).into_owned() })]
+ IdentityMissing { context: Context },
+ #[error("The handler asked to stop trying to obtain credentials")]
+ Quit,
+ #[error("Couldn't obtain {prompt}")]
+ Prompt { prompt: String, source: gix_prompt::Error },
+}
+
+/// Additional context to be passed to the credentials helper.
+#[derive(Debug, Default, Clone, Eq, PartialEq)]
+pub struct Context {
+ /// The protocol over which the credential will be used (e.g., https).
+ pub protocol: Option<String>,
+ /// The remote hostname for a network credential. This includes the port number if one was specified (e.g., "example.com:8088").
+ pub host: Option<String>,
+ /// The path with which the credential will be used. E.g., for accessing a remote https repository, this will be the repository’s path on the server.
+ /// It can also be a path on the file system.
+ pub path: Option<BString>,
+ /// The credential’s username, if we already have one (e.g., from a URL, the configuration, the user, or from a previously run helper).
+ pub username: Option<String>,
+ /// The credential’s password, if we are asking it to be stored.
+ pub password: Option<String>,
+ /// When this special attribute is read by git credential, the value is parsed as a URL and treated as if its constituent
+ /// parts were read (e.g., url=<https://example.com> would behave as if
+ /// protocol=https and host=example.com had been provided). This can help callers avoid parsing URLs themselves.
+ pub url: Option<BString>,
+ /// If true, the caller should stop asking for credentials immediately without calling more credential helpers in the chain.
+ pub quit: Option<bool>,
+}
+
+/// Convert the outcome of a helper invocation to a helper result, assuring that the identity is complete in the process.
+#[allow(clippy::result_large_err)]
+pub fn helper_outcome_to_result(outcome: Option<helper::Outcome>, action: helper::Action) -> Result {
+ fn redact(mut ctx: Context) -> Context {
+ if let Some(pw) = ctx.password.as_mut() {
+ *pw = "<redacted>".into()
+ }
+ ctx
+ }
+ match (action, outcome) {
+ (helper::Action::Get(ctx), None) => Err(Error::IdentityMissing { context: redact(ctx) }),
+ (helper::Action::Get(ctx), Some(mut outcome)) => match outcome.consume_identity() {
+ Some(identity) => Ok(Some(Outcome {
+ identity,
+ next: outcome.next,
+ })),
+ None => Err(if outcome.quit {
+ Error::Quit
+ } else {
+ Error::IdentityMissing { context: redact(ctx) }
+ }),
+ },
+ (helper::Action::Store(_) | helper::Action::Erase(_), _ignore) => Ok(None),
+ }
+}
+
+///
+pub mod context;
diff --git a/vendor/gix-credentials/tests/credentials.rs b/vendor/gix-credentials/tests/credentials.rs
new file mode 100644
index 000000000..f94dfd05e
--- /dev/null
+++ b/vendor/gix-credentials/tests/credentials.rs
@@ -0,0 +1,5 @@
+pub use gix_testtools::Result;
+
+mod helper;
+mod program;
+mod protocol;
diff --git a/vendor/gix-credentials/tests/fixtures/all-but-credentials.sh b/vendor/gix-credentials/tests/fixtures/all-but-credentials.sh
new file mode 100644
index 000000000..0610a71b0
--- /dev/null
+++ b/vendor/gix-credentials/tests/fixtures/all-but-credentials.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+echo protocol=ftp
+echo host=example.com:8080
+echo path=/path/to/git/
+
diff --git a/vendor/gix-credentials/tests/fixtures/custom-helper.sh b/vendor/gix-credentials/tests/fixtures/custom-helper.sh
new file mode 100755
index 000000000..55d6b2f94
--- /dev/null
+++ b/vendor/gix-credentials/tests/fixtures/custom-helper.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+set -eu
+
+test "$1" = get && \
+echo username=user-script && \
+echo password=pass-script
diff --git a/vendor/gix-credentials/tests/fixtures/fail.sh b/vendor/gix-credentials/tests/fixtures/fail.sh
new file mode 100644
index 000000000..84b6391bc
--- /dev/null
+++ b/vendor/gix-credentials/tests/fixtures/fail.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+exit 42
diff --git a/vendor/gix-credentials/tests/fixtures/last-pass.sh b/vendor/gix-credentials/tests/fixtures/last-pass.sh
new file mode 100644
index 000000000..2f03f8986
--- /dev/null
+++ b/vendor/gix-credentials/tests/fixtures/last-pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+set -eu
+
+echo username=user
+echo password=pass
+echo quit=1
diff --git a/vendor/gix-credentials/tests/fixtures/password.sh b/vendor/gix-credentials/tests/fixtures/password.sh
new file mode 100644
index 000000000..f75c4bc02
--- /dev/null
+++ b/vendor/gix-credentials/tests/fixtures/password.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+echo password=pass
diff --git a/vendor/gix-credentials/tests/fixtures/reflect.sh b/vendor/gix-credentials/tests/fixtures/reflect.sh
new file mode 100644
index 000000000..e4079b793
--- /dev/null
+++ b/vendor/gix-credentials/tests/fixtures/reflect.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+cat
diff --git a/vendor/gix-credentials/tests/fixtures/url.sh b/vendor/gix-credentials/tests/fixtures/url.sh
new file mode 100644
index 000000000..1eb585859
--- /dev/null
+++ b/vendor/gix-credentials/tests/fixtures/url.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+echo protocol=ftp
+echo host=github.com
+echo path=byron/gitoxide
+echo url=http://example.com:8080/path/to/git/
+
diff --git a/vendor/gix-credentials/tests/fixtures/username.sh b/vendor/gix-credentials/tests/fixtures/username.sh
new file mode 100644
index 000000000..f2bab6c28
--- /dev/null
+++ b/vendor/gix-credentials/tests/fixtures/username.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+echo username=user
diff --git a/vendor/gix-credentials/tests/helper/cascade.rs b/vendor/gix-credentials/tests/helper/cascade.rs
new file mode 100644
index 000000000..f97a64dcb
--- /dev/null
+++ b/vendor/gix-credentials/tests/helper/cascade.rs
@@ -0,0 +1,174 @@
+mod invoke {
+ use std::convert::TryInto;
+
+ use bstr::{ByteSlice, ByteVec};
+ use gix_credentials::{
+ helper::{Action, Cascade},
+ program, protocol,
+ protocol::Context,
+ Program,
+ };
+ use gix_sec::identity::Account;
+ use gix_testtools::fixture_path;
+
+ #[test]
+ fn credentials_are_filled_in_one_by_one_and_stop_when_complete() {
+ let actual = invoke_cascade(["username", "password", "custom-helper"], action_get())
+ .unwrap()
+ .expect("credentials");
+ assert_eq!(actual.identity, identity("user", "pass"));
+ }
+
+ #[test]
+ fn usernames_in_urls_are_kept_if_the_helper_does_not_overwrite_it() {
+ let actual = invoke_cascade(
+ ["password", "custom-helper"],
+ Action::get_for_url("ssh://git@host.org/path"),
+ )
+ .unwrap()
+ .expect("credentials");
+ assert_eq!(actual.identity, identity("git", "pass"));
+ }
+
+ #[test]
+ fn partial_credentials_can_be_overwritten_by_complete_ones() {
+ let actual = invoke_cascade(["username", "custom-helper"], action_get())
+ .unwrap()
+ .expect("credentials");
+ assert_eq!(actual.identity, identity("user-script", "pass-script"));
+ }
+
+ #[test]
+ fn failing_helpers_for_filling_dont_interrupt() {
+ let actual = invoke_cascade(["fail", "custom-helper"], action_get())
+ .unwrap()
+ .expect("credentials");
+ assert_eq!(actual.identity, identity("user-script", "pass-script"));
+ }
+
+ #[test]
+ fn urls_are_split_in_get_to_support_scripts() {
+ let actual = invoke_cascade(
+ ["reflect", "custom-helper"],
+ Action::get_for_url("https://example.com:8080/path/git/"),
+ )
+ .unwrap()
+ .expect("credentials");
+
+ let ctx: Context = (&actual.next).try_into().unwrap();
+ assert_eq!(ctx.protocol.as_deref().expect("protocol"), "https");
+ assert_eq!(ctx.host.as_deref().expect("host"), "example.com:8080");
+ assert_eq!(ctx.path.as_deref().expect("path").as_bstr(), "path/git");
+ }
+
+ #[test]
+ fn urls_are_split_in_get_but_can_skip_the_path_in_host_only_urls() {
+ let actual = invoke_cascade(["reflect", "custom-helper"], Action::get_for_url("http://example.com"))
+ .unwrap()
+ .expect("credentials");
+
+ let ctx: Context = (&actual.next).try_into().unwrap();
+ assert_eq!(ctx.protocol.as_deref().expect("protocol"), "http");
+ assert_eq!(ctx.host.as_deref().expect("host"), "example.com");
+ assert_eq!(ctx.path, None);
+ }
+
+ #[test]
+ fn helpers_can_set_any_context_value() {
+ let actual = invoke_cascade(
+ ["all-but-credentials", "custom-helper"],
+ Action::get_for_url("http://github.com"),
+ )
+ .unwrap()
+ .expect("credentials");
+
+ let ctx: Context = (&actual.next).try_into().unwrap();
+ assert_eq!(ctx.protocol.as_deref().expect("protocol"), "ftp");
+ assert_eq!(ctx.host.as_deref().expect("host"), "example.com:8080");
+ assert_eq!(
+ ctx.path.expect("set by helper"),
+ "/path/to/git/",
+ "values are passed verbatim even if they would otherwise look different"
+ );
+ }
+
+ #[test]
+ fn helpers_can_set_any_context_value_using_the_url_only() {
+ let actual = invoke_cascade(["url", "custom-helper"], Action::get_for_url("http://github.com"))
+ .unwrap()
+ .expect("credentials");
+
+ let ctx: Context = (&actual.next).try_into().unwrap();
+ assert_eq!(
+ ctx.protocol.as_deref().expect("protocol"),
+ "http",
+ "url is processed last, it overwrites what came before"
+ );
+ assert_eq!(ctx.host.as_deref().expect("host"), "example.com:8080");
+ assert_eq!(
+ ctx.path.expect("set by helper"),
+ "path/to/git",
+ "the url is processed like any other"
+ );
+ }
+
+ #[test]
+ fn helpers_can_quit_and_their_creds_are_taken_if_complete() {
+ let actual = invoke_cascade(["last-pass", "custom-helper"], Action::get_for_url("http://github.com"))
+ .unwrap()
+ .expect("credentials");
+
+ assert_eq!(actual.identity, identity("user", "pass"));
+ }
+
+ #[test]
+ fn bogus_password_overrides_any_helper_and_helper_overrides_username_in_url() {
+ let actual = Cascade::default()
+ .query_user_only(true)
+ .extend(fixtures(["username", "password"]))
+ .invoke(
+ Action::get_for_url("ssh://git@host/repo"),
+ gix_prompt::Options {
+ mode: gix_prompt::Mode::Disable,
+ askpass: None,
+ },
+ )
+ .unwrap()
+ .expect("credentials");
+ assert_eq!(actual.identity, identity("user", ""));
+ }
+
+ fn action_get() -> Action {
+ Action::get_for_url("does/not/matter")
+ }
+
+ fn identity(user: &str, pass: &str) -> Account {
+ Account {
+ username: user.into(),
+ password: pass.into(),
+ }
+ }
+
+ #[allow(clippy::result_large_err)]
+ fn invoke_cascade<'a>(names: impl IntoIterator<Item = &'a str>, action: Action) -> protocol::Result {
+ Cascade::default().use_http_path(true).extend(fixtures(names)).invoke(
+ action,
+ gix_prompt::Options {
+ mode: gix_prompt::Mode::Disable,
+ askpass: None,
+ },
+ )
+ }
+
+ fn fixtures<'a>(names: impl IntoIterator<Item = &'a str>) -> Vec<Program> {
+ names
+ .into_iter()
+ .map(|name| gix_path::realpath(fixture_path(format!("{name}.sh"))).unwrap())
+ .map(|path| {
+ let mut script = gix_path::to_unix_separators_on_windows(gix_path::into_bstr(path)).into_owned();
+ script.insert_str(0, "sh ");
+ Program::from_kind(program::Kind::ExternalShellScript(script))
+ })
+ .collect()
+ }
+}
diff --git a/vendor/gix-credentials/tests/helper/context.rs b/vendor/gix-credentials/tests/helper/context.rs
new file mode 100644
index 000000000..6566c6c2b
--- /dev/null
+++ b/vendor/gix-credentials/tests/helper/context.rs
@@ -0,0 +1,123 @@
+use gix_credentials::protocol::Context;
+
+#[test]
+fn encode_decode_roundtrip_works_only_for_serializing_fields() {
+ for ctx in [
+ Context {
+ protocol: Some("https".into()),
+ host: Some("github.com".into()),
+ path: Some("byron/gitoxide".into()),
+ username: Some("user".into()),
+ password: Some("pass".into()),
+ url: Some("https://github.com/byron/gitoxide".into()),
+ ..Default::default()
+ },
+ Context::default(),
+ ] {
+ let mut buf = Vec::<u8>::new();
+ ctx.write_to(&mut buf).unwrap();
+ let actual = Context::from_bytes(&buf).unwrap();
+ assert_eq!(actual, ctx, "ctx should encode itself losslessly");
+ }
+}
+
+mod write_to {
+ use gix_credentials::protocol::Context;
+
+ #[test]
+ fn quit_is_not_serialized_but_can_be_parsed() {
+ let mut buf = Vec::<u8>::new();
+ Context {
+ quit: Some(true),
+ ..Default::default()
+ }
+ .write_to(&mut buf)
+ .unwrap();
+ assert_eq!(Context::from_bytes(&buf).unwrap(), Context::default());
+ assert_eq!(
+ Context::from_bytes(b"quit=true\nurl=https://example.com").unwrap(),
+ Context {
+ quit: Some(true),
+ url: Some("https://example.com".into()),
+ ..Default::default()
+ }
+ );
+ }
+
+ #[test]
+ fn null_bytes_and_newlines_are_invalid() {
+ for input in [&b"foo\0"[..], b"foo\n"] {
+ let ctx = Context {
+ path: Some(input.into()),
+ ..Default::default()
+ };
+ let mut buf = Vec::<u8>::new();
+ let err = ctx.write_to(&mut buf).unwrap_err();
+ assert_eq!(err.kind(), std::io::ErrorKind::Other);
+ }
+ }
+}
+
+mod from_bytes {
+ use gix_credentials::protocol::Context;
+
+ #[test]
+ fn empty_newlines_cause_skipping_remaining_input() {
+ let input = b"protocol=https
+host=example.com\n
+password=secr3t
+username=bob";
+ assert_eq!(
+ Context::from_bytes(input).unwrap(),
+ Context {
+ protocol: Some("https".into()),
+ host: Some("example.com".into()),
+ ..Default::default()
+ }
+ )
+ }
+
+ #[test]
+ fn unknown_field_names_are_skipped() {
+ let input = b"protocol=https
+unknown=value
+username=bob";
+ assert_eq!(
+ Context::from_bytes(input).unwrap(),
+ Context {
+ protocol: Some("https".into()),
+ username: Some("bob".into()),
+ ..Default::default()
+ }
+ )
+ }
+
+ #[test]
+ fn quit_supports_git_config_boolean_values() {
+ for true_value in ["1", "42", "-42", "true", "on", "yes"] {
+ let input = format!("quit={true_value}");
+ assert_eq!(
+ Context::from_bytes(input.as_bytes()).unwrap().quit,
+ Some(true),
+ "{input}"
+ )
+ }
+ for false_value in ["0", "false", "off", "no"] {
+ let input = format!("quit={false_value}");
+ assert_eq!(
+ Context::from_bytes(input.as_bytes()).unwrap().quit,
+ Some(false),
+ "{input}"
+ )
+ }
+ }
+
+ #[test]
+ fn null_bytes_when_decoding() {
+ let err = Context::from_bytes(b"url=https://foo\0").unwrap_err();
+ assert!(matches!(
+ err,
+ gix_credentials::protocol::context::decode::Error::Encoding(_)
+ ));
+ }
+}
diff --git a/vendor/gix-credentials/tests/helper/invoke.rs b/vendor/gix-credentials/tests/helper/invoke.rs
new file mode 100644
index 000000000..330048548
--- /dev/null
+++ b/vendor/gix-credentials/tests/helper/invoke.rs
@@ -0,0 +1,134 @@
+use bstr::{BString, ByteVec};
+use gix_credentials::{helper, protocol::Context, Program};
+use gix_testtools::fixture_path;
+
+#[test]
+fn get() {
+ let mut outcome = gix_credentials::helper::invoke(
+ &mut script_helper("last-pass"),
+ &helper::Action::get_for_url("https://github.com/byron/gitoxide"),
+ )
+ .unwrap()
+ .expect("mock provides credentials");
+ assert_eq!(
+ outcome.consume_identity().expect("complete"),
+ gix_sec::identity::Account {
+ username: "user".into(),
+ password: "pass".into()
+ }
+ );
+ assert_eq!(
+ outcome.next.store().payload().unwrap(),
+ "username=user\npassword=pass\nquit=1\n"
+ );
+}
+
+#[test]
+fn store_and_reject() {
+ let ctx = Context {
+ url: Some("https://github.com/byron/gitoxide".into()),
+ ..Default::default()
+ };
+ let ctxbuf = || -> BString {
+ let mut buf = Vec::<u8>::new();
+ ctx.write_to(&mut buf).expect("cannot fail");
+ buf.into()
+ };
+ for action in [helper::Action::Store(ctxbuf()), helper::Action::Erase(ctxbuf())] {
+ let outcome = gix_credentials::helper::invoke(&mut script_helper("last-pass"), &action).unwrap();
+ assert!(
+ outcome.is_none(),
+ "store and erase have no outcome, they just shouldn't fail"
+ );
+ }
+}
+
+mod program {
+ use gix_credentials::{helper, program::Kind, Program};
+
+ use crate::helper::invoke::script_helper;
+
+ #[test]
+ fn builtin() {
+ assert!(
+ matches!(
+ gix_credentials::helper::invoke(
+ &mut Program::from_kind(Kind::Builtin).suppress_stderr(),
+ &helper::Action::get_for_url("/path/without/scheme/fails/with/error"),
+ )
+ .unwrap_err(),
+ helper::Error::CredentialsHelperFailed { .. }
+ ),
+ "this failure indicates we could launch the helper, even though it wasn't happy which is fine. It doesn't like the URL"
+ );
+ }
+
+ #[test]
+ fn script() {
+ assert_eq!(
+ gix_credentials::helper::invoke(
+ &mut Program::from_custom_definition(
+ "!f() { test \"$1\" = get && echo \"password=pass\" && echo \"username=user\"; }; f"
+ ),
+ &helper::Action::get_for_url("/does/not/matter"),
+ )
+ .unwrap()
+ .expect("present")
+ .consume_identity()
+ .expect("complete"),
+ gix_sec::identity::Account {
+ username: "user".into(),
+ password: "pass".into()
+ }
+ );
+ }
+
+ #[cfg(unix)] // needs executable bits to work
+ #[test]
+ fn path_to_helper_script() -> crate::Result {
+ assert_eq!(
+ gix_credentials::helper::invoke(
+ &mut Program::from_custom_definition(
+ gix_path::into_bstr(gix_path::realpath(gix_testtools::fixture_path("custom-helper.sh"))?)
+ .into_owned()
+ ),
+ &helper::Action::get_for_url("/does/not/matter"),
+ )?
+ .expect("present")
+ .consume_identity()
+ .expect("complete"),
+ gix_sec::identity::Account {
+ username: "user-script".into(),
+ password: "pass-script".into()
+ }
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn path_to_helper_as_script_to_workaround_executable_bits() -> crate::Result {
+ assert_eq!(
+ gix_credentials::helper::invoke(
+ &mut script_helper("custom-helper"),
+ &helper::Action::get_for_url("/does/not/matter")
+ )?
+ .expect("present")
+ .consume_identity()
+ .expect("complete"),
+ gix_sec::identity::Account {
+ username: "user-script".into(),
+ password: "pass-script".into()
+ }
+ );
+ Ok(())
+ }
+}
+
+pub fn script_helper(name: &str) -> Program {
+ let mut script = gix_path::to_unix_separators_on_windows(gix_path::into_bstr(
+ gix_path::realpath(fixture_path(format!("{name}.sh"))).unwrap(),
+ ))
+ .into_owned();
+ script.insert_str(0, "sh ");
+ Program::from_kind(gix_credentials::program::Kind::ExternalShellScript(script))
+}
diff --git a/vendor/gix-credentials/tests/helper/mod.rs b/vendor/gix-credentials/tests/helper/mod.rs
new file mode 100644
index 000000000..59c448065
--- /dev/null
+++ b/vendor/gix-credentials/tests/helper/mod.rs
@@ -0,0 +1,39 @@
+mod cascade;
+mod context;
+mod invoke;
+
+mod invoke_outcome_to_helper_result {
+ use gix_credentials::{helper, protocol, protocol::helper_outcome_to_result};
+
+ #[test]
+ fn missing_username_or_password_causes_failure_with_get_action() {
+ let action = helper::Action::get_for_url("does/not/matter");
+ let err = helper_outcome_to_result(
+ Some(helper::Outcome {
+ username: None,
+ password: None,
+ quit: false,
+ next: protocol::Context::default().into(),
+ }),
+ action,
+ )
+ .unwrap_err();
+ assert!(matches!(err, protocol::Error::IdentityMissing { .. }));
+ }
+
+ #[test]
+ fn quit_message_in_context_causes_special_error_ignoring_missing_identity() {
+ let action = helper::Action::get_for_url("does/not/matter");
+ let err = helper_outcome_to_result(
+ Some(helper::Outcome {
+ username: None,
+ password: None,
+ quit: true,
+ next: protocol::Context::default().into(),
+ }),
+ action,
+ )
+ .unwrap_err();
+ assert!(matches!(err, protocol::Error::Quit));
+ }
+}
diff --git a/vendor/gix-credentials/tests/program/from_custom_definition.rs b/vendor/gix-credentials/tests/program/from_custom_definition.rs
new file mode 100644
index 000000000..1b9d8a056
--- /dev/null
+++ b/vendor/gix-credentials/tests/program/from_custom_definition.rs
@@ -0,0 +1,42 @@
+use gix_credentials::{program::Kind, Program};
+
+#[test]
+fn script() {
+ assert!(
+ matches!(Program::from_custom_definition("!exe").kind, Kind::ExternalShellScript(script) if script == "exe")
+ );
+}
+
+#[test]
+fn name_with_args() {
+ let input = "name --arg --bar=\"a b\"";
+ let expected = "git credential-name --arg --bar=\"a b\"";
+ assert!(
+ matches!(Program::from_custom_definition(input).kind, Kind::ExternalName{name_and_args} if name_and_args == expected)
+ );
+}
+
+#[test]
+fn name() {
+ let input = "name";
+ let expected = "git credential-name";
+ assert!(
+ matches!(Program::from_custom_definition(input).kind, Kind::ExternalName{name_and_args} if name_and_args == expected)
+ );
+}
+
+#[test]
+fn path_with_args() {
+ let input = "/abs/name --arg --bar=\"a b\"";
+ assert!(
+ matches!(Program::from_custom_definition(input).kind, Kind::ExternalPath{path_and_args} if path_and_args == input)
+ );
+}
+
+#[test]
+fn path() {
+ let input = "/abs/name";
+ assert!(
+ matches!(Program::from_custom_definition(input).kind, Kind::ExternalPath{path_and_args} if path_and_args == input)
+ );
+}
diff --git a/vendor/gix-credentials/tests/program/mod.rs b/vendor/gix-credentials/tests/program/mod.rs
new file mode 100644
index 000000000..3672dd18e
--- /dev/null
+++ b/vendor/gix-credentials/tests/program/mod.rs
@@ -0,0 +1 @@
+mod from_custom_definition;
diff --git a/vendor/gix-credentials/tests/protocol/context.rs b/vendor/gix-credentials/tests/protocol/context.rs
new file mode 100644
index 000000000..3cfd850a3
--- /dev/null
+++ b/vendor/gix-credentials/tests/protocol/context.rs
@@ -0,0 +1,175 @@
+mod destructure_url_in_place {
+ use gix_credentials::protocol::Context;
+
+ fn url_ctx(url: &str) -> Context {
+ Context {
+ url: Some(url.into()),
+ ..Default::default()
+ }
+ }
+
+ fn assert_eq_parts(
+ url: &str,
+ proto: &str,
+ user: impl Into<Option<&'static str>>,
+ host: &str,
+ path: impl Into<Option<&'static str>>,
+ use_http_path: bool,
+ ) {
+ let mut ctx = url_ctx(url);
+ ctx.destructure_url_in_place(use_http_path).expect("splitting works");
+ assert_eq!(ctx.protocol.expect("set proto"), proto);
+ match user.into() {
+ Some(expected) => assert_eq!(ctx.username.expect("set user"), expected),
+ None => assert!(ctx.username.is_none()),
+ }
+ assert_eq!(ctx.host.expect("set host"), host);
+ match path.into() {
+ Some(expected) => assert_eq!(ctx.path.expect("set path"), expected),
+ None => assert!(ctx.path.is_none()),
+ }
+ }
+
+ #[test]
+ fn parts_are_verbatim_with_non_http_url() {
+ // path is always used for non-http
+ assert_eq_parts("ssh://user@host:21/path", "ssh", "user", "host:21", "path", false);
+ assert_eq_parts("ssh://host.org/path", "ssh", None, "host.org", "path", true);
+ }
+ #[test]
+ fn http_and_https_ignore_the_path_by_default() {
+ assert_eq_parts(
+ "http://user@example.com/path",
+ "http",
+ Some("user"),
+ "example.com",
+ None,
+ false,
+ );
+ assert_eq_parts(
+ "https://github.com/byron/gitoxide",
+ "https",
+ None,
+ "github.com",
+ None,
+ false,
+ );
+ assert_eq_parts(
+ "https://github.com/byron/gitoxide/",
+ "https",
+ None,
+ "github.com",
+ "byron/gitoxide",
+ true,
+ );
+ }
+}
+
+mod to_prompt {
+ use gix_credentials::protocol::Context;
+
+ #[test]
+ fn no_scheme_means_no_url() {
+ assert_eq!(Context::default().to_prompt("Username"), "Username: ");
+ }
+
+ #[test]
+ fn any_scheme_means_url_is_included() {
+ assert_eq!(
+ Context {
+ protocol: Some("https".into()),
+ host: Some("host".into()),
+ ..Default::default()
+ }
+ .to_prompt("Password"),
+ "Password for https://host: "
+ );
+ }
+}
+
+mod to_url {
+ use gix_credentials::protocol::Context;
+
+ #[test]
+ fn no_protocol_is_nothing() {
+ assert_eq!(Context::default().to_url(), None);
+ }
+ #[test]
+ fn protocol_alone_is_enough() {
+ assert_eq!(
+ Context {
+ protocol: Some("https".into()),
+ ..Default::default()
+ }
+ .to_url()
+ .unwrap(),
+ "https://"
+ );
+ }
+ #[test]
+ fn username_is_appended() {
+ assert_eq!(
+ Context {
+ protocol: Some("https".into()),
+ username: Some("user".into()),
+ ..Default::default()
+ }
+ .to_url()
+ .unwrap(),
+ "https://user@"
+ );
+ }
+ #[test]
+ fn host_is_appended() {
+ assert_eq!(
+ Context {
+ protocol: Some("https".into()),
+ host: Some("host".into()),
+ ..Default::default()
+ }
+ .to_url()
+ .unwrap(),
+ "https://host"
+ );
+ }
+ #[test]
+ fn path_is_appended_with_leading_slash_placed_as_needed() {
+ assert_eq!(
+ Context {
+ protocol: Some("file".into()),
+ path: Some("dir/git".into()),
+ ..Default::default()
+ }
+ .to_url()
+ .unwrap(),
+ "file:///dir/git"
+ );
+ assert_eq!(
+ Context {
+ protocol: Some("file".into()),
+ path: Some("/dir/git".into()),
+ ..Default::default()
+ }
+ .to_url()
+ .unwrap(),
+ "file:///dir/git"
+ );
+ }
+
+ #[test]
+ fn all_fields_with_port_but_password_is_never_shown() {
+ assert_eq!(
+ Context {
+ protocol: Some("https".into()),
+ username: Some("user".into()),
+ password: Some("secret".into()),
+ host: Some("example.com:8080".into()),
+ path: Some("Byron/gitoxide".into()),
+ ..Default::default()
+ }
+ .to_url()
+ .unwrap(),
+ "https://user@example.com:8080/Byron/gitoxide"
+ );
+ }
+}
diff --git a/vendor/gix-credentials/tests/protocol/mod.rs b/vendor/gix-credentials/tests/protocol/mod.rs
new file mode 100644
index 000000000..3d9885db8
--- /dev/null
+++ b/vendor/gix-credentials/tests/protocol/mod.rs
@@ -0,0 +1 @@
+mod context;