Browse Source
* feat(macos): Support XDG conventions on macOS too * store base strategy in FnmConfig * add changeset --------- Co-authored-by: Utkarsh Gupta <utkarshgupta137@gmail.com>remotes/origin/fix-insecure-world-writable-dir
![gal@spitfire.co.il](/assets/img/avatar_default.png)
![GitHub](/assets/img/avatar_default.png)
6 changed files with 104 additions and 80 deletions
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
--- |
||||
"fnm": minor |
||||
--- |
||||
|
||||
use XDG conventions in MacOS directories by default |
@ -1,26 +1,78 @@
@@ -1,26 +1,78 @@
|
||||
use etcetera::BaseStrategy; |
||||
use std::path::PathBuf; |
||||
|
||||
use crate::path_ext::PathExt; |
||||
|
||||
fn xdg_dir(env: &str) -> Option<PathBuf> { |
||||
if cfg!(windows) { |
||||
let env_var = std::env::var(env).ok()?; |
||||
Some(PathBuf::from(env_var)) |
||||
} else { |
||||
// On non-Windows platforms, `etcetera` already handles XDG variables
|
||||
None |
||||
} |
||||
} |
||||
|
||||
fn runtime_dir(basedirs: &impl BaseStrategy) -> Option<PathBuf> { |
||||
xdg_dir("XDG_RUNTIME_DIR").or_else(|| basedirs.runtime_dir()) |
||||
} |
||||
|
||||
fn state_dir(basedirs: &impl BaseStrategy) -> Option<PathBuf> { |
||||
xdg_dir("XDG_STATE_HOME").or_else(|| basedirs.state_dir()) |
||||
} |
||||
|
||||
fn cache_dir(basedirs: &impl BaseStrategy) -> PathBuf { |
||||
xdg_dir("XDG_CACHE_HOME").unwrap_or_else(|| basedirs.cache_dir()) |
||||
} |
||||
|
||||
/// A helper struct for directories in fnm that uses XDG Base Directory Specification
|
||||
/// if applicable for the platform.
|
||||
#[derive(Debug)] |
||||
pub struct Directories( |
||||
#[cfg(windows)] etcetera::base_strategy::Windows, |
||||
#[cfg(not(windows))] etcetera::base_strategy::Xdg, |
||||
); |
||||
|
||||
impl Default for Directories { |
||||
fn default() -> Self { |
||||
Self(etcetera::choose_base_strategy().expect("choosing base strategy")) |
||||
} |
||||
} |
||||
|
||||
fn state_dir() -> Option<PathBuf> { |
||||
xdg_dir("XDG_STATE_HOME").or_else(dirs::state_dir) |
||||
impl Directories { |
||||
pub fn strategy(&self) -> &impl BaseStrategy { |
||||
&self.0 |
||||
} |
||||
|
||||
fn cache_dir() -> Option<PathBuf> { |
||||
xdg_dir("XDG_CACHE_HOME").or_else(dirs::cache_dir) |
||||
pub fn default_base_dir(&self) -> PathBuf { |
||||
let strategy = self.strategy(); |
||||
let modern = strategy.data_dir().join("fnm"); |
||||
if modern.exists() { |
||||
return modern; |
||||
} |
||||
|
||||
fn runtime_dir() -> Option<PathBuf> { |
||||
xdg_dir("XDG_RUNTIME_DIR").or_else(dirs::runtime_dir) |
||||
let legacy = strategy.home_dir().join(".fnm"); |
||||
if legacy.exists() { |
||||
return legacy; |
||||
} |
||||
|
||||
pub fn multishell_storage() -> PathBuf { |
||||
runtime_dir() |
||||
.or_else(state_dir) |
||||
.or_else(cache_dir) |
||||
.unwrap_or_else(std::env::temp_dir) |
||||
.join("fnm_multishells") |
||||
#[cfg(target_os = "macos")] |
||||
{ |
||||
let basedirs = etcetera::base_strategy::Apple::new().expect("Can't get home directory"); |
||||
let legacy = basedirs.data_dir().join("fnm"); |
||||
if legacy.exists() { |
||||
return legacy; |
||||
} |
||||
} |
||||
|
||||
modern.ensure_exists_silently() |
||||
} |
||||
|
||||
pub fn multishell_storage(&self) -> PathBuf { |
||||
let basedirs = self.strategy(); |
||||
let dir = runtime_dir(basedirs) |
||||
.or_else(|| state_dir(basedirs)) |
||||
.unwrap_or_else(|| cache_dir(basedirs)); |
||||
dir.join("fnm_multishells") |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue