Skip to content

Commit

Permalink
Use color_eyre for handling errors more systematically
Browse files Browse the repository at this point in the history
  • Loading branch information
msuchane committed Feb 4, 2022
1 parent d051f2b commit 60a8d74
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 35 deletions.
109 changes: 109 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
7 changes: 5 additions & 2 deletions src/logging.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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(())
}
13 changes: 8 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use color_eyre::eyre::Result;
use log::{debug, info};

mod cmd_line;
Expand All @@ -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.");
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand Down
20 changes: 9 additions & 11 deletions src/validation.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down Expand Up @@ -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);

Expand All @@ -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
Expand Down
33 changes: 16 additions & 17 deletions src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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" => {
Expand All @@ -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(())
}
}

0 comments on commit 60a8d74

Please sign in to comment.