// use actix::prelude::*; use derive_more::Constructor; use std::{ collections::HashMap, net::SocketAddr, path::{Path, PathBuf}, str::FromStr, }; use kxio::fs::FileSystem; use tracing::info; use crate::{ForgeAlias, ForgeConfig, RepoAlias}; #[derive(Debug, thiserror::Error)] pub enum Error { #[error("fs: {0}")] KxioFs(#[from] kxio::fs::Error), #[error("deserialise toml: {0}")] TomlDe(#[from] toml::de::Error), #[error("parse IP addres/port: {0}")] AddressParse(#[from] std::net::AddrParseError), } type Result = core::result::Result; /// Mapped from the `git-next-server.toml` file #[derive(Debug, PartialEq, Eq, serde::Deserialize, Message, derive_more::Constructor)] #[rtype(result = "()")] pub struct ServerConfig { http: Http, webhook: Webhook, storage: ServerStorage, pub forge: HashMap, } impl ServerConfig { #[tracing::instrument(skip_all)] pub fn load(fs: &FileSystem) -> Result { let file = fs.base().join("git-next-server.toml"); info!(?file, ""); let str = fs.file_read_to_string(&file)?; Ok(toml::from_str(&str)?) } pub fn forges(&self) -> impl Iterator { self.forge .iter() .map(|(alias, forge)| (ForgeAlias::new(alias.clone()), forge)) } pub const fn storage(&self) -> &ServerStorage { &self.storage } pub const fn webhook(&self) -> &Webhook { &self.webhook } pub fn http(&self) -> Result { self.http.socket_addr() } } /// Defines the port the server will listen to for incoming webhooks messages #[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, derive_more::Constructor)] pub struct Http { addr: String, port: u16, } impl Http { fn socket_addr(&self) -> Result { Ok(SocketAddr::from_str(&format!( "{}:{}", self.addr, self.port ))?) } } /// Defines the Webhook Forges should send updates to /// Must be an address that is accessible from the remote forge #[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, derive_more::Constructor)] pub struct Webhook { url: String, } impl Webhook { pub fn url(&self, forge_alias: &ForgeAlias, repo_alias: &RepoAlias) -> WebhookUrl { let base_url = &self.url; WebhookUrl(format!("{base_url}/{forge_alias}/{repo_alias}")) } pub fn base_url(&self) -> &str { &self.url } } /// The URL for the webhook where forges should send their updates #[derive( Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, derive_more::AsRef, Constructor, )] pub struct WebhookUrl(String); /// The directory to store server data, such as cloned repos #[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, derive_more::Constructor)] pub struct ServerStorage { path: PathBuf, } impl ServerStorage { pub fn path(&self) -> &Path { self.path.as_path() } }