From 7ba1c6bdb6cf9217ec536832e1819d71cac4a7f0 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Sat, 19 Mar 2022 10:37:13 -0700 Subject: [PATCH] config: add support for a `$JJ_CONFIG` environment variable It's useful for tests, scripts, and debugging to be able to use specific config instead of the user's config. That's especially true for our automated tests because they didn't have a place to read config from on Windows before this patch (they read their config from `{FOLDERID_RoamingAppData}`, which I don't think we can override in tests). --- CHANGELOG.md | 6 ++++++ src/main.rs | 13 +++++++++++-- src/testutils.rs | 9 +++++++++ tests/test_global_opts.rs | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f9a4ef0e..291c6c440 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 `~/Library/Application Support/` on macOS, and `~\AppData\Roaming\` on Windows. +### New features + +* You can now set an environment variable called `$JJ_CONFIG` to a path to a + config file. That will then be read instead of your regular config file. This + is mostly intended for testing and scripts. + ## [0.3.3] - 2022-03-16 No changes, only trying to get the automated build to work. diff --git a/src/main.rs b/src/main.rs index 44d67acea..43c0b76a1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,17 +13,26 @@ // limitations under the License. use std::env; +use std::path::PathBuf; use jujutsu::commands::dispatch; use jujutsu::ui::Ui; use jujutsu_lib::settings::UserSettings; +fn config_path() -> Option { + if let Ok(config_path) = env::var("JJ_CONFIG") { + Some(PathBuf::from(config_path)) + } else { + dirs::config_dir().map(|config_dir| config_dir.join("jj").join("config.toml")) + } +} + fn read_config() -> Result { let mut config_builder = config::Config::builder(); - if let Some(config_dir) = dirs::config_dir() { + if let Some(config_path) = config_path() { config_builder = config_builder.add_source( - config::File::from(config_dir.join("jj").join("config.toml")) + config::File::from(config_path) .required(false) .format(config::FileFormat::Toml), ); diff --git a/src/testutils.rs b/src/testutils.rs index 363de5b19..b239c3741 100644 --- a/src/testutils.rs +++ b/src/testutils.rs @@ -23,6 +23,7 @@ pub struct TestEnvironment { _temp_dir: TempDir, env_root: PathBuf, home_dir: PathBuf, + config_path: PathBuf, command_number: RefCell, } @@ -32,10 +33,13 @@ impl Default for TestEnvironment { let env_root = tmp_dir.path().canonicalize().unwrap(); let home_dir = env_root.join("home"); std::fs::create_dir(&home_dir).unwrap(); + let config_path = env_root.join("config.toml"); + std::fs::write(&config_path, b"").unwrap(); Self { _temp_dir: tmp_dir, env_root, home_dir, + config_path, command_number: RefCell::new(0), } } @@ -52,6 +56,7 @@ impl TestEnvironment { let timestamp = chrono::DateTime::parse_from_rfc3339("2001-02-03T04:05:06+07:00").unwrap(); let mut command_number = self.command_number.borrow_mut(); *command_number += 1; + cmd.env("JJ_CONFIG", self.config_path.to_str().unwrap()); let timestamp = timestamp + chrono::Duration::seconds(*command_number); cmd.env("JJ_TIMESTAMP", timestamp.to_rfc3339()); cmd.env("JJ_USER", "Test User"); @@ -66,6 +71,10 @@ impl TestEnvironment { pub fn home_dir(&self) -> &Path { &self.home_dir } + + pub fn config_path(&self) -> &Path { + &self.config_path + } } pub fn get_stdout_string(assert: &assert_cmd::assert::Assert) -> String { diff --git a/tests/test_global_opts.rs b/tests/test_global_opts.rs index 8d512aa4c..6ef2a0133 100644 --- a/tests/test_global_opts.rs +++ b/tests/test_global_opts.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::io::Write; + use jujutsu::testutils::{get_stdout_string, TestEnvironment}; #[test] @@ -79,3 +81,33 @@ fn test_repo_arg_with_git_clone() { insta::assert_snapshot!(get_stdout_string(&assert), @"Error: '--repository' cannot be used with 'git clone' "); } + +#[test] +fn test_color_config() { + let test_env = TestEnvironment::default(); + let mut config_file = std::fs::File::options() + .append(true) + .open(test_env.config_path()) + .unwrap(); + config_file + .write_all( + br#"[ui] +color="always""#, + ) + .unwrap(); + config_file.flush().unwrap(); + test_env + .jj_cmd(test_env.env_root(), &["init", "repo", "--git"]) + .assert() + .success(); + + let repo_path = test_env.env_root().join("repo"); + let assert = test_env + .jj_cmd(&repo_path, &["log", "-T", "commit_id"]) + .assert() + .success(); + insta::assert_snapshot!(get_stdout_string(&assert), @r###" + @ 230dd059e1b059aefc0da06a2e5a7dbf22362f22 + o 0000000000000000000000000000000000000000 + "###); +}