use clap::{IntoApp, Parser, Subcommand};
use std::path::PathBuf;
mod common;
mod decrypt;
mod encrypt;
mod self_update;
mod updatekeys;
#[derive(Parser)]
#[clap(version, about, long_about = include_str!("../README.md"))]
struct Args {
#[clap(subcommand)]
command: Commands,
#[clap(short, long, global = true, parse(from_flag))]
verbose: bool,
#[clap(long, global = true, default_value = "sops")]
sops_binary: String,
}
#[derive(Subcommand)]
enum Commands {
Decrypt {
#[clap(short, long, env)]
files_config: PathBuf,
#[clap(long, parse(from_flag), env)]
allow_decryption_fail: bool,
},
Encrypt {
#[clap(short, long, env)]
files_config: PathBuf,
},
UpdateKeys {
#[clap(short, long, env)]
files_config: PathBuf,
},
Completions {
#[clap(arg_enum)]
shell: clap_complete_command::Shell,
},
SelfUpdate {},
}
fn main() {
let args = Args::parse();
let sops_bin = match common::find_sops(args.sops_binary.as_str()) {
Ok(b) => Some(b),
Err(err) => {
eprintln!("{}", err);
None
}
};
let result = match &args.command {
Commands::Decrypt {
files_config,
allow_decryption_fail,
} => {
if sops_bin.is_none() {
std::process::exit(exitcode::UNAVAILABLE);
}
if args.verbose {
eprintln!(
"Decrypt command called, files cfg path {:?}, allow decrypt fail {:?}",
files_config, allow_decryption_fail
);
}
decrypt::decrypt(
files_config.as_path(),
sops_bin.unwrap().as_path(),
*allow_decryption_fail,
args.verbose,
)
}
Commands::Encrypt { files_config } => {
if sops_bin.is_none() {
std::process::exit(exitcode::UNAVAILABLE);
}
if args.verbose {
eprintln!("Encrypt command called, files cfg path {:?}", files_config);
}
encrypt::encrypt(
files_config.as_path(),
sops_bin.unwrap().as_path(),
args.verbose,
)
}
Commands::UpdateKeys { files_config } => {
if sops_bin.is_none() {
std::process::exit(exitcode::UNAVAILABLE);
}
if args.verbose {
eprintln!(
"Update keys command called, files cfg path {:?}",
files_config
);
}
updatekeys::update_keys(
files_config.as_path(),
sops_bin.unwrap().as_path(),
args.verbose,
)
}
Commands::Completions { shell } => {
shell.generate(&mut Args::command(), &mut std::io::stdout());
if args.verbose {
eprintln!("shell completions generated");
};
Ok(())
}
Commands::SelfUpdate {} => match self_update::self_update() {
Ok(ok) => {
eprintln!("{}", ok);
Ok(())
}
Err(err) => Err(err.to_string()),
},
};
match result {
Ok(_) => {}
Err(err) => {
eprintln!("Command failed: {}", err);
std::process::exit(exitcode::TEMPFAIL);
}
};
}