#![deny(warnings)]
#[macro_use]
extern crate tracing;
use std::{io, process::exit};
use anyhow::Result;
use clap::{crate_name, crate_version, ArgAction, CommandFactory, Parser};
use clap_complete::Shell;
use garbage::ops::{
self, EmptyOptions, ListOptions, PutOptions, RestoreOptions,
};
use garbage_fs::{stdfs::StdFilesystem, Filesystem};
use tracing::level_filters::LevelFilter;
#[derive(Parser)]
#[clap(about, version = concat!(crate_version!(), "-", env!("GARBAGE_VERSION")), author)]
struct Opt {
#[clap(subcommand)]
command: Command,
#[clap(global = true, short = 'v', long = "verbose", action = ArgAction::Count)]
verbose: u8,
#[clap(global = true, short = 'q', long = "quiet")]
quiet: bool,
}
#[derive(Parser)]
enum Command {
#[clap(name = "empty")]
Empty(EmptyOptions),
#[clap(name = "list")]
List(ListOptions),
#[clap(name = "put", alias = "rm")]
Put(PutOptions),
#[clap(name = "restore")]
Restore(RestoreOptions),
#[clap(name = "generate-completions")]
Complete {
#[clap(required = true, value_name = "SHELL_TYPE")]
shell_type: Shell,
},
}
fn run(cmd: Command, fs: &impl Filesystem) -> Result<()> {
match cmd {
Command::Empty(options) => ops::empty(options, fs),
Command::List(options) => ops::list(options, fs),
Command::Put(options) => ops::put(options, fs),
Command::Restore(options) => ops::restore(options, fs),
Command::Complete { shell_type } => {
clap_complete::generate(
shell_type,
&mut Command::command(),
crate_name!(),
&mut std::io::stdout(),
);
Ok(())
}
}
}
fn convert_verbosity(opt: &Opt) -> LevelFilter {
if opt.quiet {
return LevelFilter::OFF;
}
match opt.verbose {
0 => LevelFilter::WARN,
1 => LevelFilter::INFO,
2 => LevelFilter::DEBUG,
_ => LevelFilter::TRACE,
}
}
fn main() -> Result<()> {
let fs = StdFilesystem::default();
let opt = Opt::parse();
let fmt = tracing_subscriber::fmt()
.with_ansi(atty::is(atty::Stream::Stderr))
.with_max_level(convert_verbosity(&opt))
.with_writer(io::stderr);
if opt.verbose < 2 {
fmt
.without_time()
.with_file(false)
.with_target(false)
.init();
} else {
fmt.init();
}
match run(opt.command, &fs) {
Ok(_) => Ok(()),
Err(err) => {
debug!("{}", err);
debug!("{:?}", err);
debug!("{}", err.backtrace());
exit(1);
}
}
}