use std::path::PathBuf; use crate::providers::Result; use serde::{Deserialize, Serialize}; use tokio::fs; #[derive(Debug, Deserialize)] pub struct Config { pub provider: Vec, } // Added #[serde(tag = "type")] so Serde knows to look for a "type" field // instead of nesting the entire structure inside the variant name. #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(tag = "type")] pub enum Provider { #[serde(rename = "github")] Github { friendly_name: String, username: String, token: Option, }, #[serde(rename = "gitea")] Gitea { friendly_name: String, base_url: String, username: String, token: Option, }, } pub enum ProviderClient { Github(crate::providers::github::Github), Gitea(crate::providers::gitea::Gitea), } impl crate::providers::Provider for ProviderClient { async fn repositories(&self) -> crate::providers::Result> { match self { ProviderClient::Github(g) => g.repositories().await, ProviderClient::Gitea(g) => g.repositories().await, } } async fn clone( &self, repo: crate::providers::Repository, folder: Option, use_ssh: bool, ) -> crate::providers::Result<()> { match self { ProviderClient::Github(g) => g.clone(repo, folder, use_ssh).await, ProviderClient::Gitea(g) => g.clone(repo, folder, use_ssh).await, } } } impl Provider { pub fn friendly_name(&self) -> &str { match self { Provider::Github { friendly_name, .. } => friendly_name, Provider::Gitea { friendly_name, .. } => friendly_name, } } pub fn into_provider_trait(self) -> ProviderClient { match self { Provider::Github { username, token, .. } => { todo!("Return ProviderClient::Github(...)") } Provider::Gitea { base_url, username, token, .. } => ProviderClient::Gitea(crate::providers::gitea::Gitea::new( base_url, username, token, )), } } } impl std::fmt::Display for Provider { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.friendly_name()) } } pub async fn parse_config(file_path: String) -> Result { let mut path = PathBuf::from(file_path); if path.starts_with("~") { if let Some(home_dir) = dirs::home_dir() { // Strip the "~" and join the rest of the path to the home directory path = home_dir.join(path.strip_prefix("~").unwrap()); } } let config = fs::read_to_string(&path).await?; let config: Config = toml::from_str(&config)?; Ok(config) }