Files
RuDS/crates/bds-cli/src/main.rs

131 lines
4.1 KiB
Rust

use std::io::{IsTerminal as _, Read as _};
use std::process::ExitCode;
use std::sync::{Arc, Mutex};
use clap::Parser;
fn main() -> ExitCode {
let cli = match bds_cli::Cli::try_parse() {
Ok(cli) => cli,
Err(error) => {
let success = matches!(
error.kind(),
clap::error::ErrorKind::DisplayHelp | clap::error::ErrorKind::DisplayVersion
);
let _ = error.print();
return if success {
ExitCode::SUCCESS
} else {
ExitCode::from(1)
};
}
};
if let bds_cli::Command::Server(args) = &cli.command {
let data_root = args
.data_dir
.clone()
.unwrap_or_else(bds_core::util::application_data_dir);
let database_path = args
.database
.clone()
.unwrap_or_else(|| data_root.join("bds.db"));
let config = match bds_server::ServerConfig::from_environment(database_path, data_root) {
Ok(mut config) => {
if let Some(bind) = args.bind {
config.bind = bind;
}
if let Some(port) = args.port {
config.port = port;
}
config
}
Err(error) => {
eprintln!("Error: {error:#}");
return ExitCode::from(1);
}
};
return run_headless(bds_server::boot::BootMode::Server, config);
}
if matches!(cli.command, bds_cli::Command::Tui) {
let data_root = bds_core::util::application_data_dir();
let config = match bds_server::ServerConfig::from_environment(
bds_core::util::application_database_path(),
data_root,
) {
Ok(config) => config,
Err(error) => {
eprintln!("Error: {error:#}");
return ExitCode::from(1);
}
};
return run_headless(bds_server::boot::BootMode::Tui, config);
}
let json = cli.json;
let needs_stdin = match &cli.command {
bds_cli::Command::Post(args) => args.stdin,
bds_cli::Command::Gallery(args) => args.post.stdin,
_ => false,
};
let mut context = bds_cli::RunContext::system();
if needs_stdin && let Err(error) = std::io::stdin().read_to_string(&mut context.stdin) {
eprintln!("Error: could not read stdin: {error}");
return ExitCode::from(1);
}
let progress = (!json).then(|| {
Arc::new(Mutex::new(bds_cli::HumanProgress::new(
std::io::stdout().is_terminal(),
)))
});
let sink = progress.as_ref().map(|progress| {
let progress = Arc::clone(progress);
Arc::new(move |update: bds_cli::CliProgress| {
let _ = progress
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner())
.write(&update, std::io::stdout().lock());
}) as bds_cli::ProgressSink
});
let result = bds_cli::run_with_progress(cli, context, sink);
if let Some(progress) = &progress {
let _ = progress
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner())
.finish(std::io::stdout().lock());
}
match result {
Ok(mut output) => {
if !json {
output.progress.clear();
}
println!("{output}");
ExitCode::SUCCESS
}
Err(error) => {
if json {
eprintln!(
"{}",
serde_json::json!({"ok": false, "error": format!("{error:#}")})
);
} else {
eprintln!("Error: {error:#}");
}
ExitCode::from(1)
}
}
}
fn run_headless(mode: bds_server::boot::BootMode, config: bds_server::ServerConfig) -> ExitCode {
match bds_server::run_headless(mode, config) {
Ok(()) => ExitCode::SUCCESS,
Err(error) => {
eprintln!("Error: {error:#}");
ExitCode::from(1)
}
}
}