From d717e8faeb5a7e842b47de20fe573ba05a628f26 Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Thu, 7 Dec 2023 08:13:50 -0600 Subject: [PATCH] Add nu lib dirs default (#11248) # Description This PR is kind of two PRs in one because they were dependent on each other. PR1 - https://github.com/nushell/nushell/commit/3de58d4dc2d441bf853c7ed7c7a456ab7645fe93 with update https://github.com/nushell/nushell/pull/11248/commits/7fcdb242d96c1a32f3deb30594d86b39f5b795ee - This follows our mantra of having everything with defaults written in nushell rust code. So, that if you run without a config, you get the same behavior as with the default config/env files. This sets NU_LIB_DIRS to $nu.config-path/scripts and sets NU_PLUGIN_DIRS to $nu.config-path/plugins. PR2 - https://github.com/nushell/nushell/commit/0e8ac876fd266632b755d27f25858f3c941605ce - The benchmarks have been broke for some time and we didn't notice it. This PR fixes that. It's dependent on PR1 because it was throwing errors because PWD needed to be set to a valid folder and `$nu` did not exist based on how the benchmark was setup. I've tested the benchmarks and they run without error now and I've also launched nushell as `nu -n --no-std-lib` and the env vars exist. closes #11236 # User-Facing Changes # Tests + Formatting # After Submitting --- benches/benchmarks.rs | 54 +++++++++++++------ .../nu-utils/src/sample_config/default_env.nu | 6 +-- src/main.rs | 27 ++++++++++ 3 files changed, 68 insertions(+), 19 deletions(-) diff --git a/benches/benchmarks.rs b/benches/benchmarks.rs index 128049ed5b..7584a55756 100644 --- a/benches/benchmarks.rs +++ b/benches/benchmarks.rs @@ -4,10 +4,35 @@ use nu_parser::parse; use nu_plugin::{EncodingType, PluginResponse}; use nu_protocol::{engine::EngineState, PipelineData, Span, Value}; use nu_utils::{get_default_config, get_default_env}; +use std::path::{Path, PathBuf}; fn load_bench_commands() -> EngineState { nu_command::add_shell_command_context(nu_cmd_lang::create_default_context()) } + +fn canonicalize_path(engine_state: &EngineState, path: &Path) -> PathBuf { + let cwd = engine_state.current_work_dir(); + + if path.exists() { + match nu_path::canonicalize_with(path, cwd) { + Ok(canon_path) => canon_path, + Err(_) => path.to_owned(), + } + } else { + path.to_owned() + } +} + +fn get_home_path(engine_state: &EngineState) -> PathBuf { + let home_path = if let Some(path) = nu_path::home_dir() { + let canon_home_path = canonicalize_path(engine_state, &path); + canon_home_path + } else { + std::path::PathBuf::new() + }; + home_path +} + // FIXME: All benchmarks live in this 1 file to speed up build times when benchmarking. // When the *_benchmarks functions were in different files, `cargo bench` would build // an executable for every single one - incredibly slowly. Would be nice to figure out @@ -15,10 +40,12 @@ fn load_bench_commands() -> EngineState { fn parser_benchmarks(c: &mut Criterion) { let mut engine_state = load_bench_commands(); - // parsing config.nu breaks without PWD set + let home_path = get_home_path(&engine_state); + + // parsing config.nu breaks without PWD set, so set a valid path engine_state.add_env_var( "PWD".into(), - Value::string("/some/dir".to_string(), Span::test_data()), + Value::string(home_path.to_string_lossy(), Span::test_data()), ); let default_env = get_default_env().as_bytes(); @@ -41,7 +68,6 @@ fn parser_benchmarks(c: &mut Criterion) { c.bench_function("eval default_env.nu", |b| { b.iter(|| { - let mut engine_state = load_bench_commands(); let mut stack = nu_protocol::engine::Stack::new(); eval_source( &mut engine_state, @@ -56,12 +82,6 @@ fn parser_benchmarks(c: &mut Criterion) { c.bench_function("eval default_config.nu", |b| { b.iter(|| { - let mut engine_state = load_bench_commands(); - // parsing config.nu breaks without PWD set - engine_state.add_env_var( - "PWD".into(), - Value::string("/some/dir".to_string(), Span::test_data()), - ); let mut stack = nu_protocol::engine::Stack::new(); eval_source( &mut engine_state, @@ -76,9 +96,17 @@ fn parser_benchmarks(c: &mut Criterion) { } fn eval_benchmarks(c: &mut Criterion) { + let mut engine_state = load_bench_commands(); + let home_path = get_home_path(&engine_state); + + // parsing config.nu breaks without PWD set, so set a valid path + engine_state.add_env_var( + "PWD".into(), + Value::string(home_path.to_string_lossy(), Span::test_data()), + ); + c.bench_function("eval default_env.nu", |b| { b.iter(|| { - let mut engine_state = load_bench_commands(); let mut stack = nu_protocol::engine::Stack::new(); eval_source( &mut engine_state, @@ -93,12 +121,6 @@ fn eval_benchmarks(c: &mut Criterion) { c.bench_function("eval default_config.nu", |b| { b.iter(|| { - let mut engine_state = load_bench_commands(); - // parsing config.nu breaks without PWD set - engine_state.add_env_var( - "PWD".into(), - Value::string("/some/dir".to_string(), Span::test_data()), - ); let mut stack = nu_protocol::engine::Stack::new(); eval_source( &mut engine_state, diff --git a/crates/nu-utils/src/sample_config/default_env.nu b/crates/nu-utils/src/sample_config/default_env.nu index 79b3285781..5585fac326 100644 --- a/crates/nu-utils/src/sample_config/default_env.nu +++ b/crates/nu-utils/src/sample_config/default_env.nu @@ -8,7 +8,7 @@ def create_left_prompt [] { # Perform tilde substitution on dir # To determine if the prefix of the path matches the home dir, we split the current path into # segments, and compare those with the segments of the home dir. In cases where the current dir - # is a parent of the home dir (e.g. `/home`, homedir is `/home/user`), this comparison will + # is a parent of the home dir (e.g. `/home`, homedir is `/home/user`), this comparison will # also evaluate to true. Inside the condition, we attempt to str replace `$home` with `~`. # Inside the condition, either: # 1. The home prefix will be replaced @@ -86,14 +86,14 @@ $env.ENV_CONVERSIONS = { } # Directories to search for scripts when calling source or use +# The default for this is $nu.default-config-dir/scripts $env.NU_LIB_DIRS = [ - # FIXME: This default is not implemented in rust code as of 2023-09-06. ($nu.default-config-dir | path join 'scripts') # add /scripts ] # Directories to search for plugin binaries when calling register +# The default for this is $nu.default-config-dir/plugins $env.NU_PLUGIN_DIRS = [ - # FIXME: This default is not implemented in rust code as of 2023-09-06. ($nu.default-config-dir | path join 'plugins') # add /plugins ] diff --git a/src/main.rs b/src/main.rs index abdfdbefab..87c0b73483 100644 --- a/src/main.rs +++ b/src/main.rs @@ -80,6 +80,33 @@ fn main() -> Result<()> { ctrlc_protection(&mut engine_state, &ctrlc); sigquit_protection(&mut engine_state); + // Begin: Default NU_LIB_DIRS, NU_PLUGIN_DIRS + // Set default NU_LIB_DIRS and NU_PLUGIN_DIRS here before the env.nu is processed. If + // the env.nu file exists, these values will be overwritten, if it does not exist, or + // there is an error reading it, these values will be used. + let nushell_config_path = if let Some(mut path) = nu_path::config_dir() { + path.push("nushell"); + path + } else { + // Not really sure what to default this to if nu_path::config_dir() returns None + std::path::PathBuf::new() + }; + + let mut default_nu_lib_dirs_path = nushell_config_path.clone(); + default_nu_lib_dirs_path.push("scripts"); + engine_state.add_env_var( + "NU_LIB_DIRS".to_string(), + Value::test_string(default_nu_lib_dirs_path.to_string_lossy()), + ); + + let mut default_nu_plugin_dirs_path = nushell_config_path; + default_nu_plugin_dirs_path.push("plugins"); + engine_state.add_env_var( + "NU_PLUGIN_DIRS".to_string(), + Value::test_string(default_nu_plugin_dirs_path.to_string_lossy()), + ); + // End: Default NU_LIB_DIRS, NU_PLUGIN_DIRS + // This is the real secret sauce to having an in-memory sqlite db. You must // start a connection to the memory database in main so it will exist for the // lifetime of the program. If it's created with how MEMORY_DB is defined