1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use crate::remote::Connection;
use crate::{Progress, Remote};
use git_protocol::transport::client::Transport;
mod error {
use crate::bstr::BString;
use crate::remote;
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
Connect(#[from] git_protocol::transport::client::connect::Error),
#[error("The {} url was missing - don't know where to establish a connection to", direction.as_str())]
MissingUrl { direction: remote::Direction },
#[error("Protocol named {given:?} is not a valid protocol. Choose between 1 and 2")]
UnknownProtocol { given: BString },
#[error("Could not verify that file:// url is a valid git directory before attempting to use it")]
FileUrl(#[from] git_discover::is_git::Error),
}
}
pub use error::Error;
impl<'repo> Remote<'repo> {
pub fn to_connection_with_transport<T, P>(&self, transport: T, progress: P) -> Connection<'_, 'repo, T, P>
where
T: Transport,
P: Progress,
{
Connection {
remote: self,
transport,
progress,
}
}
#[cfg(any(feature = "blocking-network-client", feature = "async-network-client-async-std"))]
#[git_protocol::maybe_async::maybe_async]
pub async fn connect<P>(
&self,
direction: crate::remote::Direction,
progress: P,
) -> Result<Connection<'_, 'repo, Box<dyn Transport + Send>, P>, Error>
where
P: Progress,
{
use git_protocol::transport::Protocol;
fn sanitize(mut url: git_url::Url) -> Result<git_url::Url, Error> {
if url.scheme == git_url::Scheme::File {
let mut dir = git_path::from_bstr(url.path.as_ref());
let kind = git_discover::is_git(dir.as_ref()).or_else(|_| {
dir.to_mut().push(git_discover::DOT_GIT_DIR);
git_discover::is_git(dir.as_ref())
})?;
let (git_dir, _work_dir) = git_discover::repository::Path::from_dot_git_dir(dir.into_owned(), kind)
.into_repository_and_work_tree_directories();
url.path = git_path::into_bstr(git_dir).into_owned();
}
Ok(url)
}
let protocol = self
.repo
.config
.resolved
.integer("protocol", None, "version")
.unwrap_or(Ok(2))
.map_err(|err| Error::UnknownProtocol { given: err.input })
.and_then(|num| {
Ok(match num {
1 => Protocol::V1,
2 => Protocol::V2,
num => {
return Err(Error::UnknownProtocol {
given: num.to_string().into(),
})
}
})
})?;
let url = self.url(direction).ok_or(Error::MissingUrl { direction })?.to_owned();
let transport = git_protocol::transport::connect(sanitize(url)?, protocol).await?;
Ok(self.to_connection_with_transport(transport, progress))
}
}