History

refactor

Sebastian Thiel committed 6 years ago

Commit f2ff90d1 parent c1bcc0a7 files · +66 −49Browse files

Unified · Split

7 files
  1. git-packetline/src/provider/mod.rs +4 −0
  2. git-packetline/src/provider/read.rs +10 −0
  3. git-transport/src/client/git/mod.rs +2 −4
  4. git-transport/src/client/http/mod.rs +4 −5
  5. git-transport/src/client/mod.rs +10 −26
  6. git-transport/tests/client/git.rs +14 −12
  7. git-transport/tests/client/http.rs +22 −2
git-packetline/src/provider/mod.rs+4−0
@@ -144,6 +144,10 @@ where · 143 unmodified lines
144 ReadWithSidebands::with_progress_handler(self, handle_progress)144 ReadWithSidebands::with_progress_handler(self, handle_progress)
145 }145 }
146 146
147 pub fn as_read_without_sidebands<F: FnMut(bool, &[u8])>(&mut self) -> ReadWithSidebands<T, F> {
148 ReadWithSidebands::without_progress_handler(self)
149 }
150
147 pub fn as_read(&mut self) -> ReadWithSidebands<T, fn(bool, &[u8])> {151 pub fn as_read(&mut self) -> ReadWithSidebands<T, fn(bool, &[u8])> {
148 ReadWithSidebands::new(self)152 ReadWithSidebands::new(self)
149 }153 }
git-packetline/src/provider/read.rs+10−0
@@ -54,6 +54,16 @@ where · 53 unmodified lines
54 }54 }
55 }55 }
56 56
57 pub fn without_progress_handler(parent: &'a mut Provider<T>) -> Self {
58 ReadWithSidebands {
59 parent,
60 handle_progress: None,
61 buf: vec![0; MAX_DATA_LEN],
62 pos: 0,
63 cap: 0,
64 }
65 }
66
57 pub fn set_progress_handler(&mut self, handle_progress: Option<F>) {67 pub fn set_progress_handler(&mut self, handle_progress: Option<F>) {
58 self.handle_progress = handle_progress;68 self.handle_progress = handle_progress;
59 }69 }
git-transport/src/client/git/mod.rs+2−4
@@ -41,14 +41,12 @@ where · 40 unmodified lines
41 &mut self,41 &mut self,
42 write_mode: client::WriteMode,42 write_mode: client::WriteMode,
43 on_drop: Vec<client::MessageKind>,43 on_drop: Vec<client::MessageKind>,
44 handle_progress: Option<client::HandleProgress>,
45 ) -> Result<client::RequestWriter, client::Error> {44 ) -> Result<client::RequestWriter, client::Error> {
46 Ok(client::RequestWriter::new(45 Ok(client::RequestWriter::new_from_bufread(
47 &mut self.writer,46 &mut self.writer,
48 &mut self.line_provider,47 Box::new(self.line_provider.as_read_without_sidebands()),
49 write_mode,48 write_mode,
50 on_drop,49 on_drop,
51 handle_progress,
52 ))50 ))
53 }51 }
54}52}
git-transport/src/client/http/mod.rs+4−5
@@ -103,7 +103,6 @@ impl<H: Http> client::Transport for Transport<H> { · 102 unmodified lines
103 &mut self,103 &mut self,
104 write_mode: client::WriteMode,104 write_mode: client::WriteMode,
105 on_drop: Vec<client::MessageKind>,105 on_drop: Vec<client::MessageKind>,
106 handle_progress: Option<client::HandleProgress>,
107 ) -> Result<client::RequestWriter, client::Error> {106 ) -> Result<client::RequestWriter, client::Error> {
108 let service = self.service.expect("handshake() must have been called first");107 let service = self.service.expect("handshake() must have been called first");
109 let url = append_url(&self.url, service.as_str());108 let url = append_url(&self.url, service.as_str());
@@ -113,22 +112,22 @@ impl<H: Http> client::Transport for Transport<H> { · 3 unmodified lines
113 "Expect:".into(),112 "Expect:".into(),
114 ];113 ];
115 let PostResponse {114 let PostResponse {
116 headers,115 headers: _,
117 body,116 body,
118 post_body,117 post_body,
119 } = self.http.post(&url, headers)?;118 } = self.http.post(&url, headers)?;
119 // TODO: combine header handling with body reader
120 // <Transport<H>>::check_content_type(service, "result", headers)?;120 // <Transport<H>>::check_content_type(service, "result", headers)?;
121 let line_provider = self121 let line_provider = self
122 .line_provider122 .line_provider
123 .as_mut()123 .as_mut()
124 .expect("handshake to have been called first");124 .expect("handshake to have been called first");
125 line_provider.replace(body);125 line_provider.replace(body);
126 Ok(RequestWriter::new(126 Ok(RequestWriter::new_from_bufread(
127 post_body,127 post_body,
128 line_provider,128 Box::new(line_provider.as_read_without_sidebands()),
129 write_mode,129 write_mode,
130 on_drop,130 on_drop,
131 handle_progress,
132 ))131 ))
133 }132 }
134}133}
git-transport/src/client/mod.rs+10−26
@@ -75,7 +75,7 @@ pub enum MessageKind { · 74 unmodified lines
75/// A type implementing `Write`, which when done can be transformed into a `Read` for obtaining the response.75/// A type implementing `Write`, which when done can be transformed into a `Read` for obtaining the response.
76pub struct RequestWriter<'a> {76pub struct RequestWriter<'a> {
77 pub(crate) writer: Box<dyn io::Write + 'a>,77 pub(crate) writer: Box<dyn io::Write + 'a>,
78 pub(crate) reader: Box<dyn io::BufRead + 'a>,78 pub(crate) reader: Box<dyn SetProgressHandlerBufRead + 'a>,
79}79}
80 80
81impl<'a> io::Write for RequestWriter<'a> {81impl<'a> io::Write for RequestWriter<'a> {
@@ -89,26 +89,9 @@ impl<'a> io::Write for RequestWriter<'a> { · 7 unmodified lines
89}89}
90 90
91impl<'a> RequestWriter<'a> {91impl<'a> RequestWriter<'a> {
92 pub fn new<R: io::Read, W: io::Write + 'a>(
93 writer: W,
94 line_provider: &'a mut git_packetline::Provider<R>,
95 write_mode: WriteMode,
96 on_drop: Vec<MessageKind>,
97 handle_progress: Option<HandleProgress>,
98 ) -> Self {
99 Self::new_from_bufread(
100 writer,
101 match handle_progress {
102 Some(handler) => Box::new(line_provider.as_read_with_sidebands(handler)),
103 None => Box::new(line_provider.as_read()),
104 },
105 write_mode,
106 on_drop,
107 )
108 }
109 pub fn new_from_bufread<W: io::Write + 'a>(92 pub fn new_from_bufread<W: io::Write + 'a>(
110 writer: W,93 writer: W,
111 reader: Box<dyn io::BufRead + 'a>,94 reader: Box<dyn SetProgressHandlerBufRead + 'a>,
112 write_mode: WriteMode,95 write_mode: WriteMode,
113 on_drop: Vec<MessageKind>,96 on_drop: Vec<MessageKind>,
114 ) -> Self {97 ) -> Self {
@@ -139,9 +122,15 @@ impl<'a, T: io::Read> SetProgressHandlerBufRead for git_packetline::provider::Re · 24 unmodified lines
139 }122 }
140}123}
141 124
125impl<'a> SetProgressHandlerBufRead for ResponseReader<'a> {
126 fn set_progress_handler(&mut self, handle_progress: Option<HandleProgress>) {
127 self.reader.set_progress_handler(handle_progress)
128 }
129}
130
142/// A type implementing `Read` to obtain the server response.131/// A type implementing `Read` to obtain the server response.
143pub struct ResponseReader<'a> {132pub struct ResponseReader<'a> {
144 reader: Box<dyn io::BufRead + 'a>,133 reader: Box<dyn SetProgressHandlerBufRead + 'a>,
145}134}
146 135
147impl<'a> io::Read for ResponseReader<'a> {136impl<'a> io::Read for ResponseReader<'a> {
@@ -213,10 +202,5 @@ pub trait Transport { · 65 unmodified lines
213 /// `send_mode` determines how calls to the `write(…)` method are interpreted, and `on_drop` determines what202 /// `send_mode` determines how calls to the `write(…)` method are interpreted, and `on_drop` determines what
214 /// to do when the writer is consumed or dropped.203 /// to do when the writer is consumed or dropped.
215 /// If `handle_progress` is not None, it's function passed a text line without trailing LF from which progress information can be parsed.204 /// If `handle_progress` is not None, it's function passed a text line without trailing LF from which progress information can be parsed.
216 fn request(205 fn request(&mut self, write_mode: WriteMode, on_drop: Vec<MessageKind>) -> Result<RequestWriter, Error>;
217 &mut self,
218 write_mode: WriteMode,
219 on_drop: Vec<MessageKind>,
220 handle_progress: Option<HandleProgress>,
221 ) -> Result<RequestWriter, Error>;
222}206}
git-transport/tests/client/git.rs+14−12
@@ -43,6 +43,7 @@ mod connect_message { · 42 unmodified lines
43 43
44use crate::fixture_bytes;44use crate::fixture_bytes;
45use bstr::ByteSlice;45use bstr::ByteSlice;
46use git_transport::client::SetProgressHandlerBufRead;
46use git_transport::{47use git_transport::{
47 client::{self, git, Transport},48 client::{self, git, Transport},
48 Protocol, Service,49 Protocol, Service,
@@ -94,33 +95,34 @@ fn handshake_v1_and_request() -> crate::Result { · 45 unmodified lines
94 );95 );
95 drop(res);96 drop(res);
96 97
97 let writer = c.request(client::WriteMode::Binary, Vec::new(), None)?;98 let writer = c.request(client::WriteMode::Binary, Vec::new())?;
98 assert_eq!(writer.into_read().lines().next().expect("exactly one line")?, "NAK");99 assert_eq!(writer.into_read().lines().next().expect("exactly one line")?, "NAK");
99 100
100 let sidebands = Rc::new(RefCell::new(Vec::<String>::new()));
101 let mut writer = c.request(101 let mut writer = c.request(
102 client::WriteMode::OneLFTerminatedLinePerWriteCall,102 client::WriteMode::OneLFTerminatedLinePerWriteCall,
103 vec![client::MessageKind::Flush, client::MessageKind::Text(b"done")],103 vec![client::MessageKind::Flush, client::MessageKind::Text(b"done")],
104 Some(Box::new({
105 let sb = sidebands.clone();
106 move |is_err, data| {
107 assert!(!is_err);
108 sb.deref()
109 .borrow_mut()
110 .push(std::str::from_utf8(data).expect("valid utf8").to_owned())
111 }
112 })),
113 )?;104 )?;
114 105
115 writer.write_all(b"hello")?;106 writer.write_all(b"hello")?;
116 writer.write_all(b"world")?;107 writer.write_all(b"world")?;
108
117 let mut reader = writer.into_read();109 let mut reader = writer.into_read();
110 let messages = Rc::new(RefCell::new(Vec::<String>::new()));
111 reader.set_progress_handler(Some(Box::new({
112 let sb = messages.clone();
113 move |is_err, data| {
114 assert!(!is_err);
115 sb.deref()
116 .borrow_mut()
117 .push(std::str::from_utf8(data).expect("valid utf8").to_owned())
118 }
119 })));
118 let mut pack = Vec::new();120 let mut pack = Vec::new();
119 reader.read_to_end(&mut pack)?;121 reader.read_to_end(&mut pack)?;
120 assert_eq!(pack.len(), 876, "we receive the whole pack…");122 assert_eq!(pack.len(), 876, "we receive the whole pack…");
121 123
122 drop(reader);124 drop(reader);
123 let sidebands = Rc::try_unwrap(sidebands).expect("no other handle").into_inner();125 let sidebands = Rc::try_unwrap(messages).expect("no other handle").into_inner();
124 assert_eq!(sidebands.len(), 6, "…along with some status messages");126 assert_eq!(sidebands.len(), 6, "…along with some status messages");
125 assert_eq!(127 assert_eq!(
126 out.as_slice().as_bstr(),128 out.as_slice().as_bstr(),
git-transport/tests/client/http.rs+22−2
@@ -1,10 +1,14 @@
1use crate::fixture_bytes;1use crate::fixture_bytes;
2use bstr::{ByteSlice, ByteVec};2use bstr::{ByteSlice, ByteVec};
3use git_transport::client::SetProgressHandlerBufRead;
3use git_transport::{client, client::http, client::SetServiceResponse, client::Transport, Protocol, Service};4use git_transport::{client, client::http, client::SetServiceResponse, client::Transport, Protocol, Service};
4use std::{5use std::{
6 cell::RefCell,
5 error::Error,7 error::Error,
6 io::{self, BufRead, Read, Write},8 io::{self, BufRead, Read, Write},
7 net::SocketAddr,9 net::SocketAddr,
10 ops::Deref,
11 rc::Rc,
8 time::Duration,12 time::Duration,
9};13};
10 14
@@ -258,7 +262,6 @@ fn clone_v1() -> crate::Result { · 247 unmodified lines
258 client::WriteMode::OneLFTerminatedLinePerWriteCall,262 client::WriteMode::OneLFTerminatedLinePerWriteCall,
259 // vec![client::MessageKind::Flush, client::MessageKind::Text(b"done")],263 // vec![client::MessageKind::Flush, client::MessageKind::Text(b"done")],
260 Vec::new(),264 Vec::new(),
261 None,
262 )?;265 )?;
263 eprintln!("about to write data");266 eprintln!("about to write data");
264 writer.write_all(b"hello")?;267 writer.write_all(b"hello")?;
@@ -267,8 +270,25 @@ fn clone_v1() -> crate::Result { · 2 unmodified lines
267 let mut reader = writer.into_read();270 let mut reader = writer.into_read();
268 let mut line = String::new();271 let mut line = String::new();
269 reader.read_line(&mut line)?;272 reader.read_line(&mut line)?;
270 // TODO: switch to binary with progress and273 assert_eq!(line, "NAK", "we received a NAK in text mode");
271 274
275 let messages = Rc::new(RefCell::new(Vec::<String>::new()));
276 reader.set_progress_handler(Some(Box::new({
277 let sb = messages.clone();
278 move |is_err, data| {
279 assert!(!is_err);
280 sb.deref()
281 .borrow_mut()
282 .push(std::str::from_utf8(data).expect("valid utf8").to_owned())
283 }
284 })));
285 let mut pack = Vec::new();
286 reader.read_to_end(&mut pack)?;
287 assert_eq!(pack.len(), 876, "we receive the whole pack…");
288 drop(reader);
289
290 let sidebands = Rc::try_unwrap(messages).expect("no other handle").into_inner();
291 assert_eq!(sidebands.len(), 6);
272 assert_eq!(292 assert_eq!(
273 server.received_as_string(),293 server.received_as_string(),
274 "hello world with packet lines and on-drop flush and done"294 "hello world with packet lines and on-drop flush and done"