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}