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