Add a registry for GitHostingProvider
s (#11470)
This PR adds a registry for `GitHostingProvider`s. The intent here is to help decouple these provider-specific concerns from the lower-level `git` crate. Similar to languages, the Git hosting providers live in the new `git_hosting_providers` crate. This work also lays the foundation for if we wanted to allow defining a `GitHostingProvider` from within an extension. This could be useful if we wanted to extend the support to work with self-hosted Git providers (like GitHub Enterprise). I also took the opportunity to move some of the provider-specific code out of the `util` crate, since it had leaked into there. Release Notes: - N/A
This commit is contained in:
parent
a64e20ed96
commit
88c4e0b2d8
28 changed files with 405 additions and 229 deletions
|
@ -1,78 +0,0 @@
|
|||
use crate::{git_author::GitAuthor, http::HttpClient};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use futures::AsyncReadExt;
|
||||
use isahc::{config::Configurable, AsyncBody, Request};
|
||||
use serde::Deserialize;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct CommitDetails {
|
||||
commit: Commit,
|
||||
author: Option<User>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Commit {
|
||||
author: Author,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Author {
|
||||
name: String,
|
||||
email: String,
|
||||
date: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct User {
|
||||
pub login: String,
|
||||
pub id: u64,
|
||||
pub avatar_url: String,
|
||||
}
|
||||
|
||||
pub async fn fetch_codeberg_commit_author(
|
||||
repo_owner: &str,
|
||||
repo: &str,
|
||||
commit: &str,
|
||||
client: &Arc<dyn HttpClient>,
|
||||
) -> Result<Option<GitAuthor>> {
|
||||
let url = format!("https://codeberg.org/api/v1/repos/{repo_owner}/{repo}/git/commits/{commit}");
|
||||
|
||||
let mut request = Request::get(&url)
|
||||
.redirect_policy(isahc::config::RedirectPolicy::Follow)
|
||||
.header("Content-Type", "application/json");
|
||||
|
||||
if let Ok(codeberg_token) = std::env::var("CODEBERG_TOKEN") {
|
||||
request = request.header("Authorization", format!("Bearer {}", codeberg_token));
|
||||
}
|
||||
|
||||
let mut response = client
|
||||
.send(request.body(AsyncBody::default())?)
|
||||
.await
|
||||
.with_context(|| format!("error fetching Codeberg commit details at {:?}", url))?;
|
||||
|
||||
let mut body = Vec::new();
|
||||
response.body_mut().read_to_end(&mut body).await?;
|
||||
|
||||
if response.status().is_client_error() {
|
||||
let text = String::from_utf8_lossy(body.as_slice());
|
||||
bail!(
|
||||
"status error {}, response: {text:?}",
|
||||
response.status().as_u16()
|
||||
);
|
||||
}
|
||||
|
||||
let body_str = std::str::from_utf8(&body)?;
|
||||
|
||||
serde_json::from_str::<CommitDetails>(body_str)
|
||||
.map(|codeberg_commit| {
|
||||
if let Some(author) = codeberg_commit.author {
|
||||
Some(GitAuthor {
|
||||
avatar_url: author.avatar_url,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.context("deserializing Codeberg commit details failed")
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
/// Represents the common denominator of most git hosting authors
|
||||
#[derive(Debug)]
|
||||
pub struct GitAuthor {
|
||||
pub avatar_url: String,
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
use crate::{git_author::GitAuthor, http::HttpClient};
|
||||
use crate::http::HttpClient;
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use futures::AsyncReadExt;
|
||||
use isahc::{config::Configurable, AsyncBody, Request};
|
||||
use serde::Deserialize;
|
||||
use std::sync::Arc;
|
||||
use url::Url;
|
||||
|
@ -27,75 +26,6 @@ pub struct GithubReleaseAsset {
|
|||
pub browser_download_url: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct CommitDetails {
|
||||
commit: Commit,
|
||||
author: Option<User>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Commit {
|
||||
author: Author,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Author {
|
||||
email: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct User {
|
||||
pub id: u64,
|
||||
pub avatar_url: String,
|
||||
}
|
||||
|
||||
pub async fn fetch_github_commit_author(
|
||||
repo_owner: &str,
|
||||
repo: &str,
|
||||
commit: &str,
|
||||
client: &Arc<dyn HttpClient>,
|
||||
) -> Result<Option<GitAuthor>> {
|
||||
let url = format!("https://api.github.com/repos/{repo_owner}/{repo}/commits/{commit}");
|
||||
|
||||
let mut request = Request::get(&url)
|
||||
.redirect_policy(isahc::config::RedirectPolicy::Follow)
|
||||
.header("Content-Type", "application/json");
|
||||
|
||||
if let Ok(github_token) = std::env::var("GITHUB_TOKEN") {
|
||||
request = request.header("Authorization", format!("Bearer {}", github_token));
|
||||
}
|
||||
|
||||
let mut response = client
|
||||
.send(request.body(AsyncBody::default())?)
|
||||
.await
|
||||
.with_context(|| format!("error fetching GitHub commit details at {:?}", url))?;
|
||||
|
||||
let mut body = Vec::new();
|
||||
response.body_mut().read_to_end(&mut body).await?;
|
||||
|
||||
if response.status().is_client_error() {
|
||||
let text = String::from_utf8_lossy(body.as_slice());
|
||||
bail!(
|
||||
"status error {}, response: {text:?}",
|
||||
response.status().as_u16()
|
||||
);
|
||||
}
|
||||
|
||||
let body_str = std::str::from_utf8(&body)?;
|
||||
|
||||
serde_json::from_str::<CommitDetails>(body_str)
|
||||
.map(|github_commit| {
|
||||
if let Some(author) = github_commit.author {
|
||||
Some(GitAuthor {
|
||||
avatar_url: author.avatar_url,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.context("deserializing GitHub commit details failed")
|
||||
}
|
||||
|
||||
pub async fn latest_github_release(
|
||||
repo_name_with_owner: &str,
|
||||
require_assets: bool,
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
pub mod arc_cow;
|
||||
pub mod codeberg;
|
||||
pub mod fs;
|
||||
mod git_author;
|
||||
pub mod github;
|
||||
pub mod http;
|
||||
pub mod paths;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue