Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T03:28:41.017Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

remote.rs

115 lines · 3.4 KB · rust
1use std::str::FromStr;
2use std::sync::LazyLock;
3
4use derive_more::Deref;
5use regex::Regex;
6use url::Url;
7
8/// The URL to a Git remote.
9#[derive(Debug, PartialEq, Eq, Clone, Deref)]
10pub struct RemoteUrl(Url);
11
12// Detect the `user@` prefix of an SCP-like remote (e.g. `git@host:path`). The
13// username may contain anything but the `@`/`:`/`/` that delimit the user,
14// host, and path, so match by exclusion rather than an allowlist that misses
15// names like `first.last`.
16static USERNAME_REGEX: LazyLock<Regex> =
17    LazyLock::new(|| Regex::new(r"^[^/@:]+@").expect("Failed to create USERNAME_REGEX"));
18
19impl FromStr for RemoteUrl {
20    type Err = url::ParseError;
21
22    fn from_str(input: &str) -> Result<Self, Self::Err> {
23        if USERNAME_REGEX.is_match(input) {
24            // Rewrite remote URLs like `git@github.com:user/repo.git` to `ssh://git@github.com/user/repo.git`
25            let ssh_url = format!("ssh://{}", input.replacen(':', "/", 1));
26            Ok(RemoteUrl(Url::parse(&ssh_url)?))
27        } else {
28            Ok(RemoteUrl(Url::parse(input)?))
29        }
30    }
31}
32
33#[cfg(test)]
34mod tests {
35    use pretty_assertions::assert_eq;
36
37    use super::*;
38
39    #[test]
40    fn test_parsing_valid_remote_urls() {
41        let valid_urls = vec![
42            (
43                "https://github.com/octocat/zed.git",
44                "https",
45                "github.com",
46                "/octocat/zed.git",
47            ),
48            (
49                "https://jlannister@github.com/octocat/zed.git",
50                "https",
51                "github.com",
52                "/octocat/zed.git",
53            ),
54            (
55                "git@github.com:octocat/zed.git",
56                "ssh",
57                "github.com",
58                "/octocat/zed.git",
59            ),
60            (
61                "org-000000@github.com:octocat/zed.git",
62                "ssh",
63                "github.com",
64                "/octocat/zed.git",
65            ),
66            (
67                "first.last@gitlab.example.com:group/repo.git",
68                "ssh",
69                "gitlab.example.com",
70                "/group/repo.git",
71            ),
72            (
73                "ssh://git@github.com/octocat/zed.git",
74                "ssh",
75                "github.com",
76                "/octocat/zed.git",
77            ),
78            (
79                "file:///path/to/local/zed",
80                "file",
81                "",
82                "/path/to/local/zed",
83            ),
84        ];
85
86        for (input, expected_scheme, expected_host, expected_path) in valid_urls {
87            let parsed = input.parse::<RemoteUrl>().expect("failed to parse URL");
88            let url = parsed.0;
89            assert_eq!(
90                url.scheme(),
91                expected_scheme,
92                "unexpected scheme for {input:?}",
93            );
94            assert_eq!(
95                url.host_str().unwrap_or(""),
96                expected_host,
97                "unexpected host for {input:?}",
98            );
99            assert_eq!(url.path(), expected_path, "unexpected path for {input:?}");
100        }
101    }
102
103    #[test]
104    fn test_parsing_invalid_remote_urls() {
105        let invalid_urls = vec!["not_a_url", "http://"];
106
107        for url in invalid_urls {
108            assert!(
109                url.parse::<RemoteUrl>().is_err(),
110                "expected \"{url}\" to not parse as a Git remote URL",
111            );
112        }
113    }
114}
115
Served at tenant.openagents/omega Member data and write actions are omitted.