git_hosting_providers: Allow configuring additional hosting providers via settings (#26879)

Release Notes:

- Added a new `git_hosting_providers` setting for configuring custom Git
hosting providers.

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
This commit is contained in:
khayyam 2025-03-17 08:39:52 -07:00 committed by GitHub
parent 52567f4b72
commit 7d433a30ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 101 additions and 1 deletions

2
Cargo.lock generated
View file

@ -5506,8 +5506,10 @@ dependencies = [
"indoc",
"pretty_assertions",
"regex",
"schemars",
"serde",
"serde_json",
"settings",
"url",
"util",
]

View file

@ -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"

View file

@ -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

View file

@ -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));

View file

@ -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::<SettingsStore>(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<GitHostingProviderConfig>,
}
impl Settings for GitHostingProviderSettings {
const KEY: Option<&'static str> = None;
type FileContent = Self;
fn load(sources: settings::SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
sources.json_merge()
}
}