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
117 lines
3.0 KiB
Rust
117 lines
3.0 KiB
Rust
use std::{ops::Range, sync::Arc};
|
|
|
|
use anyhow::Result;
|
|
use async_trait::async_trait;
|
|
use url::Url;
|
|
use util::http::HttpClient;
|
|
|
|
use crate::hosting_providers::{Bitbucket, Codeberg, Gitee, Github, Gitlab, Sourcehut};
|
|
use crate::Oid;
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
pub struct PullRequest {
|
|
pub number: u32,
|
|
pub url: Url,
|
|
}
|
|
|
|
pub struct BuildCommitPermalinkParams<'a> {
|
|
pub sha: &'a str,
|
|
}
|
|
|
|
pub struct BuildPermalinkParams<'a> {
|
|
pub sha: &'a str,
|
|
pub path: &'a str,
|
|
pub selection: Option<Range<u32>>,
|
|
}
|
|
|
|
/// A Git hosting provider.
|
|
#[async_trait]
|
|
pub trait GitHostingProvider {
|
|
/// Returns the name of the provider.
|
|
fn name(&self) -> String;
|
|
|
|
/// Returns the base URL of the provider.
|
|
fn base_url(&self) -> Url;
|
|
|
|
/// Returns a permalink to a Git commit on this hosting provider.
|
|
fn build_commit_permalink(
|
|
&self,
|
|
remote: &ParsedGitRemote,
|
|
params: BuildCommitPermalinkParams,
|
|
) -> Url;
|
|
|
|
/// Returns a permalink to a file and/or selection on this hosting provider.
|
|
fn build_permalink(&self, remote: ParsedGitRemote, params: BuildPermalinkParams) -> Url;
|
|
|
|
/// Returns whether this provider supports avatars.
|
|
fn supports_avatars(&self) -> bool;
|
|
|
|
/// Returns a URL fragment to the given line selection.
|
|
fn line_fragment(&self, selection: &Range<u32>) -> String {
|
|
if selection.start == selection.end {
|
|
let line = selection.start + 1;
|
|
|
|
self.format_line_number(line)
|
|
} else {
|
|
let start_line = selection.start + 1;
|
|
let end_line = selection.end + 1;
|
|
|
|
self.format_line_numbers(start_line, end_line)
|
|
}
|
|
}
|
|
|
|
/// Returns a formatted line number to be placed in a permalink URL.
|
|
fn format_line_number(&self, line: u32) -> String;
|
|
|
|
/// Returns a formatted range of line numbers to be placed in a permalink URL.
|
|
fn format_line_numbers(&self, start_line: u32, end_line: u32) -> String;
|
|
|
|
fn parse_remote_url<'a>(&self, url: &'a str) -> Option<ParsedGitRemote<'a>>;
|
|
|
|
fn extract_pull_request(
|
|
&self,
|
|
_remote: &ParsedGitRemote,
|
|
_message: &str,
|
|
) -> Option<PullRequest> {
|
|
None
|
|
}
|
|
|
|
async fn commit_author_avatar_url(
|
|
&self,
|
|
_repo_owner: &str,
|
|
_repo: &str,
|
|
_commit: Oid,
|
|
_http_client: Arc<dyn HttpClient>,
|
|
) -> Result<Option<Url>> {
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ParsedGitRemote<'a> {
|
|
pub owner: &'a str,
|
|
pub repo: &'a str,
|
|
}
|
|
|
|
pub fn parse_git_remote_url(
|
|
url: &str,
|
|
) -> Option<(
|
|
Arc<dyn GitHostingProvider + Send + Sync + 'static>,
|
|
ParsedGitRemote,
|
|
)> {
|
|
let providers: Vec<Arc<dyn GitHostingProvider + Send + Sync + 'static>> = vec![
|
|
Arc::new(Github),
|
|
Arc::new(Gitlab),
|
|
Arc::new(Bitbucket),
|
|
Arc::new(Codeberg),
|
|
Arc::new(Gitee),
|
|
Arc::new(Sourcehut),
|
|
];
|
|
|
|
providers.into_iter().find_map(|provider| {
|
|
provider
|
|
.parse_remote_url(&url)
|
|
.map(|parsed_remote| (provider, parsed_remote))
|
|
})
|
|
}
|