Unified · Split
| @@ -1646,7 +1646,6 @@ dependencies = [ · 1645 unmodified lines | ||
| 1646 | 1646 | "git-url", |
| 1647 | 1647 | "maybe-async", |
| 1648 | 1648 | "pin-project-lite", |
| 1649 | − "quick-error", | |
| 1650 | 1649 | "serde", |
| 1651 | 1650 | "thiserror", |
| 1652 | 1651 | ] |
| @@ -56,7 +56,6 @@ git-sec = { version = "^0.3.0", path = "../git-sec" } · 55 unmodified lines | ||
| 56 | 56 | git-packetline = { version = "^0.12.5", path = "../git-packetline" } |
| 57 | 57 | |
| 58 | 58 | serde = { version = "1.0.114", optional = true, default-features = false, features = ["std", "derive"]} |
| 59 | −quick-error = "2.0.0" | |
| 60 | 59 | bstr = { version = "0.2.13", default-features = false, features = ["std"] } |
| 61 | 60 | |
| 62 | 61 | # for async-client |
| @@ -1,61 +1,71 @@ | ||
| 1 | 1 | pub use crate::client::non_io_types::connect::Error; |
| 2 | −use crate::client::Transport; | |
| 3 | 2 | |
| 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 | + ) | |
| 41 | 32 | } |
| 42 | − Box::new({ | |
| 33 | + git_url::Scheme::Ssh => Box::new({ | |
| 43 | 34 | let path = std::mem::take(&mut url.path); |
| 44 | − crate::client::git::connect( | |
| 35 | + crate::client::blocking_io::ssh::connect( | |
| 45 | 36 | url.host().expect("host is present in url"), |
| 46 | 37 | path, |
| 47 | 38 | desired_version, |
| 39 | + url.user(), | |
| 48 | 40 | url.port, |
| 49 | 41 | ) |
| 50 | 42 | .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 | + } | |
| 61 | 71 | } |
| @@ -182,6 +182,8 @@ pub fn new() -> ( · 181 unmodified lines | ||
| 182 | 182 | |
| 183 | 183 | impl From<curl::Error> for http::Error { |
| 184 | 184 | fn from(err: curl::Error) -> Self { |
| 185 | − http::Error::Detail(err.to_string()) | |
| 185 | + http::Error::Detail { | |
| 186 | + description: err.to_string(), | |
| 187 | + } | |
| 186 | 188 | } |
| 187 | 189 | } |
| @@ -2,7 +2,7 @@ use bstr::{BStr, BString}; · 1 unmodified line | ||
| 2 | 2 | use std::{ |
| 3 | 3 | borrow::Cow, |
| 4 | 4 | convert::Infallible, |
| 5 | − io::{self, BufRead, Read}, | |
| 5 | + io::{BufRead, Read}, | |
| 6 | 6 | }; |
| 7 | 7 | |
| 8 | 8 | use git_packetline::PacketLineRef; |
| @@ -27,9 +27,9 @@ pub type Impl = curl::Curl; · 18 unmodified lines | ||
| 27 | 27 | pub struct Transport<H: Http> { |
| 28 | 28 | url: BString, |
| 29 | 29 | 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, | |
| 33 | 33 | http: H, |
| 34 | 34 | service: Option<Service>, |
| 35 | 35 | line_provider: Option<git_packetline::StreamingPeekableIter<H::ResponseBody>>, |
| @@ -38,7 +38,7 @@ pub struct Transport<H: Http> { · 2 unmodified lines | ||
| 38 | 38 | |
| 39 | 39 | impl Transport<Impl> { |
| 40 | 40 | /// 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 { | |
| 42 | 42 | Transport { |
| 43 | 43 | url: url.to_owned(), |
| 44 | 44 | user_agent_header: concat!("User-Agent: git/oxide-", env!("CARGO_PKG_VERSION")), |
| @@ -62,10 +62,12 @@ impl<H: Http> Transport<H> { · 17 unmodified lines | ||
| 62 | 62 | .iter() |
| 63 | 63 | .any(|l| l == &wanted_content_type) |
| 64 | 64 | { |
| 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 | + })); | |
| 69 | 71 | } |
| 70 | 72 | Ok(()) |
| 71 | 73 | } |
| @@ -106,8 +108,8 @@ impl<H: Http> client::TransportWithoutIO for Transport<H> { · 34 unmodified lines | ||
| 106 | 108 | fn request( |
| 107 | 109 | &mut self, |
| 108 | 110 | 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> { | |
| 111 | 113 | let service = self.service.expect("handshake() must have been called first"); |
| 112 | 114 | let url = append_url(self.url.as_ref(), service.as_str()); |
| 113 | 115 | let static_headers = &[ |
| @@ -207,11 +209,13 @@ impl<H: Http> client::Transport for Transport<H> { · 93 unmodified lines | ||
| 207 | 209 | line_reader.as_read().read_to_string(&mut announced_service)?; |
| 208 | 210 | let expected_service_announcement = format!("# service={}", service.as_str()); |
| 209 | 211 | 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 | + })); | |
| 215 | 219 | } |
| 216 | 220 | |
| 217 | 221 | let capabilities::recv::Outcome { |
| @@ -236,24 +240,24 @@ struct HeadersThenBody<H: Http, B: Unpin> { · 18 unmodified lines | ||
| 236 | 240 | } |
| 237 | 241 | |
| 238 | 242 | 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<()> { | |
| 240 | 244 | if let Some(headers) = self.headers.take() { |
| 241 | 245 | <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))? | |
| 243 | 247 | } |
| 244 | 248 | Ok(()) |
| 245 | 249 | } |
| 246 | 250 | } |
| 247 | 251 | |
| 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> { | |
| 250 | 254 | self.handle_headers()?; |
| 251 | 255 | self.body.read(buf) |
| 252 | 256 | } |
| 253 | 257 | } |
| 254 | 258 | |
| 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]> { | |
| 257 | 261 | self.handle_headers()?; |
| 258 | 262 | self.body.fill_buf() |
| 259 | 263 | } |
| @@ -268,7 +272,7 @@ impl<H: Http, B: ExtendedBufRead + Unpin> ExtendedBufRead for HeadersThenBody<H, · 8 unmodified lines | ||
| 268 | 272 | self.body.set_progress_handler(handle_progress) |
| 269 | 273 | } |
| 270 | 274 | |
| 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>>> { | |
| 272 | 276 | if let Err(err) = self.handle_headers() { |
| 273 | 277 | return Some(Err(err)); |
| 274 | 278 | } |
| @@ -285,6 +289,6 @@ impl<H: Http, B: ExtendedBufRead + Unpin> ExtendedBufRead for HeadersThenBody<H, · 10 unmodified lines | ||
| 285 | 289 | } |
| 286 | 290 | |
| 287 | 291 | /// 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> { | |
| 289 | 293 | Ok(Transport::new(url, desired_version)) |
| 290 | 294 | } |
| @@ -1,22 +1,13 @@ | ||
| 1 | 1 | use bstr::BStr; |
| 2 | −use std::io; | |
| 3 | 2 | |
| 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), | |
| 20 | 11 | } |
| 21 | 12 | |
| 22 | 13 | /// 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 | ||
| 52 | 43 | #[allow(clippy::type_complexity)] |
| 53 | 44 | pub trait Http { |
| 54 | 45 | /// A type providing headers line by line. |
| 55 | − type Headers: io::BufRead + Unpin; | |
| 46 | + type Headers: std::io::BufRead + Unpin; | |
| 56 | 47 | /// A type providing the response. |
| 57 | − type ResponseBody: io::BufRead; | |
| 48 | + type ResponseBody: std::io::BufRead; | |
| 58 | 49 | /// A type allowing to write the content to post. |
| 59 | − type PostBody: io::Write; | |
| 50 | + type PostBody: std::io::Write; | |
| 60 | 51 | |
| 61 | 52 | /// Initiate a `GET` request to `url` provided the given `headers`. |
| 62 | 53 | /// |
| @@ -1,19 +1,15 @@ | ||
| 1 | 1 | use std::borrow::Cow; |
| 2 | 2 | |
| 3 | 3 | use bstr::BString; |
| 4 | −use quick_error::quick_error; | |
| 5 | 4 | |
| 6 | 5 | use crate::{client::blocking_io, Protocol}; |
| 7 | 6 | |
| 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), | |
| 17 | 13 | } |
| 18 | 14 | |
| 19 | 15 | /// Connect to `host` using the ssh program to obtain data from the repository at `path` on the remote. |
| @@ -1,38 +1,25 @@ | ||
| 1 | −use std::io; | |
| 2 | − | |
| 3 | 1 | use bstr::{BStr, BString, ByteSlice}; |
| 4 | −use quick_error::quick_error; | |
| 5 | 2 | |
| 6 | 3 | #[cfg(any(feature = "blocking-client", feature = "async-client"))] |
| 7 | 4 | use crate::client; |
| 8 | 5 | use crate::Protocol; |
| 9 | 6 | |
| 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), | |
| 36 | 23 | } |
| 37 | 24 | |
| 38 | 25 | /// A structure to represent multiple [capabilities][Capability] or features supported by the server. |
| @@ -113,7 +100,10 @@ impl Capabilities { · 74 unmodified lines | ||
| 113 | 100 | return Err(Error::MalformattedVersionLine(version_line)); |
| 114 | 101 | } |
| 115 | 102 | 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 | + }); | |
| 117 | 107 | } |
| 118 | 108 | Ok(Capabilities { |
| 119 | 109 | value_sep: b'\n', |
| @@ -181,7 +171,7 @@ pub mod recv { · 61 unmodified lines | ||
| 181 | 171 | /// |
| 182 | 172 | /// This is `Some` only when protocol v1 is used. The [`io::BufRead`] must be exhausted by |
| 183 | 173 | /// the caller. |
| 184 | − pub refs: Option<Box<dyn io::BufRead + 'a>>, | |
| 174 | + pub refs: Option<Box<dyn std::io::BufRead + 'a>>, | |
| 185 | 175 | /// The [`Protocol`] the remote advertised. |
| 186 | 176 | pub protocol: Protocol, |
| 187 | 177 | } |
| @@ -1,4 +1,4 @@ | ||
| 1 | −use std::{io, io::Write}; | |
| 1 | +use std::io::Write; | |
| 2 | 2 | |
| 3 | 3 | use bstr::BString; |
| 4 | 4 | use git_packetline::PacketLineRef; |
| @@ -10,8 +10,8 @@ use crate::{ · 5 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | impl<R, W> client::TransportWithoutIO for git::Connection<R, W> |
| 12 | 12 | where |
| 13 | − R: io::Read, | |
| 14 | − W: io::Write, | |
| 13 | + R: std::io::Read, | |
| 14 | + W: std::io::Write, | |
| 15 | 15 | { |
| 16 | 16 | fn request( |
| 17 | 17 | &mut self, |
| @@ -57,8 +57,8 @@ where · 39 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | impl<R, W> client::Transport for git::Connection<R, W> |
| 59 | 59 | where |
| 60 | − R: io::Read, | |
| 61 | − W: io::Write, | |
| 60 | + R: std::io::Read, | |
| 61 | + W: std::io::Write, | |
| 62 | 62 | { |
| 63 | 63 | fn handshake<'a>( |
| 64 | 64 | &mut self, |
| @@ -92,8 +92,8 @@ where · 27 unmodified lines | ||
| 92 | 92 | |
| 93 | 93 | impl<R, W> git::Connection<R, W> |
| 94 | 94 | where |
| 95 | − R: io::Read, | |
| 96 | − W: io::Write, | |
| 95 | + R: std::io::Read, | |
| 96 | + W: std::io::Write, | |
| 97 | 97 | { |
| 98 | 98 | /// Create a connection from the given `read` and `write`, asking for `desired_version` as preferred protocol |
| 99 | 99 | /// and the transfer of the repository at `repository_path`. |
| @@ -137,29 +137,19 @@ where · 37 unmodified lines | ||
| 137 | 137 | |
| 138 | 138 | /// |
| 139 | 139 | pub mod connect { |
| 140 | − use std::{ | |
| 141 | − io, | |
| 142 | − net::{TcpStream, ToSocketAddrs}, | |
| 143 | − }; | |
| 140 | + use std::net::{TcpStream, ToSocketAddrs}; | |
| 144 | 141 | |
| 145 | 142 | use bstr::BString; |
| 146 | − use quick_error::quick_error; | |
| 147 | 143 | |
| 148 | 144 | 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 }, | |
| 163 | 153 | } |
| 164 | 154 | |
| 165 | 155 | fn parse_host(input: String) -> Result<(String, Option<u16>), Error> { |
| @@ -168,7 +158,7 @@ pub mod connect { · 2 unmodified lines | ||
| 168 | 158 | (Some(host), None) => (host.to_owned(), None), |
| 169 | 159 | (Some(host), Some(port)) => ( |
| 170 | 160 | host.to_owned(), |
| 171 | − Some(port.parse().map_err(|_| Error::VirtualHostInvalid(input))?), | |
| 161 | + Some(port.parse().map_err(|_| Error::VirtualHostInvalid { host: input })?), | |
| 172 | 162 | ), |
| 173 | 163 | _ => unreachable!("we expect at least one token, the original string"), |
| 174 | 164 | }) |
| @@ -18,7 +18,7 @@ pub use blocking_io::{ · 17 unmodified lines | ||
| 18 | 18 | }; |
| 19 | 19 | #[cfg(feature = "blocking-client")] |
| 20 | 20 | #[doc(inline)] |
| 21 | −pub use connect::connect; | |
| 21 | +pub use connect::function::connect; | |
| 22 | 22 | |
| 23 | 23 | /// |
| 24 | 24 | pub mod capabilities; |
| @@ -29,39 +29,28 @@ pub enum MessageKind { · 28 unmodified lines | ||
| 29 | 29 | Text(&'static [u8]), |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | +#[cfg(any(feature = "blocking-client", feature = "async-client"))] | |
| 32 | 33 | 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), | |
| 65 | 54 | } |
| 66 | 55 | } |
| 67 | 56 | |