#[macro_use] extern crate diesel; #[macro_use] extern crate diesel_migrations; #[macro_use] extern crate lazy_static; use std::env; use std::net::SocketAddr; use std::path::PathBuf; use actix_web::{middleware, App, HttpServer}; use anyhow::Result; use clap::{App as ClapApp, Arg}; use log::{info, warn}; use std::sync::{Arc, RwLock}; mod addressing; mod database; mod filesystem; mod hash; mod jobs; mod models; mod routes; mod schema; mod util; const VERSION: &str = env!("CARGO_PKG_VERSION"); fn main() -> Result<()> { let env = env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"); env_logger::init_from_env(env); let app = ClapApp::new("upend") .version(VERSION) .author("Tomáš Mládek ") .arg(Arg::with_name("DIRECTORY").required(true).index(1)) .arg( Arg::with_name("BIND") .long("bind") .default_value("127.0.0.1:8093") .help("address and port to bind the Web interface on") .required(true), ) .arg( Arg::with_name("NO_BROWSER") .long("no-browser") .help("Do not open web browser with the UI."), ) .arg( Arg::with_name("NO_INITIAL_UPDATE") .long("no-initial-update") .help("Don't run a database update on start."), ) .arg( Arg::with_name("REINITIALIZE") .long("reinitialize") .help("Delete and initialize database, if it exists already."), ) .arg( Arg::with_name("VAULT_NAME") .takes_value(true) .long("name") .help("Name of the vault."), ); let matches = app.get_matches(); info!("Starting UpEnd {}...", VERSION); let sys = actix::System::new("upend"); let job_container = Arc::new(RwLock::new(jobs::JobContainer::default())); let vault_path = PathBuf::from(matches.value_of("DIRECTORY").unwrap()); let open_result = database::open_upend(&vault_path, matches.is_present("REINITIALIZE")) .expect("failed to open database!"); let db_pool = open_result.pool; let bind: SocketAddr = matches .value_of("BIND") .unwrap() .parse() .expect("Incorrect bind format."); info!("Starting server at: {}", &bind); let state = routes::State { vault_name: matches.value_of("VAULT_NAME").map(|s| s.to_string()), directory: vault_path.clone(), db_pool: db_pool.clone(), job_container: job_container.clone(), }; // Start HTTP server HttpServer::new(move || { App::new() .data(state.clone()) .wrap(middleware::Logger::default().exclude("/api/jobs")) .service(routes::get_raw) .service(routes::get_query) .service(routes::get_object) .service(routes::put_object) .service(routes::delete_object) .service(routes::api_refresh) .service(routes::list_hier) .service(routes::latest_files) .service(routes::get_file) .service(routes::get_jobs) .service(routes::get_info) .service( actix_files::Files::new( "/", env::current_exe().unwrap().parent().unwrap().join("webui"), ) .index_file("index.html"), ) }) .bind(&bind)? .run(); if !matches.is_present("NO_INITIAL_UPDATE") { info!("Running initial update..."); actix::spawn(filesystem::rescan_vault(db_pool, vault_path, job_container)); } if !matches.is_present("NO_BROWSER") { let ui_result = webbrowser::open(&format!("http://localhost:{}", bind.port())); if ui_result.is_err() { warn!("Could not open UI in browser!"); } } Ok(sys.run()?) }