git_hosting_providers.rs

 1mod providers;
 2
 3use std::sync::Arc;
 4
 5use anyhow::{anyhow, Result};
 6use git::repository::GitRepository;
 7use git::GitHostingProviderRegistry;
 8use gpui::App;
 9use url::Url;
10use util::maybe;
11
12pub use crate::providers::*;
13
14/// Initializes the Git hosting providers.
15pub fn init(cx: &App) {
16    let provider_registry = GitHostingProviderRegistry::global(cx);
17    provider_registry.register_hosting_provider(Arc::new(Bitbucket));
18    provider_registry.register_hosting_provider(Arc::new(Chromium));
19    provider_registry.register_hosting_provider(Arc::new(Codeberg));
20    provider_registry.register_hosting_provider(Arc::new(Gitee));
21    provider_registry.register_hosting_provider(Arc::new(Github::new()));
22    provider_registry.register_hosting_provider(Arc::new(Gitlab::new()));
23    provider_registry.register_hosting_provider(Arc::new(Sourcehut));
24}
25
26/// Registers additional Git hosting providers.
27///
28/// These require information from the Git repository to construct, so their
29/// registration is deferred until we have a Git repository initialized.
30pub fn register_additional_providers(
31    provider_registry: Arc<GitHostingProviderRegistry>,
32    repository: Arc<dyn GitRepository>,
33) {
34    let Some(origin_url) = repository.remote_url("origin") else {
35        return;
36    };
37
38    if let Ok(gitlab_self_hosted) = Gitlab::from_remote_url(&origin_url) {
39        provider_registry.register_hosting_provider(Arc::new(gitlab_self_hosted));
40    } else if let Ok(github_self_hosted) = Github::from_remote_url(&origin_url) {
41        provider_registry.register_hosting_provider(Arc::new(github_self_hosted));
42    }
43}
44
45pub fn get_host_from_git_remote_url(remote_url: &str) -> Result<String> {
46    maybe!({
47        if let Some(remote_url) = remote_url.strip_prefix("git@") {
48            if let Some((host, _)) = remote_url.trim_start_matches("git@").split_once(':') {
49                return Some(host.to_string());
50            }
51        }
52
53        Url::parse(&remote_url)
54            .ok()
55            .and_then(|remote_url| remote_url.host_str().map(|host| host.to_string()))
56    })
57    .ok_or_else(|| anyhow!("URL has no host"))
58}
59
60#[cfg(test)]
61mod tests {
62    use super::get_host_from_git_remote_url;
63    use pretty_assertions::assert_eq;
64
65    #[test]
66    fn test_get_host_from_git_remote_url() {
67        let tests = [
68            (
69                "https://jlannister@github.com/some-org/some-repo.git",
70                Some("github.com".to_string()),
71            ),
72            (
73                "git@github.com:zed-industries/zed.git",
74                Some("github.com".to_string()),
75            ),
76            (
77                "git@my.super.long.subdomain.com:zed-industries/zed.git",
78                Some("my.super.long.subdomain.com".to_string()),
79            ),
80        ];
81
82        for (remote_url, expected_host) in tests {
83            let host = get_host_from_git_remote_url(remote_url).ok();
84            assert_eq!(host, expected_host);
85        }
86    }
87}