use crate::repo::RepoGroupManager; use crate::{Config, Global}; use axum::extract::FromRef; use clap::Parser; use std::io; use std::path::PathBuf; use std::sync::{Arc, RwLock}; use tracing::debug; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; #[derive(Parser)] #[command(author, version, about, long_about = None)] pub struct Cli { /// Directory where package archives will be stored #[arg(env = "RIETER_PKG_DIR")] pub pkg_dir: PathBuf, /// Directory where repository metadata & SQLite database is stored #[arg(env = "RIETER_DATA_DIR")] pub data_dir: PathBuf, /// API key to authenticate private routes with #[arg(env = "RIETER_API_KEY")] pub api_key: String, /// Database connection URL; either sqlite:// or postgres://. Defaults to rieter.sqlite in the /// data directory #[arg(short, long, env = "RIETER_DATABASE_URL")] pub database_url: Option, /// Port the server will listen on #[arg( short, long, value_name = "PORT", default_value_t = 8000, env = "RIETER_PORT" )] pub port: u16, /// Log levels for the tracing #[arg( long, value_name = "LOG_LEVEL", default_value = "tower_http=debug,rieterd=debug", env = "RIETER_LOG" )] pub log: String, } impl FromRef for Arc> { fn from_ref(global: &Global) -> Self { Arc::clone(&global.repo_manager) } } impl Cli { pub fn init_tracing(&self) { tracing_subscriber::registry() .with(tracing_subscriber::EnvFilter::new(self.log.clone())) .with(tracing_subscriber::fmt::layer()) .init(); } pub async fn run(&self) -> crate::Result<()> { self.init_tracing(); let db_url = if let Some(url) = &self.database_url { url.clone() } else { format!( "sqlite://{}", self.data_dir.join("rieter.sqlite").to_string_lossy() ) }; debug!("Connecting to database with URL {}", db_url); let db = crate::db::RieterDb::connect(db_url).await?; // let db = crate::db::init("postgres://rieter:rieter@localhost:5432/rieter") // .await // .unwrap(); let config = Config { data_dir: self.data_dir.clone(), repo_dir: self.data_dir.join("repos"), pkg_dir: self.pkg_dir.clone(), api_key: self.api_key.clone(), }; let repo_manager = RepoGroupManager::new(&config.repo_dir, &self.pkg_dir); let global = Global { config, repo_manager: Arc::new(RwLock::new(repo_manager)), db, }; // build our application with a single route let app = crate::web::app(global, &self.api_key); Ok(crate::web::serve(app, self.port) .await .map_err(|err| io::Error::new(io::ErrorKind::Other, err))?) } }