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(Forgejo::public_instance()));
25    provider_registry.register_hosting_provider(Arc::new(Gitea::public_instance()));
26    provider_registry.register_hosting_provider(Arc::new(Gitee));
27    provider_registry.register_hosting_provider(Arc::new(Github::public_instance()));
28    provider_registry.register_hosting_provider(Arc::new(Gitlab::public_instance()));
29    provider_registry.register_hosting_provider(Arc::new(Sourcehut));
30}
31
32/// Registers additional Git hosting providers.
33///
34/// These require information from the Git repository to construct, so their
35/// registration is deferred until we have a Git repository initialized.
36pub fn register_additional_providers(
37    provider_registry: Arc<GitHostingProviderRegistry>,
38    repository: Arc<dyn GitRepository>,
39) {
40    let Some(origin_url) = repository.remote_url("origin") else {
41        return;
42    };
43
44    if let Ok(gitlab_self_hosted) = Gitlab::from_remote_url(&origin_url) {
45        provider_registry.register_hosting_provider(Arc::new(gitlab_self_hosted));
46    } else if let Ok(github_self_hosted) = Github::from_remote_url(&origin_url) {
47        provider_registry.register_hosting_provider(Arc::new(github_self_hosted));
48    } else if let Ok(forgejo_self_hosted) = Forgejo::from_remote_url(&origin_url) {
49        provider_registry.register_hosting_provider(Arc::new(forgejo_self_hosted));
50    } else if let Ok(gitea_self_hosted) = Gitea::from_remote_url(&origin_url) {
51        provider_registry.register_hosting_provider(Arc::new(gitea_self_hosted));
52    } else if let Ok(bitbucket_self_hosted) = Bitbucket::from_remote_url(&origin_url) {
53        provider_registry.register_hosting_provider(Arc::new(bitbucket_self_hosted));
54    }
55}
56
57pub fn get_host_from_git_remote_url(remote_url: &str) -> Result<String> {
58    maybe!({
59        if let Some(remote_url) = remote_url.strip_prefix("git@")
60            && let Some((host, _)) = remote_url.trim_start_matches("git@").split_once(':')
61        {
62            return Some(host.to_string());
63        }
64
65        Url::parse(remote_url)
66            .ok()
67            .and_then(|remote_url| remote_url.host_str().map(|host| host.to_string()))
68    })
69    .context("URL has no host")
70}
71
72#[cfg(test)]
73mod tests {
74    use super::get_host_from_git_remote_url;
75    use pretty_assertions::assert_eq;
76
77    #[test]
78    fn test_get_host_from_git_remote_url() {
79        let tests = [
80            (
81                "https://jlannister@github.com/some-org/some-repo.git",
82                Some("github.com".to_string()),
83            ),
84            (
85                "git@github.com:zed-industries/zed.git",
86                Some("github.com".to_string()),
87            ),
88            (
89                "git@my.super.long.subdomain.com:zed-industries/zed.git",
90                Some("my.super.long.subdomain.com".to_string()),
91            ),
92        ];
93
94        for (remote_url, expected_host) in tests {
95            let host = get_host_from_git_remote_url(remote_url).ok();
96            assert_eq!(host, expected_host);
97        }
98    }
99}