From 5ed64444e3fea234a5a4145b15aeb2f7b6319f1f Mon Sep 17 00:00:00 2001 From: Patrick Pichler Date: Wed, 6 Oct 2021 20:32:47 +0200 Subject: [PATCH 1/4] Add systemwide config file support There is now support for a systemwide config file. The location of the system wide config file is `$(BAT_SYSTEM_CONFIG_PREFIX)/bat/config`. `$(BAT_SYSTEM_CONFIG_PREFIX)` has to be provided at compile time as an environment variable. If the environment variable is not set, a default is used. This default is `C:\ProgramData` for windows and `/etc` for every other os. --- CHANGELOG.md | 1 + README.md | 4 ++++ src/bin/bat/config.rs | 33 ++++++++++++++++++++++++++++----- src/bin/bat/main.rs | 4 ++++ 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1c0c0e4..9c193aee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ - Support for `x:+delta` syntax in line ranges (e.g. `20:+10`). See #1810 (@bojan88) - Add new `--acknowledgements` option that gives credit to theme and syntax definition authors. See #1971 (@Enselic) - Include git hash in `bat -V` and `bat --version` output if present. See #1921 (@Enselic) +- Support for separate system and user config files. See #668 (@patrickpichler) ## Bugfixes diff --git a/README.md b/README.md index 7c1611ad..95b67bd0 100644 --- a/README.md +++ b/README.md @@ -621,6 +621,10 @@ A default configuration file can be created with the `--generate-config-file` op bat --generate-config-file ``` +There is also now a systemwide configuration file, which is located under `/etc/bat/config` on +Linux and Mac OS and `C:\ProgramData\bat\config` on windows. If the system wide configuration +file is present, the content of the user configuration will simply be appended to it. + ### Format The configuration file is a simple list of command line arguments. Use `bat --help` to see a full list of possible options and values. In addition, you can add comments by prepending a line with the `#` character. diff --git a/src/bin/bat/config.rs b/src/bin/bat/config.rs index 659f67b3..696edf9e 100644 --- a/src/bin/bat/config.rs +++ b/src/bin/bat/config.rs @@ -6,6 +6,22 @@ use std::path::PathBuf; use crate::directories::PROJECT_DIRS; +#[cfg(not(target_os = "windows"))] +const DEFAULT_SYSTEM_CONFIG_PREFIX: &str = "/etc"; + +#[cfg(target_os = "windows")] +const DEFAULT_SYSTEM_CONFIG_PREFIX: &str = "C:\\ProgramData"; + +pub fn system_config_file() -> PathBuf { + let folder = option_env!("BAT_SYSTEM_CONFIG_PREFIX").unwrap_or(DEFAULT_SYSTEM_CONFIG_PREFIX); + let mut path = PathBuf::from(folder); + + path.push("bat"); + path.push("config"); + + path +} + pub fn config_file() -> PathBuf { env::var("BAT_CONFIG_PATH") .ok() @@ -87,11 +103,18 @@ pub fn generate_config_file() -> bat::error::Result<()> { } pub fn get_args_from_config_file() -> Result, shell_words::ParseError> { - Ok(fs::read_to_string(config_file()) - .ok() - .map(|content| get_args_from_str(&content)) - .transpose()? - .unwrap_or_else(Vec::new)) + let mut config = String::new(); + + if let Ok(c) = fs::read_to_string(system_config_file()) { + config.push_str(&c); + config.push('\n'); + } + + if let Ok(c) = fs::read_to_string(config_file()) { + config.push_str(&c); + } + + get_args_from_str(&config) } pub fn get_args_from_env_var() -> Option, shell_words::ParseError>> { diff --git a/src/bin/bat/main.rs b/src/bin/bat/main.rs index 7275c94a..0369e436 100644 --- a/src/bin/bat/main.rs +++ b/src/bin/bat/main.rs @@ -21,6 +21,9 @@ use crate::{ config::{config_file, generate_config_file}, }; +#[cfg(feature = "bugreport")] +use crate::config::system_config_file; + use assets::{assets_from_cache_or_binary, cache_dir, clear_assets, config_dir}; use directories::PROJECT_DIRS; use globset::GlobMatcher; @@ -256,6 +259,7 @@ fn invoke_bugreport(app: &App) { "NO_COLOR", "MANPAGER", ])) + .info(FileContent::new("System Config file", system_config_file())) .info(FileContent::new("Config file", config_file())) .info(FileContent::new( "Custom assets metadata", From 6b660ef63a94154c0e0ce05ae898b3283c090c4b Mon Sep 17 00:00:00 2001 From: Patrick Pichler Date: Thu, 28 Oct 2021 13:52:59 +0200 Subject: [PATCH 2/4] Add test for systemwide config file support There is now a new stage in the CICD workflow present, which will build `bat` with the `BAT_SYSTEM_CONFIG_PREFIX` set to load the config file from `/tests/examples/system_config/bat/config`, plus a basic set of tests, to ensure the feature is working as expected. By default the tests are set to ignored, as they need special setup before they can be run. --- .github/workflows/CICD.yml | 28 ++++++++++++++++++- tests/examples/bat.conf | 2 +- tests/examples/system_config/bat/config | 5 ++++ tests/integration_tests.rs | 36 +++---------------------- tests/system_wide_config.rs | 29 ++++++++++++++++++++ tests/utils/command.rs | 36 +++++++++++++++++++++++++ tests/utils/mod.rs | 1 + 7 files changed, 103 insertions(+), 34 deletions(-) create mode 100644 tests/examples/system_config/bat/config create mode 100644 tests/system_wide_config.rs create mode 100644 tests/utils/command.rs diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 124c7e31..710bd4f2 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -96,7 +96,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --locked --release -- --ignored + args: --locked --release --test assets -- --ignored - name: Syntax highlighting regression test run: tests/syntax-tests/regression_test.sh - name: List of languages @@ -106,6 +106,32 @@ jobs: - name: Test custom assets run: tests/syntax-tests/test_custom_assets.sh + test_with_system_config: + name: Run tests with system wide configuration + runs-on: ubuntu-20.04 + steps: + - name: Git checkout + uses: actions/checkout@v2 + - name: Prepare environment variables + run: | + echo "BAT_SYSTEM_CONFIG_PREFIX=$GITHUB_WORKSPACE/tests/examples/system_config" >> $GITHUB_ENV + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + default: true + profile: minimal + - name: Build and install bat + uses: actions-rs/cargo@v1 + with: + command: install + args: --locked --path . + - name: Run unit tests + uses: actions-rs/cargo@v1 + with: + command: test + args: --locked --test system_wide_config -- --ignored + documentation: name: Documentation runs-on: ubuntu-20.04 diff --git a/tests/examples/bat.conf b/tests/examples/bat.conf index 614ab40d..4756cd8e 100644 --- a/tests/examples/bat.conf +++ b/tests/examples/bat.conf @@ -1,5 +1,5 @@ # Make sure that the pager gets executed --paging=always -# Output a dummy message for the integration test. +# Output a dummy message for the integration test and system wide config test. --pager="echo dummy-pager-from-config" diff --git a/tests/examples/system_config/bat/config b/tests/examples/system_config/bat/config new file mode 100644 index 00000000..0750e8f5 --- /dev/null +++ b/tests/examples/system_config/bat/config @@ -0,0 +1,5 @@ +# Make sure that the pager gets executed +--paging=always + +# Output a dummy message for the integration test. +--pager="echo dummy-pager-from-system-config" diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 67df34f8..3baac02b 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -3,7 +3,6 @@ use predicates::boolean::PredicateBooleanExt; use predicates::{prelude::predicate, str::PredicateStrExt}; use serial_test::serial; use std::path::Path; -use std::process::Command; use std::str::from_utf8; use tempfile::tempdir; @@ -28,41 +27,14 @@ mod unix { use unix::*; mod utils; +use utils::command::{bat, bat_with_config}; + +#[cfg(unix)] +use utils::command::bat_raw_command; use utils::mocked_pagers; const EXAMPLES_DIR: &str = "tests/examples"; -fn bat_raw_command_with_config() -> Command { - let mut cmd = Command::cargo_bin("bat").unwrap(); - cmd.current_dir("tests/examples"); - cmd.env_remove("BAT_CACHE_PATH"); - cmd.env_remove("BAT_CONFIG_DIR"); - cmd.env_remove("BAT_CONFIG_PATH"); - cmd.env_remove("BAT_OPTS"); - cmd.env_remove("BAT_PAGER"); - cmd.env_remove("BAT_STYLE"); - cmd.env_remove("BAT_TABS"); - cmd.env_remove("BAT_THEME"); - cmd.env_remove("COLORTERM"); - cmd.env_remove("NO_COLOR"); - cmd.env_remove("PAGER"); - cmd -} - -fn bat_raw_command() -> Command { - let mut cmd = bat_raw_command_with_config(); - cmd.arg("--no-config"); - cmd -} - -fn bat_with_config() -> assert_cmd::Command { - assert_cmd::Command::from_std(bat_raw_command_with_config()) -} - -fn bat() -> assert_cmd::Command { - assert_cmd::Command::from_std(bat_raw_command()) -} - #[test] fn basic() { bat() diff --git a/tests/system_wide_config.rs b/tests/system_wide_config.rs new file mode 100644 index 00000000..7c2a9972 --- /dev/null +++ b/tests/system_wide_config.rs @@ -0,0 +1,29 @@ +use predicates::{prelude::predicate, str::PredicateStrExt}; + +mod utils; +use utils::command::bat_with_config; + +// This test is ignored, as it needs a special system wide config put into place. +// In order to run this tests, use `cargo test --test system_wide_config -- --ignored` +#[test] +#[ignore] +fn use_systemwide_config() { + bat_with_config() + .arg("test.txt") + .assert() + .success() + .stdout(predicate::eq("dummy-pager-from-system-config\n").normalize()); +} + +// This test is ignored, as it needs a special system wide config put into place +// In order to run this tests, use `cargo test --test system_wide_config -- --ignored` +#[test] +#[ignore] +fn config_overrides_system_config() { + bat_with_config() + .env("BAT_CONFIG_PATH", "bat.conf") + .arg("test.txt") + .assert() + .success() + .stdout(predicate::eq("dummy-pager-from-config\n").normalize()); +} diff --git a/tests/utils/command.rs b/tests/utils/command.rs new file mode 100644 index 00000000..64cb0baf --- /dev/null +++ b/tests/utils/command.rs @@ -0,0 +1,36 @@ +use assert_cmd::cargo::CommandCargoExt; +use std::process::Command; + +pub fn bat_raw_command_with_config() -> Command { + let mut cmd = Command::cargo_bin("bat").unwrap(); + cmd.current_dir("tests/examples"); + cmd.env_remove("BAT_CACHE_PATH"); + cmd.env_remove("BAT_CONFIG_DIR"); + cmd.env_remove("BAT_CONFIG_PATH"); + cmd.env_remove("BAT_OPTS"); + cmd.env_remove("BAT_PAGER"); + cmd.env_remove("BAT_STYLE"); + cmd.env_remove("BAT_TABS"); + cmd.env_remove("BAT_THEME"); + cmd.env_remove("COLORTERM"); + cmd.env_remove("NO_COLOR"); + cmd.env_remove("PAGER"); + cmd +} + +#[cfg(test)] +pub fn bat_raw_command() -> Command { + let mut cmd = bat_raw_command_with_config(); + cmd.arg("--no-config"); + cmd +} + +#[cfg(test)] +pub fn bat_with_config() -> assert_cmd::Command { + assert_cmd::Command::from_std(bat_raw_command_with_config()) +} + +#[cfg(test)] +pub fn bat() -> assert_cmd::Command { + assert_cmd::Command::from_std(bat_raw_command()) +} diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 724efc5b..ca1a747a 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -1 +1,2 @@ +pub mod command; pub mod mocked_pagers; From bc2dc0796b9632a494b714019c65d38b333f16e8 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Sun, 4 Sep 2022 21:03:27 +0200 Subject: [PATCH 3/4] Move up the entry to the unreleased section in CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c06342b5..47fac968 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Features - Make the default macOS theme depend on Dark Mode. See #2197, #1746 (@Enselic) +- Support for separate system and user config files. See #668 (@patrickpichler) ## Bugfixes @@ -117,7 +118,6 @@ - Support for `x:+delta` syntax in line ranges (e.g. `20:+10`). See #1810 (@bojan88) - Add new `--acknowledgements` option that gives credit to theme and syntax definition authors. See #1971 (@Enselic) - Include git hash in `bat -V` and `bat --version` output if present. See #1921 (@Enselic) -- Support for separate system and user config files. See #668 (@patrickpichler) ## Bugfixes From 799bb1639c7b02267c3669113bba9d5257c8a80a Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Sun, 4 Sep 2022 21:30:14 +0200 Subject: [PATCH 4/4] Try to fix all warnings --- tests/integration_tests.rs | 1 - tests/utils/command.rs | 2 ++ tests/utils/mocked_pagers.rs | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 3deb65a7..6a626327 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -1,4 +1,3 @@ -use assert_cmd::cargo::CommandCargoExt; use predicates::boolean::PredicateBooleanExt; use predicates::{prelude::predicate, str::PredicateStrExt}; use serial_test::serial; diff --git a/tests/utils/command.rs b/tests/utils/command.rs index 64cb0baf..87420f4b 100644 --- a/tests/utils/command.rs +++ b/tests/utils/command.rs @@ -1,3 +1,5 @@ +#![allow(unused)] // Because indirectly included by e.g.integration_tests.rs, but not everything inside is used + use assert_cmd::cargo::CommandCargoExt; use std::process::Command; diff --git a/tests/utils/mocked_pagers.rs b/tests/utils/mocked_pagers.rs index d115316d..07ae6fcd 100644 --- a/tests/utils/mocked_pagers.rs +++ b/tests/utils/mocked_pagers.rs @@ -1,3 +1,5 @@ +#![allow(unused)] // Because indirectly included by e.g. system_wide_config.rs, but not used + use assert_cmd::Command; use predicates::prelude::predicate; use std::env;