mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 12:15:42 +02:00
Convert Path to list
in main and preserve case (#14764)
# Description Fixes multiple issues related to `ENV_CONVERSION` and path-conversion-to-list. * #14681 removed some calls to `convert_env_values()`, but we found that this caused `nu -n` to no longer convert the path properly. * `ENV_CONVERSIONS` have apparently never preserved case, meaning a conversion with a key of `foo` would not update `$env.FOO` but rather create a new environment variable with a different case. * There was a partial code-path that attempted to solve this for `PATH`, but it only worked for `PATH` and `Path`. * `convert_env_values()`, which handled `ENV_CONVERSIONS` was called in multiple places in the startup depending on flags. This PR: * Refactors the startup to handle the conversion in `main()` rather than in each potential startup path * Updates `get_env_var_insensitive()` functions added in #14390 to return the name of the environment variable with its original case. This allows code that updates environment variables to preserve the case. * Makes use of the updated function in `ENV_CONVERSIONS` to preserve the case of any updated environment variables. The `ENV_CONVERSION` key itself is still case **insensitive**. * Makes use of the updated function to preserve the case of the `PATH` environment variable (normally handled separately, regardless of whether or not there was an `ENV_CONVERSION` for it). ## Before `env_convert_values` was run: * Before the user `env.nu` ran, which included `nu -c <commandstring>` and `nu <script.nu>` * Before the REPL loaded, which included `nu -n` ## After `env_convert_values` always runs once in `main()` before any config file is processed or the REPL is started # User-Facing Changes Bug fixes # Tests + Formatting - 🟢 `toolkit fmt` - 🟢 `toolkit clippy` - 🟢 `toolkit test` - 🟢 `toolkit test stdlib` Added additional tests to prevent future regression. # After Submitting There is additional cleanup that should probably be done in `convert_env_values()`. This function previously handled `ENV_CONVERSIONS`, but there is no longer any need for this since `convert_env_vars()` runs whenever `$env.ENV_CONVERSIONS` changes now. This means that the only relevant task in the old `convert_env_values()` is to convert the `PATH` to a list, and ensure that it is a list of strings. It's still calling the `from_string` conversion on every variable (just once) even though there are no `ENV_CONVERSIONS` at this point. Leaving that to another PR though, while we get the core issue fixed with this one.
This commit is contained in:
@ -48,6 +48,7 @@ impl UseAnsiColoring {
|
||||
let env_value = |env_name| {
|
||||
engine_state
|
||||
.get_env_var_insensitive(env_name)
|
||||
.map(|(_, v)| v)
|
||||
.and_then(|v| v.coerce_bool().ok())
|
||||
.unwrap_or(false)
|
||||
};
|
||||
@ -60,7 +61,7 @@ impl UseAnsiColoring {
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(cli_color) = engine_state.get_env_var_insensitive("clicolor") {
|
||||
if let Some((_, cli_color)) = engine_state.get_env_var_insensitive("clicolor") {
|
||||
if let Ok(cli_color) = cli_color.coerce_bool() {
|
||||
return cli_color;
|
||||
}
|
||||
|
@ -466,12 +466,16 @@ impl EngineState {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_env_var_insensitive(&self, name: &str) -> Option<&Value> {
|
||||
// Returns Some((name, value)) if found, None otherwise.
|
||||
// When updating environment variables, make sure to use
|
||||
// the same case (the returned "name") as the original
|
||||
// environment variable name.
|
||||
pub fn get_env_var_insensitive(&self, name: &str) -> Option<(&String, &Value)> {
|
||||
for overlay_id in self.scope.active_overlays.iter().rev() {
|
||||
let overlay_name = String::from_utf8_lossy(self.get_overlay_name(*overlay_id));
|
||||
if let Some(env_vars) = self.env_vars.get(overlay_name.as_ref()) {
|
||||
if let Some(v) = env_vars.iter().find(|(k, _)| k.eq_ignore_case(name)) {
|
||||
return Some(v.1);
|
||||
return Some((v.0, v.1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -481,16 +481,20 @@ impl Stack {
|
||||
}
|
||||
|
||||
// Case-Insensitive version of get_env_var
|
||||
// Returns Some((name, value)) if found, None otherwise.
|
||||
// When updating environment variables, make sure to use
|
||||
// the same case (from the returned "name") as the original
|
||||
// environment variable name.
|
||||
pub fn get_env_var_insensitive<'a>(
|
||||
&'a self,
|
||||
engine_state: &'a EngineState,
|
||||
name: &str,
|
||||
) -> Option<&'a Value> {
|
||||
) -> Option<(&'a String, &'a Value)> {
|
||||
for scope in self.env_vars.iter().rev() {
|
||||
for active_overlay in self.active_overlays.iter().rev() {
|
||||
if let Some(env_vars) = scope.get(active_overlay) {
|
||||
if let Some(v) = env_vars.iter().find(|(k, _)| k.eq_ignore_case(name)) {
|
||||
return Some(v.1);
|
||||
return Some((v.0, v.1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -506,7 +510,7 @@ impl Stack {
|
||||
if !is_hidden {
|
||||
if let Some(env_vars) = engine_state.env_vars.get(active_overlay) {
|
||||
if let Some(v) = env_vars.iter().find(|(k, _)| k.eq_ignore_case(name)) {
|
||||
return Some(v.1);
|
||||
return Some((v.0, v.1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user