use log::warn; use octocrab::GitHubError; use serde::Deserialize; use std::{error::Error, sync::Arc}; use url::Url; #[derive(Deserialize, Debug)] struct RepoLanguage { #[serde(flatten)] name: String, size: u64, } pub async fn language_analyze(repo: String, github_token: Option) -> Result<(), String> { let repo_url = Url::parse(repo.as_str()); if repo_url.is_err() { warn!("Invalid github repository URL"); return Err("Invalid github repository URL".to_string()); } let repo_url = repo_url.unwrap(); let repo_host = repo_url.host_str().unwrap(); if repo_host != "github.com" { warn!("Not a GitHub repository"); return Err(format!("Unsupported host: {}", repo_host)); } let mut repo_path = repo_url.path(); if repo_path.ends_with(".git") { // 处理.git后缀 repo_path = repo_path.strip_suffix(".git").unwrap(); }; let github_instance = octocrab::instance(); let github_instance = if github_token.is_some() { Arc::new( github_instance .user_access_token(github_token.unwrap()) .unwrap(), ) } else { github_instance }; let repo_lang = github_instance .get::(format!("/repos{}/languages", repo_path), None::<&()>) .await; if repo_lang.is_err() { match repo_lang.unwrap_err() { octocrab::Error::GitHub { source: error, backtrace: _, } => { // dbg!(error.message); warn!("Failed to fetch language information: {}", error.message); return Err(format!( "Failed to fetch language information: {}", error.message )); } _ => { warn!("Failed to fetch language information"); return Err("Failed to fetch language information".to_string()); } } } let repo_lang = repo_lang.unwrap(); dbg!(repo_lang); Ok(()) } mod tests { use super::language_analyze; #[tokio::test] async fn test_github_language_analyze_success() { let repo = "https://github.com/mono/SkiaSharp"; language_analyze(repo.to_string(), None).await.unwrap(); } #[tokio::test] #[should_panic] async fn test_github_language_analyze_nonexistent() { let repo = "https://github.com/nonexistant/bass"; language_analyze(repo.to_string(), None).await.unwrap(); } }