Refactor Git hosting providers (#11457)

This PR refactors the code pertaining to Git hosting providers to make
it more uniform and easy to add support for new providers.

There is now a `GitHostingProvider` trait that contains the
functionality specific to an individual Git hosting provider. Each
provider we support has an implementation of this trait.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-05-06 15:44:13 -04:00 committed by GitHub
parent 8871fec2a8
commit bb1817ff31
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 1443 additions and 883 deletions

View file

@ -61,7 +61,7 @@ struct CommitAvatarAsset {
impl Hash for CommitAvatarAsset {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.sha.hash(state);
self.remote.host.hash(state);
self.remote.host.name().hash(state);
}
}

View file

@ -41,7 +41,7 @@ mod editor_tests;
#[cfg(any(test, feature = "test-support"))]
pub mod test;
use ::git::diff::{DiffHunk, DiffHunkStatus};
use ::git::permalink::{build_permalink, BuildPermalinkParams};
use ::git::{parse_git_remote_url, BuildPermalinkParams};
pub(crate) use actions::*;
use aho_corasick::AhoCorasick;
use anyhow::{anyhow, Context as _, Result};
@ -9548,17 +9548,22 @@ impl Editor {
let selections = self.selections.all::<Point>(cx);
let selection = selections.iter().peekable().next();
build_permalink(BuildPermalinkParams {
remote_url: &origin_url,
sha: &sha,
path: &path,
selection: selection.map(|selection| {
let range = selection.range();
let start = range.start.row;
let end = range.end.row;
start..end
}),
})
let (provider, remote) = parse_git_remote_url(&origin_url)
.ok_or_else(|| anyhow!("failed to parse Git remote URL"))?;
Ok(provider.build_permalink(
remote,
BuildPermalinkParams {
sha: &sha,
path: &path,
selection: selection.map(|selection| {
let range = selection.range();
let start = range.start.row;
let end = range.end.row;
start..end
}),
},
))
}
pub fn copy_permalink_to_line(&mut self, _: &CopyPermalinkToLine, cx: &mut ViewContext<Self>) {

View file

@ -4,10 +4,7 @@ use anyhow::Result;
use collections::HashMap;
use git::{
blame::{Blame, BlameEntry},
hosting_provider::HostingProvider,
permalink::{build_commit_permalink, parse_git_remote_url},
pull_request::{extract_pull_request, PullRequest},
Oid,
parse_git_remote_url, GitHostingProvider, Oid, PullRequest,
};
use gpui::{Model, ModelContext, Subscription, Task};
use language::{markdown, Bias, Buffer, BufferSnapshot, Edit, LanguageRegistry, ParsedMarkdown};
@ -50,13 +47,23 @@ impl<'a> sum_tree::Dimension<'a, GitBlameEntrySummary> for u32 {
}
}
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct GitRemote {
pub host: HostingProvider,
pub host: Arc<dyn GitHostingProvider + Send + Sync + 'static>,
pub owner: String,
pub repo: String,
}
impl std::fmt::Debug for GitRemote {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("GitRemote")
.field("host", &self.host.name())
.field("owner", &self.owner)
.field("repo", &self.repo)
.finish()
}
}
impl GitRemote {
pub fn host_supports_avatars(&self) -> bool {
self.host.supports_avatars()
@ -440,10 +447,10 @@ async fn parse_commit_messages(
for (oid, message) in messages {
let parsed_message = parse_markdown(&message, &languages).await;
let permalink = if let Some(git_remote) = parsed_remote_url.as_ref() {
Some(build_commit_permalink(
git::permalink::BuildCommitPermalinkParams {
remote: git_remote,
let permalink = if let Some((provider, git_remote)) = parsed_remote_url.as_ref() {
Some(provider.build_commit_permalink(
git_remote,
git::BuildCommitPermalinkParams {
sha: oid.to_string().as_str(),
},
))
@ -455,15 +462,17 @@ async fn parse_commit_messages(
deprecated_permalinks.get(&oid).cloned()
};
let remote = parsed_remote_url.as_ref().map(|remote| GitRemote {
host: remote.provider.clone(),
owner: remote.owner.to_string(),
repo: remote.repo.to_string(),
});
let remote = parsed_remote_url
.as_ref()
.map(|(provider, remote)| GitRemote {
host: provider.clone(),
owner: remote.owner.to_string(),
repo: remote.repo.to_string(),
});
let pull_request = parsed_remote_url
.as_ref()
.and_then(|remote| extract_pull_request(remote, &message));
.and_then(|(provider, remote)| provider.extract_pull_request(remote, &message));
commit_details.insert(
oid,