…it's much easier for callers to get a write handle to write into from their own code instead of passing a Read that captures everything they care about. This just requires them to signal that they are done writing by dropping the writer. Fair enough, that's all done in our custom transport code who knows the system. Thinking about it, it will probably yield that handle to code in git-protocol, which then also needs to know about that.
Unified · Split
| @@ -3,7 +3,6 @@ use curl::easy::Easy2; · 2 unmodified lines | ||
| 3 | 3 | use git_features::pipe; |
| 4 | 4 | use std::{ |
| 5 | 5 | io, |
| 6 | − io::Read, | |
| 7 | 6 | sync::mpsc::{sync_channel, Receiver, SyncSender, TrySendError}, |
| 8 | 7 | thread, |
| 9 | 8 | }; |
| @@ -37,8 +36,7 @@ impl Curl { · 27 unmodified lines | ||
| 37 | 36 | &mut self, |
| 38 | 37 | url: &str, |
| 39 | 38 | headers: impl IntoIterator<Item = impl AsRef<str>>, |
| 40 | − post_body: Option<impl Read>, | |
| 41 | − ) -> Result<(pipe::Reader, pipe::Reader), http::Error> { | |
| 39 | + ) -> Result<http::PostResponse<pipe::Reader, pipe::Reader, pipe::Writer>, http::Error> { | |
| 42 | 40 | let mut list = curl::easy::List::new(); |
| 43 | 41 | for header in headers { |
| 44 | 42 | list.append(header.as_ref())?; |
| @@ -56,16 +54,16 @@ impl Curl { · 11 unmodified lines | ||
| 56 | 54 | let Response { |
| 57 | 55 | headers, |
| 58 | 56 | body, |
| 59 | − mut upload_body, | |
| 57 | + upload_body, | |
| 60 | 58 | } = match self.res.recv() { |
| 61 | 59 | Ok(res) => res, |
| 62 | 60 | Err(_) => return Err(self.restore_thread_after_failure()), |
| 63 | 61 | }; |
| 64 | − if let Some(mut body) = post_body { | |
| 65 | − io::copy(&mut body, &mut upload_body)?; | |
| 66 | − } | |
| 67 | − | |
| 68 | − Ok((headers, body)) | |
| 62 | + Ok(http::PostResponse { | |
| 63 | + post_body: upload_body, | |
| 64 | + headers, | |
| 65 | + body, | |
| 66 | + }) | |
| 69 | 67 | } |
| 70 | 68 | |
| 71 | 69 | fn restore_thread_after_failure(&mut self) -> http::Error { |
| @@ -170,21 +168,21 @@ impl From<curl::Error> for http::Error { · 98 unmodified lines | ||
| 170 | 168 | impl crate::client::http::Http for Curl { |
| 171 | 169 | type Headers = pipe::Reader; |
| 172 | 170 | type ResponseBody = pipe::Reader; |
| 171 | + type PostBody = pipe::Writer; | |
| 173 | 172 | |
| 174 | 173 | fn get( |
| 175 | 174 | &mut self, |
| 176 | 175 | url: &str, |
| 177 | 176 | headers: impl IntoIterator<Item = impl AsRef<str>>, |
| 178 | − ) -> Result<(Self::Headers, Self::ResponseBody), http::Error> { | |
| 179 | − self.make_request(url, headers, None::<std::fs::File>) | |
| 177 | + ) -> Result<http::GetResponse<Self::Headers, Self::ResponseBody>, http::Error> { | |
| 178 | + self.make_request(url, headers).map(Into::into) | |
| 180 | 179 | } |
| 181 | 180 | |
| 182 | 181 | fn post( |
| 183 | 182 | &mut self, |
| 184 | − _url: &str, | |
| 185 | − _headers: impl IntoIterator<Item = impl AsRef<str>>, | |
| 186 | − _body: impl Read, | |
| 187 | − ) -> Result<(Self::Headers, Self::ResponseBody), http::Error> { | |
| 188 | − unimplemented!() | |
| 183 | + url: &str, | |
| 184 | + headers: impl IntoIterator<Item = impl AsRef<str>>, | |
| 185 | + ) -> Result<http::PostResponse<Self::Headers, Self::ResponseBody, Self::PostBody>, http::Error> { | |
| 186 | + self.make_request(url, headers) | |
| 189 | 187 | } |
| 190 | 188 | } |
| @@ -20,21 +20,42 @@ quick_error! { · 19 unmodified lines | ||
| 20 | 20 | #[cfg(feature = "http-client-curl")] |
| 21 | 21 | pub(crate) mod curl; |
| 22 | 22 | |
| 23 | +pub struct GetResponse<H, B> { | |
| 24 | + headers: H, | |
| 25 | + body: B, | |
| 26 | +} | |
| 27 | + | |
| 28 | +pub struct PostResponse<H, B, PB> { | |
| 29 | + /// **Note**: Implementations should drop the handle to avoid deadlocks | |
| 30 | + post_body: PB, | |
| 31 | + headers: H, | |
| 32 | + body: B, | |
| 33 | +} | |
| 34 | + | |
| 35 | +impl<A, B, C> From<PostResponse<A, B, C>> for GetResponse<A, B> { | |
| 36 | + fn from(v: PostResponse<A, B, C>) -> Self { | |
| 37 | + GetResponse { | |
| 38 | + headers: v.headers, | |
| 39 | + body: v.body, | |
| 40 | + } | |
| 41 | + } | |
| 42 | +} | |
| 43 | + | |
| 23 | 44 | trait Http { |
| 24 | 45 | type Headers: io::BufRead; |
| 25 | 46 | type ResponseBody: io::BufRead; |
| 47 | + type PostBody: io::Write; | |
| 26 | 48 | |
| 27 | 49 | fn get( |
| 28 | 50 | &mut self, |
| 29 | 51 | url: &str, |
| 30 | 52 | headers: impl IntoIterator<Item = impl AsRef<str>>, |
| 31 | − ) -> Result<(Self::Headers, Self::ResponseBody), Error>; | |
| 53 | + ) -> Result<GetResponse<Self::Headers, Self::ResponseBody>, Error>; | |
| 32 | 54 | fn post( |
| 33 | 55 | &mut self, |
| 34 | 56 | url: &str, |
| 35 | 57 | headers: impl IntoIterator<Item = impl AsRef<str>>, |
| 36 | − body: impl io::Read, | |
| 37 | − ) -> Result<(Self::Headers, Self::ResponseBody), Error>; | |
| 58 | + ) -> Result<PostResponse<Self::Headers, Self::ResponseBody, Self::PostBody>, Error>; | |
| 38 | 59 | } |
| 39 | 60 | |
| 40 | 61 | #[cfg(feature = "http-client-curl")] |