added config parsing, and the selection between multiple providers.

This commit is contained in:
2026-07-10 21:03:45 -05:00
parent 4283b1af2a
commit 8348946c3c
9 changed files with 351 additions and 32 deletions
+105
View File
@@ -0,0 +1,105 @@
use std::path::PathBuf;
use crate::providers::Result;
use serde::{Deserialize, Serialize};
use tokio::fs;
#[derive(Debug, Deserialize)]
pub struct Config {
pub provider: Vec<Provider>,
}
// 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<String>,
},
#[serde(rename = "gitea")]
Gitea {
friendly_name: String,
base_url: String,
username: String,
token: Option<String>,
},
}
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<Vec<crate::providers::Repository>> {
match self {
ProviderClient::Github(g) => g.repositories().await,
ProviderClient::Gitea(g) => g.repositories().await,
}
}
async fn clone(
&self,
repo: crate::providers::Repository,
folder: Option<String>,
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<Config> {
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)
}