diff --git a/Cargo.lock b/Cargo.lock index 58d232020a..9b4248114c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5506,8 +5506,10 @@ dependencies = [ "indoc", "pretty_assertions", "regex", + "schemars", "serde", "serde_json", + "settings", "url", "util", ] diff --git a/assets/settings/default.json b/assets/settings/default.json index cabef3c9ca..5e5930ea30 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -852,6 +852,14 @@ // "min_column": 0 } }, + // The list of custom Git hosting providers. + "git_hosting_providers": [ + // { + // "provider": "github", + // "name": "BigCorp GitHub", + // "base_url": "https://code.big-corp.com" + // } + ], // Configuration for how direnv configuration should be loaded. May take 2 values: // 1. Load direnv configuration using `direnv export json` directly. // "load_direnv": "direct" diff --git a/crates/git_hosting_providers/Cargo.toml b/crates/git_hosting_providers/Cargo.toml index 164e9816dd..1aa594c105 100644 --- a/crates/git_hosting_providers/Cargo.toml +++ b/crates/git_hosting_providers/Cargo.toml @@ -19,8 +19,10 @@ git.workspace = true gpui.workspace = true http_client.workspace = true regex.workspace = true +schemars.workspace = true serde.workspace = true serde_json.workspace = true +settings.workspace = true url.workspace = true util.workspace = true diff --git a/crates/git_hosting_providers/src/git_hosting_providers.rs b/crates/git_hosting_providers/src/git_hosting_providers.rs index acc0a4b98a..441136aa1f 100644 --- a/crates/git_hosting_providers/src/git_hosting_providers.rs +++ b/crates/git_hosting_providers/src/git_hosting_providers.rs @@ -1,4 +1,5 @@ mod providers; +mod settings; use std::sync::Arc; @@ -10,9 +11,12 @@ use url::Url; use util::maybe; pub use crate::providers::*; +pub use crate::settings::*; /// Initializes the Git hosting providers. -pub fn init(cx: &App) { +pub fn init(cx: &mut App) { + crate::settings::init(cx); + let provider_registry = GitHostingProviderRegistry::global(cx); provider_registry.register_hosting_provider(Arc::new(Bitbucket::public_instance())); provider_registry.register_hosting_provider(Arc::new(Chromium)); diff --git a/crates/git_hosting_providers/src/settings.rs b/crates/git_hosting_providers/src/settings.rs new file mode 100644 index 0000000000..0901ae3141 --- /dev/null +++ b/crates/git_hosting_providers/src/settings.rs @@ -0,0 +1,84 @@ +use std::sync::Arc; + +use anyhow::Result; +use git::GitHostingProviderRegistry; +use gpui::App; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use settings::{Settings, SettingsStore}; +use url::Url; +use util::ResultExt as _; + +use crate::{Bitbucket, Github, Gitlab}; + +pub(crate) fn init(cx: &mut App) { + GitHostingProviderSettings::register(cx); + + init_git_hosting_provider_settings(cx); +} + +fn init_git_hosting_provider_settings(cx: &mut App) { + update_git_hosting_providers_from_settings(cx); + + cx.observe_global::(update_git_hosting_providers_from_settings) + .detach(); +} + +fn update_git_hosting_providers_from_settings(cx: &mut App) { + let settings = GitHostingProviderSettings::get_global(cx); + let provider_registry = GitHostingProviderRegistry::global(cx); + + for provider in settings.git_hosting_providers.iter() { + let Some(url) = Url::parse(&provider.base_url).log_err() else { + continue; + }; + + let provider = match provider.provider { + GitHostingProviderKind::Bitbucket => Arc::new(Bitbucket::new(&provider.name, url)) as _, + GitHostingProviderKind::Github => Arc::new(Github::new(&provider.name, url)) as _, + GitHostingProviderKind::Gitlab => Arc::new(Gitlab::new(&provider.name, url)) as _, + }; + + provider_registry.register_hosting_provider(provider); + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum GitHostingProviderKind { + Github, + Gitlab, + Bitbucket, +} + +/// A custom Git hosting provider. +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +pub struct GitHostingProviderConfig { + /// The type of the provider. + /// + /// Must be one of `github`, `gitlab`, or `bitbucket`. + pub provider: GitHostingProviderKind, + + /// The base URL for the provider (e.g., "https://code.corp.big.com"). + pub base_url: String, + + /// The display name for the provider (e.g., "BigCorp GitHub"). + pub name: String, +} + +#[derive(Default, Clone, Serialize, Deserialize, JsonSchema)] +pub struct GitHostingProviderSettings { + /// The list of custom Git hosting providers. + #[serde(default)] + pub git_hosting_providers: Vec, +} + +impl Settings for GitHostingProviderSettings { + const KEY: Option<&'static str> = None; + + type FileContent = Self; + + fn load(sources: settings::SettingsSources, _: &mut App) -> Result { + sources.json_merge() + } +}