From 26959c6a04235669ff4979f0549e6c967ceab3d0 Mon Sep 17 00:00:00 2001 From: Brian M Date: Mon, 1 May 2023 20:04:03 -0700 Subject: [PATCH] better cli --- src/main.rs | 62 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/src/main.rs b/src/main.rs index 966f553..6fd90f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,46 +1,70 @@ use anyhow::{bail, Context, Result}; -use sources::Source; +use std::env::args; use std::fs::File; use std::io::{BufRead, BufReader}; use crate::sinks::strongbox_csv::Strongbox; -use crate::sinks::Sink; use crate::sources::enpass_json::EnpassJson; +use sinks::Sink; +use sources::Source; mod sinks; mod sources; mod universal; fn main() -> Result<()> { - let reader: Box = match std::env::args().nth(1).as_deref() { - Some("-") => Box::new(BufReader::new(std::io::stdin())), - Some(filename) => Box::new(BufReader::new( - File::open(filename).with_context(|| format!("Unable to read {filename}"))?, - )), - None => { - bail!("Export .json from your password manager and provide the path to the file as an argument, or \"-\" to read from stdin."); + let mut args = args(); + let invocation = args.next().unwrap(); + let (source_name, source_reader, sink_name, sink_destination) = match ( + args.next(), + args.next(), + args.next().as_deref(), + args.next(), + args.next(), + ) { + (Some(source_name), Some(source_path), Some("to"), Some(sink_name), Some(sink_path)) => { + let source_reader: Box = if source_name == "stdin" { + Box::new(BufReader::new(std::io::stdin())) + } else { + Box::new(BufReader::new( + File::open(&source_path) + .with_context(|| format!("Unable to read {source_path}"))?, + )) + }; + + let sink_destination = File::options() + .write(true) + .truncate(true) + .create(true) + .open(&sink_path) + .with_context(|| format!("Unable to open {sink_path}"))?; + + (source_name, source_reader, sink_name, sink_destination) + } + _ => { + println!("Usage: {invocation} enpass SOURCE_FILE to strongbox OUTPUT_FILE"); + println!("Sample usage: {invocation} enpass ./export.json to strongbox ./out.csv"); + return Ok(()); } }; - let source_name = "enpass"; - let source: Box = match source_name { - "enpass" => Box::new(EnpassJson::from_reader(reader)?), + let source: Box = match source_name.as_str() { + "enpass" => Box::new( + EnpassJson::from_reader(source_reader) + .with_context(|| format!("Unable to parse the enpass .json export"))?, + ), _ => bail!("Unsupported source name"), }; - let sink_path = "./output.csv"; - let sink_destination = - File::open(sink_path).with_context(|| format!("Unable to open {sink_path}"))?; - let sink_name = "strongbox"; - let mut sink: Box = match sink_name { + let mut sink: Box = match sink_name.as_str() { "strongbox" => Box::new(Strongbox::with_output(sink_destination)), _ => bail!("Unsupported target name"), }; sink.convert_from_source(source) - .with_context(|| format!("Conversion from {source_name} to {sink_name}"))?; + .with_context(|| format!("Unable to convert to {sink_name}"))?; - println!("Saved to output.csv"); + println!("Conversion successful!"); Ok(()) }