From 60a8d74bc52d3950abde7caaf2ad28d398a33abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Such=C3=A1nek?= Date: Fri, 4 Feb 2022 18:11:14 +0100 Subject: [PATCH] Use color_eyre for handling errors more systematically --- Cargo.lock | 109 ++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 + src/logging.rs | 7 ++- src/main.rs | 13 +++--- src/validation.rs | 20 ++++----- src/write.rs | 33 +++++++------- 6 files changed, 149 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 22e53c0..25c588d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aho-corasick" version = "0.7.18" @@ -74,12 +89,33 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "backtrace" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "cc" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" + [[package]] name = "cfg-if" version = "1.0.0" @@ -115,6 +151,35 @@ dependencies = [ "textwrap", ] +[[package]] +name = "color-eyre" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6ec7641ff3474b7593009c809db602c414cd97c7d47a78ed004162b74ff96c" +dependencies = [ + "backtrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", +] + +[[package]] +name = "eyre" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc225d8f637923fe585089fcf03e705c222131232d2c1fb622e84ecf725d0eb8" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" + [[package]] name = "hashbrown" version = "0.11.2" @@ -136,6 +201,12 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + [[package]] name = "indexmap" version = "1.8.0" @@ -179,12 +250,23 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + [[package]] name = "newdoc" version = "2.9.5" dependencies = [ "askama", "clap", + "color-eyre", "log", "regex", "simplelog", @@ -220,6 +302,21 @@ dependencies = [ "autocfg", ] +[[package]] +name = "object" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + [[package]] name = "os_str_bytes" version = "6.0.0" @@ -229,6 +326,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "owo-colors" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20448fd678ec04e6ea15bbe0476874af65e98a01515d667aa49f1434dc44ebf4" + [[package]] name = "percent-encoding" version = "2.1.0" @@ -270,6 +373,12 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + [[package]] name = "serde" version = "1.0.134" diff --git a/Cargo.toml b/Cargo.toml index 6dda612..371216c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,8 @@ regex = "1" log = "0.4" simplelog = "0.11" askama = "0.11" +# Disable support for tracing_error and SpanTrace in eyre +color-eyre = { version = "0.6", default-features = false } [package.metadata.rpm.cargo] diff --git a/src/logging.rs b/src/logging.rs index bdc6708..2d68ec4 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -1,8 +1,9 @@ +use color_eyre::eyre::{Context, Result}; use simplelog::{ColorChoice, ConfigBuilder, LevelFilter, TermLogger, TerminalMode}; /// This function initializes the `simplelog` logging system, which plugs into the `log` /// infrastructure. The function returns nothing. It only affects the global state when it runs. -pub fn initialize_logger(verbose: bool, quiet: bool) { +pub fn initialize_logger(verbose: bool, quiet: bool) -> Result<()> { // Set the verbosity level based on the command-line options. // Our `clap` configuration ensures that `verbose` and `quiet` can never be both true. let verbosity = if verbose { @@ -31,5 +32,7 @@ pub fn initialize_logger(verbose: bool, quiet: bool) { // Try to use color if possible. ColorChoice::Auto, ) - .expect("Failed to configure the terminal logging."); + .context("Failed to configure the terminal logging.")?; + + Ok(()) } diff --git a/src/main.rs b/src/main.rs index 6a0bfed..69f0f5e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use color_eyre::eyre::Result; use log::{debug, info}; mod cmd_line; @@ -20,14 +21,14 @@ pub struct Options { detect_directory: bool, } -fn main() { +fn main() -> Result<()> { // Parse the command-line options let cmdline_args = cmd_line::get_args(); // Determine the configured verbosity level let verbose = cmdline_args.is_present("verbose"); let quiet = cmdline_args.is_present("quiet"); // Initialize the logging system based on the set verbosity - logging::initialize_logger(verbose, quiet); + logging::initialize_logger(verbose, quiet)?; if cmdline_args.is_present("detect-directory") { info!("The `--detect-directory` (`-D`) option is now enabled by default."); @@ -74,7 +75,7 @@ fn main() { // Write all non-populated modules to the disk for module in &non_populated { - module.write_file(&options); + module.write_file(&options)?; } // Treat the populated assembly module as a special case: @@ -96,15 +97,17 @@ fn main() { .include(include_statements) .into(); - populated.write_file(&options); + populated.write_file(&options)?; } // Validate all file names specified on the command line if let Some(files_iterator) = cmdline_args.values_of("validate") { for file in files_iterator { - validation::validate(file); + validation::validate(file)?; } } + + Ok(()) } /// Process all titles that have been specified on the command line and that belong to a single diff --git a/src/validation.rs b/src/validation.rs index 0c4cb8f..4a5a085 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -1,11 +1,13 @@ -use log::{debug, error}; -use regex::{Regex, RegexBuilder}; /// This module provides functionality to validate (lint) existing module and assembly files, /// to check if the files meet the template structure and other requirements. use std::fmt; use std::fs; use std::path::Path; +use color_eyre::eyre::{Context, Result}; +use log::debug; +use regex::{Regex, RegexBuilder}; + use crate::module::ModuleType; #[derive(Clone, Copy, Debug)] @@ -96,20 +98,14 @@ impl fmt::Display for IssueReport { /// The main validation function. Checks all possible issues in a single file, loaded from a file name. /// Prints the issues to the standard output. -pub fn validate(file_name: &str) { +pub fn validate(file_name: &str) -> Result<()> { debug!("Validating file `{}`", file_name); let path = Path::new(file_name); let base_name = path.file_name().unwrap().to_str().unwrap(); - let read_result = fs::read_to_string(path); - let content = match read_result { - Ok(content) => content, - Err(err) => { - error!("Error reading file `{}`: {}", file_name, err); - return; - } - }; + let content = + fs::read_to_string(path).context(format!("Error reading file `{}`.", file_name))?; let mod_type = determine_mod_type(base_name, &content); @@ -127,6 +123,8 @@ pub fn validate(file_name: &str) { }; report_issues(reports, file_name); + + Ok(()) } /// Print a sorted, human-readable report about the issues found in the file diff --git a/src/write.rs b/src/write.rs index 88ff719..1518fc3 100644 --- a/src/write.rs +++ b/src/write.rs @@ -2,14 +2,15 @@ use std::fs; use std::io; use std::path::PathBuf; -use log::{debug, error, info, warn}; +use color_eyre::eyre::{Context, Result}; +use log::{debug, info, warn}; use crate::module::Module; use crate::Options; impl Module { /// Write the generated module content to the path specified in `options` with the set file name. - pub fn write_file(&self, options: &Options) { + pub fn write_file(&self, options: &Options) -> Result<()> { // Compose the full (but still relative) file path from the target directory and the file name let full_path_buf: PathBuf = [&options.target_dir, &self.file_name].iter().collect(); let full_path = full_path_buf.as_path(); @@ -26,7 +27,7 @@ impl Module { io::stdin() .read_line(&mut answer) - .expect("Failed to read your response"); + .context("Failed to read your response")?; match answer.trim().to_lowercase().as_str() { "y" | "yes" => { @@ -36,24 +37,22 @@ impl Module { info!("→ Preserving the existing file."); // Break from generating this particular module. // Other modules that might be in the queue will be generated on next iteration. - return; + return Ok(()); } }; } // If the target file doesn't exist, try to write to it - let result = fs::write(full_path, &self.text); - match result { - // If the write succeeds, print the include statement - Ok(()) => { - debug!("Successfully written file `{}`", &full_path.display()); - info!("‣ File generated: {}", full_path.display()); - info!(" {}", self.include_statement); - } - // If the write fails, print why it failed - Err(e) => { - error!("Failed to write the `{}` file: {}", &full_path.display(), e); - } - } + fs::write(full_path, &self.text).context(format!( + "Failed to write the `{}` file.", + &full_path.display() + ))?; + + // If the write succeeds, print the include statement + debug!("Successfully written file `{}`", &full_path.display()); + info!("‣ File generated: {}", full_path.display()); + info!(" {}", self.include_statement); + + Ok(()) } }