diff options
author | Teddy Wing | 2022-03-20 23:42:00 +0100 |
---|---|---|
committer | Teddy Wing | 2022-03-20 23:42:00 +0100 |
commit | b94637ae80ed4b6b2a725c3ff22e821233be0f33 (patch) | |
tree | 2262080a9bae11cabefc62e61ba1ddd283cf54fb | |
parent | d12125737b9068a653124c21cfc66b67c4b7704b (diff) | |
download | yaqlite-b94637ae80ed4b6b2a725c3ff22e821233be0f33.tar.bz2 |
main: Print errors to standard error instead of panicking with `unwrap`
Use `anyhow` to add context to errors and a `main()` wrapper that prints
error messages and their context to standard error.
-rw-r--r-- | Cargo.lock | 14 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/main.rs | 73 |
3 files changed, 77 insertions, 12 deletions
@@ -14,6 +14,12 @@ dependencies = [ ] [[package]] +name = "anyhow" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" + +[[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -60,6 +66,12 @@ dependencies = [ ] [[package]] +name = "exitcode" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193" + +[[package]] name = "fallible-iterator" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -314,7 +326,9 @@ dependencies = [ name = "yaqlite" version = "0.0.1" dependencies = [ + "anyhow", "clap", + "exitcode", "rusqlite", "thiserror", "yaml-rust-davvid", @@ -4,6 +4,8 @@ version = "0.0.1" edition = "2021" [dependencies] +anyhow = "1.0.56" +exitcode = "1.1.2" rusqlite = { version = "0.27.0", features = ["modern_sqlite"] } thiserror = "1.0.30" yaml-rust = { package = "yaml-rust-davvid", version = "0.5.1" } diff --git a/src/main.rs b/src/main.rs index 9a82d25..bb979b2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,6 +41,25 @@ enum Command { fn main() { + match run() { + Ok(_) => (), + Err(e) => { + eprint!("error"); + + for cause in e.chain() { + eprint!(": {}", cause); + } + + eprintln!(); + + std::process::exit(exitcode::SOFTWARE); + } + } +} + +fn run() -> anyhow::Result<()> { + use anyhow::Context; + let args = Args::parse(); match args.command { @@ -54,23 +73,37 @@ fn main() { None => "-", }; - let mut dbconn = rusqlite::Connection::open(database).unwrap(); + let mut dbconn = rusqlite::Connection::open(&database) + .with_context(|| + format!("can't connect to database '{}'", database) + )?; let mut text_data; if input_file == "-" { use std::io::Read; text_data = String::new(); - std::io::stdin().read_to_string(&mut text_data).unwrap(); + std::io::stdin().read_to_string(&mut text_data) + .context("can't read from stdin")?; } else { - text_data = std::fs::read_to_string(input_file).unwrap(); + text_data = std::fs::read_to_string(input_file) + .with_context(|| + format!("can't read from file '{}'", input_file), + )?; } - let mut yaml_data = yaml::YamlLoader::load_from_str(&text_data).unwrap(); + let mut yaml_data = yaml::YamlLoader::load_from_str(&text_data) + .context("can't parse YAML")?; - yaqlite::insert(&mut dbconn, &table_name, &mut yaml_data).unwrap(); + yaqlite::insert(&mut dbconn, &table_name, &mut yaml_data) + .context("failed to insert data")?; - dbconn.close().unwrap(); + dbconn.close() + .map_err(|e| { + let (_, err) = e; + err + }) + .context("failed to close database")?; }, Command::Select { @@ -85,7 +118,10 @@ fn main() { exclude_column = Some(Vec::new()); } - let dbconn = rusqlite::Connection::open(database).unwrap(); + let dbconn = rusqlite::Connection::open(&database) + .with_context(|| + format!("can't connect to database '{}'", database) + )?; let yaml_data = match primary_key { Some(pk) => yaqlite::select_by_column( @@ -94,14 +130,18 @@ fn main() { &pk, &record_id, exclude_column.as_deref(), - ).unwrap(), + ).with_context(|| + format!("can't select record '{}'", record_id), + )?, None => yaqlite::select( &dbconn, &table_name, &record_id, exclude_column.as_deref(), - ).unwrap(), + ).with_context(|| + format!("can't select record '{}'", record_id), + )?, }; let stdout = std::io::stdout(); @@ -109,15 +149,24 @@ fn main() { let mut buffer = yaqlite::yaml::IoAdapter::new(&mut stdout_handle); let mut emitter = yaml_rust::YamlEmitter::new(&mut buffer); emitter.multiline_strings(true); - emitter.dump(&yaml_data).unwrap(); + emitter.dump(&yaml_data) + .context("can't serialize YAML")?; // YamlEmitter doesn't output a trailing newline. { use std::io::Write; - writeln!(stdout_handle, "").unwrap(); + writeln!(stdout_handle, "") + .context("failed to write to stdout")?; } - dbconn.close().unwrap(); + dbconn.close() + .map_err(|e| { + let (_, err) = e; + err + }) + .context("failed to close database")?; }, }; + + Ok(()) } |