ok/jj
1
0
Fork 0
forked from mirrors/jj

cli: allow config in ~/.jjconfig.toml

As I said in 095fb9fef4, removing support for `~/.jjconfig` was an
experiment. I've heard from a few people (including in #233) that they
would prefer to have configs in the home directory. This patch
therefore restores that functionality, except I added a `.toml`
extension to the file to clarify the expected format to users and
editors.

After this patch, we still allow configs in `$XDG_CONFIG_HOME` (and
the other paths used by `dirs::config_dir()`), but we error out there
are config files in both that location and `~/.jjconfig.toml`.
This commit is contained in:
Martin von Zweigbergk 2022-05-07 23:54:51 -07:00 committed by Martin von Zweigbergk
parent 8b54ac58bd
commit 0f5e360d96
4 changed files with 23 additions and 8 deletions

View file

@ -40,6 +40,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
"sparse", only to different degrees. Use the `jj sparse` command to manage
the paths included in the sparse checkout.
* Configuration is now also read from `~/.jjconfig.toml`.
* The `$JJ_CONFIG` environment variable can now point to a directory. If it
does, all files in the directory will be read, in alphabetical order.

View file

@ -14,25 +14,39 @@
use std::env;
use std::path::PathBuf;
use thiserror::Error;
use jujutsu_lib::settings::UserSettings;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum ConfigError {
#[error(transparent)]
ConfigReadError(#[from] config::ConfigError),
#[error("Both {0} and {1} exist. Please consolidate you configs in one of them.")]
AmbiguousSource(PathBuf, PathBuf),
}
fn config_path() -> Option<PathBuf> {
fn config_path() -> Result<Option<PathBuf>, ConfigError> {
if let Ok(config_path) = env::var("JJ_CONFIG") {
// TODO: We should probably support colon-separated (std::env::split_paths)
// paths here
Some(PathBuf::from(config_path))
Ok(Some(PathBuf::from(config_path)))
} else {
// TODO: Should we drop the final `/config.toml` and read all files in the
// directory?
dirs::config_dir().map(|config_dir| config_dir.join("jj").join("config.toml"))
let platform_specific_config_path = dirs::config_dir()
.map(|config_dir| config_dir.join("jj").join("config.toml"))
.filter(|path| path.exists());
let home_config_path = dirs::home_dir()
.map(|home_dir| home_dir.join(".jjconfig.toml"))
.filter(|path| path.exists());
match (&platform_specific_config_path, &home_config_path) {
(Some(xdg_config_path), Some(home_config_path)) => Err(ConfigError::AmbiguousSource(
xdg_config_path.clone(),
home_config_path.clone(),
)),
_ => Ok(platform_specific_config_path.or(home_config_path)),
}
}
}
@ -66,7 +80,7 @@ fn env_overrides() -> config::Config {
pub fn read_config() -> Result<UserSettings, ConfigError> {
let mut config_builder = config::Config::builder().add_source(env_base());
if let Some(config_path) = config_path() {
if let Some(config_path) = config_path()? {
let mut files = vec![];
if config_path.is_dir() {
if let Ok(read_dir) = config_path.read_dir() {

View file

@ -48,8 +48,7 @@ fn main() {
}
Err(err) => {
let mut ui = Ui::for_terminal(UserSettings::default());
ui.write_error(&format!("Invalid config: {}\n", err))
.unwrap();
ui.write_error(&format!("Config error: {}\n", err)).unwrap();
std::process::exit(1);
}
}

View file

@ -126,7 +126,7 @@ fn test_invalid_config() {
test_env.add_config(b"[section]key = value-missing-quotes");
let stderr = test_env.jj_cmd_failure(test_env.env_root(), &["init", "repo"]);
insta::assert_snapshot!(stderr.replace('\\', "/"), @r###"
Invalid config: expected newline, found an identifier at line 1 column 10 in config/config0001.toml
Config error: expected newline, found an identifier at line 1 column 10 in config/config0001.toml
"###);
}