]> git.proxmox.com Git - rustc.git/blob - vendor/gix-transport/src/client/git/async_io.rs
New upstream version 1.76.0+dfsg1
[rustc.git] / vendor / gix-transport / src / client / git / async_io.rs
1 use std::{borrow::Cow, error::Error};
2
3 use async_trait::async_trait;
4 use bstr::{BStr, BString, ByteVec};
5 use futures_io::{AsyncRead, AsyncWrite};
6 use futures_lite::AsyncWriteExt;
7 use gix_packetline::PacketLineRef;
8
9 use crate::{
10 client::{self, capabilities, git, Capabilities, SetServiceResponse},
11 Protocol, Service,
12 };
13
14 impl<R, W> client::TransportWithoutIO for git::Connection<R, W>
15 where
16 R: AsyncRead + Unpin,
17 W: AsyncWrite + Unpin,
18 {
19 fn request(
20 &mut self,
21 write_mode: client::WriteMode,
22 on_into_read: client::MessageKind,
23 trace: bool,
24 ) -> Result<client::RequestWriter<'_>, client::Error> {
25 Ok(client::RequestWriter::new_from_bufread(
26 &mut self.writer,
27 Box::new(self.line_provider.as_read_without_sidebands()),
28 write_mode,
29 on_into_read,
30 trace,
31 ))
32 }
33 fn to_url(&self) -> Cow<'_, BStr> {
34 self.custom_url.as_ref().map_or_else(
35 || {
36 let mut possibly_lossy_url = self.path.clone();
37 possibly_lossy_url.insert_str(0, "file://");
38 Cow::Owned(possibly_lossy_url)
39 },
40 |url| Cow::Borrowed(url.as_ref()),
41 )
42 }
43
44 fn connection_persists_across_multiple_requests(&self) -> bool {
45 true
46 }
47
48 fn configure(&mut self, _config: &dyn std::any::Any) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
49 Ok(())
50 }
51 }
52
53 #[async_trait(?Send)]
54 impl<R, W> client::Transport for git::Connection<R, W>
55 where
56 R: AsyncRead + Unpin,
57 W: AsyncWrite + Unpin,
58 {
59 async fn handshake<'a>(
60 &mut self,
61 service: Service,
62 extra_parameters: &'a [(&'a str, Option<&'a str>)],
63 ) -> Result<SetServiceResponse<'_>, client::Error> {
64 if self.mode == git::ConnectMode::Daemon {
65 let mut line_writer = gix_packetline::Writer::new(&mut self.writer).binary_mode();
66 line_writer
67 .write_all(&git::message::connect(
68 service,
69 self.desired_version,
70 &self.path,
71 self.virtual_host.as_ref(),
72 extra_parameters,
73 ))
74 .await?;
75 line_writer.flush().await?;
76 }
77
78 let capabilities::recv::Outcome {
79 capabilities,
80 refs,
81 protocol: actual_protocol,
82 } = Capabilities::from_lines_with_version_detection(&mut self.line_provider).await?;
83 Ok(SetServiceResponse {
84 actual_protocol,
85 capabilities,
86 refs,
87 })
88 }
89 }
90
91 impl<R, W> git::Connection<R, W>
92 where
93 R: AsyncRead + Unpin,
94 W: AsyncWrite + Unpin,
95 {
96 /// Create a connection from the given `read` and `write`, asking for `desired_version` as preferred protocol
97 /// and the transfer of the repository at `repository_path`.
98 ///
99 /// `virtual_host` along with a port to which to connect to, while `mode` determines the kind of endpoint to connect to.
100 /// If `trace` is `true`, all packetlines received or sent will be passed to the facilities of the `gix-trace` crate.
101 pub fn new(
102 read: R,
103 write: W,
104 desired_version: Protocol,
105 repository_path: impl Into<BString>,
106 virtual_host: Option<(impl Into<String>, Option<u16>)>,
107 mode: git::ConnectMode,
108 trace: bool,
109 ) -> Self {
110 git::Connection {
111 writer: write,
112 line_provider: gix_packetline::StreamingPeekableIter::new(read, &[PacketLineRef::Flush], trace),
113 path: repository_path.into(),
114 virtual_host: virtual_host.map(|(h, p)| (h.into(), p)),
115 desired_version,
116 custom_url: None,
117 mode,
118 }
119 }
120 }
121
122 #[cfg(feature = "async-std")]
123 mod async_net {
124 use std::time::Duration;
125
126 use async_std::net::TcpStream;
127
128 use crate::client::{git, Error};
129
130 impl git::Connection<TcpStream, TcpStream> {
131 /// Create a new TCP connection using the `git` protocol of `desired_version`, and make a connection to `host`
132 /// at `port` for accessing the repository at `path` on the server side.
133 /// If `trace` is `true`, all packetlines received or sent will be passed to the facilities of the `gix-trace` crate.
134 pub async fn new_tcp(
135 host: &str,
136 port: Option<u16>,
137 path: bstr::BString,
138 desired_version: crate::Protocol,
139 trace: bool,
140 ) -> Result<git::Connection<TcpStream, TcpStream>, Error> {
141 let read = async_std::io::timeout(
142 Duration::from_secs(5),
143 TcpStream::connect(&(host, port.unwrap_or(9418))),
144 )
145 .await?;
146 let write = read.clone();
147 Ok(git::Connection::new(
148 read,
149 write,
150 desired_version,
151 path,
152 None::<(String, _)>,
153 git::ConnectMode::Daemon,
154 trace,
155 ))
156 }
157 }
158 }