gix_protocol/fetch/arguments/
blocking_io.rs

1use std::io::Write;
2
3use gix_transport::client::{
4    self,
5    blocking_io::{ExtendedBufRead, Transport, TransportV2Ext},
6};
7
8use crate::{fetch::Arguments, Command};
9
10impl Arguments {
11    /// Send fetch arguments to the server, and indicate this is the end of negotiations only if `add_done_argument` is present.
12    pub fn send<'a, T: Transport + 'a>(
13        &mut self,
14        transport: &'a mut T,
15        add_done_argument: bool,
16    ) -> Result<Box<dyn ExtendedBufRead<'a> + Unpin + 'a>, client::Error> {
17        if self.haves.is_empty() {
18            assert!(add_done_argument, "If there are no haves, is_done must be true.");
19        }
20        match self.version {
21            gix_transport::Protocol::V0 | gix_transport::Protocol::V1 => {
22                let (on_into_read, retained_state) = self.prepare_v1(
23                    transport.connection_persists_across_multiple_requests(),
24                    add_done_argument,
25                )?;
26                let mut line_writer = transport.request(
27                    client::WriteMode::OneLfTerminatedLinePerWriteCall,
28                    on_into_read,
29                    self.trace,
30                )?;
31                let had_args = !self.args.is_empty();
32                for arg in self.args.drain(..) {
33                    line_writer.write_all(&arg)?;
34                }
35                if had_args {
36                    line_writer.write_message(client::MessageKind::Flush)?;
37                }
38                for line in self.haves.drain(..) {
39                    line_writer.write_all(&line)?;
40                }
41                if let Some(next_args) = retained_state {
42                    self.args = next_args;
43                }
44                Ok(line_writer.into_read()?)
45            }
46            gix_transport::Protocol::V2 => {
47                let retained_state = self.args.clone();
48                self.args.append(&mut self.haves);
49                if add_done_argument {
50                    self.args.push("done".into());
51                }
52                transport.invoke(
53                    Command::Fetch.as_str(),
54                    self.features.iter().filter(|(_, v)| v.is_some()).cloned(),
55                    Some(std::mem::replace(&mut self.args, retained_state).into_iter()),
56                    self.trace,
57                )
58            }
59        }
60    }
61}