mirror of
https://github.com/nushell/nushell.git
synced 2024-11-22 00:13:21 +01:00
Use directories for autoloading (#13382)
fixes https://github.com/nushell/nushell/issues/13378 # Description This PR tries to improve usage of system APIs to determine the location of vendored autoload files. # User-Facing Changes The paths listed in #13180 and #13217 are changing. This has not been part of a release yet, so arguably the user facing changes are only to unreleased features anyway. # Tests + Formatting Haven't done, but if someone wants to help me here, I'm open to doing it. I just don't know how to properly test this. # After Submitting
This commit is contained in:
parent
e281c03403
commit
4665323bb4
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -3344,6 +3344,8 @@ dependencies = [
|
|||||||
"chrono",
|
"chrono",
|
||||||
"chrono-humanize",
|
"chrono-humanize",
|
||||||
"convert_case",
|
"convert_case",
|
||||||
|
"dirs",
|
||||||
|
"dirs-sys",
|
||||||
"fancy-regex",
|
"fancy-regex",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"log",
|
"log",
|
||||||
@ -3367,6 +3369,7 @@ dependencies = [
|
|||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"typetag",
|
"typetag",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -84,6 +84,7 @@ deunicode = "1.6.0"
|
|||||||
dialoguer = { default-features = false, version = "0.11" }
|
dialoguer = { default-features = false, version = "0.11" }
|
||||||
digest = { default-features = false, version = "0.10" }
|
digest = { default-features = false, version = "0.10" }
|
||||||
dirs = "5.0"
|
dirs = "5.0"
|
||||||
|
dirs-sys = "0.4"
|
||||||
dtparse = "2.0"
|
dtparse = "2.0"
|
||||||
encoding_rs = "0.8"
|
encoding_rs = "0.8"
|
||||||
fancy-regex = "0.13"
|
fancy-regex = "0.13"
|
||||||
@ -178,6 +179,7 @@ v_htmlescape = "0.15.0"
|
|||||||
wax = "0.6"
|
wax = "0.6"
|
||||||
which = "6.0.0"
|
which = "6.0.0"
|
||||||
windows = "0.54"
|
windows = "0.54"
|
||||||
|
windows-sys = "0.48"
|
||||||
winreg = "0.52"
|
winreg = "0.52"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -833,7 +833,7 @@ fn variables_completions() {
|
|||||||
"plugin-path".into(),
|
"plugin-path".into(),
|
||||||
"startup-time".into(),
|
"startup-time".into(),
|
||||||
"temp-path".into(),
|
"temp-path".into(),
|
||||||
"vendor-autoload-dir".into(),
|
"vendor-autoload-dirs".into(),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Match results
|
// Match results
|
||||||
|
@ -23,6 +23,7 @@ byte-unit = { version = "5.1", features = [ "serde" ] }
|
|||||||
chrono = { workspace = true, features = [ "serde", "std", "unstable-locales" ], default-features = false }
|
chrono = { workspace = true, features = [ "serde", "std", "unstable-locales" ], default-features = false }
|
||||||
chrono-humanize = { workspace = true }
|
chrono-humanize = { workspace = true }
|
||||||
convert_case = { workspace = true }
|
convert_case = { workspace = true }
|
||||||
|
dirs = { workspace = true }
|
||||||
fancy-regex = { workspace = true }
|
fancy-regex = { workspace = true }
|
||||||
indexmap = { workspace = true }
|
indexmap = { workspace = true }
|
||||||
lru = { workspace = true }
|
lru = { workspace = true }
|
||||||
@ -38,6 +39,10 @@ log = { workspace = true }
|
|||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
nix = { workspace = true, default-features = false, features = ["signal"] }
|
nix = { workspace = true, default-features = false, features = ["signal"] }
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
dirs-sys = { workspace = true }
|
||||||
|
windows-sys = { workspace = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
plugin = [
|
plugin = [
|
||||||
"brotli",
|
"brotli",
|
||||||
|
@ -185,24 +185,15 @@ pub(crate) fn create_nu_constant(engine_state: &EngineState, span: Span) -> Valu
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create a system level directory for nushell scripts, modules, completions, etc
|
|
||||||
// that can be changed by setting the NU_VENDOR_AUTOLOAD_DIR env var on any platform
|
|
||||||
// before nushell is compiled OR if NU_VENDOR_AUTOLOAD_DIR is not set for non-windows
|
|
||||||
// systems, the PREFIX env var can be set before compile and used as PREFIX/nushell/vendor/autoload
|
|
||||||
record.push(
|
record.push(
|
||||||
"vendor-autoload-dir",
|
"vendor-autoload-dirs",
|
||||||
// pseudo code
|
Value::list(
|
||||||
// if env var NU_VENDOR_AUTOLOAD_DIR is set, in any platform, use it
|
get_vendor_autoload_dirs(engine_state)
|
||||||
// if not, if windows, use ALLUSERPROFILE\nushell\vendor\autoload
|
.iter()
|
||||||
// if not, if non-windows, if env var PREFIX is set, use PREFIX/share/nushell/vendor/autoload
|
.map(|path| Value::string(path.to_string_lossy(), span))
|
||||||
// if not, use the default /usr/share/nushell/vendor/autoload
|
.collect(),
|
||||||
|
span,
|
||||||
// check to see if NU_VENDOR_AUTOLOAD_DIR env var is set, if not, use the default
|
),
|
||||||
if let Some(path) = get_vendor_autoload_dir(engine_state) {
|
|
||||||
Value::string(path.to_string_lossy(), span)
|
|
||||||
} else {
|
|
||||||
Value::error(ShellError::ConfigDirNotFound { span: Some(span) }, span)
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
record.push("temp-path", {
|
record.push("temp-path", {
|
||||||
@ -259,39 +250,95 @@ pub(crate) fn create_nu_constant(engine_state: &EngineState, span: Span) -> Valu
|
|||||||
Value::record(record, span)
|
Value::record(record, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_vendor_autoload_dir(engine_state: &EngineState) -> Option<PathBuf> {
|
pub fn get_vendor_autoload_dirs(_engine_state: &EngineState) -> Vec<PathBuf> {
|
||||||
// pseudo code
|
// load order for autoload dirs
|
||||||
// if env var NU_VENDOR_AUTOLOAD_DIR is set, in any platform, use it
|
// /Library/Application Support/nushell/vendor/autoload on macOS
|
||||||
// if not, if windows, use ALLUSERPROFILE\nushell\vendor\autoload
|
// <dir>/nushell/vendor/autoload for every dir in XDG_DATA_DIRS in reverse order on platforms other than windows. If XDG_DATA_DIRS is not set, it falls back to <PREFIX>/share if PREFIX ends in local, or <PREFIX>/local/share:<PREFIX>/share otherwise. If PREFIX is not set, fall back to /usr/local/share:/usr/share.
|
||||||
// if not, if non-windows, if env var PREFIX is set, use PREFIX/share/nushell/vendor/autoload
|
// %ProgramData%\nushell\vendor\autoload on windows
|
||||||
// if not, use the default /usr/share/nushell/vendor/autoload
|
// NU_VENDOR_AUTOLOAD_DIR from compile time, if env var is set at compile time
|
||||||
|
// if on macOS, additionally check XDG_DATA_HOME, which `dirs` is only doing on Linux
|
||||||
|
// <data_dir>/nushell/vendor/autoload of the current user according to the `dirs` crate
|
||||||
|
// NU_VENDOR_AUTOLOAD_DIR at runtime, if env var is set
|
||||||
|
|
||||||
// check to see if NU_VENDOR_AUTOLOAD_DIR env var is set, if not, use the default
|
let into_autoload_path_fn = |mut path: PathBuf| {
|
||||||
Some(
|
path.push("nushell");
|
||||||
option_env!("NU_VENDOR_AUTOLOAD_DIR")
|
path.push("vendor");
|
||||||
.map(String::from)
|
path.push("autoload");
|
||||||
.unwrap_or_else(|| {
|
path
|
||||||
if cfg!(windows) {
|
};
|
||||||
let all_user_profile = match engine_state.get_env_var("ALLUSERPROFILE") {
|
|
||||||
Some(v) => format!(
|
let mut dirs = Vec::new();
|
||||||
"{}\\nushell\\vendor\\autoload",
|
|
||||||
v.coerce_string().unwrap_or("C:\\ProgramData".into())
|
let mut append_fn = |path: PathBuf| {
|
||||||
),
|
if !dirs.contains(&path) {
|
||||||
None => "C:\\ProgramData\\nushell\\vendor\\autoload".into(),
|
dirs.push(path)
|
||||||
};
|
}
|
||||||
all_user_profile
|
};
|
||||||
} else {
|
|
||||||
// In non-Windows environments, if NU_VENDOR_AUTOLOAD_DIR is not set
|
#[cfg(target_os = "macos")]
|
||||||
// check to see if PREFIX env var is set, and use it as PREFIX/nushell/vendor/autoload
|
std::iter::once("/Library/Application Support")
|
||||||
// otherwise default to /usr/share/nushell/vendor/autoload
|
.map(PathBuf::from)
|
||||||
option_env!("PREFIX").map(String::from).map_or_else(
|
.map(into_autoload_path_fn)
|
||||||
|| "/usr/local/share/nushell/vendor/autoload".into(),
|
.for_each(&mut append_fn);
|
||||||
|prefix| format!("{}/share/nushell/vendor/autoload", prefix),
|
#[cfg(unix)]
|
||||||
)
|
{
|
||||||
}
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
|
||||||
|
std::env::var_os("XDG_DATA_DIRS")
|
||||||
|
.or_else(|| {
|
||||||
|
option_env!("PREFIX").map(|prefix| {
|
||||||
|
if prefix.ends_with("local") {
|
||||||
|
std::ffi::OsString::from(format!("{prefix}/share"))
|
||||||
|
} else {
|
||||||
|
std::ffi::OsString::from(format!("{prefix}/local/share:{prefix}/share"))
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.into(),
|
.unwrap_or_else(|| std::ffi::OsString::from("/usr/local/share/:/usr/share/"))
|
||||||
)
|
.as_encoded_bytes()
|
||||||
|
.split(|b| *b == b':')
|
||||||
|
.map(|split| into_autoload_path_fn(PathBuf::from(std::ffi::OsStr::from_bytes(split))))
|
||||||
|
.rev()
|
||||||
|
.for_each(&mut append_fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
dirs_sys::known_folder(windows_sys::Win32::UI::Shell::FOLDERID_ProgramData)
|
||||||
|
.into_iter()
|
||||||
|
.map(into_autoload_path_fn)
|
||||||
|
.for_each(&mut append_fn);
|
||||||
|
|
||||||
|
option_env!("NU_VENDOR_AUTOLOAD_DIR")
|
||||||
|
.into_iter()
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.for_each(&mut append_fn);
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
std::env::var("XDG_DATA_HOME")
|
||||||
|
.ok()
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.or_else(|| {
|
||||||
|
dirs::home_dir().map(|mut home| {
|
||||||
|
home.push(".local");
|
||||||
|
home.push("share");
|
||||||
|
home
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.map(into_autoload_path_fn)
|
||||||
|
.into_iter()
|
||||||
|
.for_each(&mut append_fn);
|
||||||
|
|
||||||
|
dirs::data_dir()
|
||||||
|
.into_iter()
|
||||||
|
.map(into_autoload_path_fn)
|
||||||
|
.for_each(&mut append_fn);
|
||||||
|
|
||||||
|
std::env::var_os("NU_VENDOR_AUTOLOAD_DIR")
|
||||||
|
.into_iter()
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.for_each(&mut append_fn);
|
||||||
|
|
||||||
|
dirs
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_const_call(
|
fn eval_const_call(
|
||||||
|
@ -200,8 +200,7 @@ pub(crate) fn read_vendor_autoload_files(engine_state: &mut EngineState, stack:
|
|||||||
column!()
|
column!()
|
||||||
);
|
);
|
||||||
|
|
||||||
// read and source vendor_autoload_files file if exists
|
for autoload_dir in nu_protocol::eval_const::get_vendor_autoload_dirs(engine_state) {
|
||||||
if let Some(autoload_dir) = nu_protocol::eval_const::get_vendor_autoload_dir(engine_state) {
|
|
||||||
warn!("read_vendor_autoload_files: {}", autoload_dir.display());
|
warn!("read_vendor_autoload_files: {}", autoload_dir.display());
|
||||||
|
|
||||||
if autoload_dir.exists() {
|
if autoload_dir.exists() {
|
||||||
|
Loading…
Reference in New Issue
Block a user