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}