1use query::Query;
2use scp::ScpPath;
3use url::Url;
4
5
6#[derive(Clone, Debug, Serialize, Deserialize)]
8pub struct Remote {
9 url: String,
10}
11
12impl Remote {
13 pub fn new<S: Into<String>>(url: S) -> Remote {
14 Remote { url: url.into() }
16 }
17
18 pub fn url(&self) -> &str {
19 &self.url
20 }
21}
22
23impl Remote {
24 pub fn from_url(url: &Url) -> ::Result<Self> {
25 let url = if url.scheme() == "ssh" {
26 let username = url.username();
27 let host = url.host_str().ok_or("empty host")?;
28 let path = url.path().trim_left_matches("/");
29 format!("{}@{}:{}", username, host, path)
30 } else {
31 url.as_str().to_owned()
32 };
33 Ok(Self { url })
34 }
35
36 pub fn from_scp(scp: &ScpPath) -> Self {
37 Self {
38 url: scp.to_string(),
39 }
40 }
41
42 pub fn from_path(path: &str, is_ssh: bool, host: &str) -> ::Result<Self> {
43 if is_ssh {
44 let scp: ScpPath = format!("git@{}:{}", host, path).parse()?;
45 Ok(Self::from_scp(&scp))
46 } else {
47 let url = Url::parse(&format!("https://{}/{}.git", host, path))?;
48 Self::from_url(&url)
49 }
50 }
51
52 pub fn from_query(query: &Query, is_ssh: bool, host: &str) -> ::Result<Self> {
53 match *query {
54 Query::Url(ref url) => Self::from_url(url),
55 Query::Scp(ref path) => Ok(Self::from_scp(path)),
56 Query::Path(ref path) => Self::from_path(path, is_ssh, host),
57 }
58 }
59}
60
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn path_https() {
68 let s = "ubnt-intrepid/rhq";
69 let query: Query = s.parse().unwrap();
70 let remote = Remote::from_query(&query, false, "github.com").unwrap();
71 assert_eq!(remote.url, "https://github.com/ubnt-intrepid/rhq.git");
72 }
73
74 #[test]
75 fn path_scp() {
76 let s = "ubnt-intrepid/rhq";
77 let query: Query = s.parse().unwrap();
78 let remote = Remote::from_query(&query, true, "github.com").unwrap();
79 assert_eq!(remote.url, "git@github.com:ubnt-intrepid/rhq.git");
80 }
81}