repo_cli/query/
scp.rs

1use super::ScpPath;
2use anyhow::{anyhow, Result};
3use regex::Regex;
4use std::str::FromStr;
5use url::Url;
6
7impl ScpPath {
8    pub fn parse(s: &str) -> Result<Self> {
9        s.parse()
10    }
11}
12
13impl FromStr for ScpPath {
14    type Err = anyhow::Error;
15
16    fn from_str(s: &str) -> Result<Self> {
17        // Example of regex construction: https://regex101.com/r/elsHDo/1
18        let regex = Regex::new(r"^((?:[^@]+@)?)([^:]+):/?(.+)$")?;
19
20        let captures = regex
21            .captures(s)
22            .ok_or_else(|| anyhow!("url: {} does not match scp regex", s))?;
23
24        let username = captures
25            .get(1)
26            .map(|s| s.as_str())
27            .map(|s| s.trim_end_matches('@'))
28            .unwrap_or("git")
29            .to_owned();
30
31        let host = captures.get(2).unwrap().as_str().to_owned();
32        let path = captures
33            .get(3)
34            .unwrap()
35            .as_str()
36            .trim_end_matches(".git")
37            .to_owned();
38
39        Ok(Self {
40            host,
41            username,
42            path,
43        })
44    }
45}
46
47impl ScpPath {
48    pub fn to_url(&self) -> Url {
49        let str = format!("ssh://{}@{}/{}", self.username, self.host, self.path);
50        Url::parse(&str).unwrap()
51    }
52}
53
54#[allow(clippy::from_over_into)]
55impl Into<Url> for ScpPath {
56    fn into(self) -> Url {
57        self.to_url()
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn git_ssh() {
67        let scp = ScpPath::from_str("git@github.com:edeneast/repo").unwrap();
68
69        assert_eq!(scp.username, "git");
70        assert_eq!(scp.host, "github.com");
71        assert_eq!(scp.path, "edeneast/repo");
72    }
73
74    #[test]
75    fn to_url() {
76        let scp = ScpPath::from_str("git@github.com:edeneast/repo").unwrap();
77        let url = scp.to_url();
78
79        assert_eq!(url.as_str(), "ssh://git@github.com/edeneast/repo");
80    }
81}