Better TOML parsing error message (#1332)

The error handling for config loading was pretty poor.
That's because we didn't use the correct syntax to show the entire context with `anhow`.
See ["Display representations"](https://docs.rs/anyhow/latest/anyhow/struct.Error.html#display-representations).
This commit is contained in:
Matthias Endler 2024-01-04 22:17:14 +01:00 committed by GitHub
parent f3ac86acbd
commit d3d0cd513d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 23 additions and 9 deletions

View file

@ -63,7 +63,7 @@ use std::io::{self, BufRead, BufReader, ErrorKind, Write};
use std::path::PathBuf;
use std::sync::Arc;
use anyhow::{Context, Error, Result};
use anyhow::{bail, Context, Error, Result};
use clap::Parser;
use color::YELLOW;
use commands::CommandParams;
@ -159,8 +159,10 @@ fn load_config() -> Result<LycheeOptions> {
match Config::load_from_file(config_file) {
Ok(c) => opts.config.merge(c),
Err(e) => {
error!("Error while loading config file {:?}: {}", config_file, e);
std::process::exit(ExitCode::ConfigFile as i32);
bail!(
"Cannot load configuration file `{}`: {e:?}",
config_file.display()
);
}
}
} else {
@ -253,7 +255,13 @@ fn load_cache(cfg: &Config) -> Option<Cache> {
fn run_main() -> Result<i32> {
use std::process::exit;
let opts = load_config()?;
let opts = match load_config() {
Ok(opts) => opts,
Err(e) => {
error!("Error while loading config: {e}");
exit(ExitCode::ConfigFile as i32);
}
};
let runtime = match opts.config.threads {
Some(threads) => {

View file

@ -408,8 +408,7 @@ impl Config {
pub(crate) fn load_from_file(path: &Path) -> Result<Config> {
// Read configuration file
let contents = fs::read_to_string(path)?;
toml::from_str(&contents)
.map_err(|err| anyhow::anyhow!("Failed to parse configuration file: {}", err))
toml::from_str(&contents).with_context(|| "Failed to parse configuration file")
}
/// Merge the configuration from TOML into the CLI configuration

View file

@ -12,7 +12,10 @@ mod cli {
use assert_json_diff::assert_json_include;
use http::StatusCode;
use lychee_lib::{InputSource, ResponseBody};
use predicates::str::{contains, is_empty};
use predicates::{
prelude::predicate,
str::{contains, is_empty},
};
use pretty_assertions::assert_eq;
use regex::Regex;
use serde::Serialize;
@ -602,7 +605,11 @@ mod cli {
.arg("-")
.env_clear()
.assert()
.failure();
.failure()
.stderr(predicate::str::contains("Cannot load configuration file"))
.stderr(predicate::str::contains("Failed to parse"))
.stderr(predicate::str::contains("TOML parse error"))
.stderr(predicate::str::contains("expected newline"));
}
#[tokio::test]

View file

@ -203,7 +203,7 @@ impl Input {
InputSource::FsPath(ref path) => {
if path.is_dir() {
for entry in WalkDir::new(path).skip_hidden(true)
.process_read_dir(move |_, _, _, children| {
.process_read_dir(move |_, _, (), children| {
children.retain(|child| {
let Ok(entry) = child.as_ref() else { return true };