History

[clone] Improve usability of posts…

…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.

Sebastian Thiel committed 6 years ago

Commit e1b944e1 parent d0bdbe42 files · +38 −19Browse files

Unified · Split

2 files
  1. git-transport/src/client/http/curl.rs +14 −16
  2. git-transport/src/client/http/mod.rs +24 −3
git-transport/src/client/http/curl.rs+14−16
@@ -3,7 +3,6 @@ use curl::easy::Easy2; · 2 unmodified lines
3use git_features::pipe;3use git_features::pipe;
4use std::{4use std::{
5 io,5 io,
6 io::Read,
7 sync::mpsc::{sync_channel, Receiver, SyncSender, TrySendError},6 sync::mpsc::{sync_channel, Receiver, SyncSender, TrySendError},
8 thread,7 thread,
9};8};
@@ -37,8 +36,7 @@ impl Curl { · 27 unmodified lines
37 &mut self,36 &mut self,
38 url: &str,37 url: &str,
39 headers: impl IntoIterator<Item = impl AsRef<str>>,38 headers: impl IntoIterator<Item = impl AsRef<str>>,
40 post_body: Option<impl Read>,39 ) -> Result<http::PostResponse<pipe::Reader, pipe::Reader, pipe::Writer>, http::Error> {
41 ) -> Result<(pipe::Reader, pipe::Reader), http::Error> {
42 let mut list = curl::easy::List::new();40 let mut list = curl::easy::List::new();
43 for header in headers {41 for header in headers {
44 list.append(header.as_ref())?;42 list.append(header.as_ref())?;
@@ -56,16 +54,16 @@ impl Curl { · 11 unmodified lines
56 let Response {54 let Response {
57 headers,55 headers,
58 body,56 body,
59 mut upload_body,57 upload_body,
60 } = match self.res.recv() {58 } = match self.res.recv() {
61 Ok(res) => res,59 Ok(res) => res,
62 Err(_) => return Err(self.restore_thread_after_failure()),60 Err(_) => return Err(self.restore_thread_after_failure()),
63 };61 };
64 if let Some(mut body) = post_body {62 Ok(http::PostResponse {
65 io::copy(&mut body, &mut upload_body)?;63 post_body: upload_body,
66 }64 headers,
67 65 body,
68 Ok((headers, body))66 })
69 }67 }
70 68
71 fn restore_thread_after_failure(&mut self) -> http::Error {69 fn restore_thread_after_failure(&mut self) -> http::Error {
@@ -170,21 +168,21 @@ impl From<curl::Error> for http::Error { · 98 unmodified lines
170impl crate::client::http::Http for Curl {168impl crate::client::http::Http for Curl {
171 type Headers = pipe::Reader;169 type Headers = pipe::Reader;
172 type ResponseBody = pipe::Reader;170 type ResponseBody = pipe::Reader;
171 type PostBody = pipe::Writer;
173 172
174 fn get(173 fn get(
175 &mut self,174 &mut self,
176 url: &str,175 url: &str,
177 headers: impl IntoIterator<Item = impl AsRef<str>>,176 headers: impl IntoIterator<Item = impl AsRef<str>>,
178 ) -> Result<(Self::Headers, Self::ResponseBody), http::Error> {177 ) -> Result<http::GetResponse<Self::Headers, Self::ResponseBody>, http::Error> {
179 self.make_request(url, headers, None::<std::fs::File>)178 self.make_request(url, headers).map(Into::into)
180 }179 }
181 180
182 fn post(181 fn post(
183 &mut self,182 &mut self,
184 _url: &str,183 url: &str,
185 _headers: impl IntoIterator<Item = impl AsRef<str>>,184 headers: impl IntoIterator<Item = impl AsRef<str>>,
186 _body: impl Read,185 ) -> Result<http::PostResponse<Self::Headers, Self::ResponseBody, Self::PostBody>, http::Error> {
187 ) -> Result<(Self::Headers, Self::ResponseBody), http::Error> {186 self.make_request(url, headers)
188 unimplemented!()
189 }187 }
190}188}
git-transport/src/client/http/mod.rs+24−3
@@ -20,21 +20,42 @@ quick_error! { · 19 unmodified lines
20#[cfg(feature = "http-client-curl")]20#[cfg(feature = "http-client-curl")]
21pub(crate) mod curl;21pub(crate) mod curl;
22 22
23pub struct GetResponse<H, B> {
24 headers: H,
25 body: B,
26}
27
28pub 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
35impl<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
23trait Http {44trait Http {
24 type Headers: io::BufRead;45 type Headers: io::BufRead;
25 type ResponseBody: io::BufRead;46 type ResponseBody: io::BufRead;
47 type PostBody: io::Write;
26 48
27 fn get(49 fn get(
28 &mut self,50 &mut self,
29 url: &str,51 url: &str,
30 headers: impl IntoIterator<Item = impl AsRef<str>>,52 headers: impl IntoIterator<Item = impl AsRef<str>>,
31 ) -> Result<(Self::Headers, Self::ResponseBody), Error>;53 ) -> Result<GetResponse<Self::Headers, Self::ResponseBody>, Error>;
32 fn post(54 fn post(
33 &mut self,55 &mut self,
34 url: &str,56 url: &str,
35 headers: impl IntoIterator<Item = impl AsRef<str>>,57 headers: impl IntoIterator<Item = impl AsRef<str>>,
36 body: impl io::Read,58 ) -> Result<PostResponse<Self::Headers, Self::ResponseBody, Self::PostBody>, Error>;
37 ) -> Result<(Self::Headers, Self::ResponseBody), Error>;
38}59}
39 60
40#[cfg(feature = "http-client-curl")]61#[cfg(feature = "http-client-curl")]