History

change!: use `thiserror` instead of `quickerror` (#450)

Sebastian Thiel committed 4 years ago

Commit 71a43d01 parent 9d9fe6c11 files · +168 −198Browse files

Unified · Split

11 files
  1. Cargo.lock +0 −1
  2. git-transport/Cargo.toml +0 −1
  3. git-transport/src/client/blocking_io/connect.rs +60 −50
  4. git-transport/src/client/blocking_io/http/curl/remote.rs +3 −1
  5. git-transport/src/client/blocking_io/http/mod.rs +28 −24
  6. git-transport/src/client/blocking_io/http/traits.rs +11 −20
  7. git-transport/src/client/blocking_io/ssh.rs +6 −10
  8. git-transport/src/client/capabilities.rs +21 −31
  9. git-transport/src/client/git/blocking_io.rs +17 −27
  10. git-transport/src/client/mod.rs +1 −1
  11. git-transport/src/client/non_io_types.rs +21 −32
Cargo.lock+0−1
@@ -1646,7 +1646,6 @@ dependencies = [ · 1645 unmodified lines
16461646 "git-url",
16471647 "maybe-async",
16481648 "pin-project-lite",
1649− "quick-error",
16501649 "serde",
16511650 "thiserror",
16521651 ]
git-transport/Cargo.toml+0−1
@@ -56,7 +56,6 @@ git-sec = { version = "^0.3.0", path = "../git-sec" } · 55 unmodified lines
5656 git-packetline = { version = "^0.12.5", path = "../git-packetline" }
5757
5858 serde = { version = "1.0.114", optional = true, default-features = false, features = ["std", "derive"]}
59−quick-error = "2.0.0"
6059 bstr = { version = "0.2.13", default-features = false, features = ["std"] }
6160
6261 # for async-client
git-transport/src/client/blocking_io/connect.rs+60−50
@@ -1,61 +1,71 @@
11 pub use crate::client::non_io_types::connect::Error;
2−use crate::client::Transport;
32
4−/// A general purpose connector connecting to a repository identified by the given `url`.
5−///
6−/// This includes connections to
7−/// [local repositories][crate::client::file::connect()],
8−/// [repositories over ssh][crate::client::ssh::connect()],
9−/// [git daemons][crate::client::git::connect()],
10−/// and if compiled in connections to [git repositories over https][crate::client::http::connect()].
11−///
12−/// Use `desired_version` to set the desired protocol version to use when connecting, but not that the server may downgrade it.
13−pub fn connect(url: &[u8], desired_version: crate::Protocol) -> Result<Box<dyn Transport + Send>, Error> {
14− let urlb = url;
15− let mut url = git_url::parse(urlb)?;
16− Ok(match url.scheme {
17− git_url::Scheme::Radicle => return Err(Error::UnsupportedScheme(url.scheme)),
18− git_url::Scheme::File => {
19− if url.user().is_some() || url.host().is_some() || url.port.is_some() {
20− return Err(Error::UnsupportedUrlTokens(urlb.into(), url.scheme));
21− }
22− Box::new(
23− crate::client::blocking_io::file::connect(url.path, desired_version)
24− .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?,
25− )
26− }
27− git_url::Scheme::Ssh => Box::new({
28− let path = std::mem::take(&mut url.path);
29− crate::client::blocking_io::ssh::connect(
30− url.host().expect("host is present in url"),
31− path,
32− desired_version,
33− url.user(),
34− url.port,
35− )
36− .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?
37− }),
38− git_url::Scheme::Git => {
39− if url.user().is_some() {
40− return Err(Error::UnsupportedUrlTokens(urlb.into(), url.scheme));
3+pub(crate) mod function {
4+ use crate::client::non_io_types::connect::Error;
5+ use crate::client::Transport;
6+
7+ /// A general purpose connector connecting to a repository identified by the given `url`.
8+ ///
9+ /// This includes connections to
10+ /// [local repositories][crate::client::file::connect()],
11+ /// [repositories over ssh][crate::client::ssh::connect()],
12+ /// [git daemons][crate::client::git::connect()],
13+ /// and if compiled in connections to [git repositories over https][crate::client::http::connect()].
14+ ///
15+ /// Use `desired_version` to set the desired protocol version to use when connecting, but not that the server may downgrade it.
16+ pub fn connect(url: &[u8], desired_version: crate::Protocol) -> Result<Box<dyn Transport + Send>, Error> {
17+ let urlb = url;
18+ let mut url = git_url::parse(urlb)?;
19+ Ok(match url.scheme {
20+ git_url::Scheme::Radicle => return Err(Error::UnsupportedScheme(url.scheme)),
21+ git_url::Scheme::File => {
22+ if url.user().is_some() || url.host().is_some() || url.port.is_some() {
23+ return Err(Error::UnsupportedUrlTokens {
24+ url: urlb.into(),
25+ scheme: url.scheme,
26+ });
27+ }
28+ Box::new(
29+ crate::client::blocking_io::file::connect(url.path, desired_version)
30+ .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?,
31+ )
4132 }
42− Box::new({
33+ git_url::Scheme::Ssh => Box::new({
4334 let path = std::mem::take(&mut url.path);
44− crate::client::git::connect(
35+ crate::client::blocking_io::ssh::connect(
4536 url.host().expect("host is present in url"),
4637 path,
4738 desired_version,
39+ url.user(),
4840 url.port,
4941 )
5042 .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?
51− })
52− }
53− #[cfg(not(feature = "http-client-curl"))]
54− git_url::Scheme::Https | git_url::Scheme::Http => return Err(Error::CompiledWithoutHttp(url.scheme)),
55− #[cfg(feature = "http-client-curl")]
56− git_url::Scheme::Https | git_url::Scheme::Http => Box::new(
57− crate::client::http::connect(urlb.into(), desired_version)
58− .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?,
59− ),
60− })
43+ }),
44+ git_url::Scheme::Git => {
45+ if url.user().is_some() {
46+ return Err(Error::UnsupportedUrlTokens {
47+ url: urlb.into(),
48+ scheme: url.scheme,
49+ });
50+ }
51+ Box::new({
52+ let path = std::mem::take(&mut url.path);
53+ crate::client::git::connect(
54+ url.host().expect("host is present in url"),
55+ path,
56+ desired_version,
57+ url.port,
58+ )
59+ .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?
60+ })
61+ }
62+ #[cfg(not(feature = "http-client-curl"))]
63+ git_url::Scheme::Https | git_url::Scheme::Http => return Err(Error::CompiledWithoutHttp(url.scheme)),
64+ #[cfg(feature = "http-client-curl")]
65+ git_url::Scheme::Https | git_url::Scheme::Http => Box::new(
66+ crate::client::http::connect(urlb.into(), desired_version)
67+ .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?,
68+ ),
69+ })
70+ }
6171 }
git-transport/src/client/blocking_io/http/curl/remote.rs+3−1
@@ -182,6 +182,8 @@ pub fn new() -> ( · 181 unmodified lines
182182
183183 impl From<curl::Error> for http::Error {
184184 fn from(err: curl::Error) -> Self {
185− http::Error::Detail(err.to_string())
185+ http::Error::Detail {
186+ description: err.to_string(),
187+ }
186188 }
187189 }
git-transport/src/client/blocking_io/http/mod.rs+28−24
@@ -2,7 +2,7 @@ use bstr::{BStr, BString}; · 1 unmodified line
22 use std::{
33 borrow::Cow,
44 convert::Infallible,
5− io::{self, BufRead, Read},
5+ io::{BufRead, Read},
66 };
77
88 use git_packetline::PacketLineRef;
@@ -27,9 +27,9 @@ pub type Impl = curl::Curl; · 18 unmodified lines
2727 pub struct Transport<H: Http> {
2828 url: BString,
2929 user_agent_header: &'static str,
30− desired_version: crate::Protocol,
31− supported_versions: [crate::Protocol; 1],
32− actual_version: crate::Protocol,
30+ desired_version: Protocol,
31+ supported_versions: [Protocol; 1],
32+ actual_version: Protocol,
3333 http: H,
3434 service: Option<Service>,
3535 line_provider: Option<git_packetline::StreamingPeekableIter<H::ResponseBody>>,
@@ -38,7 +38,7 @@ pub struct Transport<H: Http> { · 2 unmodified lines
3838
3939 impl Transport<Impl> {
4040 /// Create a new instance to communicate to `url` using the given `desired_version` of the `git` protocol.
41− pub fn new(url: &BStr, desired_version: crate::Protocol) -> Self {
41+ pub fn new(url: &BStr, desired_version: Protocol) -> Self {
4242 Transport {
4343 url: url.to_owned(),
4444 user_agent_header: concat!("User-Agent: git/oxide-", env!("CARGO_PKG_VERSION")),
@@ -62,10 +62,12 @@ impl<H: Http> Transport<H> { · 17 unmodified lines
6262 .iter()
6363 .any(|l| l == &wanted_content_type)
6464 {
65− return Err(client::Error::Http(Error::Detail(format!(
66− "Didn't find '{}' header to indicate 'smart' protocol, and 'dumb' protocol is not supported.",
67− wanted_content_type
68− ))));
65+ return Err(client::Error::Http(Error::Detail {
66+ description: format!(
67+ "Didn't find '{}' header to indicate 'smart' protocol, and 'dumb' protocol is not supported.",
68+ wanted_content_type
69+ ),
70+ }));
6971 }
7072 Ok(())
7173 }
@@ -106,8 +108,8 @@ impl<H: Http> client::TransportWithoutIO for Transport<H> { · 34 unmodified lines
106108 fn request(
107109 &mut self,
108110 write_mode: client::WriteMode,
109− on_into_read: client::MessageKind,
110− ) -> Result<client::RequestWriter<'_>, client::Error> {
111+ on_into_read: MessageKind,
112+ ) -> Result<RequestWriter<'_>, client::Error> {
111113 let service = self.service.expect("handshake() must have been called first");
112114 let url = append_url(self.url.as_ref(), service.as_str());
113115 let static_headers = &[
@@ -207,11 +209,13 @@ impl<H: Http> client::Transport for Transport<H> { · 93 unmodified lines
207209 line_reader.as_read().read_to_string(&mut announced_service)?;
208210 let expected_service_announcement = format!("# service={}", service.as_str());
209211 if announced_service.trim() != expected_service_announcement {
210− return Err(client::Error::Http(Error::Detail(format!(
211− "Expected to see {:?}, but got {:?}",
212− expected_service_announcement,
213− announced_service.trim()
214− ))));
212+ return Err(client::Error::Http(Error::Detail {
213+ description: format!(
214+ "Expected to see {:?}, but got {:?}",
215+ expected_service_announcement,
216+ announced_service.trim()
217+ ),
218+ }));
215219 }
216220
217221 let capabilities::recv::Outcome {
@@ -236,24 +240,24 @@ struct HeadersThenBody<H: Http, B: Unpin> { · 18 unmodified lines
236240 }
237241
238242 impl<H: Http, B: Unpin> HeadersThenBody<H, B> {
239− fn handle_headers(&mut self) -> io::Result<()> {
243+ fn handle_headers(&mut self) -> std::io::Result<()> {
240244 if let Some(headers) = self.headers.take() {
241245 <Transport<H>>::check_content_type(self.service, "result", headers)
242− .map_err(|err| io::Error::new(io::ErrorKind::Other, err))?
246+ .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err))?
243247 }
244248 Ok(())
245249 }
246250 }
247251
248−impl<H: Http, B: ExtendedBufRead + Unpin> io::Read for HeadersThenBody<H, B> {
249− fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
252+impl<H: Http, B: ExtendedBufRead + Unpin> Read for HeadersThenBody<H, B> {
253+ fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
250254 self.handle_headers()?;
251255 self.body.read(buf)
252256 }
253257 }
254258
255−impl<H: Http, B: ExtendedBufRead + Unpin> io::BufRead for HeadersThenBody<H, B> {
256− fn fill_buf(&mut self) -> io::Result<&[u8]> {
259+impl<H: Http, B: ExtendedBufRead + Unpin> BufRead for HeadersThenBody<H, B> {
260+ fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
257261 self.handle_headers()?;
258262 self.body.fill_buf()
259263 }
@@ -268,7 +272,7 @@ impl<H: Http, B: ExtendedBufRead + Unpin> ExtendedBufRead for HeadersThenBody<H, · 8 unmodified lines
268272 self.body.set_progress_handler(handle_progress)
269273 }
270274
271− fn peek_data_line(&mut self) -> Option<io::Result<Result<&[u8], client::Error>>> {
275+ fn peek_data_line(&mut self) -> Option<std::io::Result<Result<&[u8], client::Error>>> {
272276 if let Err(err) = self.handle_headers() {
273277 return Some(Err(err));
274278 }
@@ -285,6 +289,6 @@ impl<H: Http, B: ExtendedBufRead + Unpin> ExtendedBufRead for HeadersThenBody<H, · 10 unmodified lines
285289 }
286290
287291 /// Connect to the given `url` via HTTP/S using the `desired_version` of the `git` protocol.
288−pub fn connect(url: &BStr, desired_version: crate::Protocol) -> Result<Transport<Impl>, Infallible> {
292+pub fn connect(url: &BStr, desired_version: Protocol) -> Result<Transport<Impl>, Infallible> {
289293 Ok(Transport::new(url, desired_version))
290294 }
git-transport/src/client/blocking_io/http/traits.rs+11−20
@@ -1,22 +1,13 @@
11 use bstr::BStr;
2−use std::io;
32
4−use quick_error::quick_error;
5−
6−quick_error! {
7− /// The error used by the [Http] trait.
8− #[derive(Debug)]
9− #[allow(missing_docs)]
10− pub enum Error {
11− Detail(description: String) {
12− display("{}", description)
13− }
14− PostBody(err: io::Error) {
15− display("An IO error occurred while uploading the body of a POST request")
16− from()
17− source(err)
18− }
19− }
3+/// The error used by the [Http] trait.
4+#[derive(Debug, thiserror::Error)]
5+#[allow(missing_docs)]
6+pub enum Error {
7+ #[error("{description}")]
8+ Detail { description: String },
9+ #[error("An IO error occurred while uploading the body of a POST request")]
10+ PostBody(#[from] std::io::Error),
2011 }
2112
2213 /// The return value of [Http::get()].
@@ -52,11 +43,11 @@ impl<A, B, C> From<PostResponse<A, B, C>> for GetResponse<A, B> { · 29 unmodified lines
5243 #[allow(clippy::type_complexity)]
5344 pub trait Http {
5445 /// A type providing headers line by line.
55− type Headers: io::BufRead + Unpin;
46+ type Headers: std::io::BufRead + Unpin;
5647 /// A type providing the response.
57− type ResponseBody: io::BufRead;
48+ type ResponseBody: std::io::BufRead;
5849 /// A type allowing to write the content to post.
59− type PostBody: io::Write;
50+ type PostBody: std::io::Write;
6051
6152 /// Initiate a `GET` request to `url` provided the given `headers`.
6253 ///
git-transport/src/client/blocking_io/ssh.rs+6−10
@@ -1,19 +1,15 @@
11 use std::borrow::Cow;
22
33 use bstr::BString;
4−use quick_error::quick_error;
54
65 use crate::{client::blocking_io, Protocol};
76
8−quick_error! {
9− /// The error used in [`connect()`].
10− #[derive(Debug)]
11− #[allow(missing_docs)]
12− pub enum Error {
13− UnsupportedSshCommand(command: String) {
14− display("The ssh command '{}' is not currently supported", command)
15− }
16− }
7+/// The error used in [`connect()`].
8+#[derive(Debug, thiserror::Error)]
9+#[allow(missing_docs)]
10+pub enum Error {
11+ #[error("The ssh command {0:?} is not currently supported")]
12+ UnsupportedSshCommand(String),
1713 }
1814
1915 /// Connect to `host` using the ssh program to obtain data from the repository at `path` on the remote.
git-transport/src/client/capabilities.rs+21−31
@@ -1,38 +1,25 @@
1−use std::io;
2−
31 use bstr::{BStr, BString, ByteSlice};
4−use quick_error::quick_error;
52
63 #[cfg(any(feature = "blocking-client", feature = "async-client"))]
74 use crate::client;
85 use crate::Protocol;
96
10−quick_error! {
11− /// The error used in [`Capabilities::from_bytes()`] and [`Capabilities::from_lines()`].
12− #[derive(Debug)]
13− #[allow(missing_docs)]
14− pub enum Error {
15− MissingDelimitingNullByte {
16− display("Capabilities were missing entirely as there was no 0 byte")
17− }
18− NoCapabilities {
19− display("there was not a single capability behind the delimiter")
20− }
21− MissingVersionLine {
22− display("a version line was expected, but none was retrieved")
23− }
24− MalformattedVersionLine(actual: String) {
25− display("expected 'version X', got '{}'", actual)
26− }
27− UnsupportedVersion(wanted: Protocol, got: String) {
28− display("Got unsupported version '{}', expected '{}'", got, *wanted as usize)
29− }
30− Io(err: io::Error) {
31− display("An IO error occurred while reading V2 lines")
32− from()
33− source(err)
34− }
35− }
7+/// The error used in [`Capabilities::from_bytes()`] and [`Capabilities::from_lines()`].
8+#[derive(Debug, thiserror::Error)]
9+#[allow(missing_docs)]
10+pub enum Error {
11+ #[error("Capabilities were missing entirely as there was no 0 byte")]
12+ MissingDelimitingNullByte,
13+ #[error("there was not a single capability behind the delimiter")]
14+ NoCapabilities,
15+ #[error("a version line was expected, but none was retrieved")]
16+ MissingVersionLine,
17+ #[error("expected 'version X', got {0:?}")]
18+ MalformattedVersionLine(String),
19+ #[error("Got unsupported version '{}', expected {actual:?}", *desired as u8)]
20+ UnsupportedVersion { desired: Protocol, actual: String },
21+ #[error("An IO error occurred while reading V2 lines")]
22+ Io(#[from] std::io::Error),
3623 }
3724
3825 /// A structure to represent multiple [capabilities][Capability] or features supported by the server.
@@ -113,7 +100,10 @@ impl Capabilities { · 74 unmodified lines
113100 return Err(Error::MalformattedVersionLine(version_line));
114101 }
115102 if value != " 2" {
116− return Err(Error::UnsupportedVersion(Protocol::V2, value.to_owned()));
103+ return Err(Error::UnsupportedVersion {
104+ desired: Protocol::V2,
105+ actual: value.to_owned(),
106+ });
117107 }
118108 Ok(Capabilities {
119109 value_sep: b'\n',
@@ -181,7 +171,7 @@ pub mod recv { · 61 unmodified lines
181171 ///
182172 /// This is `Some` only when protocol v1 is used. The [`io::BufRead`] must be exhausted by
183173 /// the caller.
184− pub refs: Option<Box<dyn io::BufRead + 'a>>,
174+ pub refs: Option<Box<dyn std::io::BufRead + 'a>>,
185175 /// The [`Protocol`] the remote advertised.
186176 pub protocol: Protocol,
187177 }
git-transport/src/client/git/blocking_io.rs+17−27
@@ -1,4 +1,4 @@
1−use std::{io, io::Write};
1+use std::io::Write;
22
33 use bstr::BString;
44 use git_packetline::PacketLineRef;
@@ -10,8 +10,8 @@ use crate::{ · 5 unmodified lines
1010
1111 impl<R, W> client::TransportWithoutIO for git::Connection<R, W>
1212 where
13− R: io::Read,
14− W: io::Write,
13+ R: std::io::Read,
14+ W: std::io::Write,
1515 {
1616 fn request(
1717 &mut self,
@@ -57,8 +57,8 @@ where · 39 unmodified lines
5757
5858 impl<R, W> client::Transport for git::Connection<R, W>
5959 where
60− R: io::Read,
61− W: io::Write,
60+ R: std::io::Read,
61+ W: std::io::Write,
6262 {
6363 fn handshake<'a>(
6464 &mut self,
@@ -92,8 +92,8 @@ where · 27 unmodified lines
9292
9393 impl<R, W> git::Connection<R, W>
9494 where
95− R: io::Read,
96− W: io::Write,
95+ R: std::io::Read,
96+ W: std::io::Write,
9797 {
9898 /// Create a connection from the given `read` and `write`, asking for `desired_version` as preferred protocol
9999 /// and the transfer of the repository at `repository_path`.
@@ -137,29 +137,19 @@ where · 37 unmodified lines
137137
138138 ///
139139 pub mod connect {
140− use std::{
141− io,
142− net::{TcpStream, ToSocketAddrs},
143− };
140+ use std::net::{TcpStream, ToSocketAddrs};
144141
145142 use bstr::BString;
146− use quick_error::quick_error;
147143
148144 use crate::client::git;
149− quick_error! {
150− /// The error used in [`connect()`].
151− #[derive(Debug)]
152− #[allow(missing_docs)]
153− pub enum Error {
154− Io(err: io::Error){
155− display("An IO error occurred when connecting to the server")
156− from()
157− source(err)
158− }
159− VirtualHostInvalid(host: String) {
160− display("Could not parse '{}' as virtual host with format <host>[:port]", host)
161− }
162− }
145+ /// The error used in [`connect()`].
146+ #[derive(Debug, thiserror::Error)]
147+ #[allow(missing_docs)]
148+ pub enum Error {
149+ #[error("An IO error occurred when connecting to the server")]
150+ Io(#[from] std::io::Error),
151+ #[error("Could not parse {host:?} as virtual host with format <host>[:port]")]
152+ VirtualHostInvalid { host: String },
163153 }
164154
165155 fn parse_host(input: String) -> Result<(String, Option<u16>), Error> {
@@ -168,7 +158,7 @@ pub mod connect { · 2 unmodified lines
168158 (Some(host), None) => (host.to_owned(), None),
169159 (Some(host), Some(port)) => (
170160 host.to_owned(),
171− Some(port.parse().map_err(|_| Error::VirtualHostInvalid(input))?),
161+ Some(port.parse().map_err(|_| Error::VirtualHostInvalid { host: input })?),
172162 ),
173163 _ => unreachable!("we expect at least one token, the original string"),
174164 })
git-transport/src/client/mod.rs+1−1
@@ -18,7 +18,7 @@ pub use blocking_io::{ · 17 unmodified lines
1818 };
1919 #[cfg(feature = "blocking-client")]
2020 #[doc(inline)]
21−pub use connect::connect;
21+pub use connect::function::connect;
2222
2323 ///
2424 pub mod capabilities;
git-transport/src/client/non_io_types.rs+21−32
@@ -29,39 +29,28 @@ pub enum MessageKind { · 28 unmodified lines
2929 Text(&'static [u8]),
3030 }
3131
32+#[cfg(any(feature = "blocking-client", feature = "async-client"))]
3233 pub(crate) mod connect {
33− use quick_error::quick_error;
34− quick_error! {
35− /// The error used in [`connect()`][crate::connect()].
36− #[derive(Debug)]
37− #[allow(missing_docs)]
38− pub enum Error {
39− Url(err: git_url::parse::Error) {
40− display("The URL could not be parsed")
41− from()
42− source(err)
43− }
44− PathConversion(err: bstr::Utf8Error) {
45− display("The git repository paths could not be converted to UTF8")
46− from()
47− source(err)
48− }
49− Connection(err: Box<dyn std::error::Error + Send + Sync>) {
50− display("connection failed")
51− from()
52− source(&**err)
53− }
54− UnsupportedUrlTokens(url: bstr::BString, scheme: git_url::Scheme) {
55− display("The url '{}' contains information that would not be used by the '{}' protocol", url, scheme)
56− }
57− UnsupportedScheme(scheme: git_url::Scheme) {
58− display("The '{}' protocol is currently unsupported", scheme)
59− }
60− #[cfg(not(feature = "http-client-curl"))]
61− CompiledWithoutHttp(scheme: git_url::Scheme) {
62− display("'{}' is not compiled in. Compile with the 'http-client-curl' cargo feature", scheme)
63− }
64− }
34+ /// The error used in [`connect()`][crate::connect()].
35+ #[derive(Debug, thiserror::Error)]
36+ #[allow(missing_docs)]
37+ pub enum Error {
38+ #[error(transparent)]
39+ Url(#[from] git_url::parse::Error),
40+ #[error("The git repository path could not be converted to UTF8")]
41+ PathConversion(#[from] bstr::Utf8Error),
42+ #[error("connection failed")]
43+ Connection(#[from] Box<dyn std::error::Error + Send + Sync>),
44+ #[error("The url {url:?} contains information that would not be used by the {scheme} protocol")]
45+ UnsupportedUrlTokens {
46+ url: bstr::BString,
47+ scheme: git_url::Scheme,
48+ },
49+ #[error("The '{0}' protocol is currently unsupported")]
50+ UnsupportedScheme(git_url::Scheme),
51+ #[cfg(not(feature = "http-client-curl"))]
52+ #[error("'{0}' is not compiled in. Compile with the 'http-client-curl' cargo feature")]
53+ CompiledWithoutHttp(git_url::Scheme),
6554 }
6655 }
6756