From 588ff32d182e3ad4862518d85da5aa5f808188f9 Mon Sep 17 00:00:00 2001 From: Keith Hall Date: Sat, 27 Sep 2025 23:33:10 +0300 Subject: [PATCH 1/3] Fix help/version/diagnostic commands with invalid config --- src/bin/bat/app.rs | 18 +++++++-- tests/integration_tests.rs | 75 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs index b3d48cba..c784eabf 100644 --- a/src/bin/bat/app.rs +++ b/src/bin/bat/app.rs @@ -57,15 +57,27 @@ impl App { } fn matches(interactive_output: bool) -> Result { + // Check if we should skip config file processing for special arguments + // that don't require full application setup (help, version, diagnostic) + let should_skip_config = wild::args_os().any(|arg| { + matches!(arg.to_str(), Some("-h" | "--help" | "-V" | "--version" | "--diagnostic" | "--diagnostics")) + }); + let args = if wild::args_os().nth(1) == Some("cache".into()) { // Skip the config file and env vars wild::args_os().collect::>() - } else if wild::args_os().any(|arg| arg == "--no-config") { - // Skip the arguments in bats config file + } else if wild::args_os().any(|arg| arg == "--no-config") || should_skip_config { + // Skip the arguments in bats config file when --no-config is present + // or when user requests help, version, or diagnostic information let mut cli_args = wild::args_os(); - let mut args = get_args_from_env_vars(); + let mut args = if should_skip_config { + // For special commands, don't even try to load env vars that might fail + vec![] + } else { + get_args_from_env_vars() + }; // Put the zero-th CLI argument (program name) first args.insert(0, cli_args.next().unwrap()); diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index f0ebef12..6b9d7263 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -1286,6 +1286,81 @@ fn diagnostic_sanity_check() { .stderr(""); } +#[test] +fn help_works_with_invalid_config() { + let tmp_dir = tempdir().expect("can create temporary directory"); + let tmp_config_path = tmp_dir.path().join("invalid-config.conf"); + + // Write an invalid config file + std::fs::write(&tmp_config_path, "--invalid-option").expect("can write config file"); + + // --help should work despite invalid config + bat_with_config() + .env("BAT_CONFIG_PATH", tmp_config_path.to_str().unwrap()) + .arg("--help") + .assert() + .success() + .stdout(predicate::str::contains("A cat(1) clone with syntax highlighting")); + + // -h should also work + bat_with_config() + .env("BAT_CONFIG_PATH", tmp_config_path.to_str().unwrap()) + .arg("-h") + .assert() + .success() + .stdout(predicate::str::contains("A cat(1) clone with wings")); +} + +#[test] +fn version_works_with_invalid_config() { + let tmp_dir = tempdir().expect("can create temporary directory"); + let tmp_config_path = tmp_dir.path().join("invalid-config.conf"); + + // Write an invalid config file + std::fs::write(&tmp_config_path, "--invalid-option").expect("can write config file"); + + // --version should work despite invalid config + bat_with_config() + .env("BAT_CONFIG_PATH", tmp_config_path.to_str().unwrap()) + .arg("--version") + .assert() + .success() + .stdout(predicate::str::contains("bat ")); + + // -V should also work + bat_with_config() + .env("BAT_CONFIG_PATH", tmp_config_path.to_str().unwrap()) + .arg("-V") + .assert() + .success() + .stdout(predicate::str::contains("bat ")); +} + +#[test] +fn diagnostic_works_with_invalid_config() { + let tmp_dir = tempdir().expect("can create temporary directory"); + let tmp_config_path = tmp_dir.path().join("invalid-config.conf"); + + // Write an invalid config file + std::fs::write(&tmp_config_path, "--invalid-option").expect("can write config file"); + + // --diagnostic should work despite invalid config + bat_with_config() + .env("BAT_CONFIG_PATH", tmp_config_path.to_str().unwrap()) + .arg("--diagnostic") + .assert() + .success() + .stdout(predicate::str::contains("#### Software version")); + + // --diagnostics (alias) should also work + bat_with_config() + .env("BAT_CONFIG_PATH", tmp_config_path.to_str().unwrap()) + .arg("--diagnostics") + .assert() + .success() + .stdout(predicate::str::contains("#### Software version")); +} + #[test] fn config_location_test() { bat_with_config() From 2badaf5d9988dff29f1e50943dd12c25e2ac54c4 Mon Sep 17 00:00:00 2001 From: Keith Hall Date: Sat, 27 Sep 2025 23:54:52 +0300 Subject: [PATCH 2/3] cargo fmt --- src/bin/bat/app.rs | 5 ++++- tests/integration_tests.rs | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs index c784eabf..a8e1e0db 100644 --- a/src/bin/bat/app.rs +++ b/src/bin/bat/app.rs @@ -60,7 +60,10 @@ impl App { // Check if we should skip config file processing for special arguments // that don't require full application setup (help, version, diagnostic) let should_skip_config = wild::args_os().any(|arg| { - matches!(arg.to_str(), Some("-h" | "--help" | "-V" | "--version" | "--diagnostic" | "--diagnostics")) + matches!( + arg.to_str(), + Some("-h" | "--help" | "-V" | "--version" | "--diagnostic" | "--diagnostics") + ) }); let args = if wild::args_os().nth(1) == Some("cache".into()) { diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 6b9d7263..75021eb5 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -1300,7 +1300,9 @@ fn help_works_with_invalid_config() { .arg("--help") .assert() .success() - .stdout(predicate::str::contains("A cat(1) clone with syntax highlighting")); + .stdout(predicate::str::contains( + "A cat(1) clone with syntax highlighting", + )); // -h should also work bat_with_config() From 98b75db115303ddcbe39c443479abe7c4ba1b3b3 Mon Sep 17 00:00:00 2001 From: Keith Hall Date: Wed, 8 Oct 2025 22:45:35 +0300 Subject: [PATCH 3/3] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2c6d0fb..eda003b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - Correctly determine the end of the line in UTF16LE/BE input #3369 (@keith-hall) - `--style=changes` no longer prints a two-space indent when the file is unmodified, see issue #2710 and PR #3406 (@jyn514) - Add missing shell completions, see #3411 (@keith-hall) +- Execute help/version/diagnostic commands even with invalid config/arguments present, see #3414 (@keith-hall) ## Other