131 lines
4.1 KiB
Rust
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)
|
|
}
|
|
}
|
|
}
|