diff --git a/crates/git_hosting_providers/src/providers/gitee.rs b/crates/git_hosting_providers/src/providers/gitee.rs index e2bcb66682..120a360cb1 100644 --- a/crates/git_hosting_providers/src/providers/gitee.rs +++ b/crates/git_hosting_providers/src/providers/gitee.rs @@ -1,5 +1,11 @@ -use std::str::FromStr; +use std::{str::FromStr, sync::Arc}; +use anyhow::{Context as _, Result, bail}; +use async_trait::async_trait; +use futures::AsyncReadExt; +use gpui::SharedString; +use http_client::{AsyncBody, HttpClient, HttpRequestExt, Request}; +use serde::Deserialize; use url::Url; use git::{ @@ -9,6 +15,55 @@ use git::{ pub struct Gitee; +#[derive(Debug, Deserialize)] +struct CommitDetails { + author: Option, +} + +#[derive(Debug, Deserialize)] +struct Author { + avatar_url: String, +} + +impl Gitee { + async fn fetch_gitee_commit_author( + &self, + repo_owner: &str, + repo: &str, + commit: &str, + client: &Arc, + ) -> Result> { + let url = format!("https://gitee.com/api/v5/repos/{repo_owner}/{repo}/commits/{commit}"); + + let request = Request::get(&url) + .header("Content-Type", "application/json") + .follow_redirects(http_client::RedirectPolicy::FollowAll); + + let mut response = client + .send(request.body(AsyncBody::default())?) + .await + .with_context(|| format!("error fetching Gitee 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::(body_str) + .map(|commit| commit.author) + .context("failed to deserialize Gitee commit details") + } +} + +#[async_trait] impl GitHostingProvider for Gitee { fn name(&self) -> String { "Gitee".to_string() @@ -19,7 +74,7 @@ impl GitHostingProvider for Gitee { } fn supports_avatars(&self) -> bool { - false + true } fn format_line_number(&self, line: u32) -> String { @@ -80,6 +135,26 @@ impl GitHostingProvider for Gitee { ); permalink } + + async fn commit_author_avatar_url( + &self, + repo_owner: &str, + repo: &str, + commit: SharedString, + http_client: Arc, + ) -> Result> { + let commit = commit.to_string(); + let avatar_url = self + .fetch_gitee_commit_author(repo_owner, repo, &commit, &http_client) + .await? + .map(|author| -> Result { + let mut url = Url::parse(&author.avatar_url)?; + url.set_query(Some("width=128")); + Ok(url) + }) + .transpose()?; + Ok(avatar_url) + } } #[cfg(test)]