use clap::{Args, Parser, Subcommand};
use rvaultlib::{decrypt::decrypt, edit::edit, encrypt::encrypt};
#[derive(Parser)]
#[command(name = "rvault", version)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Args)]
struct CommonArgs {
#[arg(short, long, required = true)]
input: String,
#[arg(short, long)]
output: Option<String>,
#[arg(short, long, required = true)]
password: String,
#[arg(short = 'k', long, value_delimiter = ',')]
key: Vec<String>,
#[arg(long)]
overwrite: bool,
#[arg(long)]
stdout: bool,
}
#[derive(Subcommand)]
enum Commands {
Encrypt {
#[command(flatten)]
common: CommonArgs,
#[arg(long)]
ansible: bool,
},
Decrypt {
#[command(flatten)]
common: CommonArgs,
},
Edit {
#[command(flatten)]
common: CommonArgs,
#[arg(short = 'a', long)]
interactive: bool,
},
}
fn resolve_output(
input: &str,
output: Option<&str>,
overwrite: bool,
stdout: bool,
) -> Option<String> {
match output {
Some(o) => Some(o.to_string()),
None if overwrite => Some(input.to_string()),
None if stdout => Some("stdout".to_string()),
None => {
eprintln!("No output file, --overwrite flag or --stdout given, cancel.");
None
}
}
}
fn main() {
let cli = Cli::parse();
match cli.command {
Commands::Encrypt {
common,
ansible: _,
} => {
let Some(output) = resolve_output(
&common.input,
common.output.as_deref(),
common.overwrite,
common.stdout,
) else {
std::process::exit(1);
};
if let Err(e) = encrypt(&common.input, &output, &common.password, &common.key) {
eprintln!("error: {e}");
std::process::exit(1);
}
}
Commands::Decrypt { common } => {
let Some(output) = resolve_output(
&common.input,
common.output.as_deref(),
common.overwrite,
common.stdout,
) else {
std::process::exit(1);
};
if let Err(e) = decrypt(&common.input, &output, &common.password, &common.key) {
eprintln!("error: {e}");
std::process::exit(1);
}
}
Commands::Edit {
common,
interactive,
} => {
if common.key.is_empty() && !interactive {
eprintln!("No keys given. Use --key to specify keys or -a/--interactive to edit all encrypted values.");
std::process::exit(1);
}
let Some(output) = resolve_output(
&common.input,
common.output.as_deref(),
common.overwrite,
common.stdout,
) else {
std::process::exit(1);
};
if let Err(e) = edit(&common.input, &output, &common.password, &common.key) {
eprintln!("error: {e}");
std::process::exit(1);
}
}
}
}