use std::{fs::File, io::BufReader, path::PathBuf}; use clap::{Parser, Subcommand}; use talon::{Result, Talon}; #[derive(Parser)] #[clap(author, version, about)] struct Cli { #[clap(subcommand)] command: Commands, #[clap(short, long, value_parser, default_value = ".", global = true)] directory: PathBuf, } #[derive(Subcommand)] enum Commands { /// Run the Talon server Run, /// Export the database in ndjson format (prints to stdout) Export, /// Import a ndjson-formatted file into the database Import { #[clap(value_parser)] file: Option, }, /// Delete unreferenced files from the storage Purge, /// Show statistics about your Talon instance Stats, /// Print build info Info, /// Print version Version, } #[tokio::main] async fn main() -> Result<()> { if std::env::var_os("RUST_LOG").is_none() { std::env::set_var("RUST_LOG", "info"); } tracing_subscriber::fmt::init(); let cli = Cli::parse(); let new_tln = || Talon::new(cli.directory); match cli.command { Commands::Run => { let talon = new_tln()?; talon.launch().await?; } Commands::Export => { let talon = new_tln()?; let stdout = std::io::stdout().lock(); talon.db.export(stdout)?; } Commands::Import { file } => { let talon = new_tln()?; match file { Some(file) => { let reader = BufReader::new(File::open(file)?); talon.db.import(reader)?; } None => { let stdin = std::io::stdin().lock(); talon.db.import(stdin)?; } } } Commands::Purge => { let talon = new_tln()?; let (n, bytes) = talon.storage.purge()?; println!("{n} files purged, {bytes} bytes freed"); } Commands::Stats => { let talon = new_tln()?; let stats = talon.storage.stats()?; println!("Websites: {}", stats.n_websites); println!("Files: {}", stats.n_files); println!("Storage used: {} bytes", stats.storage_used); } Commands::Info => talon::build::print_build_in(), Commands::Version => println!("{}", talon::build::PKG_VERSION), } Ok(()) }