mirror of
https://github.com/martinvonz/jj.git
synced 2025-05-05 15:32:49 +00:00
config: default to XDG config files on macOS
Support existing users with the "legacy" config directory, as well. This will be deprecated in a latter commit.
This commit is contained in:
parent
f9966a644b
commit
6f6496ba83
@ -81,6 +81,10 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
* Fixed bash and zsh shell completion when completing aliases of multiple arguments.
|
||||
[#5377](https://github.com/jj-vcs/jj/issues/5377)
|
||||
|
||||
* On macOS, jj now defaults to looking for its config in `$XDG_CONFIG_HOME`
|
||||
(`~/.config` by default) rather than the more GUI-native
|
||||
`~/Library/Application Support`.
|
||||
|
||||
### Packaging changes
|
||||
|
||||
* Jujutsu now uses
|
||||
|
@ -218,6 +218,7 @@ fn create_dir_all(path: &Path) -> std::io::Result<()> {
|
||||
#[derive(Clone, Default, Debug)]
|
||||
struct UnresolvedConfigEnv {
|
||||
config_dir: Option<PathBuf>,
|
||||
macos_legacy_config_dir: Option<PathBuf>,
|
||||
home_dir: Option<PathBuf>,
|
||||
jj_config: Option<String>,
|
||||
}
|
||||
@ -246,9 +247,22 @@ impl UnresolvedConfigEnv {
|
||||
config_dir.push("conf.d");
|
||||
ConfigPath::new(config_dir)
|
||||
});
|
||||
let legacy_platform_config_path =
|
||||
self.macos_legacy_config_dir.clone().map(|mut config_dir| {
|
||||
config_dir.push("jj");
|
||||
config_dir.push("config.toml");
|
||||
ConfigPath::new(config_dir)
|
||||
});
|
||||
let legacy_platform_config_dir = self.macos_legacy_config_dir.map(|mut config_dir| {
|
||||
config_dir.push("jj");
|
||||
config_dir.push("conf.d");
|
||||
ConfigPath::new(config_dir)
|
||||
});
|
||||
|
||||
if let Some(path) = home_config_path {
|
||||
if path.exists() || platform_config_path.is_none() {
|
||||
if path.exists()
|
||||
|| (platform_config_path.is_none() && legacy_platform_config_path.is_none())
|
||||
{
|
||||
paths.push(path);
|
||||
}
|
||||
}
|
||||
@ -259,13 +273,25 @@ impl UnresolvedConfigEnv {
|
||||
paths.push(path);
|
||||
}
|
||||
|
||||
// theoretically this should be an `if let Some(...) = ... && ..., but that
|
||||
// theoretically these should be an `if let Some(...) = ... && ..., but that
|
||||
// isn't stable
|
||||
if let Some(path) = platform_config_dir {
|
||||
if path.exists() {
|
||||
paths.push(path);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(path) = legacy_platform_config_path {
|
||||
if path.exists() {
|
||||
paths.push(path);
|
||||
}
|
||||
}
|
||||
if let Some(path) = legacy_platform_config_dir {
|
||||
if path.exists() {
|
||||
paths.push(path);
|
||||
}
|
||||
}
|
||||
|
||||
paths
|
||||
}
|
||||
}
|
||||
@ -282,7 +308,13 @@ pub struct ConfigEnv {
|
||||
impl ConfigEnv {
|
||||
/// Initializes configuration loader based on environment variables.
|
||||
pub fn from_environment() -> Self {
|
||||
let config_dir = if cfg!(target_os = "macos") {
|
||||
let config_dir = etcetera::choose_base_strategy()
|
||||
.ok()
|
||||
.map(|s| s.config_dir());
|
||||
|
||||
// older versions of jj used a more "GUI" config option,
|
||||
// which is not designed for user-editable configuration of CLI utilities.
|
||||
let macos_legacy_config_dir = if cfg!(target_os = "macos") {
|
||||
etcetera::base_strategy::choose_native_strategy()
|
||||
.ok()
|
||||
.map(|s| {
|
||||
@ -291,9 +323,7 @@ impl ConfigEnv {
|
||||
s.data_dir()
|
||||
})
|
||||
} else {
|
||||
etcetera::choose_base_strategy()
|
||||
.ok()
|
||||
.map(|s| s.config_dir())
|
||||
None
|
||||
};
|
||||
|
||||
// Canonicalize home as we do canonicalize cwd in CliRunner. $HOME might
|
||||
@ -304,6 +334,7 @@ impl ConfigEnv {
|
||||
|
||||
let env = UnresolvedConfigEnv {
|
||||
config_dir,
|
||||
macos_legacy_config_dir,
|
||||
home_dir: home_dir.clone(),
|
||||
jj_config: env::var("JJ_CONFIG").ok(),
|
||||
};
|
||||
@ -1574,6 +1605,51 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn config_path_macos_legacy_exists() -> TestCase {
|
||||
TestCase {
|
||||
files: &["macos-legacy/jj/config.toml"],
|
||||
env: UnresolvedConfigEnv {
|
||||
home_dir: Some("home".into()),
|
||||
config_dir: Some("config".into()),
|
||||
macos_legacy_config_dir: Some("macos-legacy".into()),
|
||||
..Default::default()
|
||||
},
|
||||
wants: vec![
|
||||
Want::new("config/jj/config.toml"),
|
||||
Want::existing("macos-legacy/jj/config.toml"),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
fn config_path_macos_legacy_both_exist() -> TestCase {
|
||||
TestCase {
|
||||
files: &["macos-legacy/jj/config.toml", "config/jj/config.toml"],
|
||||
env: UnresolvedConfigEnv {
|
||||
home_dir: Some("home".into()),
|
||||
config_dir: Some("config".into()),
|
||||
macos_legacy_config_dir: Some("macos-legacy".into()),
|
||||
..Default::default()
|
||||
},
|
||||
wants: vec![
|
||||
Want::existing("config/jj/config.toml"),
|
||||
Want::existing("macos-legacy/jj/config.toml"),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
fn config_path_macos_legacy_new() -> TestCase {
|
||||
TestCase {
|
||||
files: &[],
|
||||
env: UnresolvedConfigEnv {
|
||||
home_dir: Some("home".into()),
|
||||
config_dir: Some("config".into()),
|
||||
macos_legacy_config_dir: Some("macos-legacy".into()),
|
||||
..Default::default()
|
||||
},
|
||||
wants: vec![Want::new("config/jj/config.toml")],
|
||||
}
|
||||
}
|
||||
|
||||
#[test_case(config_path_home_existing())]
|
||||
#[test_case(config_path_home_new())]
|
||||
#[test_case(config_path_home_existing_platform_new())]
|
||||
@ -1592,6 +1668,9 @@ mod tests {
|
||||
#[test_case(config_path_platform_existing_conf_dir_existing())]
|
||||
#[test_case(config_path_all_existing())]
|
||||
#[test_case(config_path_none())]
|
||||
#[test_case(config_path_macos_legacy_exists())]
|
||||
#[test_case(config_path_macos_legacy_both_exist())]
|
||||
#[test_case(config_path_macos_legacy_new())]
|
||||
fn test_config_path(case: TestCase) {
|
||||
let tmp = setup_config_fs(case.files);
|
||||
let env = resolve_config_env(&case.env, tmp.path());
|
||||
@ -1631,6 +1710,7 @@ mod tests {
|
||||
let home_dir = env.home_dir.as_ref().map(|p| root.join(p));
|
||||
let env = UnresolvedConfigEnv {
|
||||
config_dir: env.config_dir.as_ref().map(|p| root.join(p)),
|
||||
macos_legacy_config_dir: env.macos_legacy_config_dir.as_ref().map(|p| root.join(p)),
|
||||
home_dir: home_dir.clone(),
|
||||
jj_config: env.jj_config.as_ref().map(|p| {
|
||||
join_paths(split_paths(p).map(|p| {
|
||||
|
@ -1599,11 +1599,15 @@ The files in the `conf.d` directory are loaded in lexicographic order. This allo
|
||||
configs to be split across multiple files and combines well
|
||||
with [Conditional Variables](#conditional-variables).
|
||||
|
||||
| Platform | Location of `<PLATFORM_SPECIFIC>` dir | Example config file location |
|
||||
| :------- | :------------------------------------ | :-------------------------------------------------------- |
|
||||
| Linux | `$XDG_CONFIG_HOME` or `$HOME/.config` | `/home/alice/.config/jj/config.toml` |
|
||||
| macOS | `$HOME/Library/Application Support` | `/Users/Alice/Library/Application Support/jj/config.toml` |
|
||||
| Windows | `{FOLDERID_RoamingAppData}` | `C:\Users\Alice\AppData\Roaming\jj\config.toml` |
|
||||
| Platform | Location of `<PLATFORM_SPECIFIC>` dir | Example config file location |
|
||||
| :-------------- | :------------------------------------ | :-------------------------------------------------------- |
|
||||
| Linux and macOS | `$XDG_CONFIG_HOME` or `$HOME/.config` | `/home/alice/.config/jj/config.toml` |
|
||||
| Windows | `{FOLDERID_RoamingAppData}` | `C:\Users\Alice\AppData\Roaming\jj\config.toml` |
|
||||
|
||||
On macOS, jj used to put the user config in `~/Library/Application Support`,
|
||||
and jj will still look there for backwards compatibility purposes; this is
|
||||
considered a deprecated location, and you should use the new default
|
||||
`XDG_CONFIG_HOME`.
|
||||
|
||||
The location of the `jj` user config files/directories can also be overridden with the
|
||||
`JJ_CONFIG` environment variable. If it is not empty, it will be used instead
|
||||
|
Loading…
x
Reference in New Issue
Block a user