mod actors; mod config; use actix::prelude::*; use std::path::PathBuf; use tracing::{error, info}; use crate::{ filesystem::FileSystem, server::config::{ForgeName, RepoName}, }; pub fn init(fs: FileSystem) { let file_name = "git-next-server.toml"; let path = PathBuf::from(file_name); if fs.file_exists(&path) { eprintln!( "The configuration file already exists at {} - not overwritting it.", file_name ); } else { match fs.write_file(file_name, include_str!("../../server-default.toml")) { Ok(_) => println!("Created a default configuration file at {}", file_name), Err(e) => { eprintln!("Failed to write to the configuration file: {}", e) } } } } pub fn start(fs: FileSystem) { let Ok(_) = init_logging() else { eprintln!("Failed to initialize logging."); return; }; info!("Starting Server..."); let config = match config::ServerConfig::load(&fs) { Ok(config) => config, Err(err) => { error!("Failed to load config file. Error: {}", err); return; } }; info!("Config loaded"); info!("Loaded config"); let mut actors: Vec<(ForgeName, RepoName, actors::repo::RepoActor)> = vec![]; config.forges().for_each(|(forge_name, forge)| { let span = tracing::info_span!("Forge", %forge_name); let _guard = span.enter(); info!("Forge: {}", forge_name); info!("Forge Type: {}", forge.forge_type()); info!("Hostname: {}", forge.hostname()); info!("User: {}", forge.user()); forge.repos().for_each(|(repo_name, repo)| { let span = tracing::info_span!("Repo", %repo_name, %repo); let _guard = span.enter(); info!("Creating Repo"); let actor = actors::repo::RepoActor { details: config::RepoDetails::new(&repo_name, repo, &forge_name, forge), }; actors.push((forge_name.clone(), repo_name, actor)); info!("Created Repo"); }); }); info!("Sending StartRepo to all actors..."); actix::System::new().block_on(async { let mut addresses: Vec> = vec![]; actors.into_iter().for_each(|actor| { let (forge_name, repo_name, actor) = actor; let span = tracing::info_span!("Forge/Repo", %forge_name, %repo_name); let _guard = span.enter(); info!("Starting actor"); let addr = actor.start(); info!("Sending StartRepo to actor"); addr.do_send(actors::repo::StartRepo); addresses.push(addr); info!("Sent StartRepo to actor"); }); let _ = actix_rt::signal::ctrl_c().await; info!("Ctrl-C received, shutting down..."); drop(addresses); }); } pub fn init_logging() -> Result<(), tracing::subscriber::SetGlobalDefaultError> { use tracing_subscriber::prelude::*; let console_layer = console_subscriber::ConsoleLayer::builder().spawn(); let subscriber = tracing_subscriber::fmt::layer() // NOTE: set RUSTLOG in ${root}/.cargo/config .with_target(false) .with_file(true) .with_line_number(true); tracing_subscriber::registry() .with(console_layer) .with(subscriber) .init(); Ok(()) }