git_hosting_providers.rs

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